From 614d4e40e148520ac511cbe0606bcbdcf24c8a08 Mon Sep 17 00:00:00 2001 From: "W. Trevor King" Date: Sat, 21 Nov 2009 15:18:02 -0500 Subject: Added restrict_file_access to becommands' execute() args. + associated adjustments in other files. See cmdutil.restrict_file_access.__doc__ for an explanation of the security hole this closes. --- becommands/subscribe.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'becommands/subscribe.py') diff --git a/becommands/subscribe.py b/becommands/subscribe.py index 0a23057..051341b 100644 --- a/becommands/subscribe.py +++ b/becommands/subscribe.py @@ -55,7 +55,7 @@ class InvalidType (ValueError): self.type_root = type_root -def execute(args, manipulate_encodings=True): +def execute(args, manipulate_encodings=True, restrict_file_access=False): """ >>> bd = bugdir.SimpleBugDir() >>> bd.set_sync_with_disk(True) -- cgit From 129c100046231ed15d2f16eaa90b5c01e41a442c Mon Sep 17 00:00:00 2001 From: "W. Trevor King" Date: Sat, 5 Dec 2009 01:58:41 -0500 Subject: Moved subscription types from becommands/subscribe.py to libbe/diff.py. --- becommands/subscribe.py | 105 +++++++++++++++++------------------------------- 1 file changed, 36 insertions(+), 69 deletions(-) (limited to 'becommands/subscribe.py') diff --git a/becommands/subscribe.py b/becommands/subscribe.py index 051341b..4220c37 100644 --- a/becommands/subscribe.py +++ b/becommands/subscribe.py @@ -14,47 +14,12 @@ # with this program; if not, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. """(Un)subscribe to change notification""" -from libbe import cmdutil, bugdir, tree +from libbe import cmdutil, bugdir, tree, diff import os, copy __desc__ = __doc__ TAG="SUBSCRIBE:" -class SubscriptionType (tree.Tree): - """ - Trees of subscription types to allow users to select exactly what - notifications they want to subscribe to. - """ - def __init__(self, type_name, *args, **kwargs): - tree.Tree.__init__(self, *args, **kwargs) - self.type = type_name - def __str__(self): - return self.type - def __repr__(self): - return "" % str(self) - def string_tree(self, indent=0): - lines = [] - for depth,node in self.thread(): - lines.append("%s%s" % (" "*(indent+2*depth), node)) - return "\n".join(lines) - -BUGDIR_TYPE_NEW = SubscriptionType("new") -BUGDIR_TYPE_ALL = SubscriptionType("all", [BUGDIR_TYPE_NEW]) - -# same name as BUGDIR_TYPE_ALL for consistency -BUG_TYPE_ALL = SubscriptionType(str(BUGDIR_TYPE_ALL)) - -INVALID_TYPE = SubscriptionType("INVALID") - -class InvalidType (ValueError): - def __init__(self, type_name, type_root): - msg = "Invalid type %s for tree:\n%s" \ - % (type_name, type_root.string_tree(4)) - ValueError.__init__(self, msg) - self.type_name = type_name - self.type_root = type_root - - def execute(args, manipulate_encodings=True, restrict_file_access=False): """ >>> bd = bugdir.SimpleBugDir() @@ -127,19 +92,19 @@ def execute(args, manipulate_encodings=True, restrict_file_access=False): types = options.types.split(",") if len(args) == 0 or args[0] == "DIR": # directory-wide subscriptions - type_root = BUGDIR_TYPE_ALL + type_root = diff.BUGDIR_TYPE_ALL entity = bd entity_name = "bug directory" else: # bug-specific subscriptions - type_root = BUG_TYPE_ALL + type_root = diff.BUG_TYPE_ALL bug = bd.bug_from_shortname(args[0]) entity = bug entity_name = bug.uuid if options.list_all == True: entity_name = "anything in the bug directory" - types = [type_from_name(name, type_root, default=INVALID_TYPE, - default_ok=options.unsubscribe) + types = [diff.type_from_name(name, type_root, default=diff.INVALID_TYPE, + default_ok=options.unsubscribe) for name in types] estrs = entity.extra_strings if options.list == True or options.list_all == True: @@ -210,8 +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. -""" % (BUG_TYPE_ALL.string_tree(6), BUGDIR_TYPE_ALL.string_tree(6), - BUGDIR_TYPE_ALL) +""" % (diff.BUG_TYPE_ALL.string_tree(6), diff.BUGDIR_TYPE_ALL.string_tree(6), + diff.BUGDIR_TYPE_ALL) def help(): return get_parser().help_str() + longhelp @@ -227,7 +192,7 @@ def _parse_string(string, type_root): assert string.startswith(TAG), string string = string[len(TAG):] subscriber,types,servers = string.split("\t") - types = [type_from_name(name, type_root) for name in types.split(",")] + types = [diff.type_from_name(name, type_root) for name in types.split(",")] return (subscriber,types,servers.split(",")) def _get_subscriber(extra_strings, subscriber, type_root): @@ -240,16 +205,6 @@ def _get_subscriber(extra_strings, subscriber, type_root): # functions exposed to other modules -def type_from_name(name, type_root, default=None, default_ok=False): - if name == str(type_root): - return type_root - for t in type_root.traverse(): - if name == str(t): - return t - if default_ok: - return default - raise InvalidType(name, type_root) - def subscribe(extra_strings, subscriber, types, servers, type_root): args = _get_subscriber(extra_strings, subscriber, type_root) if args == None: # no match @@ -311,17 +266,22 @@ def get_subscribers(extra_strings, type, server, type_root, >>> def sgs(*args, **kwargs): ... return sorted(get_subscribers(*args, **kwargs)) >>> es = [] - >>> es = subscribe(es, "John Doe ", [BUGDIR_TYPE_ALL], ["a.com"], BUGDIR_TYPE_ALL) - >>> es = subscribe(es, "Jane Doe ", [BUGDIR_TYPE_NEW], ["*"], BUGDIR_TYPE_ALL) - >>> sgs(es, BUGDIR_TYPE_ALL, "a.com", BUGDIR_TYPE_ALL) + >>> es = subscribe(es, "John Doe ", [diff.BUGDIR_TYPE_ALL], + ... ["a.com"], diff.BUGDIR_TYPE_ALL) + >>> es = subscribe(es, "Jane Doe ", [diff.BUGDIR_TYPE_NEW], + ... ["*"], diff.BUGDIR_TYPE_ALL) + >>> sgs(es, diff.BUGDIR_TYPE_ALL, "a.com", diff.BUGDIR_TYPE_ALL) ['John Doe '] - >>> sgs(es, BUGDIR_TYPE_ALL, "a.com", BUGDIR_TYPE_ALL, match_descendant_types=True) + >>> sgs(es, diff.BUGDIR_TYPE_ALL, "a.com", diff.BUGDIR_TYPE_ALL, + ... match_descendant_types=True) ['Jane Doe ', 'John Doe '] - >>> sgs(es, BUGDIR_TYPE_ALL, "b.net", BUGDIR_TYPE_ALL, match_descendant_types=True) + >>> sgs(es, diff.BUGDIR_TYPE_ALL, "b.net", diff.BUGDIR_TYPE_ALL, + ... match_descendant_types=True) ['Jane Doe '] - >>> sgs(es, BUGDIR_TYPE_NEW, "a.com", BUGDIR_TYPE_ALL) + >>> sgs(es, diff.BUGDIR_TYPE_NEW, "a.com", diff.BUGDIR_TYPE_ALL) ['Jane Doe '] - >>> sgs(es, BUGDIR_TYPE_NEW, "a.com", BUGDIR_TYPE_ALL, match_ancestor_types=True) + >>> sgs(es, diff.BUGDIR_TYPE_NEW, "a.com", diff.BUGDIR_TYPE_ALL, + ... match_ancestor_types=True) ['Jane Doe ', 'John Doe '] """ for string in extra_strings: @@ -360,9 +320,12 @@ def get_bugdir_subscribers(bugdir, server): >>> bd = bugdir.SimpleBugDir(sync_with_disk=False) >>> a = bd.bug_from_shortname("a") - >>> bd.extra_strings = subscribe(bd.extra_strings, "John Doe ", [BUGDIR_TYPE_ALL], ["a.com"], BUGDIR_TYPE_ALL) - >>> bd.extra_strings = subscribe(bd.extra_strings, "Jane Doe ", [BUGDIR_TYPE_NEW], ["*"], BUGDIR_TYPE_ALL) - >>> a.extra_strings = subscribe(a.extra_strings, "John Doe ", [BUG_TYPE_ALL], ["a.com"], BUG_TYPE_ALL) + >>> bd.extra_strings = subscribe(bd.extra_strings, "John Doe ", + ... [diff.BUGDIR_TYPE_ALL], ["a.com"], diff.BUGDIR_TYPE_ALL) + >>> bd.extra_strings = subscribe(bd.extra_strings, "Jane Doe ", + ... [diff.BUGDIR_TYPE_NEW], ["*"], diff.BUGDIR_TYPE_ALL) + >>> a.extra_strings = subscribe(a.extra_strings, "John Doe ", + ... [diff.BUG_TYPE_ALL], ["a.com"], diff.BUG_TYPE_ALL) >>> subscribers = get_bugdir_subscribers(bd, "a.com") >>> subscribers["Jane Doe "]["DIR"] [] @@ -375,14 +338,18 @@ def get_bugdir_subscribers(bugdir, server): >>> bd.cleanup() """ subscribers = {} - for sub in get_subscribers(bugdir.extra_strings, BUGDIR_TYPE_ALL, server, - BUGDIR_TYPE_ALL, match_descendant_types=True): - i,s,ts,srvs = _get_subscriber(bugdir.extra_strings,sub,BUGDIR_TYPE_ALL) + for sub in get_subscribers(bugdir.extra_strings, diff.BUGDIR_TYPE_ALL, + server, diff.BUGDIR_TYPE_ALL, + match_descendant_types=True): + i,s,ts,srvs = _get_subscriber(bugdir.extra_strings, sub, + diff.BUGDIR_TYPE_ALL) subscribers[sub] = {"DIR":ts} for bug in bugdir: - for sub in get_subscribers(bug.extra_strings, BUG_TYPE_ALL, server, - BUG_TYPE_ALL, match_descendant_types=True): - i,s,ts,srvs = _get_subscriber(bug.extra_strings,sub,BUG_TYPE_ALL) + for sub in get_subscribers(bug.extra_strings, diff.BUG_TYPE_ALL, + server, diff.BUG_TYPE_ALL, + match_descendant_types=True): + i,s,ts,srvs = _get_subscriber(bug.extra_strings, sub, + diff.BUG_TYPE_ALL) if sub in subscribers: subscribers[sub][bug.uuid] = ts else: -- cgit From 1f59c7ef9019879d0b5e407492e4a6e04c5a29cc Mon Sep 17 00:00:00 2001 From: "W. Trevor King" Date: Sat, 5 Dec 2009 03:22:25 -0500 Subject: 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 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'becommands/subscribe.py') 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(): -- cgit From 3cf0394832176a18f658ef3a89521bcccd57cb9e Mon Sep 17 00:00:00 2001 From: "W. Trevor King" Date: Sat, 5 Dec 2009 04:21:04 -0500 Subject: More 'DIR'->diff.BUGDIR_ID updates --- becommands/subscribe.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'becommands/subscribe.py') diff --git a/becommands/subscribe.py b/becommands/subscribe.py index 3f4998e..19aac53 100644 --- a/becommands/subscribe.py +++ b/becommands/subscribe.py @@ -91,7 +91,7 @@ def execute(args, manipulate_encodings=True, restrict_file_access=False): servers = options.servers.split(",") types = options.types.split(",") - if len(args) == 0 or args[0] == "DIR": # directory-wide subscriptions + if len(args) == 0 or args[0] == diff.BUGDIR_ID: # directory-wide subscriptions type_root = diff.BUGDIR_TYPE_ALL entity = bd entity_name = "bug directory" @@ -314,7 +314,7 @@ def get_bugdir_subscribers(bugdir, server): Returns a dict of dicts: subscribers[user][id] = types where id is either a bug.uuid (in the case of a bug subscription) - or "DIR" (in the case of a bugdir subscription). + or "%(bugdir_id)s" (in the case of a bugdir subscription). Only checks bugs that are currently in memory, so you might want to call bugdir.load_all_bugs() first. @@ -328,16 +328,16 @@ def get_bugdir_subscribers(bugdir, server): >>> a.extra_strings = subscribe(a.extra_strings, "John Doe ", ... [diff.BUG_TYPE_ALL], ["a.com"], diff.BUG_TYPE_ALL) >>> subscribers = get_bugdir_subscribers(bd, "a.com") - >>> subscribers["Jane Doe "]["DIR"] + >>> subscribers["Jane Doe "]["%(bugdir_id)s"] [] - >>> subscribers["John Doe "]["DIR"] + >>> subscribers["John Doe "]["%(bugdir_id)s"] [] >>> subscribers["John Doe "]["a"] [] >>> get_bugdir_subscribers(bd, "b.net") - {'Jane Doe ': {'DIR': []}} + {'Jane Doe ': {'%(bugdir_id)s': []}} >>> bd.cleanup() - """ + """ % {'bugdir_id':diff.BUGDIR_ID} subscribers = {} for sub in get_subscribers(bugdir.extra_strings, diff.BUGDIR_TYPE_ALL, server, diff.BUGDIR_TYPE_ALL, -- cgit From fdf9925ffaada614544d1b2d3ccecb42f1549acb Mon Sep 17 00:00:00 2001 From: "W. Trevor King" Date: Mon, 7 Dec 2009 07:18:48 -0500 Subject: be --dir DIR COMMAND now roots the bugdir in DIR without changing directories. Previously, for the directory structure A |-- X `-- Y You could do something like A$ be --dir X diff --dir ../Y Now it's A$ be --dir X diff --dir Y The --root option to `be init` has been removed as redundant. Replace calls like be init --root DIR with be --dir DIR init --- becommands/subscribe.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'becommands/subscribe.py') diff --git a/becommands/subscribe.py b/becommands/subscribe.py index 19aac53..69554f7 100644 --- a/becommands/subscribe.py +++ b/becommands/subscribe.py @@ -20,7 +20,8 @@ __desc__ = __doc__ TAG="SUBSCRIBE:" -def execute(args, manipulate_encodings=True, restrict_file_access=False): +def execute(args, manipulate_encodings=True, restrict_file_access=False, + dir="."): """ >>> bd = bugdir.SimpleBugDir() >>> bd.set_sync_with_disk(True) @@ -73,7 +74,8 @@ def execute(args, manipulate_encodings=True, restrict_file_access=False): raise cmdutil.UsageError("Too many arguments.") bd = bugdir.BugDir(from_disk=True, - manipulate_encodings=manipulate_encodings) + manipulate_encodings=manipulate_encodings, + root=dir) subscriber = options.subscriber if subscriber == None: -- cgit From 49a7771336ce09f6d42c7699ef32aecea0e83182 Mon Sep 17 00:00:00 2001 From: "W. Trevor King" Date: Mon, 7 Dec 2009 20:07:55 -0500 Subject: Initial directory restructuring to clarify dependencies --- becommands/subscribe.py | 360 ------------------------------------------------ 1 file changed, 360 deletions(-) delete mode 100644 becommands/subscribe.py (limited to 'becommands/subscribe.py') diff --git a/becommands/subscribe.py b/becommands/subscribe.py deleted file mode 100644 index 69554f7..0000000 --- a/becommands/subscribe.py +++ /dev/null @@ -1,360 +0,0 @@ -# Copyright (C) 2009 W. Trevor King -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# 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., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -"""(Un)subscribe to change notification""" -from libbe import cmdutil, bugdir, tree, diff -import os, copy -__desc__ = __doc__ - -TAG="SUBSCRIBE:" - -def execute(args, manipulate_encodings=True, restrict_file_access=False, - dir="."): - """ - >>> bd = bugdir.SimpleBugDir() - >>> bd.set_sync_with_disk(True) - >>> os.chdir(bd.root) - >>> a = bd.bug_from_shortname("a") - >>> print a.extra_strings - [] - >>> execute(["-s","John Doe ", "a"], manipulate_encodings=False) # doctest: +NORMALIZE_WHITESPACE - Subscriptions for a: - John Doe all * - >>> bd._clear_bugs() # resync our copy of bug - >>> a = bd.bug_from_shortname("a") - >>> print a.extra_strings - ['SUBSCRIBE:John Doe \\tall\\t*'] - >>> execute(["-s","Jane Doe ", "-S", "a.com,b.net", "a"], manipulate_encodings=False) # doctest: +NORMALIZE_WHITESPACE - Subscriptions for a: - Jane Doe all a.com,b.net - John Doe all * - >>> execute(["-s","Jane Doe ", "-S", "a.edu", "a"], manipulate_encodings=False) # doctest: +NORMALIZE_WHITESPACE - Subscriptions for a: - Jane Doe all a.com,a.edu,b.net - John Doe all * - >>> execute(["-u", "-s","Jane Doe ", "-S", "a.com", "a"], manipulate_encodings=False) # doctest: +NORMALIZE_WHITESPACE - Subscriptions for a: - Jane Doe all a.edu,b.net - John Doe all * - >>> execute(["-s","Jane Doe ", "-S", "*", "a"], manipulate_encodings=False) # doctest: +NORMALIZE_WHITESPACE - Subscriptions for a: - Jane Doe all * - John Doe all * - >>> execute(["-u", "-s","Jane Doe ", "a"], manipulate_encodings=False) # doctest: +NORMALIZE_WHITESPACE - Subscriptions for a: - John Doe all * - >>> execute(["-u", "-s","John Doe ", "a"], manipulate_encodings=False) - >>> execute(["-s","Jane Doe ", "-t", "new", "DIR"], manipulate_encodings=False) # doctest: +NORMALIZE_WHITESPACE - Subscriptions for bug directory: - Jane Doe new * - >>> execute(["-s","Jane Doe ", "DIR"], manipulate_encodings=False) # doctest: +NORMALIZE_WHITESPACE - Subscriptions for bug directory: - Jane Doe all * - >>> bd.cleanup() - """ - parser = get_parser() - options, args = parser.parse_args(args) - cmdutil.default_complete(options, args, parser, - bugid_args={0: lambda bug : bug.active==True}) - - if len(args) > 1: - help() - raise cmdutil.UsageError("Too many arguments.") - - bd = bugdir.BugDir(from_disk=True, - manipulate_encodings=manipulate_encodings, - root=dir) - - subscriber = options.subscriber - if subscriber == None: - subscriber = bd.user_id - if options.unsubscribe == True: - if options.servers == None: - options.servers = "INVALID" - if options.types == None: - options.types = "INVALID" - else: - if options.servers == None: - options.servers = "*" - if options.types == None: - options.types = "all" - servers = options.servers.split(",") - types = options.types.split(",") - - if len(args) == 0 or args[0] == diff.BUGDIR_ID: # directory-wide subscriptions - type_root = diff.BUGDIR_TYPE_ALL - entity = bd - entity_name = "bug directory" - else: # bug-specific subscriptions - type_root = diff.BUG_TYPE_ALL - bug = bd.bug_from_shortname(args[0]) - entity = bug - entity_name = bug.uuid - if options.list_all == True: - entity_name = "anything in the bug directory" - - types = [diff.type_from_name(name, type_root, default=diff.INVALID_TYPE, - default_ok=options.unsubscribe) - for name in types] - estrs = entity.extra_strings - if options.list == True or options.list_all == True: - pass - else: # alter subscriptions - if options.unsubscribe == True: - estrs = unsubscribe(estrs, subscriber, types, servers, type_root) - else: # add the tag - estrs = subscribe(estrs, subscriber, types, servers, type_root) - entity.extra_strings = estrs # reassign to notice change - - if options.list_all == True: - bd.load_all_bugs() - subscriptions = get_bugdir_subscribers(bd, servers[0]) - else: - subscriptions = [] - for estr in entity.extra_strings: - if estr.startswith(TAG): - subscriptions.append(estr[len(TAG):]) - - if len(subscriptions) > 0: - print "Subscriptions for %s:" % entity_name - print '\n'.join(subscriptions) - - -def get_parser(): - parser = cmdutil.CmdOptionParser("be subscribe ID") - parser.add_option("-u", "--unsubscribe", action="store_true", - dest="unsubscribe", default=False, - help="Unsubscribe instead of subscribing.") - parser.add_option("-a", "--list-all", action="store_true", - dest="list_all", default=False, - help="List all subscribers (no ID argument, read only action).") - parser.add_option("-l", "--list", action="store_true", - dest="list", default=False, - help="List subscribers (read only action).") - parser.add_option("-s", "--subscriber", dest="subscriber", - metavar="SUBSCRIBER", - help="Email address of the subscriber (defaults to bugdir.user_id).") - parser.add_option("-S", "--servers", dest="servers", metavar="SERVERS", - help="Servers from which you want notification.") - parser.add_option("-t", "--type", dest="types", metavar="TYPES", - help="Types of changes you wish to be notified about.") - return parser - -longhelp=""" -ID can be either a bug id, or blank/"DIR", in which case it refers to the -whole bug directory. - -SERVERS specifies the servers from which you would like to receive -notification. Multiple severs may be specified in a comma-separated -list, or you can use "*" to match all servers (the default). If you -have not selected a server, it should politely refrain from notifying -you of changes, although there is no way to guarantee this behavior. - -Available TYPES: - For bugs: -%s - For %s: -%s - -For unsubscription, any listed SERVERS and TYPES are removed from your -subscription. Either the catch-all server "*" or type "%s" will -remove SUBSCRIBER entirely from the specified ID. - -This command is intended for use primarily by public interfaces, since -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_ID, - diff.BUGDIR_TYPE_ALL.string_tree(6), - diff.BUGDIR_TYPE_ALL) - -def help(): - return get_parser().help_str() + longhelp - -# internal helper functions - -def _generate_string(subscriber, types, servers): - types = sorted([str(t) for t in types]) - servers = sorted(servers) - return "%s%s\t%s\t%s" % (TAG,subscriber,",".join(types),",".join(servers)) - -def _parse_string(string, type_root): - assert string.startswith(TAG), string - string = string[len(TAG):] - subscriber,types,servers = string.split("\t") - types = [diff.type_from_name(name, type_root) for name in types.split(",")] - return (subscriber,types,servers.split(",")) - -def _get_subscriber(extra_strings, subscriber, type_root): - for i,string in enumerate(extra_strings): - if string.startswith(TAG): - s,ts,srvs = _parse_string(string, type_root) - if s == subscriber: - return i,s,ts,srvs # match! - return None # no match - -# functions exposed to other modules - -def subscribe(extra_strings, subscriber, types, servers, type_root): - args = _get_subscriber(extra_strings, subscriber, type_root) - if args == None: # no match - extra_strings.append(_generate_string(subscriber, types, servers)) - return extra_strings - # Alter matched string - i,s,ts,srvs = args - for t in types: - if t not in ts: - ts.append(t) - # remove descendant types - all_ts = copy.copy(ts) - for t in all_ts: - for tt in all_ts: - if tt in ts and t.has_descendant(tt): - ts.remove(tt) - if "*" in servers+srvs: - srvs = ["*"] - else: - srvs = list(set(servers+srvs)) - extra_strings[i] = _generate_string(subscriber, ts, srvs) - return extra_strings - -def unsubscribe(extra_strings, subscriber, types, servers, type_root): - args = _get_subscriber(extra_strings, subscriber, type_root) - if args == None: # no match - return extra_strings # pass - # Remove matched string - i,s,ts,srvs = args - all_ts = copy.copy(ts) - for t in types: - for tt in all_ts: - if tt in ts and t.has_descendant(tt): - ts.remove(tt) - if "*" in servers+srvs: - srvs = [] - else: - for srv in servers: - if srv in srvs: - srvs.remove(srv) - if len(ts) == 0 or len(srvs) == 0: - extra_strings.pop(i) - else: - extra_strings[i] = _generate_string(subscriber, ts, srvs) - return extra_strings - -def get_subscribers(extra_strings, type, server, type_root, - match_ancestor_types=False, - match_descendant_types=False): - """ - Set match_ancestor_types=True if you want to find eveyone who - cares about your particular type. - - Set match_descendant_types=True if you want to find subscribers - who may only care about some subset of your type. This is useful - for generating lists of all the subscribers in a given set of - extra_strings. - - >>> def sgs(*args, **kwargs): - ... return sorted(get_subscribers(*args, **kwargs)) - >>> es = [] - >>> es = subscribe(es, "John Doe ", [diff.BUGDIR_TYPE_ALL], - ... ["a.com"], diff.BUGDIR_TYPE_ALL) - >>> es = subscribe(es, "Jane Doe ", [diff.BUGDIR_TYPE_NEW], - ... ["*"], diff.BUGDIR_TYPE_ALL) - >>> sgs(es, diff.BUGDIR_TYPE_ALL, "a.com", diff.BUGDIR_TYPE_ALL) - ['John Doe '] - >>> sgs(es, diff.BUGDIR_TYPE_ALL, "a.com", diff.BUGDIR_TYPE_ALL, - ... match_descendant_types=True) - ['Jane Doe ', 'John Doe '] - >>> sgs(es, diff.BUGDIR_TYPE_ALL, "b.net", diff.BUGDIR_TYPE_ALL, - ... match_descendant_types=True) - ['Jane Doe '] - >>> sgs(es, diff.BUGDIR_TYPE_NEW, "a.com", diff.BUGDIR_TYPE_ALL) - ['Jane Doe '] - >>> sgs(es, diff.BUGDIR_TYPE_NEW, "a.com", diff.BUGDIR_TYPE_ALL, - ... match_ancestor_types=True) - ['Jane Doe ', 'John Doe '] - """ - for string in extra_strings: - if not string.startswith(TAG): - continue - subscriber,types,servers = _parse_string(string, type_root) - type_match = False - if type in types: - type_match = True - if type_match == False and match_ancestor_types == True: - for t in types: - if t.has_descendant(type): - type_match = True - break - if type_match == False and match_descendant_types == True: - for t in types: - if type.has_descendant(t): - type_match = True - break - server_match = False - if server in servers or servers == ["*"] or server == "*": - server_match = True - if type_match == True and server_match == True: - yield subscriber - -def get_bugdir_subscribers(bugdir, server): - """ - I have a bugdir. Who cares about it, and what do they care about? - Returns a dict of dicts: - subscribers[user][id] = types - where id is either a bug.uuid (in the case of a bug subscription) - or "%(bugdir_id)s" (in the case of a bugdir subscription). - - Only checks bugs that are currently in memory, so you might want - to call bugdir.load_all_bugs() first. - - >>> bd = bugdir.SimpleBugDir(sync_with_disk=False) - >>> a = bd.bug_from_shortname("a") - >>> bd.extra_strings = subscribe(bd.extra_strings, "John Doe ", - ... [diff.BUGDIR_TYPE_ALL], ["a.com"], diff.BUGDIR_TYPE_ALL) - >>> bd.extra_strings = subscribe(bd.extra_strings, "Jane Doe ", - ... [diff.BUGDIR_TYPE_NEW], ["*"], diff.BUGDIR_TYPE_ALL) - >>> a.extra_strings = subscribe(a.extra_strings, "John Doe ", - ... [diff.BUG_TYPE_ALL], ["a.com"], diff.BUG_TYPE_ALL) - >>> subscribers = get_bugdir_subscribers(bd, "a.com") - >>> subscribers["Jane Doe "]["%(bugdir_id)s"] - [] - >>> subscribers["John Doe "]["%(bugdir_id)s"] - [] - >>> subscribers["John Doe "]["a"] - [] - >>> get_bugdir_subscribers(bd, "b.net") - {'Jane Doe ': {'%(bugdir_id)s': []}} - >>> bd.cleanup() - """ % {'bugdir_id':diff.BUGDIR_ID} - subscribers = {} - for sub in get_subscribers(bugdir.extra_strings, diff.BUGDIR_TYPE_ALL, - server, diff.BUGDIR_TYPE_ALL, - match_descendant_types=True): - i,s,ts,srvs = _get_subscriber(bugdir.extra_strings, sub, - diff.BUGDIR_TYPE_ALL) - subscribers[sub] = {"DIR":ts} - for bug in bugdir: - for sub in get_subscribers(bug.extra_strings, diff.BUG_TYPE_ALL, - server, diff.BUG_TYPE_ALL, - match_descendant_types=True): - i,s,ts,srvs = _get_subscriber(bug.extra_strings, sub, - diff.BUG_TYPE_ALL) - if sub in subscribers: - subscribers[sub][bug.uuid] = ts - else: - subscribers[sub] = {bug.uuid:ts} - return subscribers -- cgit