Mercurial > p > roundup > code
comparison roundup/admin.py @ 6959:3211745e8d7c
flake8 fixes.
| author | John Rouillard <rouilj@ieee.org> |
|---|---|
| date | Mon, 12 Sep 2022 21:52:52 -0400 |
| parents | f924af12ef50 |
| children | d3d20e145cea |
comparison
equal
deleted
inserted
replaced
| 6958:e54a2db40a9e | 6959:3211745e8d7c |
|---|---|
| 21 """ | 21 """ |
| 22 from __future__ import print_function | 22 from __future__ import print_function |
| 23 | 23 |
| 24 __docformat__ = 'restructuredtext' | 24 __docformat__ = 'restructuredtext' |
| 25 | 25 |
| 26 import csv, getopt, getpass, operator, os, re, shutil, sys | 26 import csv |
| 27 import getopt | |
| 28 import getpass | |
| 29 import operator | |
| 30 import os | |
| 31 import re | |
| 32 import shutil | |
| 33 import sys | |
| 27 | 34 |
| 28 from roundup import date, hyperdb, init, password, token | 35 from roundup import date, hyperdb, init, password, token |
| 29 from roundup import __version__ as roundup_version | 36 from roundup import __version__ as roundup_version |
| 30 import roundup.instance | 37 import roundup.instance |
| 31 from roundup.configuration import (CoreConfig, NoConfigError, | 38 from roundup.configuration import (CoreConfig, NoConfigError, |
| 155 h = _(command.__doc__).split('\n')[0] | 162 h = _(command.__doc__).split('\n')[0] |
| 156 commands.append(' '+h[7:]) | 163 commands.append(' '+h[7:]) |
| 157 commands.sort() | 164 commands.sort() |
| 158 commands.append(_( | 165 commands.append(_( |
| 159 """Commands may be abbreviated as long as the abbreviation | 166 """Commands may be abbreviated as long as the abbreviation |
| 160 matches only one command, e.g. l == li == lis == list.""")) | 167 matches only one command, e.g. l == li == lis == list.""")) # noqa: E122 |
| 161 sys.stdout.write('\n'.join(commands) + '\n\n') | 168 sys.stdout.write('\n'.join(commands) + '\n\n') |
| 162 | 169 |
| 163 def help_commands_html(self, indent_re=re.compile(r'^(\s+)\S+')): | 170 indent_re = re.compile(r'^(\s+)\S+') |
| 171 | |
| 172 def help_commands_html(self, indent_re=indent_re): | |
| 164 """ Produce an HTML command list. | 173 """ Produce an HTML command list. |
| 165 """ | 174 """ |
| 166 commands = sorted(iter(self.commands.values()), | 175 commands = sorted(iter(self.commands.values()), |
| 167 key=operator.attrgetter('__name__')) | 176 key=operator.attrgetter('__name__')) |
| 168 for command in commands: | 177 for command in commands: |
| 172 print(""" | 181 print(""" |
| 173 <tr><td valign=top><strong>%(name)s</strong></td> | 182 <tr><td valign=top><strong>%(name)s</strong></td> |
| 174 <td><tt>%(usage)s</tt><p> | 183 <td><tt>%(usage)s</tt><p> |
| 175 <pre>""" % locals()) | 184 <pre>""" % locals()) |
| 176 indent = indent_re.match(h[3]) | 185 indent = indent_re.match(h[3]) |
| 177 if indent: indent = len(indent.group(1)) | 186 if indent: indent = len(indent.group(1)) # noqa: E701 |
| 178 for line in h[3:]: | 187 for line in h[3:]: |
| 179 if indent: | 188 if indent: |
| 180 print(line[indent:]) | 189 print(line[indent:]) |
| 181 else: | 190 else: |
| 182 print(line) | 191 print(line) |
| 247 """)) | 256 """)) |
| 248 for name, command in list(self.commands.items()): | 257 for name, command in list(self.commands.items()): |
| 249 print(_('%s:') % name) | 258 print(_('%s:') % name) |
| 250 print(' ', _(command.__doc__)) | 259 print(' ', _(command.__doc__)) |
| 251 | 260 |
| 252 def do_help(self, args, nl_re=re.compile('[\r\n]'), | 261 nl_re = re.compile('[\r\n]') |
| 253 indent_re=re.compile(r'^(\s+)\S+')): | 262 # indent_re defined above |
| 263 | |
| 264 def do_help(self, args, nl_re=nl_re, indent_re=indent_re): | |
| 254 ''"""Usage: help topic | 265 ''"""Usage: help topic |
| 255 Give help about topic. | 266 Give help about topic. |
| 256 | 267 |
| 257 commands -- list commands | 268 commands -- list commands |
| 258 <command> -- help specific to a command | 269 <command> -- help specific to a command |
| 279 # display the help for each match, removing the docstring indent | 290 # display the help for each match, removing the docstring indent |
| 280 for _name, help in cmd_docs: | 291 for _name, help in cmd_docs: |
| 281 lines = nl_re.split(_(help.__doc__)) | 292 lines = nl_re.split(_(help.__doc__)) |
| 282 print(lines[0]) | 293 print(lines[0]) |
| 283 indent = indent_re.match(lines[1]) | 294 indent = indent_re.match(lines[1]) |
| 284 if indent: indent = len(indent.group(1)) | 295 if indent: indent = len(indent.group(1)) # noqa: E701 |
| 285 for line in lines[1:]: | 296 for line in lines[1:]: |
| 286 if indent: | 297 if indent: |
| 287 print(line[indent:]) | 298 print(line[indent:]) |
| 288 else: | 299 else: |
| 289 print(line) | 300 print(line) |
| 318 # (2 dirs up) | 329 # (2 dirs up) |
| 319 # | 330 # |
| 320 # we're interested in where the directory containing "share" is | 331 # we're interested in where the directory containing "share" is |
| 321 debug = False | 332 debug = False |
| 322 templates = {} | 333 templates = {} |
| 323 if debug: print(__file__) | 334 if debug: print(__file__) # noqa: E701 |
| 324 for N in 2, 4, 5, 6: | 335 for N in 2, 4, 5, 6: |
| 325 path = __file__ | 336 path = __file__ |
| 326 # move up N elements in the path | 337 # move up N elements in the path |
| 327 for _i in range(N): | 338 for _i in range(N): |
| 328 path = os.path.dirname(path) | 339 path = os.path.dirname(path) |
| 329 tdir = os.path.join(path, 'share', 'roundup', 'templates') | 340 tdir = os.path.join(path, 'share', 'roundup', 'templates') |
| 330 if debug or trace_search: print(tdir) | 341 if debug or trace_search: print(tdir) # noqa: E701 |
| 331 if os.path.isdir(tdir): | 342 if os.path.isdir(tdir): |
| 332 templates = init.listTemplates(tdir) | 343 templates = init.listTemplates(tdir) |
| 333 if debug: print(" Found templates breaking loop") | 344 if debug: print(" Found templates breaking loop") # noqa: E701 |
| 334 break | 345 break |
| 335 | 346 |
| 336 # search for data files parallel to the roundup | 347 # search for data files parallel to the roundup |
| 337 # install dir. E.G. a wheel install | 348 # install dir. E.G. a wheel install |
| 338 # use roundup.__path__ and go up a level then use sys.prefix | 349 # use roundup.__path__ and go up a level then use sys.prefix |
| 347 for _N in 1, 2: | 358 for _N in 1, 2: |
| 348 path = os.path.dirname(path) | 359 path = os.path.dirname(path) |
| 349 # path is /usr/local/lib/python3.10/site-packages | 360 # path is /usr/local/lib/python3.10/site-packages |
| 350 tdir = os.path.join(path, sys.prefix[1:], 'share', | 361 tdir = os.path.join(path, sys.prefix[1:], 'share', |
| 351 'roundup', 'templates') | 362 'roundup', 'templates') |
| 352 if debug or trace_search: print(tdir) | 363 if debug or trace_search: print(tdir) # noqa: E701 |
| 353 if os.path.isdir(tdir): | 364 if os.path.isdir(tdir): |
| 354 templates.update(init.listTemplates(tdir)) | 365 templates.update(init.listTemplates(tdir)) |
| 355 | 366 |
| 356 try: | 367 try: |
| 357 # sigh pip 3.10 in virtual env finds another place to bury them. | 368 # sigh pip 3.10 in virtual env finds another place to bury them. |
| 358 # why local and sys.base_prefix are in path I do not know. | 369 # why local and sys.base_prefix are in path I do not know. |
| 359 # path is /usr/local/lib/python3.10/site-packages | 370 # path is /usr/local/lib/python3.10/site-packages |
| 360 tdir = os.path.join(path, sys.base_prefix[1:], 'local', 'share', | 371 tdir = os.path.join(path, sys.base_prefix[1:], 'local', 'share', |
| 361 'roundup', 'templates') | 372 'roundup', 'templates') |
| 362 if debug or trace_search: print(tdir) | 373 if debug or trace_search: print(tdir) # noqa: E701 |
| 363 if os.path.isdir(tdir): | 374 if os.path.isdir(tdir): |
| 364 templates.update(init.listTemplates(tdir)) | 375 templates.update(init.listTemplates(tdir)) |
| 365 # path is /usr/local/lib/python3.10/site-packages | 376 # path is /usr/local/lib/python3.10/site-packages |
| 366 | |
| 367 | 377 |
| 368 tdir = os.path.join(path, sys.base_prefix[1:], 'share', | 378 tdir = os.path.join(path, sys.base_prefix[1:], 'share', |
| 369 'roundup', 'templates') | 379 'roundup', 'templates') |
| 370 if debug or trace_search: print(tdir) | 380 if debug or trace_search: print(tdir) # noqa: E701 |
| 371 if os.path.isdir(tdir): | 381 if os.path.isdir(tdir): |
| 372 templates.update(init.listTemplates(tdir)) | 382 templates.update(init.listTemplates(tdir)) |
| 373 except AttributeError: | 383 except AttributeError: |
| 374 pass # sys.base_prefix doesn't work under python2 | 384 pass # sys.base_prefix doesn't work under python2 |
| 375 | 385 |
| 376 # Try subdirs of the current dir | 386 # Try subdirs of the current dir |
| 377 templates.update(init.listTemplates(os.getcwd())) | 387 templates.update(init.listTemplates(os.getcwd())) |
| 378 if debug or trace_search: print(os.getcwd() + '/*') | 388 if debug or trace_search: print(os.getcwd() + '/*') # noqa: E701 |
| 379 | 389 |
| 380 # Finally, try the current directory as a template | 390 # Finally, try the current directory as a template |
| 381 template = init.loadTemplateInfo(os.getcwd()) | 391 template = init.loadTemplateInfo(os.getcwd()) |
| 382 if debug or trace_search: print(os.getcwd()) | 392 if debug or trace_search: print(os.getcwd()) # noqa: E701 |
| 383 if template: | 393 if template: |
| 384 if debug: print(" Found template %s"%template['name']) | 394 if debug: print(" Found template %s" % # noqa: E701 |
| 395 template['name']) | |
| 385 templates[template['name']] = template | 396 templates[template['name']] = template |
| 386 | 397 |
| 387 return templates | 398 return templates |
| 388 | 399 |
| 389 def help_initopts(self): | 400 def help_initopts(self): |
| 432 os.path.join(tracker_home, 'config.py')])): | 443 os.path.join(tracker_home, 'config.py')])): |
| 433 if not self.force: | 444 if not self.force: |
| 434 ok = my_input(_( | 445 ok = my_input(_( |
| 435 """WARNING: There appears to be a tracker in "%(tracker_home)s"! | 446 """WARNING: There appears to be a tracker in "%(tracker_home)s"! |
| 436 If you re-install it, you will lose all the data! | 447 If you re-install it, you will lose all the data! |
| 437 Erase it? Y/N: """) % locals()) | 448 Erase it? Y/N: """) % locals()) # noqa: E122 |
| 438 if ok.strip().lower() != 'y': | 449 if ok.strip().lower() != 'y': |
| 439 return 0 | 450 return 0 |
| 440 | 451 |
| 441 # clear it out so the install isn't confused | 452 # clear it out so the install isn't confused |
| 442 shutil.rmtree(tracker_home) | 453 shutil.rmtree(tracker_home) |
| 521 ... see the documentation on customizing for more information. | 532 ... see the documentation on customizing for more information. |
| 522 | 533 |
| 523 You MUST run the "roundup-admin initialise" command once you've performed | 534 You MUST run the "roundup-admin initialise" command once you've performed |
| 524 the above steps. | 535 the above steps. |
| 525 --------------------------------------------------------------------------- | 536 --------------------------------------------------------------------------- |
| 526 """) % { | 537 """) % {'database_config_file': os.path.join(tracker_home, 'schema.py'), |
| 527 'database_config_file': os.path.join(tracker_home, 'schema.py'), | 538 'database_init_file': os.path.join(tracker_home, 'initial_data.py')}) \ |
| 528 'database_init_file': os.path.join(tracker_home, 'initial_data.py'), | 539 # noqa: E122 |
| 529 }) | |
| 530 return 0 | 540 return 0 |
| 531 | 541 |
| 532 def _get_choice(self, list_name, prompt, options, argument, default=None): | 542 def _get_choice(self, list_name, prompt, options, argument, default=None): |
| 533 if default is None: | 543 if default is None: |
| 534 default = options[0] # just pick the first one | 544 default = options[0] # just pick the first one |
| 596 if tracker.exists(): | 606 if tracker.exists(): |
| 597 if not self.force: | 607 if not self.force: |
| 598 ok = my_input(_( | 608 ok = my_input(_( |
| 599 """WARNING: The database is already initialised! | 609 """WARNING: The database is already initialised! |
| 600 If you re-initialise it, you will lose all the data! | 610 If you re-initialise it, you will lose all the data! |
| 601 Erase it? Y/N: """)) | 611 Erase it? Y/N: """)) # noqa: E122 |
| 602 if ok.strip().lower() != 'y': | 612 if ok.strip().lower() != 'y': |
| 603 return 0 | 613 return 0 |
| 604 | 614 |
| 605 # nuke it | 615 # nuke it |
| 606 tracker.nuke() | 616 tracker.nuke() |
| 653 # print | 663 # print |
| 654 properties = cl.getprops() | 664 properties = cl.getprops() |
| 655 property = properties[propname] | 665 property = properties[propname] |
| 656 if not (isinstance(property, hyperdb.Multilink) or | 666 if not (isinstance(property, hyperdb.Multilink) or |
| 657 isinstance(property, hyperdb.Link)): | 667 isinstance(property, hyperdb.Link)): |
| 658 raise UsageError(_('property %s is not of type' | 668 raise UsageError(_( |
| 669 'property %s is not of type' | |
| 659 ' Multilink or Link so -d flag does not ' | 670 ' Multilink or Link so -d flag does not ' |
| 660 'apply.') % propname) | 671 'apply.') % propname) |
| 661 propclassname = self.db.getclass(property.classname).classname | 672 propclassname = self.db.getclass(property.classname).classname |
| 662 id = cl.get(nodeid, propname) | 673 id = cl.get(nodeid, propname) |
| 663 for i in id: | 674 for i in id: |
| 670 if self.print_designator: | 681 if self.print_designator: |
| 671 properties = cl.getprops() | 682 properties = cl.getprops() |
| 672 property = properties[propname] | 683 property = properties[propname] |
| 673 if not (isinstance(property, hyperdb.Multilink) or | 684 if not (isinstance(property, hyperdb.Multilink) or |
| 674 isinstance(property, hyperdb.Link)): | 685 isinstance(property, hyperdb.Link)): |
| 675 raise UsageError(_('property %s is not of type' | 686 raise UsageError(_( |
| 687 'property %s is not of type' | |
| 676 ' Multilink or Link so -d flag does not ' | 688 ' Multilink or Link so -d flag does not ' |
| 677 'apply.') % propname) | 689 'apply.') % propname) |
| 678 propclassname = self.db.getclass(property.classname).classname | 690 propclassname = self.db.getclass(property.classname).classname |
| 679 id = cl.get(nodeid, propname) | 691 id = cl.get(nodeid, propname) |
| 680 for i in id: | 692 for i in id: |
| 801 lastprop = pn # get current component | 813 lastprop = pn # get current component |
| 802 # get classname for this link | 814 # get classname for this link |
| 803 try: | 815 try: |
| 804 curclassname = curclass.getprops()[pn].classname | 816 curclassname = curclass.getprops()[pn].classname |
| 805 except KeyError: | 817 except KeyError: |
| 806 raise UsageError(_("Class %(curclassname)s has " | 818 raise UsageError(_( |
| 807 "no property %(pn)s in %(propname)s." % locals())) | 819 "Class %(curclassname)s has " |
| 820 "no property %(pn)s in %(propname)s." % | |
| 821 locals())) | |
| 808 # get class object | 822 # get class object |
| 809 curclass = self.get_class(curclassname) | 823 curclass = self.get_class(curclassname) |
| 810 except AttributeError: | 824 except AttributeError: |
| 811 # curclass.getprops()[pn].classname raises this | 825 # curclass.getprops()[pn].classname raises this |
| 812 # when we are at a non link/multilink property | 826 # when we are at a non link/multilink property |
| 980 props = {} | 994 props = {} |
| 981 properties = cl.getprops(protected=0) | 995 properties = cl.getprops(protected=0) |
| 982 if len(args) == 1: | 996 if len(args) == 1: |
| 983 # ask for the properties | 997 # ask for the properties |
| 984 for key in properties: | 998 for key in properties: |
| 985 if key == 'id': continue | 999 if key == 'id': continue # noqa: E701 |
| 986 value = properties[key] | 1000 value = properties[key] |
| 987 name = value.__class__.__name__ | 1001 name = value.__class__.__name__ |
| 988 if isinstance(value, hyperdb.Password): | 1002 if isinstance(value, hyperdb.Password): |
| 989 again = None | 1003 again = None |
| 990 while value != again: | 1004 while value != again: |
| 992 % | 1006 % |
| 993 {'propname': key.capitalize()}) | 1007 {'propname': key.capitalize()}) |
| 994 again = getpass.getpass(_(' %(propname)s (Again): ') | 1008 again = getpass.getpass(_(' %(propname)s (Again): ') |
| 995 % | 1009 % |
| 996 {'propname': key.capitalize()}) | 1010 {'propname': key.capitalize()}) |
| 997 if value != again: print(_('Sorry, try again...')) | 1011 if value != again: |
| 1012 print(_('Sorry, try again...')) | |
| 998 if value: | 1013 if value: |
| 999 props[key] = value | 1014 props[key] = value |
| 1000 else: | 1015 else: |
| 1001 value = my_input(_('%(propname)s (%(proptype)s): ') % { | 1016 value = my_input(_('%(propname)s (%(proptype)s): ') % { |
| 1002 'propname': key.capitalize(), 'proptype': name}) | 1017 'propname': key.capitalize(), 'proptype': name}) |
| 1007 | 1022 |
| 1008 # convert types | 1023 # convert types |
| 1009 for propname in props: | 1024 for propname in props: |
| 1010 try: | 1025 try: |
| 1011 props[propname] = hyperdb.rawToHyperdb(self.db, cl, None, | 1026 props[propname] = hyperdb.rawToHyperdb(self.db, cl, None, |
| 1012 propname, props[propname]) | 1027 propname, |
| 1028 props[propname]) | |
| 1013 except hyperdb.HyperdbValueError as message: | 1029 except hyperdb.HyperdbValueError as message: |
| 1014 raise UsageError(message) | 1030 raise UsageError(message) |
| 1015 | 1031 |
| 1016 # check for the key property | 1032 # check for the key property |
| 1017 propname = cl.getkey() | 1033 propname = cl.getkey() |
| 1095 | 1111 |
| 1096 templates = self.listTemplates(trace_search=trace_search) | 1112 templates = self.listTemplates(trace_search=trace_search) |
| 1097 | 1113 |
| 1098 for name in sorted(list(templates.keys())): | 1114 for name in sorted(list(templates.keys())): |
| 1099 templates[name]['description'] = textwrap.fill( | 1115 templates[name]['description'] = textwrap.fill( |
| 1100 "\n".join([ line.lstrip() for line in | 1116 "\n".join([line.lstrip() for line in |
| 1101 templates[name]['description'].split("\n")]), | 1117 templates[name]['description'].split("\n")]), |
| 1102 70, | 1118 70, |
| 1103 subsequent_indent=" " | 1119 subsequent_indent=" " |
| 1104 ) | 1120 ) |
| 1105 print(""" | 1121 print(""" |
| 1106 Name: %(name)s | 1122 Name: %(name)s |
| 1107 Path: %(path)s | 1123 Path: %(path)s |
| 1108 Desc: %(description)s | 1124 Desc: %(description)s |
| 1109 """%templates[name]) | 1125 """ % templates[name]) |
| 1110 | 1126 |
| 1111 def do_table(self, args): | 1127 def do_table(self, args): |
| 1112 ''"""Usage: table classname [property[,property]*] | 1128 ''"""Usage: table classname [property[,property]*] |
| 1113 List the instances of a class in tabular form. | 1129 List the instances of a class in tabular form. |
| 1114 | 1130 |
| 1397 # on imports to rdbms. | 1413 # on imports to rdbms. |
| 1398 all_nodes = cl.getnodeids() | 1414 all_nodes = cl.getnodeids() |
| 1399 | 1415 |
| 1400 classkey = cl.getkey() | 1416 classkey = cl.getkey() |
| 1401 if classkey: # False sorts before True, so negate is_retired | 1417 if classkey: # False sorts before True, so negate is_retired |
| 1402 keysort = lambda i: (cl.get(i, classkey), | 1418 keysort = lambda i: (cl.get(i, classkey), # noqa: E731 |
| 1403 not cl.is_retired(i)) | 1419 not cl.is_retired(i)) |
| 1404 all_nodes.sort(key=keysort) | 1420 all_nodes.sort(key=keysort) |
| 1405 # if there is no classkey no need to sort | 1421 # if there is no classkey no need to sort |
| 1406 | 1422 |
| 1407 for nodeid in all_nodes: | 1423 for nodeid in all_nodes: |
| 1578 pack_before = date.Date(value) | 1594 pack_before = date.Date(value) |
| 1579 self.db.pack(pack_before) | 1595 self.db.pack(pack_before) |
| 1580 self.db_uncommitted = True | 1596 self.db_uncommitted = True |
| 1581 return 0 | 1597 return 0 |
| 1582 | 1598 |
| 1583 def do_reindex(self, args, desre=re.compile('([A-Za-z]+)([0-9]+)')): | 1599 designator_re = re.compile('([A-Za-z]+)([0-9]+)') |
| 1600 | |
| 1601 def do_reindex(self, args, desre=designator_re): | |
| 1584 ''"""Usage: reindex [classname|designator]* | 1602 ''"""Usage: reindex [classname|designator]* |
| 1585 Re-generate a tracker's search indexes. | 1603 Re-generate a tracker's search indexes. |
| 1586 | 1604 |
| 1587 This will re-generate the search indexes for a tracker. | 1605 This will re-generate the search indexes for a tracker. |
| 1588 This will typically happen automatically. | 1606 This will typically happen automatically. |
| 1635 sys.stdout.write(_('Role "%(name)s":\n') % role.__dict__) | 1653 sys.stdout.write(_('Role "%(name)s":\n') % role.__dict__) |
| 1636 for permission in role.permissions: | 1654 for permission in role.permissions: |
| 1637 d = permission.__dict__ | 1655 d = permission.__dict__ |
| 1638 if permission.klass: | 1656 if permission.klass: |
| 1639 if permission.properties: | 1657 if permission.properties: |
| 1640 sys.stdout.write(_(' %(description)s (%(name)s for "%(klass)s"' + | 1658 sys.stdout.write(_( |
| 1641 ': %(properties)s only)\n') % d) | 1659 ' %(description)s (%(name)s for "%(klass)s"' + |
| 1660 ': %(properties)s only)\n') % d) | |
| 1642 # verify that properties exist; report bad props | 1661 # verify that properties exist; report bad props |
| 1643 bad_props = [] | 1662 bad_props = [] |
| 1644 cl = self.db.getclass(permission.klass) | 1663 cl = self.db.getclass(permission.klass) |
| 1645 class_props = cl.getprops(protected=True) | 1664 class_props = cl.getprops(protected=True) |
| 1646 for p in permission.properties: | 1665 for p in permission.properties: |
| 1647 if p in class_props: | 1666 if p in class_props: |
| 1648 continue | 1667 continue |
| 1649 else: | 1668 else: |
| 1650 bad_props.append(p) | 1669 bad_props.append(p) |
| 1651 if bad_props: | 1670 if bad_props: |
| 1652 sys.stdout.write(_('\n **Invalid properties for %(class)s: %(props)s\n\n') % {"class": permission.klass, "props": bad_props}) | 1671 sys.stdout.write(_( |
| 1672 '\n **Invalid properties for %(class)s: ' | |
| 1673 '%(props)s\n\n') % { | |
| 1674 "class": permission.klass, | |
| 1675 "props": bad_props}) | |
| 1653 return 1 | 1676 return 1 |
| 1654 else: | 1677 else: |
| 1655 sys.stdout.write(_(' %(description)s (%(name)s for ' | 1678 sys.stdout.write(_(' %(description)s (%(name)s for ' |
| 1656 '"%(klass)s" only)\n') % d) | 1679 '"%(klass)s" only)\n') % d) |
| 1657 else: | 1680 else: |
| 1677 using anydbm). | 1700 using anydbm). |
| 1678 | 1701 |
| 1679 It's safe to run this even if it's not required, so just get | 1702 It's safe to run this even if it's not required, so just get |
| 1680 into the habit. | 1703 into the habit. |
| 1681 """ | 1704 """ |
| 1682 if getattr(self.db, 'db_version_updated'): | 1705 if self.db.db_version_updated: |
| 1683 print(_('Tracker updated')) | 1706 print(_('Tracker updated')) |
| 1684 self.db_uncommitted = True | 1707 self.db_uncommitted = True |
| 1685 else: | 1708 else: |
| 1686 print(_('No migration action required')) | 1709 print(_('No migration action required')) |
| 1687 return 0 | 1710 return 0 |
| 1753 return 1 | 1776 return 1 |
| 1754 except NoConfigError as message: # noqa: F841 | 1777 except NoConfigError as message: # noqa: F841 |
| 1755 self.tracker_home = '' | 1778 self.tracker_home = '' |
| 1756 print(_("Error: Couldn't open tracker: %(message)s") % locals()) | 1779 print(_("Error: Couldn't open tracker: %(message)s") % locals()) |
| 1757 return 1 | 1780 return 1 |
| 1758 except ParsingOptionError as message: # message used via locals | 1781 # message used via locals |
| 1782 except ParsingOptionError as message: # noqa: F841 | |
| 1759 print("%(message)s" % locals()) | 1783 print("%(message)s" % locals()) |
| 1760 return 1 | 1784 return 1 |
| 1761 | 1785 |
| 1762 # only open the database once! | 1786 # only open the database once! |
| 1763 if not self.db: | 1787 if not self.db: |
| 1764 self.db = tracker.open(self.name) | 1788 self.db = tracker.open(self.name) |
| 1765 # dont use tracker.config["TRACKER_LANGUAGE"] here as the | 1789 # dont use tracker.config["TRACKER_LANGUAGE"] here as the |
| 1766 # cli operator likely wants to have i18n as set in the | 1790 # cli operator likely wants to have i18n as set in the |
| 1767 # environment. | 1791 # environment. |
| 1768 # This is needed to fetch the locale's of the tracker's home dir. | 1792 # This is needed to fetch the locale's of the tracker's home dir. |
| 1769 self.db.i18n = get_translation (tracker_home = tracker.tracker_home) | 1793 self.db.i18n = get_translation(tracker_home=tracker.tracker_home) |
| 1770 | 1794 |
| 1771 self.db.tx_Source = 'cli' | 1795 self.db.tx_Source = 'cli' |
| 1772 | 1796 |
| 1773 # do the command | 1797 # do the command |
| 1774 ret = 0 | 1798 ret = 0 |
| 1799 try: | 1823 try: |
| 1800 command = my_input(_('roundup> ')) | 1824 command = my_input(_('roundup> ')) |
| 1801 except EOFError: | 1825 except EOFError: |
| 1802 print(_('exit...')) | 1826 print(_('exit...')) |
| 1803 break | 1827 break |
| 1804 if not command: continue | 1828 if not command: continue # noqa: E701 |
| 1805 try: | 1829 try: |
| 1806 args = token.token_split(command) | 1830 args = token.token_split(command) |
| 1807 except ValueError: | 1831 except ValueError: |
| 1808 continue # Ignore invalid quoted token | 1832 continue # Ignore invalid quoted token |
| 1809 if not args: continue | 1833 if not args: continue # noqa: E701 |
| 1810 if args[0] in ('quit', 'exit'): break | 1834 if args[0] in ('quit', 'exit'): break # noqa: E701 |
| 1811 self.run_command(args) | 1835 self.run_command(args) |
| 1812 | 1836 |
| 1813 # exit.. check for transactions | 1837 # exit.. check for transactions |
| 1814 if self.db and self.db_uncommitted: | 1838 if self.db and self.db_uncommitted: |
| 1815 commit = my_input(_('There are unsaved changes. Commit them (y/N)? ')) | 1839 commit = my_input(_('There are unsaved changes. Commit them (y/N)? ')) |
| 1877 try: | 1901 try: |
| 1878 if not args: | 1902 if not args: |
| 1879 self.interactive() | 1903 self.interactive() |
| 1880 else: | 1904 else: |
| 1881 ret = self.run_command(args) | 1905 ret = self.run_command(args) |
| 1882 if self.db: self.db.commit() | 1906 if self.db: self.db.commit() # noqa: E701 |
| 1883 return ret | 1907 return ret |
| 1884 finally: | 1908 finally: |
| 1885 if self.db: | 1909 if self.db: |
| 1886 self.db.close() | 1910 self.db.close() |
| 1887 | 1911 |
