diff options
author | W. Trevor King <wking@drexel.edu> | 2008-12-04 12:42:22 -0500 |
---|---|---|
committer | W. Trevor King <wking@drexel.edu> | 2008-12-04 12:42:22 -0500 |
commit | 30d707caba54c452dc33168536c8fa3c33ed47bd (patch) | |
tree | b1bb38c83342d10fcdf0b66bedbdcc1c389bad94 /libbe | |
parent | f6c5402f58b8450ee4e1a78da87b560491abbd45 (diff) | |
parent | 72f9263f3d812fb817e0bc4f5c7d07b60df2cd6c (diff) | |
download | bugseverywhere-30d707caba54c452dc33168536c8fa3c33ed47bd.tar.gz |
Merged in the successful per-tree-config branch.
Diffstat (limited to 'libbe')
-rw-r--r-- | libbe/bug.py | 61 | ||||
-rw-r--r-- | libbe/bugdir.py | 43 | ||||
-rw-r--r-- | libbe/cmdutil.py | 2 | ||||
-rw-r--r-- | libbe/comment.py | 2 | ||||
-rw-r--r-- | libbe/diff.py | 17 | ||||
-rw-r--r-- | libbe/mapfile.py | 65 |
6 files changed, 135 insertions, 55 deletions
diff --git a/libbe/bug.py b/libbe/bug.py index 14f3db0..f871c7a 100644 --- a/libbe/bug.py +++ b/libbe/bug.py @@ -34,9 +34,9 @@ import utility # Use a tuple of (category, description) tuples since we don't have # ordered dicts in Python yet http://www.python.org/dev/peps/pep-0372/ -# in order of increasing severity -severity_level_def = ( - ("wishlist","A feature that could improve usefullness, but not a bug."), +# in order of increasing severity. (name, description) pairs +severity_def = ( + ("wishlist","A feature that could improve usefulness, but not a bug."), ("minor","The standard bug level."), ("serious","A bug that requires workarounds."), ("critical","A bug that prevents some features from working at all."), @@ -52,25 +52,50 @@ active_status_def = ( inactive_status_def = ( ("closed", "The bug is no longer relevant."), ("fixed", "The bug should no longer occur."), - ("wontfix","It's not a bug, it's a feature."), - ("disabled", "?")) + ("wontfix","It's not a bug, it's a feature.")) ### Convert the description tuples to more useful formats -severity_values = tuple([val for val,description in severity_level_def]) -severity_description = dict(severity_level_def) +severity_values = () +severity_description = {} severity_index = {} -for i in range(len(severity_values)): - severity_index[severity_values[i]] = i - -active_status_values = tuple(val for val,description in active_status_def) -inactive_status_values = tuple(val for val,description in inactive_status_def) -status_values = active_status_values + inactive_status_values -status_description = dict(active_status_def+inactive_status_def) +def load_severities(severity_def): + global severity_values + global severity_description + global severity_index + if severity_def == settings_object.EMPTY: + return + severity_values = tuple([val for val,description in severity_def]) + severity_description = dict(severity_def) + severity_index = {} + for i,severity in enumerate(severity_values): + severity_index[severity] = i +load_severities(severity_def) + +active_status_values = [] +inactive_status_values = [] +status_values = [] +status_description = {} status_index = {} -for i in range(len(status_values)): - status_index[status_values[i]] = i +def load_status(active_status_def, inactive_status_def): + global active_status_values + global inactive_status_values + global status_values + global status_description + global status_index + if active_status_def == settings_object.EMPTY: + active_status_def = globals()["active_status_def"] + if inactive_status_def == settings_object.EMPTY: + inactive_status_def = globals()["inactive_status_def"] + active_status_values = tuple([val for val,description in active_status_def]) + inactive_status_values = tuple([val for val,description in inactive_status_def]) + status_values = active_status_values + inactive_status_values + status_description = dict(tuple(active_status_def) + tuple(inactive_status_def)) + status_index = {} + for i,status in enumerate(status_values): + status_index[status] = i +load_status(active_status_def, inactive_status_def) class Bug(settings_object.SavedSettingsObject): @@ -113,14 +138,14 @@ class Bug(settings_object.SavedSettingsObject): @_versioned_property(name="severity", doc="A measure of the bug's importance", default="minor", - allowed=severity_values, + check_fn=lambda s: s in severity_values, require_save=True) def severity(): return {} @_versioned_property(name="status", doc="The bug's current status", default="open", - allowed=status_values, + check_fn=lambda s: s in status_values, require_save=True) def status(): return {} diff --git a/libbe/bugdir.py b/libbe/bugdir.py index f93576f..98110dd 100644 --- a/libbe/bugdir.py +++ b/libbe/bugdir.py @@ -170,12 +170,17 @@ class BugDir (list, settings_object.SavedSettingsObject): @_versioned_property(name="user_id", doc= -"""The user's prefered name, e.g 'John Doe <jdoe@example.com>'. Note +"""The user's prefered name, e.g. 'John Doe <jdoe@example.com>'. Note that the Arch RCS backend *enforces* ids with this format.""", change_hook=_set_user_id, generator=_guess_user_id) def user_id(): return {} + @_versioned_property(name="default_assignee", + doc= +"""The default assignee for new bugs e.g. 'John Doe <jdoe@example.com>'.""") + def default_assignee(): return {} + @_versioned_property(name="rcs_name", doc="""The name of the current RCS. Kept seperate to make saving/loading settings easy. Don't set this attribute. Set .rcs instead, and @@ -218,6 +223,35 @@ settings easy. Don't set this attribute. Set .rcs instead, and @doc_property(doc="A dict of (bug-uuid, bug-instance) pairs.") def _bug_map(): return {} + def _setup_severities(self, severities): + if severities != None and severities != settings_object.EMPTY: + bug.load_severities(severities) + def _set_severities(self, old_severities, new_severities): + self._setup_severities(new_severities) + self._prop_save_settings(old_severities, new_severities) + @_versioned_property(name="severities", + doc="The allowed bug severities and their descriptions.", + change_hook=_set_severities) + def severities(): return {} + + def _setup_status(self, active_status, inactive_status): + bug.load_status(active_status, inactive_status) + def _set_active_status(self, old_active_status, new_active_status): + self._setup_status(new_active_status, self.inactive_status) + self._prop_save_settings(old_active_status, new_active_status) + @_versioned_property(name="active_status", + doc="The allowed active bug states and their descriptions.", + change_hook=_set_active_status) + def active_status(): return {} + + def _set_inactive_status(self, old_inactive_status, new_inactive_status): + self._setup_status(self.active_status, new_inactive_status) + self._prop_save_settings(old_inactive_status, new_inactive_status) + @_versioned_property(name="inactive_status", + doc="The allowed inactive bug states and their descriptions.", + change_hook=_set_inactive_status) + def inactive_status(): return {} + def __init__(self, root=None, sink_to_existing_root=True, assert_new_BugDir=False, allow_rcs_init=False, @@ -318,6 +352,8 @@ settings easy. Don't set this attribute. Set .rcs instead, and self.rcs = rcs.rcs_by_name(self.rcs_name) self._setup_encoding(self.encoding) + self._setup_severities(self.severities) + self._setup_status(self.active_status, self.inactive_status) def load_all_bugs(self): "Warning: this could take a while." @@ -369,7 +405,10 @@ settings easy. Don't set this attribute. Set .rcs instead, and if "rcs_name" in duplicate_settings: duplicate_settings["rcs_name"] = "None" duplicate_settings["user_id"] = self.user_id - self._save_settings(duplicate_settings_path, duplicate_settings) + if "disabled" in bug.status_values: + # Hack to support old versions of BE bugs + duplicate_settings["inactive_status"] = self.inactive_status + self._save_settings(duplicate_settings_path, duplicate_settings) return BugDir(duplicate_path, from_disk=True, manipulate_encodings=self._manipulate_encodings) diff --git a/libbe/cmdutil.py b/libbe/cmdutil.py index eefed58..6be7540 100644 --- a/libbe/cmdutil.py +++ b/libbe/cmdutil.py @@ -97,11 +97,13 @@ def raise_get_help(option, opt, value, parser): raise GetHelp def raise_get_completions(option, opt, value, parser): + print "got completion arg" raise GetCompletions(completions(sys.argv[1])) class CmdOptionParser(optparse.OptionParser): def __init__(self, usage): optparse.OptionParser.__init__(self, usage) + self.disable_interspersed_args() self.remove_option("-h") self.add_option("-h", "--help", action="callback", callback=raise_get_help, help="Print a help message") diff --git a/libbe/comment.py b/libbe/comment.py index 6c0e5c0..cb5ea59 100644 --- a/libbe/comment.py +++ b/libbe/comment.py @@ -275,6 +275,8 @@ class Comment(Tree, settings_object.SavedSettingsObject): self._setup_saved_settings() def save_settings(self): + parent_dir = os.path.dirname(self.get_path()) + self.rcs.mkdir(parent_dir) self.rcs.mkdir(self.get_path()) path = self.get_path("values") mapfile.map_save(self.rcs, path, self._get_saved_settings()) diff --git a/libbe/diff.py b/libbe/diff.py index 5fc0166..17d6c50 100644 --- a/libbe/diff.py +++ b/libbe/diff.py @@ -15,9 +15,8 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA """Compare two bug trees""" -from libbe import cmdutil, bugdir +from libbe import cmdutil, bugdir, bug from libbe.utility import time_to_str -from libbe.bug import cmp_severity import doctest def diff(old_bugdir, new_bugdir): @@ -41,17 +40,17 @@ def diff(old_bugdir, new_bugdir): def diff_report(diff_data, bug_dir): (removed, modified, added) = diff_data def modified_cmp(left, right): - return cmp_severity(left[1], right[1]) + return bug.cmp_severity(left[1], right[1]) - added.sort(cmp_severity) - removed.sort(cmp_severity) + added.sort(bug.cmp_severity) + removed.sort(bug.cmp_severity) modified.sort(modified_cmp) lines = [] if len(added) > 0: lines.append("New bug reports:") - for bug in added: - lines.extend(bug.string(shortlist=True).splitlines()) + for bg in added: + lines.extend(bg.string(shortlist=True).splitlines()) lines.append("") if len(modified) > 0: @@ -69,8 +68,8 @@ def diff_report(diff_data, bug_dir): if len(removed) > 0: lines.append("Removed bug reports:") - for bug in removed: - lines.extend(bug.string(shortlist=True).splitlines()) + for bg in removed: + lines.extend(bg.string(shortlist=True).splitlines()) lines.append("") return '\n'.join(lines) diff --git a/libbe/mapfile.py b/libbe/mapfile.py index 559d713..c36d454 100644 --- a/libbe/mapfile.py +++ b/libbe/mapfile.py @@ -14,6 +14,7 @@ # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +import yaml import os.path import errno import utility @@ -29,17 +30,20 @@ class IllegalValue(Exception): Exception.__init__(self, 'Illegal value "%s"' % value) self.value = value -def generate(map, context=3): - """Generate a format-2 mapfile content string. This is a simpler - format, but should merge better, because there's no chance of - confusion for appends, and lines are unique for both key and - value. - +def generate(map): + """Generate a YAML mapfile content string. >>> generate({"q":"p"}) - '\\n\\n\\nq=p\\n\\n\\n\\n' + 'q: p\\n\\n' + >>> generate({"q":u"Fran\u00e7ais"}) + 'q: Fran\\xc3\\xa7ais\\n\\n' + >>> generate({"q":u"hello"}) + 'q: hello\\n\\n' >>> generate({"q=":"p"}) Traceback (most recent call last): IllegalKey: Illegal key "q=" + >>> generate({"q:":"p"}) + Traceback (most recent call last): + IllegalKey: Illegal key "q:" >>> generate({"q\\n":"p"}) Traceback (most recent call last): IllegalKey: Illegal key "q\\n" @@ -53,7 +57,6 @@ def generate(map, context=3): Traceback (most recent call last): IllegalValue: Illegal value "p\\n" """ - assert(context > 0) keys = map.keys() keys.sort() for key in keys: @@ -61,6 +64,7 @@ def generate(map, context=3): assert not key.startswith('>') assert('\n' not in key) assert('=' not in key) + assert(':' not in key) assert(len(key) > 0) except AssertionError: raise IllegalKey(key.encode('string_escape')) @@ -69,20 +73,19 @@ def generate(map, context=3): lines = [] for key in keys: - for i in range(context): - lines.append("") - lines.append("%s=%s" % (key, map[key])) - for i in range(context): - lines.append("") - return '\n'.join(lines) + '\n' + lines.append(yaml.safe_dump({key: map[key]}, + default_flow_style=False, + allow_unicode=True)) + lines.append("") + return '\n'.join(lines) def parse(contents): """ - Parse a format-2 mapfile string. - >>> parse('\\n\\n\\nq=p\\n\\n\\n\\n')['q'] + Parse a YAML mapfile string. + >>> parse('q: p\\n\\n')['q'] + 'p' + >>> parse('q: \\'p\\'\\n\\n')['q'] 'p' - >>> parse('\\n\\nq=\\'p\\'\\n\\n\\n\\n')['q'] - "\'p\'" >>> contents = generate({"a":"b", "c":"d", "e":"f"}) >>> dict = parse(contents) >>> dict["a"] @@ -92,15 +95,25 @@ def parse(contents): >>> dict["e"] 'f' """ - result = {} + old_format = False for line in contents.splitlines(): - line = line.rstrip('\n') - if len(line) == 0: - continue - name,value = [field for field in line.split('=', 1)] - assert not result.has_key(name) - result[name] = value - return result + if len(line.split("=")) == 2: + old_format = True + break + if old_format: # translate to YAML. Hack to deal with old BE bugs. + newlines = [] + for line in contents.splitlines(): + line = line.rstrip('\n') + if len(line) == 0: + continue + fields = line.split("=") + if len(fields) == 2: + key,value = fields + newlines.append('%s: "%s"' % (key, value.replace('"','\\"'))) + else: + newlines.append(line) + contents = '\n'.join(newlines) + return yaml.load(contents) def map_save(rcs, path, map, allow_no_rcs=False): """Save the map as a mapfile to the specified path""" |