Mercurial > p > roundup > code
comparison roundup/admin.py @ 2307:f786a1b9dbdf
translatabe strings adjustments, postponed help text translation
| author | Alexander Smishlajev <a1s@users.sourceforge.net> |
|---|---|
| date | Fri, 14 May 2004 20:01:16 +0000 |
| parents | 19d1cd9ab09b |
| children | 8d5c95c33447 |
comparison
equal
deleted
inserted
replaced
| 2306:1421b19cd61b | 2307:f786a1b9dbdf |
|---|---|
| 13 # BIZAR SOFTWARE PTY LTD SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, | 13 # BIZAR SOFTWARE PTY LTD SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, |
| 14 # BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS | 14 # BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS |
| 15 # FOR A PARTICULAR PURPOSE. THE CODE PROVIDED HEREUNDER IS ON AN "AS IS" | 15 # FOR A PARTICULAR PURPOSE. THE CODE PROVIDED HEREUNDER IS ON AN "AS IS" |
| 16 # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE, | 16 # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE, |
| 17 # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. | 17 # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. |
| 18 # | 18 # |
| 19 # $Id: admin.py,v 1.68 2004-04-17 01:47:37 richard Exp $ | 19 # $Id: admin.py,v 1.69 2004-05-14 20:01:16 a1s Exp $ |
| 20 | 20 |
| 21 '''Administration commands for maintaining Roundup trackers. | 21 '''Administration commands for maintaining Roundup trackers. |
| 22 ''' | 22 ''' |
| 23 __docformat__ = 'restructuredtext' | 23 __docformat__ = 'restructuredtext' |
| 24 | 24 |
| 129 roundup-admin help all -- all available help | 129 roundup-admin help all -- all available help |
| 130 ''')%locals() | 130 ''')%locals() |
| 131 self.help_commands() | 131 self.help_commands() |
| 132 | 132 |
| 133 def help_commands(self): | 133 def help_commands(self): |
| 134 ''' List the commands available with their precis help. | 134 ''' List the commands available with their precise help. |
| 135 ''' | 135 ''' |
| 136 print _('Commands:'), | 136 print _('Commands:'), |
| 137 commands = [''] | 137 commands = [''] |
| 138 for command in self.commands.values(): | 138 for command in self.commands.values(): |
| 139 h = command.__doc__.split('\n')[0] | 139 h = _(command.__doc__).split('\n')[0] |
| 140 commands.append(' '+h[7:]) | 140 commands.append(' '+h[7:]) |
| 141 commands.sort() | 141 commands.sort() |
| 142 commands.append(_('Commands may be abbreviated as long as the abbreviation matches only one')) | 142 commands.append(_( |
| 143 commands.append(_('command, e.g. l == li == lis == list.')) | 143 """Commands may be abbreviated as long as the abbreviation |
| 144 matches only one command, e.g. l == li == lis == list.""")) | |
| 144 print '\n'.join(commands) | 145 print '\n'.join(commands) |
| 145 print | 146 print |
| 146 | 147 |
| 147 def help_commands_html(self, indent_re=re.compile(r'^(\s+)\S+')): | 148 def help_commands_html(self, indent_re=re.compile(r'^(\s+)\S+')): |
| 148 ''' Produce an HTML command list. | 149 ''' Produce an HTML command list. |
| 150 commands = self.commands.values() | 151 commands = self.commands.values() |
| 151 def sortfun(a, b): | 152 def sortfun(a, b): |
| 152 return cmp(a.__name__, b.__name__) | 153 return cmp(a.__name__, b.__name__) |
| 153 commands.sort(sortfun) | 154 commands.sort(sortfun) |
| 154 for command in commands: | 155 for command in commands: |
| 155 h = command.__doc__.split('\n') | 156 h = _(command.__doc__).split('\n') |
| 156 name = command.__name__[3:] | 157 name = command.__name__[3:] |
| 157 usage = h[0] | 158 usage = h[0] |
| 158 print _(''' | 159 print _(''' |
| 159 <tr><td valign=top><strong>%(name)s</strong></td> | 160 <tr><td valign=top><strong>%(name)s</strong></td> |
| 160 <td><tt>%(usage)s</tt><p> | 161 <td><tt>%(usage)s</tt><p> |
| 169 print _('</pre></td></tr>\n') | 170 print _('</pre></td></tr>\n') |
| 170 | 171 |
| 171 def help_all(self): | 172 def help_all(self): |
| 172 print _(''' | 173 print _(''' |
| 173 All commands (except help) require a tracker specifier. This is just the path | 174 All commands (except help) require a tracker specifier. This is just the path |
| 174 to the roundup tracker you're working with. A roundup tracker is where | 175 to the roundup tracker you're working with. A roundup tracker is where |
| 175 roundup keeps the database and configuration file that defines an issue | 176 roundup keeps the database and configuration file that defines an issue |
| 176 tracker. It may be thought of as the issue tracker's "home directory". It may | 177 tracker. It may be thought of as the issue tracker's "home directory". It may |
| 177 be specified in the environment variable TRACKER_HOME or on the command | 178 be specified in the environment variable TRACKER_HOME or on the command |
| 178 line as "-i tracker". | 179 line as "-i tracker". |
| 179 | 180 |
| 203 \\ (1 token: \) | 204 \\ (1 token: \) |
| 204 \n\r\t (1 token: a newline, carriage-return and tab) | 205 \n\r\t (1 token: a newline, carriage-return and tab) |
| 205 | 206 |
| 206 When multiple nodes are specified to the roundup get or roundup set | 207 When multiple nodes are specified to the roundup get or roundup set |
| 207 commands, the specified properties are retrieved or set on all the listed | 208 commands, the specified properties are retrieved or set on all the listed |
| 208 nodes. | 209 nodes. |
| 209 | 210 |
| 210 When multiple results are returned by the roundup get or roundup find | 211 When multiple results are returned by the roundup get or roundup find |
| 211 commands, they are printed one per line (default) or joined by commas (with | 212 commands, they are printed one per line (default) or joined by commas (with |
| 212 the -c) option. | 213 the -c) option. |
| 213 | 214 |
| 214 Where the command changes data, a login name/password is required. The | 215 Where the command changes data, a login name/password is required. The |
| 215 login may be specified as either "name" or "name:password". | 216 login may be specified as either "name" or "name:password". |
| 216 . ROUNDUP_LOGIN environment variable | 217 . ROUNDUP_LOGIN environment variable |
| 217 . the -u command-line option | 218 . the -u command-line option |
| 218 If either the name or password is not supplied, they are obtained from the | 219 If either the name or password is not supplied, they are obtained from the |
| 219 command-line. | 220 command-line. |
| 220 | 221 |
| 221 Date format examples: | 222 Date format examples: |
| 222 "2000-04-17.03:45" means <Date 2000-04-17.08:45:00> | 223 "2000-04-17.03:45" means <Date 2000-04-17.08:45:00> |
| 223 "2000-04-17" means <Date 2000-04-17.00:00:00> | 224 "2000-04-17" means <Date 2000-04-17.00:00:00> |
| 224 "01-25" means <Date yyyy-01-25.00:00:00> | 225 "01-25" means <Date yyyy-01-25.00:00:00> |
| 230 | 231 |
| 231 Command help: | 232 Command help: |
| 232 ''') | 233 ''') |
| 233 for name, command in self.commands.items(): | 234 for name, command in self.commands.items(): |
| 234 print _('%s:')%name | 235 print _('%s:')%name |
| 235 print _(' '), command.__doc__ | 236 print _(' '), _(command.__doc__) |
| 236 | 237 |
| 237 def do_help(self, args, nl_re=re.compile('[\r\n]'), | 238 def do_help(self, args, nl_re=re.compile('[\r\n]'), |
| 238 indent_re=re.compile(r'^(\s+)\S+')): | 239 indent_re=re.compile(r'^(\s+)\S+')): |
| 239 '''Usage: help topic | 240 ""'''Usage: help topic |
| 240 Give help about topic. | 241 Give help about topic. |
| 241 | 242 |
| 242 commands -- list commands | 243 commands -- list commands |
| 243 <command> -- help specific to a command | 244 <command> -- help specific to a command |
| 244 initopts -- init command options | 245 initopts -- init command options |
| 246 ''' | 247 ''' |
| 247 if len(args)>0: | 248 if len(args)>0: |
| 248 topic = args[0] | 249 topic = args[0] |
| 249 else: | 250 else: |
| 250 topic = 'help' | 251 topic = 'help' |
| 251 | 252 |
| 252 | 253 |
| 253 # try help_ methods | 254 # try help_ methods |
| 254 if self.help.has_key(topic): | 255 if self.help.has_key(topic): |
| 255 self.help[topic]() | 256 self.help[topic]() |
| 256 return 0 | 257 return 0 |
| 262 print _('Sorry, no help for "%(topic)s"')%locals() | 263 print _('Sorry, no help for "%(topic)s"')%locals() |
| 263 return 1 | 264 return 1 |
| 264 | 265 |
| 265 # display the help for each match, removing the docsring indent | 266 # display the help for each match, removing the docsring indent |
| 266 for name, help in l: | 267 for name, help in l: |
| 267 lines = nl_re.split(help.__doc__) | 268 lines = nl_re.split(_(help.__doc__)) |
| 268 print lines[0] | 269 print lines[0] |
| 269 indent = indent_re.match(lines[1]) | 270 indent = indent_re.match(lines[1]) |
| 270 if indent: indent = len(indent.group(1)) | 271 if indent: indent = len(indent.group(1)) |
| 271 for line in lines[1:]: | 272 for line in lines[1:]: |
| 272 if indent: | 273 if indent: |
| 335 import roundup.backends | 336 import roundup.backends |
| 336 backends = roundup.backends.__all__ | 337 backends = roundup.backends.__all__ |
| 337 print _('Back ends:'), ', '.join(backends) | 338 print _('Back ends:'), ', '.join(backends) |
| 338 | 339 |
| 339 def do_install(self, tracker_home, args): | 340 def do_install(self, tracker_home, args): |
| 340 '''Usage: install [template [backend [admin password]]] | 341 ""'''Usage: install [template [backend [admin password]]] |
| 341 Install a new Roundup tracker. | 342 Install a new Roundup tracker. |
| 342 | 343 |
| 343 The command will prompt for the tracker home directory (if not supplied | 344 The command will prompt for the tracker home directory (if not supplied |
| 344 through TRACKER_HOME or the -i option). The template, backend and admin | 345 through TRACKER_HOME or the -i option). The template, backend and admin |
| 345 password may be specified on the command-line as arguments, in that | 346 password may be specified on the command-line as arguments, in that |
| 361 if not os.path.exists(parent): | 362 if not os.path.exists(parent): |
| 362 raise UsageError, _('Instance home parent directory "%(parent)s"' | 363 raise UsageError, _('Instance home parent directory "%(parent)s"' |
| 363 ' does not exist')%locals() | 364 ' does not exist')%locals() |
| 364 | 365 |
| 365 if os.path.exists(os.path.join(tracker_home, 'config.py')): | 366 if os.path.exists(os.path.join(tracker_home, 'config.py')): |
| 366 print _('WARNING: There appears to be a tracker in ' | 367 ok = raw_input(_( |
| 367 '"%(tracker_home)s"!')%locals() | 368 """WARNING: There appears to be a tracker in "%(tracker_home)s"! |
| 368 print _('If you re-install it, you will lose all the data!') | 369 If you re-install it, you will lose all the data! |
| 369 ok = raw_input(_('Erase it? Y/N: ')).strip() | 370 Erase it? Y/N: """) % locals()) |
| 370 if ok.strip().lower() != 'y': | 371 if ok.strip().lower() != 'y': |
| 371 return 0 | 372 return 0 |
| 372 | 373 |
| 373 # clear it out so the install isn't confused | 374 # clear it out so the install isn't confused |
| 374 shutil.rmtree(tracker_home) | 375 shutil.rmtree(tracker_home) |
| 415 } | 416 } |
| 416 return 0 | 417 return 0 |
| 417 | 418 |
| 418 | 419 |
| 419 def do_initialise(self, tracker_home, args): | 420 def do_initialise(self, tracker_home, args): |
| 420 '''Usage: initialise [adminpw] | 421 ""'''Usage: initialise [adminpw] |
| 421 Initialise a new Roundup tracker. | 422 Initialise a new Roundup tracker. |
| 422 | 423 |
| 423 The administrator details will be set at this step. | 424 The administrator details will be set at this step. |
| 424 | 425 |
| 425 Execute the tracker's initialisation function dbinit.init() | 426 Execute the tracker's initialisation function dbinit.init() |
| 447 db_exists = tracker.select_db.Database.exists(tracker.config) | 448 db_exists = tracker.select_db.Database.exists(tracker.config) |
| 448 except AttributeError: | 449 except AttributeError: |
| 449 # TODO: move this code to exists() static method in every backend | 450 # TODO: move this code to exists() static method in every backend |
| 450 db_exists = os.path.exists(os.path.join(tracker_home, 'db')) | 451 db_exists = os.path.exists(os.path.join(tracker_home, 'db')) |
| 451 if db_exists: | 452 if db_exists: |
| 452 print _('WARNING: The database is already initialised!') | 453 ok = raw_input(_( |
| 453 print _('If you re-initialise it, you will lose all the data!') | 454 """WARNING: The database is already initialised! |
| 454 ok = raw_input(_('Erase it? Y/N: ')).strip() | 455 If you re-initialise it, you will lose all the data! |
| 456 Erase it? Y/N: """)) | |
| 455 if ok.strip().lower() != 'y': | 457 if ok.strip().lower() != 'y': |
| 456 return 0 | 458 return 0 |
| 457 | 459 |
| 458 # Get a database backend in use by tracker | 460 # Get a database backend in use by tracker |
| 459 try: | 461 try: |
| 468 | 470 |
| 469 return 0 | 471 return 0 |
| 470 | 472 |
| 471 | 473 |
| 472 def do_get(self, args): | 474 def do_get(self, args): |
| 473 '''Usage: get property designator[,designator]* | 475 ""'''Usage: get property designator[,designator]* |
| 474 Get the given property of one or more designator(s). | 476 Get the given property of one or more designator(s). |
| 475 | 477 |
| 476 Retrieves the property value of the nodes specified by the designators. | 478 Retrieves the property value of the nodes specified by the designators. |
| 477 ''' | 479 ''' |
| 478 if len(args) < 2: | 480 if len(args) < 2: |
| 541 | 543 |
| 542 return 0 | 544 return 0 |
| 543 | 545 |
| 544 | 546 |
| 545 def do_set(self, args, pwre = re.compile(r'{(\w+)}(.+)')): | 547 def do_set(self, args, pwre = re.compile(r'{(\w+)}(.+)')): |
| 546 '''Usage: set items property=value property=value ... | 548 ""'''Usage: set items property=value property=value ... |
| 547 Set the given properties of one or more items(s). | 549 Set the given properties of one or more items(s). |
| 548 | 550 |
| 549 The items are specified as a class or as a comma-separated | 551 The items are specified as a class or as a comma-separated |
| 550 list of item designators (ie "designator[,designator,...]"). | 552 list of item designators (ie "designator[,designator,...]"). |
| 551 | 553 |
| 595 import traceback; traceback.print_exc() | 597 import traceback; traceback.print_exc() |
| 596 raise UsageError, message | 598 raise UsageError, message |
| 597 return 0 | 599 return 0 |
| 598 | 600 |
| 599 def do_find(self, args): | 601 def do_find(self, args): |
| 600 '''Usage: find classname propname=value ... | 602 ""'''Usage: find classname propname=value ... |
| 601 Find the nodes of the given class with a given link property value. | 603 Find the nodes of the given class with a given link property value. |
| 602 | 604 |
| 603 Find the nodes of the given class with a given link property value. The | 605 Find the nodes of the given class with a given link property value. The |
| 604 value may be either the nodeid of the linked node, or its key value. | 606 value may be either the nodeid of the linked node, or its key value. |
| 605 ''' | 607 ''' |
| 634 # get the linked-to class and look up the key property | 636 # get the linked-to class and look up the key property |
| 635 link_class = self.db.getclass(property.classname) | 637 link_class = self.db.getclass(property.classname) |
| 636 try: | 638 try: |
| 637 props[propname] = link_class.lookup(value) | 639 props[propname] = link_class.lookup(value) |
| 638 except TypeError: | 640 except TypeError: |
| 639 raise UsageError, _('%(classname)s has no key property"')%{ | 641 raise UsageError, _('%(classname)s has no key property')%{ |
| 640 'classname': link_class.classname} | 642 'classname': link_class.classname} |
| 641 | 643 |
| 642 # now do the find | 644 # now do the find |
| 643 try: | 645 try: |
| 644 id = [] | 646 id = [] |
| 645 designator = [] | 647 designator = [] |
| 646 if self.separator: | 648 if self.separator: |
| 647 if self.print_designator: | 649 if self.print_designator: |
| 666 except (ValueError, TypeError), message: | 668 except (ValueError, TypeError), message: |
| 667 raise UsageError, message | 669 raise UsageError, message |
| 668 return 0 | 670 return 0 |
| 669 | 671 |
| 670 def do_specification(self, args): | 672 def do_specification(self, args): |
| 671 '''Usage: specification classname | 673 ""'''Usage: specification classname |
| 672 Show the properties for a classname. | 674 Show the properties for a classname. |
| 673 | 675 |
| 674 This lists the properties for a given class. | 676 This lists the properties for a given class. |
| 675 ''' | 677 ''' |
| 676 if len(args) < 1: | 678 if len(args) < 1: |
| 686 print _('%(key)s: %(value)s (key property)')%locals() | 688 print _('%(key)s: %(value)s (key property)')%locals() |
| 687 else: | 689 else: |
| 688 print _('%(key)s: %(value)s')%locals() | 690 print _('%(key)s: %(value)s')%locals() |
| 689 | 691 |
| 690 def do_display(self, args): | 692 def do_display(self, args): |
| 691 '''Usage: display designator[,designator]* | 693 ""'''Usage: display designator[,designator]* |
| 692 Show the property values for the given node(s). | 694 Show the property values for the given node(s). |
| 693 | 695 |
| 694 This lists the properties and their associated values for the given | 696 This lists the properties and their associated values for the given |
| 695 node. | 697 node. |
| 696 ''' | 698 ''' |
| 713 for key in keys: | 715 for key in keys: |
| 714 value = cl.get(nodeid, key) | 716 value = cl.get(nodeid, key) |
| 715 print _('%(key)s: %(value)s')%locals() | 717 print _('%(key)s: %(value)s')%locals() |
| 716 | 718 |
| 717 def do_create(self, args, pwre = re.compile(r'{(\w+)}(.+)')): | 719 def do_create(self, args, pwre = re.compile(r'{(\w+)}(.+)')): |
| 718 '''Usage: create classname property=value ... | 720 ""'''Usage: create classname property=value ... |
| 719 Create a new entry of a given class. | 721 Create a new entry of a given class. |
| 720 | 722 |
| 721 This creates a new entry of the given class using the property | 723 This creates a new entry of the given class using the property |
| 722 name=value arguments provided on the command line after the "create" | 724 name=value arguments provided on the command line after the "create" |
| 723 command. | 725 command. |
| 777 except (TypeError, IndexError, ValueError), message: | 779 except (TypeError, IndexError, ValueError), message: |
| 778 raise UsageError, message | 780 raise UsageError, message |
| 779 return 0 | 781 return 0 |
| 780 | 782 |
| 781 def do_list(self, args): | 783 def do_list(self, args): |
| 782 '''Usage: list classname [property] | 784 ""'''Usage: list classname [property] |
| 783 List the instances of a class. | 785 List the instances of a class. |
| 784 | 786 |
| 785 Lists all instances of the given class. If the property is not | 787 Lists all instances of the given class. If the property is not |
| 786 specified, the "label" property is used. The label property is tried | 788 specified, the "label" property is used. The label property is tried |
| 787 in order: the key, "name", "title" and then the first property, | 789 in order: the key, "name", "title" and then the first property, |
| 830 '"%(propname)s"')%locals() | 832 '"%(propname)s"')%locals() |
| 831 print _('%(nodeid)4s: %(value)s')%locals() | 833 print _('%(nodeid)4s: %(value)s')%locals() |
| 832 return 0 | 834 return 0 |
| 833 | 835 |
| 834 def do_table(self, args): | 836 def do_table(self, args): |
| 835 '''Usage: table classname [property[,property]*] | 837 ""'''Usage: table classname [property[,property]*] |
| 836 List the instances of a class in tabular form. | 838 List the instances of a class in tabular form. |
| 837 | 839 |
| 838 Lists all instances of the given class. If the properties are not | 840 Lists all instances of the given class. If the properties are not |
| 839 specified, all properties are displayed. By default, the column widths | 841 specified, all properties are displayed. By default, the column widths |
| 840 are the width of the largest value. The width may be explicitly defined | 842 are the width of the largest value. The width may be explicitly defined |
| 841 by defining the property as "name:width". For example:: | 843 by defining the property as "name:width". For example:: |
| 842 | 844 |
| 843 roundup> table priority id,name:10 | 845 roundup> table priority id,name:10 |
| 844 Id Name | 846 Id Name |
| 845 1 fatal-bug | 847 1 fatal-bug |
| 846 2 bug | 848 2 bug |
| 847 3 usability | 849 3 usability |
| 848 4 feature | 850 4 feature |
| 849 | 851 |
| 850 Also to make the width of the column the width of the label, | 852 Also to make the width of the column the width of the label, |
| 851 leave a trailing : without a width on the property. For example:: | 853 leave a trailing : without a width on the property. For example:: |
| 852 | 854 |
| 853 roundup> table priority id,name: | 855 roundup> table priority id,name: |
| 854 Id Name | 856 Id Name |
| 855 1 fata | 857 1 fata |
| 856 2 bug | 858 2 bug |
| 857 3 usab | 859 3 usab |
| 858 4 feat | 860 4 feat |
| 859 | 861 |
| 860 will result in a the 4 character wide "Name" column. | 862 will result in a the 4 character wide "Name" column. |
| 861 ''' | 863 ''' |
| 899 for nodeid in cl.list(): | 901 for nodeid in cl.list(): |
| 900 curlen = len(str(cl.get(nodeid, spec))) | 902 curlen = len(str(cl.get(nodeid, spec))) |
| 901 if curlen > maxlen: | 903 if curlen > maxlen: |
| 902 maxlen = curlen | 904 maxlen = curlen |
| 903 props.append((spec, maxlen)) | 905 props.append((spec, maxlen)) |
| 904 | 906 |
| 905 # now display the heading | 907 # now display the heading |
| 906 print ' '.join([name.capitalize().ljust(width) for name,width in props]) | 908 print ' '.join([name.capitalize().ljust(width) for name,width in props]) |
| 907 | 909 |
| 908 # and the table data | 910 # and the table data |
| 909 for nodeid in cl.list(): | 911 for nodeid in cl.list(): |
| 923 l.append(f%value[:width]) | 925 l.append(f%value[:width]) |
| 924 print ' '.join(l) | 926 print ' '.join(l) |
| 925 return 0 | 927 return 0 |
| 926 | 928 |
| 927 def do_history(self, args): | 929 def do_history(self, args): |
| 928 '''Usage: history designator | 930 ""'''Usage: history designator |
| 929 Show the history entries of a designator. | 931 Show the history entries of a designator. |
| 930 | 932 |
| 931 Lists the journal entries for the node identified by the designator. | 933 Lists the journal entries for the node identified by the designator. |
| 932 ''' | 934 ''' |
| 933 if len(args) < 1: | 935 if len(args) < 1: |
| 944 except IndexError: | 946 except IndexError: |
| 945 raise UsageError, _('no such %(classname)s node "%(nodeid)s"')%locals() | 947 raise UsageError, _('no such %(classname)s node "%(nodeid)s"')%locals() |
| 946 return 0 | 948 return 0 |
| 947 | 949 |
| 948 def do_commit(self, args): | 950 def do_commit(self, args): |
| 949 '''Usage: commit | 951 ""'''Usage: commit |
| 950 Commit changes made to the database during an interactive session. | 952 Commit changes made to the database during an interactive session. |
| 951 | 953 |
| 952 The changes made during an interactive session are not | 954 The changes made during an interactive session are not |
| 953 automatically written to the database - they must be committed | 955 automatically written to the database - they must be committed |
| 954 using this command. | 956 using this command. |
| 958 ''' | 960 ''' |
| 959 self.db.commit() | 961 self.db.commit() |
| 960 return 0 | 962 return 0 |
| 961 | 963 |
| 962 def do_rollback(self, args): | 964 def do_rollback(self, args): |
| 963 '''Usage: rollback | 965 ""'''Usage: rollback |
| 964 Undo all changes that are pending commit to the database. | 966 Undo all changes that are pending commit to the database. |
| 965 | 967 |
| 966 The changes made during an interactive session are not | 968 The changes made during an interactive session are not |
| 967 automatically written to the database - they must be committed | 969 automatically written to the database - they must be committed |
| 968 manually. This command undoes all those changes, so a commit | 970 manually. This command undoes all those changes, so a commit |
| 970 ''' | 972 ''' |
| 971 self.db.rollback() | 973 self.db.rollback() |
| 972 return 0 | 974 return 0 |
| 973 | 975 |
| 974 def do_retire(self, args): | 976 def do_retire(self, args): |
| 975 '''Usage: retire designator[,designator]* | 977 ""'''Usage: retire designator[,designator]* |
| 976 Retire the node specified by designator. | 978 Retire the node specified by designator. |
| 977 | 979 |
| 978 This action indicates that a particular node is not to be retrieved by | 980 This action indicates that a particular node is not to be retrieved by |
| 979 the list or find commands, and its key value may be re-used. | 981 the list or find commands, and its key value may be re-used. |
| 980 ''' | 982 ''' |
| 993 except IndexError: | 995 except IndexError: |
| 994 raise UsageError, _('no such %(classname)s node "%(nodeid)s"')%locals() | 996 raise UsageError, _('no such %(classname)s node "%(nodeid)s"')%locals() |
| 995 return 0 | 997 return 0 |
| 996 | 998 |
| 997 def do_restore(self, args): | 999 def do_restore(self, args): |
| 998 '''Usage: restore designator[,designator]* | 1000 ""'''Usage: restore designator[,designator]* |
| 999 Restore the retired node specified by designator. | 1001 Restore the retired node specified by designator. |
| 1000 | 1002 |
| 1001 The given nodes will become available for users again. | 1003 The given nodes will become available for users again. |
| 1002 ''' | 1004 ''' |
| 1003 if len(args) < 1: | 1005 if len(args) < 1: |
| 1015 except IndexError: | 1017 except IndexError: |
| 1016 raise UsageError, _('no such %(classname)s node "%(nodeid)s"')%locals() | 1018 raise UsageError, _('no such %(classname)s node "%(nodeid)s"')%locals() |
| 1017 return 0 | 1019 return 0 |
| 1018 | 1020 |
| 1019 def do_export(self, args): | 1021 def do_export(self, args): |
| 1020 '''Usage: export [class[,class]] export_dir | 1022 ""'''Usage: export [class[,class]] export_dir |
| 1021 Export the database to colon-separated-value files. | 1023 Export the database to colon-separated-value files. |
| 1022 | 1024 |
| 1023 Optionally limit the export to just the names classes. | 1025 Optionally limit the export to just the names classes. |
| 1024 | 1026 |
| 1025 This action exports the current data from the database into | 1027 This action exports the current data from the database into |
| 1067 map(journals.writerow, cl.export_journals()) | 1069 map(journals.writerow, cl.export_journals()) |
| 1068 jf.close() | 1070 jf.close() |
| 1069 return 0 | 1071 return 0 |
| 1070 | 1072 |
| 1071 def do_import(self, args): | 1073 def do_import(self, args): |
| 1072 '''Usage: import import_dir | 1074 ""'''Usage: import import_dir |
| 1073 Import a database from the directory containing CSV files, two per | 1075 Import a database from the directory containing CSV files, two per |
| 1074 class to import. | 1076 class to import. |
| 1075 | 1077 |
| 1076 The files used in the import are: | 1078 The files used in the import are: |
| 1077 | 1079 |
| 1127 self.db.setid(classname, str(maxid+1)) | 1129 self.db.setid(classname, str(maxid+1)) |
| 1128 | 1130 |
| 1129 return 0 | 1131 return 0 |
| 1130 | 1132 |
| 1131 def do_pack(self, args): | 1133 def do_pack(self, args): |
| 1132 '''Usage: pack period | date | 1134 ""'''Usage: pack period | date |
| 1133 | 1135 |
| 1134 Remove journal entries older than a period of time specified or | 1136 Remove journal entries older than a period of time specified or |
| 1135 before a certain date. | 1137 before a certain date. |
| 1136 | 1138 |
| 1137 A period is specified using the suffixes "y", "m", and "d". The | 1139 A period is specified using the suffixes "y", "m", and "d". The |
| 1138 suffix "w" (for "week") means 7 days. | 1140 suffix "w" (for "week") means 7 days. |
| 1139 | 1141 |
| 1140 "3y" means three years | 1142 "3y" means three years |
| 1141 "2y 1m" means two years and one month | 1143 "2y 1m" means two years and one month |
| 1142 "1m 25d" means one month and 25 days | 1144 "1m 25d" means one month and 25 days |
| 1143 "2w 3d" means two weeks and three days | 1145 "2w 3d" means two weeks and three days |
| 1144 | 1146 |
| 1145 Date format is "YYYY-MM-DD" eg: | 1147 Date format is "YYYY-MM-DD" eg: |
| 1146 2001-01-01 | 1148 2001-01-01 |
| 1147 | 1149 |
| 1148 ''' | 1150 ''' |
| 1149 if len(args) <> 1: | 1151 if len(args) <> 1: |
| 1150 raise UsageError, _('Not enough arguments supplied') | 1152 raise UsageError, _('Not enough arguments supplied') |
| 1151 | 1153 |
| 1152 # are we dealing with a period or a date | 1154 # are we dealing with a period or a date |
| 1153 value = args[0] | 1155 value = args[0] |
| 1154 date_re = re.compile(r''' | 1156 date_re = re.compile(r''' |
| 1155 (?P<date>\d\d\d\d-\d\d?-\d\d?)? # yyyy-mm-dd | 1157 (?P<date>\d\d\d\d-\d\d?-\d\d?)? # yyyy-mm-dd |
| 1156 (?P<period>(\d+y\s*)?(\d+m\s*)?(\d+d\s*)?)? | 1158 (?P<period>(\d+y\s*)?(\d+m\s*)?(\d+d\s*)?)? |
| 1165 pack_before = date.Date(value) | 1167 pack_before = date.Date(value) |
| 1166 self.db.pack(pack_before) | 1168 self.db.pack(pack_before) |
| 1167 return 0 | 1169 return 0 |
| 1168 | 1170 |
| 1169 def do_reindex(self, args): | 1171 def do_reindex(self, args): |
| 1170 '''Usage: reindex | 1172 ""'''Usage: reindex |
| 1171 Re-generate a tracker's search indexes. | 1173 Re-generate a tracker's search indexes. |
| 1172 | 1174 |
| 1173 This will re-generate the search indexes for a tracker. This will | 1175 This will re-generate the search indexes for a tracker. This will |
| 1174 typically happen automatically. | 1176 typically happen automatically. |
| 1175 ''' | 1177 ''' |
| 1176 self.db.indexer.force_reindex() | 1178 self.db.indexer.force_reindex() |
| 1177 self.db.reindex() | 1179 self.db.reindex() |
| 1178 return 0 | 1180 return 0 |
| 1179 | 1181 |
| 1180 def do_security(self, args): | 1182 def do_security(self, args): |
| 1181 '''Usage: security [Role name] | 1183 ""'''Usage: security [Role name] |
| 1182 Display the Permissions available to one or all Roles. | 1184 Display the Permissions available to one or all Roles. |
| 1183 ''' | 1185 ''' |
| 1184 if len(args) == 1: | 1186 if len(args) == 1: |
| 1185 role = args[0] | 1187 role = args[0] |
| 1186 try: | 1188 try: |
| 1291 return ret | 1293 return ret |
| 1292 | 1294 |
| 1293 def interactive(self): | 1295 def interactive(self): |
| 1294 '''Run in an interactive mode | 1296 '''Run in an interactive mode |
| 1295 ''' | 1297 ''' |
| 1296 print _('Roundup %s ready for input.'%roundup_version) | 1298 print _('Roundup %s ready for input.\nType "help" for help.' |
| 1297 print _('Type "help" for help.') | 1299 % roundup_version) |
| 1298 try: | 1300 try: |
| 1299 import readline | 1301 import readline |
| 1300 except ImportError: | 1302 except ImportError: |
| 1301 print _('Note: command history and editing not available') | 1303 print _('Note: command history and editing not available') |
| 1302 | 1304 |
