From 4db1a045a0606bead191a563abc54dfa8352efe0 Mon Sep 17 00:00:00 2001 From: "W. Trevor King" Date: Wed, 29 Aug 2012 23:26:17 -0400 Subject: Rewrite commands to use bugdirs instead of a single bugdir. The bulk of the work is in regard to XML, with new BugDir.xml and .from_xml methods to support the new entity. I also split the guts import_xml's ._run method into sub-methods to make the import logic more obvious. --- libbe/bugdir.py | 167 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 163 insertions(+), 4 deletions(-) (limited to 'libbe/bugdir.py') diff --git a/libbe/bugdir.py b/libbe/bugdir.py index a3a388c..8f11075 100644 --- a/libbe/bugdir.py +++ b/libbe/bugdir.py @@ -220,6 +220,8 @@ class BugDir (list, settings_object.SavedSettingsObject): directory=False) self.save_settings() for bug in self: + bug.bugdir = self + bug.storage = self.storage bug.save() # methods for managing bugs @@ -261,6 +263,8 @@ class BugDir (list, settings_object.SavedSettingsObject): def append(self, bug, update=False): super(BugDir, self).append(bug) if update: + bug.bugdir = self + bug.storage = self.storage self._bug_map_gen() if (hasattr(self, '_uuids_cache') and not bug.uuid in self._uuids_cache): @@ -292,7 +296,9 @@ class BugDir (list, settings_object.SavedSettingsObject): def xml(self, indent=0, show_bugs=False, show_comments=False): """ >>> bug.load_severities(bug.severity_def) - >>> bug.load_status(active_status_def=bug.active_status_def, inactive_status_def=bug.inactive_status_def) + >>> bug.load_status( + ... active_status_def=bug.active_status_def, + ... inactive_status_def=bug.inactive_status_def) >>> bugdirA = SimpleBugDir(memory=True) >>> bugdirA.severities >>> bugdirA.severities = (('minor', 'The standard bug level.'),) @@ -347,7 +353,10 @@ class BugDir (list, settings_object.SavedSettingsObject): >>> bug.load_severities(bug.severity_def) - >>> bug.load_status(active_status_def=bug.active_status_def, inactive_status_def=bug.inactive_status_def) + >>> bug.load_status( + ... active_status_def=bug.active_status_def, + ... inactive_status_def=bug.inactive_status_def) + >>> bugdirA.cleanup() """ info = [('uuid', self.uuid), ('short-name', self.id.user()), @@ -391,7 +400,9 @@ class BugDir (list, settings_object.SavedSettingsObject): """ Note: If a bugdir uuid is given, set .alt_id to it's value. >>> bug.load_severities(bug.severity_def) - >>> bug.load_status(active_status_def=bug.active_status_def, inactive_status_def=bug.inactive_status_def) + >>> bug.load_status( + ... active_status_def=bug.active_status_def, + ... inactive_status_def=bug.inactive_status_def) >>> bugdirA = SimpleBugDir(memory=True) >>> bugdirA.severities = (('minor', 'The standard bug level.'),) >>> bugdirA.inactive_status = ( @@ -422,7 +433,10 @@ class BugDir (list, settings_object.SavedSettingsObject): >>> bugdirC.xml(show_bugs=True, show_comments=True) == xml True >>> bug.load_severities(bug.severity_def) - >>> bug.load_status(active_status_def=bug.active_status_def, inactive_status_def=bug.inactive_status_def) + >>> bug.load_status( + ... active_status_def=bug.active_status_def, + ... inactive_status_def=bug.inactive_status_def) + >>> bugdirA.cleanup() """ if type(xml_string) == types.UnicodeType: xml_string = xml_string.strip().encode('unicode_escape') @@ -507,6 +521,151 @@ class BugDir (list, settings_object.SavedSettingsObject): self.alt_id = uuid self.extra_strings = estrs + def merge(self, other, accept_changes=True, + accept_extra_strings=True, accept_bugs=True, + accept_comments=True, change_exception=False): + """Merge info from other into this bugdir. + + Overrides any attributes in self that are listed in + other.explicit_attrs. + + >>> bugdirA = SimpleBugDir() + >>> bugdirA.extra_strings += ['TAG: favorite'] + >>> bugdirB = SimpleBugDir() + >>> bugdirB.explicit_attrs = ['target'] + >>> bugdirB.target = '1234' + >>> bugdirB.extra_strings += ['TAG: very helpful'] + >>> bugdirB.extra_strings += ['TAG: useful'] + >>> bugA = bugdirB.bug_from_uuid('a') + >>> commA = bugA.comment_root.new_reply(body='comment A') + >>> commA.uuid = 'uuid-commA' + >>> commA.date = 'Thu, 01 Jan 1970 00:01:00 +0000' + >>> bugC = bugdirB.new_bug(summary='bug C', _uuid='c') + >>> bugC.alt_id = 'alt-c' + >>> bugC.time_string = 'Thu, 01 Jan 1970 00:02:00 +0000' + >>> bugdirA.merge( + ... bugdirB, accept_changes=False, accept_extra_strings=False, + ... accept_bugs=False, change_exception=False) + >>> print(bugdirA.target) + None + >>> bugdirA.merge( + ... bugdirB, accept_changes=False, accept_extra_strings=False, + ... accept_bugs=False, change_exception=True) + Traceback (most recent call last): + ... + ValueError: Merge would change target "None"->"1234" for bugdir abc123 + >>> print(bugdirA.target) + None + >>> bugdirA.merge( + ... bugdirB, accept_changes=True, accept_extra_strings=False, + ... accept_bugs=False, change_exception=True) + Traceback (most recent call last): + ... + ValueError: Merge would add extra string "TAG: useful" for bugdir abc123 + >>> print(bugdirA.target) + 1234 + >>> print(bugdirA.extra_strings) + ['TAG: favorite'] + >>> bugdirA.merge( + ... bugdirB, accept_changes=True, accept_extra_strings=True, + ... accept_bugs=False, change_exception=True) + Traceback (most recent call last): + ... + ValueError: Merge would add bug c (alt: alt-c) to bugdir abc123 + >>> print(bugdirA.extra_strings) + ['TAG: favorite', 'TAG: useful', 'TAG: very helpful'] + >>> bugdirA.merge( + ... bugdirB, accept_changes=True, accept_extra_strings=True, + ... accept_bugs=True, change_exception=True) + >>> print(bugdirA.xml(show_bugs=True, show_comments=True)) + ... # doctest: +ELLIPSIS, +REPORT_UDIFF + + abc123 + abc + 1234 + TAG: favorite + TAG: useful + TAG: very helpful + + a + abc/a + minor + open + John Doe <jdoe@example.com> + Thu, 01 Jan 1970 00:00:00 +0000 + Bug A + + uuid-commA + abc/a/uui + + Thu, 01 Jan 1970 00:01:00 +0000 + text/plain + comment A + + + + b + abc/b + minor + closed + Jane Doe <jdoe@example.com> + Thu, 01 Jan 1970 00:00:00 +0000 + Bug B + + + c + abc/c + minor + open + Thu, 01 Jan 1970 00:02:00 +0000 + bug C + + + >>> bugdirA.cleanup() + >>> bugdirB.cleanup() + """ + if hasattr(other, 'explicit_attrs'): + for attr in other.explicit_attrs: + old = getattr(self, attr) + new = getattr(other, attr) + if old != new: + if accept_changes: + setattr(self, attr, new) + elif change_exception: + raise ValueError( + ('Merge would change {} "{}"->"{}" for bugdir {}' + ).format(attr, old, new, self.uuid)) + for estr in other.extra_strings: + if not estr in self.extra_strings: + if accept_extra_strings: + self.extra_strings += [estr] + elif change_exception: + raise ValueError( + ('Merge would add extra string "{}" for bugdir {}' + ).format(estr, self.uuid)) + for o_bug in other: + try: + s_bug = self.bug_from_uuid(o_bug.uuid) + except KeyError as e: + try: + s_bug = self.bug_from_uuid(o_bug.alt_id) + except KeyError as e: + s_bug = None + if s_bug is None: + if accept_bugs: + o_bug_copy = copy.copy(o_bug) + o_bug_copy.bugdir = self + o_bug_copy.id = libbe.util.id.ID(o_bug_copy, 'bug') + self.append(o_bug_copy) + elif change_exception: + raise ValueError( + ('Merge would add bug {} (alt: {}) to bugdir {}' + ).format(o_bug.uuid, o_bug.alt_id, self.uuid)) + else: + s_bug.merge(o_bug, accept_changes=accept_changes, + accept_extra_strings=accept_extra_strings, + change_exception=change_exception) + # methods for id generation def sibling_uuids(self): -- cgit