Merged Anton Batenev's report of Nicolas Alvarez' unicode-in-be-new bug
[be.git] / libbe / command / due.py
1 # Copyright (C) 2009-2010 W. Trevor King <wking@drexel.edu>
2 #
3 # This program is free software; you can redistribute it and/or modify
4 # it under the terms of the GNU General Public License as published by
5 # the Free Software Foundation; either version 2 of the License, or
6 # (at your option) any later version.
7 #
8 # This program is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 # GNU General Public License for more details.
12 #
13 # You should have received a copy of the GNU General Public License along
14 # with this program; if not, write to the Free Software Foundation, Inc.,
15 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
16
17 import libbe
18 import libbe.command
19 import libbe.command.util
20 import libbe.util.utility
21
22
23 DUE_TAG = 'DUE:'
24
25
26 class Due (libbe.command.Command):
27     """Set bug due dates
28
29     >>> import sys
30     >>> import libbe.bugdir
31     >>> bd = libbe.bugdir.SimpleBugDir(memory=False)
32     >>> io = libbe.command.StringInputOutput()
33     >>> io.stdout = sys.stdout
34     >>> ui = libbe.command.UserInterface(io=io)
35     >>> ui.storage_callbacks.set_storage(bd.storage)
36     >>> cmd = Due(ui=ui)
37
38     >>> ret = ui.run(cmd, args=['/a'])
39     No due date assigned.
40     >>> ret = ui.run(cmd, args=['/a', 'Thu, 01 Jan 1970 00:00:00 +0000'])
41     >>> ret = ui.run(cmd, args=['/a'])
42     Thu, 01 Jan 1970 00:00:00 +0000
43     >>> ret = ui.run(cmd, args=['/a', 'none'])
44     >>> ret = ui.run(cmd, args=['/a'])
45     No due date assigned.
46     >>> ui.cleanup()
47     >>> bd.cleanup()
48     """
49     name = 'due'
50
51     def __init__(self, *args, **kwargs):
52         libbe.command.Command.__init__(self, *args, **kwargs)
53         self.args.extend([
54                 libbe.command.Argument(
55                     name='bug-id', metavar='BUG-ID',
56                     completion_callback=libbe.command.util.complete_bug_id),
57                 libbe.command.Argument(
58                     name='due', metavar='DUE', optional=True),
59                 ])
60
61     def _run(self, **params):
62         bugdir = self._get_bugdir()
63         bug,dummy_comment = libbe.command.util.bug_comment_from_user_id(
64             bugdir, params['bug-id'])
65         if params['due'] == None:
66             due_time = get_due(bug)
67             if due_time is None:
68                 print >> self.stdout, 'No due date assigned.'
69             else:
70                 print >> self.stdout, libbe.util.utility.time_to_str(due_time)
71         else:
72             if params['due'] == 'none':
73                 remove_due(bug)
74             else:
75                 due_time = libbe.util.utility.str_to_time(params['due'])
76                 set_due(bug, due_time)
77
78     def _long_help(self):
79         return """
80 If no DATE is specified, the bug's current due date is printed.  If
81 DATE is specified, it will be assigned to the bug.
82 """
83
84 # internal helper functions
85
86 def _generate_due_string(time):
87     return "%s%s" % (DUE_TAG, libbe.util.utility.time_to_str(time))
88
89 def _parse_due_string(string):
90     assert string.startswith(DUE_TAG)
91     return libbe.util.utility.str_to_time(string[len(DUE_TAG):])
92
93 # functions exposed to other modules
94
95 def get_due(bug):
96     matched = []
97     for line in bug.extra_strings:
98         if line.startswith(DUE_TAG):
99             matched.append(_parse_due_string(line))
100     if len(matched) == 0:
101         return None
102     if len(matched) > 1:
103         raise Exception('Several due dates for %s?:\n  %s'
104                         % (bug.uuid, '\n  '.join(matched)))
105     return matched[0]
106
107 def remove_due(bug):
108     estrs = bug.extra_strings
109     for due_str in [s for s in estrs if s.startswith(DUE_TAG)]:
110         estrs.remove(due_str)
111     bug.extra_strings = estrs # reassign to notice change
112
113 def set_due(bug, time):
114     remove_due(bug)
115     estrs = bug.extra_strings
116     estrs.append(_generate_due_string(time))
117     bug.extra_strings = estrs # reassign to notice change