From 1f59c7ef9019879d0b5e407492e4a6e04c5a29cc Mon Sep 17 00:00:00 2001 From: "W. Trevor King" Date: Sat, 5 Dec 2009 03:22:25 -0500 Subject: [PATCH] Added subscriptions option to diff.Diff.report_tree(). Also added diff.BUGDIR_ID to avoid lots of magic 'DIR' definitions, and added diff.Subscription class to make the old (id, type) tuples a bit more elegant. --- becommands/subscribe.py | 5 ++- libbe/diff.py | 97 ++++++++++++++++++++++++++++++++--------- 2 files changed, 80 insertions(+), 22 deletions(-) diff --git a/becommands/subscribe.py b/becommands/subscribe.py index 4220c37..3f4998e 100644 --- a/becommands/subscribe.py +++ b/becommands/subscribe.py @@ -163,7 +163,7 @@ you of changes, although there is no way to guarantee this behavior. Available TYPES: For bugs: %s - For DIR : + For %s: %s For unsubscription, any listed SERVERS and TYPES are removed from your @@ -175,7 +175,8 @@ if you're just hacking away on your private repository, you'll known what's changed ;). This command just (un)sets the appropriate subscriptions, and leaves it up to each interface to perform the notification. -""" % (diff.BUG_TYPE_ALL.string_tree(6), diff.BUGDIR_TYPE_ALL.string_tree(6), +""" % (diff.BUG_TYPE_ALL.string_tree(6), diff.BUGDIR_ID, + diff.BUGDIR_TYPE_ALL.string_tree(6), diff.BUGDIR_TYPE_ALL) def help(): diff --git a/libbe/diff.py b/libbe/diff.py index 66d9f4b..b5384a8 100644 --- a/libbe/diff.py +++ b/libbe/diff.py @@ -19,6 +19,7 @@ """Compare two bug trees.""" import difflib +import types import libbe from libbe import bugdir, bug, settings_object, tree @@ -45,6 +46,7 @@ class SubscriptionType (tree.Tree): lines.append("%s%s" % (" "*(indent+2*depth), node)) return "\n".join(lines) +BUGDIR_ID = "DIR" BUGDIR_TYPE_NEW = SubscriptionType("new") BUGDIR_TYPE_ALL = SubscriptionType("all", [BUGDIR_TYPE_NEW]) @@ -71,7 +73,32 @@ def type_from_name(name, type_root, default=None, default_ok=False): return default raise InvalidType(name, type_root) - +class Subscription (object): + """ + >>> subscriptions = [Subscription('XYZ', 'all', type_root=BUG_TYPE_ALL), + ... Subscription('DIR', 'new', type_root=BUGDIR_TYPE_ALL), + ... Subscription('ABC', BUG_TYPE_ALL),] + >>> print sorted(subscriptions) + [, , ] + """ + def __init__(self, id, subscription_type, **kwargs): + if type(subscription_type) in types.StringTypes: + subscription_type = type_from_name(subscription_type, **kwargs) + self.id = id + self.type = subscription_type + def __cmp__(self, other): + for attr in 'id', 'type': + value = cmp(getattr(self, attr), getattr(other, attr)) + if value != 0: + if self.id == BUGDIR_ID: + return -1 + elif other.id == BUGDIR_ID: + return 1 + return value + def __str__(self): + return str(self.type) + def __repr__(self): + return "" % (self.id, self.type) class DiffTree (tree.Tree): """ @@ -233,6 +260,19 @@ class Diff (object): New comments: from John Doe on Thu, 01 Jan 1970 00:00:00 +0000 I'm closing this bug... + + You can also limit the report generation by providing a list of + subscriptions. + + >>> subscriptions = [Subscription('DIR', BUGDIR_TYPE_NEW), + ... Subscription('b', BUG_TYPE_ALL)] + >>> r = d.report_tree(subscriptions) + >>> print r.report_string() + New bugs: + c:om: Bug C + Removed bugs: + b:cm: Bug B + >>> bd.cleanup() """ def __init__(self, old_bugdir, new_bugdir): @@ -241,7 +281,7 @@ class Diff (object): # data assembly methods - def _changed_bugs(self): + def _changed_bugs(self, subscriptions): """ Search for differences in all bugs between .old_bugdir and .new_bugdir. Returns @@ -250,33 +290,48 @@ class Diff (object): removed bugs respectively. modified_bugs is a list of (old_bug,new_bug) pairs. """ - if hasattr(self, "__changed_bugs"): - return self.__changed_bugs + bugdir_types = [s.type for s in subscriptions if s.id == BUGDIR_ID] + if BUGDIR_TYPE_ALL in bugdir_types: + new_uuids = list(self.new_bugdir.uuids()) + old_uuids = list(self.old_bugdir.uuids()) + elif BUGDIR_TYPE_NEW in bugdir_types: + new_uuids = list(self.new_bugdir.uuids()) + old_uuids = [] + subscribed_bugs = [s.id for s in subscriptions + if BUG_TYPE_ALL.has_descendant( \ + s.type, match_self=True)] + new_uuids.extend([s for s in subscribed_bugs + if self.new_bugdir.has_bug(s)]) + new_uuids = sorted(set(new_uuids)) + old_uuids.extend([s for s in subscribed_bugs + if self.old_bugdir.has_bug(s)]) + old_uuids = sorted(set(old_uuids)) added = [] removed = [] modified = [] - for uuid in self.new_bugdir.uuids(): + for uuid in new_uuids: new_bug = self.new_bugdir.bug_from_uuid(uuid) try: old_bug = self.old_bugdir.bug_from_uuid(uuid) except KeyError: added.append(new_bug) - else: + continue + if BUGDIR_TYPE_ALL in bugdir_types \ + or uuid in subscribed_bugs: if old_bug.sync_with_disk == True: old_bug.load_comments() if new_bug.sync_with_disk == True: new_bug.load_comments() if old_bug != new_bug: modified.append((old_bug, new_bug)) - for uuid in self.old_bugdir.uuids(): + for uuid in old_uuids: if not self.new_bugdir.has_bug(uuid): old_bug = self.old_bugdir.bug_from_uuid(uuid) removed.append(old_bug) added.sort() removed.sort() modified.sort(self._bug_modified_cmp) - self.__changed_bugs = (added, modified, removed) - return self.__changed_bugs + return (added, modified, removed) def _bug_modified_cmp(self, left, right): return cmp(left[1], right[1]) def _changed_comments(self, old, new): @@ -348,25 +403,28 @@ class Diff (object): # report generation methods - def report_tree(self, diff_tree=DiffTree): + def report_tree(self, subscriptions=None, diff_tree=DiffTree): """ Pretty bare to make it easy to adjust to specific cases. You can pass in a DiffTree subclass via diff_tree to override the default report assembly process. """ - if hasattr(self, "__report_tree"): - return self.__report_tree + if subscriptions == None: + subscriptions = [Subscription(BUGDIR_ID, BUGDIR_TYPE_ALL)] bugdir_settings = sorted(self.new_bugdir.settings_properties) bugdir_settings.remove("vcs_name") # tweaked by bugdir.duplicate_bugdir root = diff_tree("bugdir") - bugdir_attribute_changes = self._bugdir_attribute_changes() - if len(bugdir_attribute_changes) > 0: - bugdir = diff_tree("settings", bugdir_attribute_changes, - self.bugdir_attribute_change_string) - root.append(bugdir) + bugdir_subscriptions = [s.type for s in subscriptions + if s.id == BUGDIR_ID] + if BUGDIR_TYPE_ALL in bugdir_subscriptions: + bugdir_attribute_changes = self._bugdir_attribute_changes() + if len(bugdir_attribute_changes) > 0: + bugdir = diff_tree("settings", bugdir_attribute_changes, + self.bugdir_attribute_change_string) + root.append(bugdir) bug_root = diff_tree("bugs") root.append(bug_root) - add,mod,rem = self._changed_bugs() + add,mod,rem = self._changed_bugs(subscriptions) bnew = diff_tree("new", "New bugs:", requires_children=True) bug_root.append(bnew) for bug in add: @@ -416,8 +474,7 @@ class Diff (object): self.comment_body_change_string) c.append(cbody) cr.extend([cnew, crem, cmod]) - self.__report_tree = root - return self.__report_tree + return root # change data -> string methods. # Feel free to play with these in subclasses. -- 2.26.2