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 --- libbe/command/subscribe.py | 360 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 360 insertions(+) create mode 100644 libbe/command/subscribe.py (limited to 'libbe/command/subscribe.py') diff --git a/libbe/command/subscribe.py b/libbe/command/subscribe.py new file mode 100644 index 0000000..69554f7 --- /dev/null +++ b/libbe/command/subscribe.py @@ -0,0 +1,360 @@ +# 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 From 66343859b94ab7417bd4560ccc1c023d9ba6d1d2 Mon Sep 17 00:00:00 2001 From: "W. Trevor King" Date: Tue, 15 Dec 2009 01:07:18 -0500 Subject: Transitioned diff and subscribe to Command-format" They don't work yet, since I still need to fix up libbe.diff and replace BugDir.duplicate_bugdir() with something based on the new Storage backend. --- libbe/command/subscribe.py | 292 ++++++++++++++++++++++++--------------------- 1 file changed, 157 insertions(+), 135 deletions(-) (limited to 'libbe/command/subscribe.py') diff --git a/libbe/command/subscribe.py b/libbe/command/subscribe.py index 69554f7..5c5acdb 100644 --- a/libbe/command/subscribe.py +++ b/libbe/command/subscribe.py @@ -13,146 +13,170 @@ # 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__ + +import copy +import os + +import libbe +import libbe.bug +import libbe.command +import libbe.diff +import libbe.command.util +import libbe.util.tree + 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") + +class Subscribe (libbe.command.Command): + """(Un)subscribe to change notification + + >>> import sys + >>> import libbe.bugdir + >>> bd = libbe.bugdir.SimpleBugDir(memory=False) + >>> cmd = Subscribe() + >>> cmd._storage = bd.storage + >>> cmd._setup_io = lambda i_enc,o_enc : None + >>> cmd.stdout = sys.stdout + + >>> a = bd.bug_from_uuid('a') >>> print a.extra_strings [] - >>> execute(["-s","John Doe ", "a"], manipulate_encodings=False) # doctest: +NORMALIZE_WHITESPACE - Subscriptions for a: + >>> ret = cmd.run({'subscriber':'John Doe '], ['/a']) # doctest: +NORMALIZE_WHITESPACE + Subscriptions for abc/a: John Doe all * - >>> bd._clear_bugs() # resync our copy of bug - >>> a = bd.bug_from_shortname("a") + >>> bd.flush_reload() + >>> a = bd.bug_from_uuid('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: + >>> ret = cmd.run({'subscriber':'Jane Doe ', 'servers':'a.com,b.net'}, ['/a']) # doctest: +NORMALIZE_WHITESPACE + Subscriptions for abc/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 + >>> ret = cmd.run({'subscriber':'Jane Doe ', 'servers':'a.edu'}, ['/a']) # 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 + >>> ret = cmd.run({'-u', 'subscriber':'Jane Doe ', 'servers':'a.com'}, ['/a']) # 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 + >>> ret = cmd.run({'subscriber':'Jane Doe ', 'servers':'*'}, ['/a']) # doctest: +NORMALIZE_WHITESPACE Subscriptions for a: Jane Doe all * John Doe all * - >>> execute(["-u", "-s","Jane Doe ", "a"], manipulate_encodings=False) # doctest: +NORMALIZE_WHITESPACE + >>> ret = cmd.run({'unsubscribe':True, 'subscriber':'Jane Doe '}, ['/a']) # 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 + >>> ret = cmd.run({'unsubscribe':True, 'subscriber':'John Doe '}, ['/a']) + >>> ret = cmd.run({'subscriber':'Jane Doe ', '-t':'new'}, 'DIR']) # doctest: +NORMALIZE_WHITESPACE Subscriptions for bug directory: Jane Doe new * - >>> execute(["-s","Jane Doe ", "DIR"], manipulate_encodings=False) # doctest: +NORMALIZE_WHITESPACE + >>> ret = cmd.run({'subscriber':'Jane Doe '}, ['DIR']) # 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}) + name = 'subscribe' - if len(args) > 1: - help() - raise cmdutil.UsageError("Too many arguments.") + def __init__(self, *args, **kwargs): + libbe.command.Command.__init__(self, *args, **kwargs) + self.options.extend([ + libbe.command.Option(name='unsubscribe', short_name='u', + help='Unsubscribe instead of subscribing'), + libbe.command.Option(name='list-all', short_name='a', + help='List all subscribers (no ID argument, read only action)'), + libbe.command.Option(name='list', short_name='l', + help='List subscribers (read only action).'), + libbe.command.Option(name='subscriber', short_name='s', + help='Email address of the subscriber (defaults to bugdir.user_id).', + arg=libbe.command.Argument( + name='subscriber', metavar='EMAIL')), + libbe.command.Option(name='servers', short_name='S', + help='Servers from which you want notification.', + arg=libbe.command.Argument( + name='servers', metavar='STRING')), + libbe.command.Option(name='types', short_name='t', + help='Types of changes you wish to be notified about.', + arg=libbe.command.Argument( + name='types', metavar='STRING')), + ]) + self.args.extend([ + libbe.command.Argument( + name='id', metavar='ID', default=None, + optional=True, repeatable=True, + completion_callback=libbe.command.util.complete_bug_comment_id), + ]) - 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 + def _run(self, **params): + bugdir = self._get_bugdir() + if params['list-all'] == True or params['list'] == True: + writeable = bugdir.storage.writeable + bugdir.storage.writeable = False + if params['list-all'] == True: + assert len(params['id']) == 0, params['id'] + subscriber = params['subscriber'] + if subscriber == None: + subscriber = self._get_user_id() + if params['unsubscribe'] == True: + if params['servers'] == None: + params['servers'] = 'INVALID' + if params['types'] == None: + params['types'] = 'INVALID' + else: + if params['servers'] == None: + params['servers'] = '*' + if params['types'] == None: + params['types'] = 'all' + servers = params['servers'].split(',') + types = params['types'].split(',') + + if params['id'] == None: + params['id'] = libbe.diff.BUGDIR_ID + for id in params['id']: + if id == libbe.diff.BUGDIR_ID: # directory-wide subscriptions + type_root = libbe.diff.BUGDIR_TYPE_ALL + entity = bugdir + entity_name = 'bug directory' + else: # bug-specific subscriptions + type_root = libbe.diff.BUG_TYPE_ALL + bug,dummy_comment = libbe.command.util.bug_comment_from_user_id( + bugdir, params['id']) + entity = bug + entity_name = bug.id.user() + if params['list-all'] == True: + entity_name = 'anything in the bug directory' + types = [libbe.diff.type_from_name(name, type_root, default=libbe.diff.INVALID_TYPE, + default_ok=params['unsubscribe']) + for name in types] + estrs = entity.extra_strings + if params['list'] == True or params['list-all'] == True: + pass + else: # alter subscriptions + if params['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 params['list-all'] == True: + bugdir.load_all_bugs() + subscriptions = get_bugdir_subscribers(bugdir, servers[0]) + else: + subscriptions = [] + for estr in entity.extra_strings: + if estr.startswith(TAG): + subscriptions.append(estr[len(TAG):]) + + if len(subscriptions) > 0: + print >> self.stdout, 'Subscriptions for %s:' % entity_name + print >> self.stdout, '\n'.join(subscriptions) + if params['list-all'] == True or params['list'] == True: + bugdir.storage.writeable = writeable + return 0 -longhelp=""" + def _long_help(self): + return """ ID can be either a bug id, or blank/"DIR", in which case it refers to the whole bug directory. @@ -177,12 +201,10 @@ 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) +""" % (libbe.diff.BUG_TYPE_ALL.string_tree(6), libbe.diff.BUGDIR_ID, + libbe.diff.BUGDIR_TYPE_ALL.string_tree(6), + libbe.diff.BUGDIR_TYPE_ALL) -def help(): - return get_parser().help_str() + longhelp # internal helper functions @@ -195,7 +217,7 @@ 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(",")] + types = [libbe.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): @@ -269,21 +291,21 @@ 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 ", [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) + >>> es = subscribe(es, "John Doe ", [libbe.diff.BUGDIR_TYPE_ALL], + ... ["a.com"], libbe.diff.BUGDIR_TYPE_ALL) + >>> es = subscribe(es, "Jane Doe ", [libbe.diff.BUGDIR_TYPE_NEW], + ... ["*"], libbe.diff.BUGDIR_TYPE_ALL) + >>> sgs(es, libbe.diff.BUGDIR_TYPE_ALL, "a.com", libbe.diff.BUGDIR_TYPE_ALL) ['John Doe '] - >>> sgs(es, diff.BUGDIR_TYPE_ALL, "a.com", diff.BUGDIR_TYPE_ALL, + >>> sgs(es, libbe.diff.BUGDIR_TYPE_ALL, "a.com", libbe.diff.BUGDIR_TYPE_ALL, ... match_descendant_types=True) ['Jane Doe ', 'John Doe '] - >>> sgs(es, diff.BUGDIR_TYPE_ALL, "b.net", diff.BUGDIR_TYPE_ALL, + >>> sgs(es, libbe.diff.BUGDIR_TYPE_ALL, "b.net", libbe.diff.BUGDIR_TYPE_ALL, ... match_descendant_types=True) ['Jane Doe '] - >>> sgs(es, diff.BUGDIR_TYPE_NEW, "a.com", diff.BUGDIR_TYPE_ALL) + >>> sgs(es, libbe.diff.BUGDIR_TYPE_NEW, "a.com", libbe.diff.BUGDIR_TYPE_ALL) ['Jane Doe '] - >>> sgs(es, diff.BUGDIR_TYPE_NEW, "a.com", diff.BUGDIR_TYPE_ALL, + >>> sgs(es, libbe.diff.BUGDIR_TYPE_NEW, "a.com", libbe.diff.BUGDIR_TYPE_ALL, ... match_ancestor_types=True) ['Jane Doe ', 'John Doe '] """ @@ -324,11 +346,11 @@ 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 ", - ... [diff.BUGDIR_TYPE_ALL], ["a.com"], diff.BUGDIR_TYPE_ALL) + ... [libbe.diff.BUGDIR_TYPE_ALL], ["a.com"], libbe.diff.BUGDIR_TYPE_ALL) >>> bd.extra_strings = subscribe(bd.extra_strings, "Jane Doe ", - ... [diff.BUGDIR_TYPE_NEW], ["*"], diff.BUGDIR_TYPE_ALL) + ... [libbe.diff.BUGDIR_TYPE_NEW], ["*"], libbe.diff.BUGDIR_TYPE_ALL) >>> a.extra_strings = subscribe(a.extra_strings, "John Doe ", - ... [diff.BUG_TYPE_ALL], ["a.com"], diff.BUG_TYPE_ALL) + ... [libbe.diff.BUG_TYPE_ALL], ["a.com"], libbe.diff.BUG_TYPE_ALL) >>> subscribers = get_bugdir_subscribers(bd, "a.com") >>> subscribers["Jane Doe "]["%(bugdir_id)s"] [] @@ -339,20 +361,20 @@ def get_bugdir_subscribers(bugdir, server): >>> get_bugdir_subscribers(bd, "b.net") {'Jane Doe ': {'%(bugdir_id)s': []}} >>> bd.cleanup() - """ % {'bugdir_id':diff.BUGDIR_ID} + """ % {'bugdir_id':libbe.diff.BUGDIR_ID} subscribers = {} - for sub in get_subscribers(bugdir.extra_strings, diff.BUGDIR_TYPE_ALL, - server, diff.BUGDIR_TYPE_ALL, + for sub in get_subscribers(bugdir.extra_strings, libbe.diff.BUGDIR_TYPE_ALL, + server, libbe.diff.BUGDIR_TYPE_ALL, match_descendant_types=True): i,s,ts,srvs = _get_subscriber(bugdir.extra_strings, sub, - diff.BUGDIR_TYPE_ALL) + libbe.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, + for sub in get_subscribers(bug.extra_strings, libbe.diff.BUG_TYPE_ALL, + server, libbe.diff.BUG_TYPE_ALL, match_descendant_types=True): i,s,ts,srvs = _get_subscriber(bug.extra_strings, sub, - diff.BUG_TYPE_ALL) + libbe.diff.BUG_TYPE_ALL) if sub in subscribers: subscribers[sub][bug.uuid] = ts else: -- cgit From 58bedebfddbb8e1fc8f0a441163526feaecb753b Mon Sep 17 00:00:00 2001 From: "W. Trevor King" Date: Tue, 15 Dec 2009 03:31:48 -0500 Subject: Transition to Command-format complete. Well, except for going through and updating the _long_help() strings. $ python test.py libbe.command succeeds for everything except Diff and Subscribe, which is expected since I haven't fixed up libbe.diff yet. --- libbe/command/subscribe.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'libbe/command/subscribe.py') diff --git a/libbe/command/subscribe.py b/libbe/command/subscribe.py index 5c5acdb..e86a9c8 100644 --- a/libbe/command/subscribe.py +++ b/libbe/command/subscribe.py @@ -35,14 +35,14 @@ class Subscribe (libbe.command.Command): >>> import libbe.bugdir >>> bd = libbe.bugdir.SimpleBugDir(memory=False) >>> cmd = Subscribe() - >>> cmd._storage = bd.storage + >>> cmd._bugdir = bd >>> cmd._setup_io = lambda i_enc,o_enc : None >>> cmd.stdout = sys.stdout >>> a = bd.bug_from_uuid('a') >>> print a.extra_strings [] - >>> ret = cmd.run({'subscriber':'John Doe '], ['/a']) # doctest: +NORMALIZE_WHITESPACE + >>> ret = cmd.run({'subscriber':'John Doe '}, ['/a']) # doctest: +NORMALIZE_WHITESPACE Subscriptions for abc/a: John Doe all * >>> bd.flush_reload() @@ -57,7 +57,7 @@ class Subscribe (libbe.command.Command): Subscriptions for a: Jane Doe all a.com,a.edu,b.net John Doe all * - >>> ret = cmd.run({'-u', 'subscriber':'Jane Doe ', 'servers':'a.com'}, ['/a']) # doctest: +NORMALIZE_WHITESPACE + >>> ret = cmd.run({'unsubscribe':True, 'subscriber':'Jane Doe ', 'servers':'a.com'}, ['/a']) # doctest: +NORMALIZE_WHITESPACE Subscriptions for a: Jane Doe all a.edu,b.net John Doe all * @@ -69,7 +69,7 @@ class Subscribe (libbe.command.Command): Subscriptions for a: John Doe all * >>> ret = cmd.run({'unsubscribe':True, 'subscriber':'John Doe '}, ['/a']) - >>> ret = cmd.run({'subscriber':'Jane Doe ', '-t':'new'}, 'DIR']) # doctest: +NORMALIZE_WHITESPACE + >>> ret = cmd.run({'subscriber':'Jane Doe ', 'types':'new'}, ['DIR']) # doctest: +NORMALIZE_WHITESPACE Subscriptions for bug directory: Jane Doe new * >>> ret = cmd.run({'subscriber':'Jane Doe '}, ['DIR']) # doctest: +NORMALIZE_WHITESPACE -- cgit From 380889988b6d7881c4e0b5968053f85676d27211 Mon Sep 17 00:00:00 2001 From: "W. Trevor King" Date: Tue, 15 Dec 2009 04:32:19 -0500 Subject: Fixed libbe.command.subscribe --- libbe/command/subscribe.py | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) (limited to 'libbe/command/subscribe.py') diff --git a/libbe/command/subscribe.py b/libbe/command/subscribe.py index e86a9c8..4f72624 100644 --- a/libbe/command/subscribe.py +++ b/libbe/command/subscribe.py @@ -22,6 +22,7 @@ import libbe.bug import libbe.command import libbe.diff import libbe.command.util +import libbe.util.id import libbe.util.tree @@ -54,19 +55,19 @@ class Subscribe (libbe.command.Command): Jane Doe all a.com,b.net John Doe all * >>> ret = cmd.run({'subscriber':'Jane Doe ', 'servers':'a.edu'}, ['/a']) # doctest: +NORMALIZE_WHITESPACE - Subscriptions for a: + Subscriptions for abc/a: Jane Doe all a.com,a.edu,b.net John Doe all * >>> ret = cmd.run({'unsubscribe':True, 'subscriber':'Jane Doe ', 'servers':'a.com'}, ['/a']) # doctest: +NORMALIZE_WHITESPACE - Subscriptions for a: + Subscriptions for abc/a: Jane Doe all a.edu,b.net John Doe all * >>> ret = cmd.run({'subscriber':'Jane Doe ', 'servers':'*'}, ['/a']) # doctest: +NORMALIZE_WHITESPACE - Subscriptions for a: + Subscriptions for abc/a: Jane Doe all * John Doe all * >>> ret = cmd.run({'unsubscribe':True, 'subscriber':'Jane Doe '}, ['/a']) # doctest: +NORMALIZE_WHITESPACE - Subscriptions for a: + Subscriptions for abc/a: John Doe all * >>> ret = cmd.run({'unsubscribe':True, 'subscriber':'John Doe '}, ['/a']) >>> ret = cmd.run({'subscriber':'Jane Doe ', 'types':'new'}, ['DIR']) # doctest: +NORMALIZE_WHITESPACE @@ -103,7 +104,7 @@ class Subscribe (libbe.command.Command): ]) self.args.extend([ libbe.command.Argument( - name='id', metavar='ID', default=None, + name='id', metavar='ID', default=tuple(), optional=True, repeatable=True, completion_callback=libbe.command.util.complete_bug_comment_id), ]) @@ -131,17 +132,17 @@ class Subscribe (libbe.command.Command): servers = params['servers'].split(',') types = params['types'].split(',') - if params['id'] == None: - params['id'] = libbe.diff.BUGDIR_ID - for id in params['id']: - if id == libbe.diff.BUGDIR_ID: # directory-wide subscriptions + if len(params['id']) == 0: + params['id'] = [libbe.diff.BUGDIR_ID] + for _id in params['id']: + if _id == libbe.diff.BUGDIR_ID: # directory-wide subscriptions type_root = libbe.diff.BUGDIR_TYPE_ALL entity = bugdir entity_name = 'bug directory' else: # bug-specific subscriptions type_root = libbe.diff.BUG_TYPE_ALL bug,dummy_comment = libbe.command.util.bug_comment_from_user_id( - bugdir, params['id']) + bugdir, _id) entity = bug entity_name = bug.id.user() if params['list-all'] == True: -- cgit From 89b7a1411e4658e831f5d635534b24355dbb941d Mon Sep 17 00:00:00 2001 From: "W. Trevor King" Date: Tue, 15 Dec 2009 06:44:20 -0500 Subject: Fixed libbe.command.diff + ugly BugDir.duplicate_bugdir implementation duplicate_bugdir() works, but for the vcs backends, it could require shelling out for _every_ file read. This could, and probably will, be horribly slow. Still it works ;). I'm not sure what a better implementation would be. The old implementation checked out the entire earlier state into a temporary directory pros: single shell out, simple upgrade implementation cons: wouldn't work well for HTTP backens I think a good solution would run along the lines of the currently commented out code in duplicate_bugdir(), where a VersionedStorage.changed_since(revision) call would give you a list of changed files. diff could work off of that directly, without the need to generate a whole duplicate bugdir. I'm stuck on how to handle upgrades though... Also removed trailing whitespace from all python files. --- libbe/command/subscribe.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'libbe/command/subscribe.py') diff --git a/libbe/command/subscribe.py b/libbe/command/subscribe.py index 4f72624..a837f99 100644 --- a/libbe/command/subscribe.py +++ b/libbe/command/subscribe.py @@ -131,7 +131,7 @@ class Subscribe (libbe.command.Command): params['types'] = 'all' servers = params['servers'].split(',') types = params['types'].split(',') - + if len(params['id']) == 0: params['id'] = [libbe.diff.BUGDIR_ID] for _id in params['id']: @@ -159,7 +159,7 @@ class Subscribe (libbe.command.Command): else: # add the tag estrs = subscribe(estrs, subscriber, types, servers, type_root) entity.extra_strings = estrs # reassign to notice change - + if params['list-all'] == True: bugdir.load_all_bugs() subscriptions = get_bugdir_subscribers(bugdir, servers[0]) @@ -168,7 +168,7 @@ class Subscribe (libbe.command.Command): for estr in entity.extra_strings: if estr.startswith(TAG): subscriptions.append(estr[len(TAG):]) - + if len(subscriptions) > 0: print >> self.stdout, 'Subscriptions for %s:' % entity_name print >> self.stdout, '\n'.join(subscriptions) -- cgit From cfae8a8302f06a84196700138d7ddbb25e91ea31 Mon Sep 17 00:00:00 2001 From: "W. Trevor King" Date: Thu, 31 Dec 2009 14:32:39 -0500 Subject: Added UserInterface and other improved abstractions for command handling --- libbe/command/subscribe.py | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) (limited to 'libbe/command/subscribe.py') diff --git a/libbe/command/subscribe.py b/libbe/command/subscribe.py index a837f99..78d6fe0 100644 --- a/libbe/command/subscribe.py +++ b/libbe/command/subscribe.py @@ -35,47 +35,49 @@ class Subscribe (libbe.command.Command): >>> import sys >>> import libbe.bugdir >>> bd = libbe.bugdir.SimpleBugDir(memory=False) - >>> cmd = Subscribe() - >>> cmd._bugdir = bd - >>> cmd._setup_io = lambda i_enc,o_enc : None - >>> cmd.stdout = sys.stdout + >>> io = libbe.command.StringInputOutput() + >>> io.stdout = sys.stdout + >>> ui = libbe.command.UserInterface(io=io) + >>> ui.storage_callbacks.set_bugdir(bd) + >>> cmd = Subscribe(ui=ui) >>> a = bd.bug_from_uuid('a') >>> print a.extra_strings [] - >>> ret = cmd.run({'subscriber':'John Doe '}, ['/a']) # doctest: +NORMALIZE_WHITESPACE + >>> ret = ui.run(cmd, {'subscriber':'John Doe '}, ['/a']) # doctest: +NORMALIZE_WHITESPACE Subscriptions for abc/a: John Doe all * >>> bd.flush_reload() >>> a = bd.bug_from_uuid('a') >>> print a.extra_strings ['SUBSCRIBE:John Doe \\tall\\t*'] - >>> ret = cmd.run({'subscriber':'Jane Doe ', 'servers':'a.com,b.net'}, ['/a']) # doctest: +NORMALIZE_WHITESPACE + >>> ret = ui.run(cmd, {'subscriber':'Jane Doe ', 'servers':'a.com,b.net'}, ['/a']) # doctest: +NORMALIZE_WHITESPACE Subscriptions for abc/a: Jane Doe all a.com,b.net John Doe all * - >>> ret = cmd.run({'subscriber':'Jane Doe ', 'servers':'a.edu'}, ['/a']) # doctest: +NORMALIZE_WHITESPACE + >>> ret = ui.run(cmd, {'subscriber':'Jane Doe ', 'servers':'a.edu'}, ['/a']) # doctest: +NORMALIZE_WHITESPACE Subscriptions for abc/a: Jane Doe all a.com,a.edu,b.net John Doe all * - >>> ret = cmd.run({'unsubscribe':True, 'subscriber':'Jane Doe ', 'servers':'a.com'}, ['/a']) # doctest: +NORMALIZE_WHITESPACE + >>> ret = ui.run(cmd, {'unsubscribe':True, 'subscriber':'Jane Doe ', 'servers':'a.com'}, ['/a']) # doctest: +NORMALIZE_WHITESPACE Subscriptions for abc/a: Jane Doe all a.edu,b.net John Doe all * - >>> ret = cmd.run({'subscriber':'Jane Doe ', 'servers':'*'}, ['/a']) # doctest: +NORMALIZE_WHITESPACE + >>> ret = ui.run(cmd, {'subscriber':'Jane Doe ', 'servers':'*'}, ['/a']) # doctest: +NORMALIZE_WHITESPACE Subscriptions for abc/a: Jane Doe all * John Doe all * - >>> ret = cmd.run({'unsubscribe':True, 'subscriber':'Jane Doe '}, ['/a']) # doctest: +NORMALIZE_WHITESPACE + >>> ret = ui.run(cmd, {'unsubscribe':True, 'subscriber':'Jane Doe '}, ['/a']) # doctest: +NORMALIZE_WHITESPACE Subscriptions for abc/a: John Doe all * - >>> ret = cmd.run({'unsubscribe':True, 'subscriber':'John Doe '}, ['/a']) - >>> ret = cmd.run({'subscriber':'Jane Doe ', 'types':'new'}, ['DIR']) # doctest: +NORMALIZE_WHITESPACE + >>> ret = ui.run(cmd, {'unsubscribe':True, 'subscriber':'John Doe '}, ['/a']) + >>> ret = ui.run(cmd, {'subscriber':'Jane Doe ', 'types':'new'}, ['DIR']) # doctest: +NORMALIZE_WHITESPACE Subscriptions for bug directory: Jane Doe new * - >>> ret = cmd.run({'subscriber':'Jane Doe '}, ['DIR']) # doctest: +NORMALIZE_WHITESPACE + >>> ret = ui.run(cmd, {'subscriber':'Jane Doe '}, ['DIR']) # doctest: +NORMALIZE_WHITESPACE Subscriptions for bug directory: Jane Doe all * + >>> ui.cleanup() >>> bd.cleanup() """ name = 'subscribe' -- cgit From 4d4283ecd654f1efb058cd7f7dba6be88b70ee92 Mon Sep 17 00:00:00 2001 From: "W. Trevor King" Date: Fri, 1 Jan 2010 08:11:08 -0500 Subject: Updated copyright information --- libbe/command/subscribe.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'libbe/command/subscribe.py') diff --git a/libbe/command/subscribe.py b/libbe/command/subscribe.py index 78d6fe0..bd36639 100644 --- a/libbe/command/subscribe.py +++ b/libbe/command/subscribe.py @@ -1,4 +1,4 @@ -# Copyright (C) 2009 W. Trevor King +# Copyright (C) 2009-2010 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 -- cgit From d3993355255769745d490ba7c6b25458fb8cd605 Mon Sep 17 00:00:00 2001 From: "W. Trevor King" Date: Sat, 23 Jan 2010 18:49:13 -0500 Subject: Update --subscriber option help string for Subscribe --- libbe/command/subscribe.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'libbe/command/subscribe.py') diff --git a/libbe/command/subscribe.py b/libbe/command/subscribe.py index bd36639..d1cf72e 100644 --- a/libbe/command/subscribe.py +++ b/libbe/command/subscribe.py @@ -92,7 +92,7 @@ class Subscribe (libbe.command.Command): libbe.command.Option(name='list', short_name='l', help='List subscribers (read only action).'), libbe.command.Option(name='subscriber', short_name='s', - help='Email address of the subscriber (defaults to bugdir.user_id).', + help='Email address of the subscriber (defaults to your user id).', arg=libbe.command.Argument( name='subscriber', metavar='EMAIL')), libbe.command.Option(name='servers', short_name='S', -- cgit