Mercurial > p > roundup > code
comparison roundup/admin.py @ 6585:d4371b131c9c
flake 8 improvements
Renamed some variables from l to something (I hope) more descriptive.
Left a number of long lines and unindented quoted ''' string blocks.
The blocks are often inside a _() translation function call. Adding
white space to indent them would mess up the translation tables
and require reformatting as they are output. I might be able to
reformat:
_(
''' message for the
user here on multiple lines'''
)
as separate concatenated lines and preserve the translation key but...
| author | John Rouillard <rouilj@ieee.org> |
|---|---|
| date | Sun, 16 Jan 2022 12:54:26 -0500 |
| parents | 8687c096a945 |
| children | 408fd477761f |
comparison
equal
deleted
inserted
replaced
| 6584:770503bd211e | 6585:d4371b131c9c |
|---|---|
| 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, os, re, shutil, sys, operator | 26 import csv, getopt, getpass, operator, os, re, shutil, sys |
| 27 | 27 |
| 28 from roundup import date, hyperdb, init, password, token | 28 from roundup import date, hyperdb, init, password, token |
| 29 from roundup import __version__ as roundup_version | 29 from roundup import __version__ as roundup_version |
| 30 import roundup.instance | 30 import roundup.instance |
| 31 from roundup.configuration import (CoreConfig, NoConfigError, | 31 from roundup.configuration import (CoreConfig, NoConfigError, |
| 50 | 50 |
| 51 def get(self, key, default=_marker): | 51 def get(self, key, default=_marker): |
| 52 if key in self.data: | 52 if key in self.data: |
| 53 return [(key, self.data[key])] | 53 return [(key, self.data[key])] |
| 54 keylist = sorted(self.data) | 54 keylist = sorted(self.data) |
| 55 l = [] | 55 matching_keys = [] |
| 56 for ki in keylist: | 56 for ki in keylist: |
| 57 if ki.startswith(key): | 57 if ki.startswith(key): |
| 58 l.append((ki, self.data[ki])) | 58 matching_keys.append((ki, self.data[ki])) |
| 59 if not l and default is self._marker: | 59 if not matching_keys and default is self._marker: |
| 60 raise KeyError(key) | 60 raise KeyError(key) |
| 61 return l | 61 # FIXME: what happens if default is not self._marker but |
| 62 # there are no matching keys? Should (default, self.data[default]) | |
| 63 # be returned??? | |
| 64 return matching_keys | |
| 62 | 65 |
| 63 | 66 |
| 64 class AdminTool: | 67 class AdminTool: |
| 65 """ A collection of methods used in maintaining Roundup trackers. | 68 """ A collection of methods used in maintaining Roundup trackers. |
| 66 | 69 |
| 100 | 103 |
| 101 The args list is specified as ``prop=value prop=value ...``. | 104 The args list is specified as ``prop=value prop=value ...``. |
| 102 """ | 105 """ |
| 103 props = {} | 106 props = {} |
| 104 for arg in args: | 107 for arg in args: |
| 105 l = arg.split('=', 1) | 108 key_val = arg.split('=', 1) |
| 106 # if = not in string, will return one element | 109 # if = not in string, will return one element |
| 107 if len(l) < 2: | 110 if len(key_val) < 2: |
| 108 raise UsageError(_('argument "%(arg)s" not propname=value') % | 111 raise UsageError(_('argument "%(arg)s" not propname=value') % |
| 109 locals()) | 112 locals()) |
| 110 key, value = l | 113 key, value = key_val |
| 111 if value: | 114 if value: |
| 112 props[key] = value | 115 props[key] = value |
| 113 else: | 116 else: |
| 114 props[key] = None | 117 props[key] = None |
| 115 return props | 118 return props |
| 116 | 119 |
| 117 def usage(self, message=''): | 120 def usage(self, message=''): |
| 118 """ Display a simple usage message. | 121 """ Display a simple usage message. |
| 119 """ | 122 """ |
| 120 if message: | 123 if message: |
| 121 message = _('Problem: %(message)s\n\n')% locals() | 124 message = _('Problem: %(message)s\n\n') % locals() |
| 122 sys.stdout.write(_("""%(message)sUsage: roundup-admin [options] [<command> <arguments>] | 125 sys.stdout.write(_("""%(message)sUsage: roundup-admin [options] [<command> <arguments>] |
| 123 | 126 |
| 124 Options: | 127 Options: |
| 125 -i instance home -- specify the issue tracker "home directory" to administer | 128 -i instance home -- specify the issue tracker "home directory" to administer |
| 126 -u -- the user[:password] to use for commands (default admin) | 129 -u -- the user[:password] to use for commands (default admin) |
| 266 self.help[topic]() | 269 self.help[topic]() |
| 267 return 0 | 270 return 0 |
| 268 | 271 |
| 269 # try command docstrings | 272 # try command docstrings |
| 270 try: | 273 try: |
| 271 l = self.commands.get(topic) | 274 cmd_docs = self.commands.get(topic) |
| 272 except KeyError: | 275 except KeyError: |
| 273 print(_('Sorry, no help for "%(topic)s"') % locals()) | 276 print(_('Sorry, no help for "%(topic)s"') % locals()) |
| 274 return 1 | 277 return 1 |
| 275 | 278 |
| 276 # display the help for each match, removing the docstring indent | 279 # display the help for each match, removing the docstring indent |
| 277 for _name, help in l: | 280 for _name, help in cmd_docs: |
| 278 lines = nl_re.split(_(help.__doc__)) | 281 lines = nl_re.split(_(help.__doc__)) |
| 279 print(lines[0]) | 282 print(lines[0]) |
| 280 indent = indent_re.match(lines[1]) | 283 indent = indent_re.match(lines[1]) |
| 281 if indent: indent = len(indent.group(1)) | 284 if indent: indent = len(indent.group(1)) |
| 282 for line in lines[1:]: | 285 for line in lines[1:]: |
| 337 # __file__ should be something like: | 340 # __file__ should be something like: |
| 338 # /usr/local/lib/python3.10/site-packages/roundup/admin.py | 341 # /usr/local/lib/python3.10/site-packages/roundup/admin.py |
| 339 # os.prefix should be /usr, /usr/local or root of virtualenv | 342 # os.prefix should be /usr, /usr/local or root of virtualenv |
| 340 # strip leading / to make os.path.join work right. | 343 # strip leading / to make os.path.join work right. |
| 341 path = __file__ | 344 path = __file__ |
| 342 for N in 1, 2: | 345 for _N in 1, 2: |
| 343 path = os.path.dirname(path) | 346 path = os.path.dirname(path) |
| 344 # path is /usr/local/lib/python3.10/site-packages | 347 # path is /usr/local/lib/python3.10/site-packages |
| 345 tdir = os.path.join(path, sys.prefix[1:], 'share', | 348 tdir = os.path.join(path, sys.prefix[1:], 'share', |
| 346 'roundup', 'templates') | 349 'roundup', 'templates') |
| 347 if os.path.isdir(tdir): | 350 if os.path.isdir(tdir): |
| 348 templates.update(init.listTemplates(tdir)) | 351 templates.update(init.listTemplates(tdir)) |
| 349 | 352 |
| 350 # OK, now try as if we're in the roundup source distribution | 353 # OK, now try as if we're in the roundup source distribution |
| 351 # directory, so this module will be in .../roundup-*/roundup/admin.py | 354 # directory, so this module will be in .../roundup-*/roundup/admin.py |
| 352 # and we're interested in the .../roundup-*/ part. | 355 # and we're interested in the .../roundup-*/ part. |
| 353 path = __file__ | 356 path = __file__ |
| 354 for _i in range(2): | 357 for _i in range(2): |
| 456 | 459 |
| 457 # load config_ini.ini from template if it exists. | 460 # load config_ini.ini from template if it exists. |
| 458 # it sets parameters like template_engine that are | 461 # it sets parameters like template_engine that are |
| 459 # template specific. | 462 # template specific. |
| 460 template_config = UserConfig(templates[template]['path'] + | 463 template_config = UserConfig(templates[template]['path'] + |
| 461 "/config_ini.ini") | 464 "/config_ini.ini") |
| 462 for k in template_config.keys(): | 465 for k in template_config.keys(): |
| 463 if k == 'HOME': # ignore home. It is a default param. | 466 if k == 'HOME': # ignore home. It is a default param. |
| 464 continue | 467 continue |
| 465 defns[k] = template_config[k] | 468 defns[k] = template_config[k] |
| 466 | 469 |
| 604 """ | 607 """ |
| 605 if len(args) < 2: | 608 if len(args) < 2: |
| 606 raise UsageError(_('Not enough arguments supplied')) | 609 raise UsageError(_('Not enough arguments supplied')) |
| 607 propname = args[0] | 610 propname = args[0] |
| 608 designators = args[1].split(',') | 611 designators = args[1].split(',') |
| 609 l = [] | 612 linked_props = [] |
| 610 for designator in designators: | 613 for designator in designators: |
| 611 # decode the node designator | 614 # decode the node designator |
| 612 try: | 615 try: |
| 613 classname, nodeid = hyperdb.splitDesignator(designator) | 616 classname, nodeid = hyperdb.splitDesignator(designator) |
| 614 except hyperdb.DesignatorError as message: | 617 except hyperdb.DesignatorError as message: |
| 640 ' Multilink or Link so -d flag does not ' | 643 ' Multilink or Link so -d flag does not ' |
| 641 'apply.') % propname) | 644 'apply.') % propname) |
| 642 propclassname = self.db.getclass(property.classname).classname | 645 propclassname = self.db.getclass(property.classname).classname |
| 643 id = cl.get(nodeid, propname) | 646 id = cl.get(nodeid, propname) |
| 644 for i in id: | 647 for i in id: |
| 645 l.append(propclassname + i) | 648 linked_props.append(propclassname + i) |
| 646 else: | 649 else: |
| 647 id = cl.get(nodeid, propname) | 650 id = cl.get(nodeid, propname) |
| 648 for i in id: | 651 for i in id: |
| 649 l.append(i) | 652 linked_props.append(i) |
| 650 else: | 653 else: |
| 651 if self.print_designator: | 654 if self.print_designator: |
| 652 properties = cl.getprops() | 655 properties = cl.getprops() |
| 653 property = properties[propname] | 656 property = properties[propname] |
| 654 if not (isinstance(property, hyperdb.Multilink) or | 657 if not (isinstance(property, hyperdb.Multilink) or |
| 667 '"%(nodeid)s"') % locals()) | 670 '"%(nodeid)s"') % locals()) |
| 668 except KeyError: | 671 except KeyError: |
| 669 raise UsageError(_('no such %(classname)s property ' | 672 raise UsageError(_('no such %(classname)s property ' |
| 670 '"%(propname)s"') % locals()) | 673 '"%(propname)s"') % locals()) |
| 671 if self.separator: | 674 if self.separator: |
| 672 print(self.separator.join(l)) | 675 print(self.separator.join(linked_props)) |
| 673 | 676 |
| 674 return 0 | 677 return 0 |
| 675 | 678 |
| 676 def do_set(self, args): | 679 def do_set(self, args): |
| 677 ''"""Usage: set items property=value property=value ... | 680 ''"""Usage: set items property=value property=value ... |
| 764 # multiple , separated values become a list | 767 # multiple , separated values become a list |
| 765 for propname, value in props.items(): | 768 for propname, value in props.items(): |
| 766 if ',' in value: | 769 if ',' in value: |
| 767 values = value.split(',') | 770 values = value.split(',') |
| 768 else: | 771 else: |
| 769 values = [ value ] | 772 values = [value] |
| 770 | 773 |
| 771 props[propname] = [] | 774 props[propname] = [] |
| 772 # start handling transitive props | 775 # start handling transitive props |
| 773 # given filter issue assignedto.roles=Admin | 776 # given filter issue assignedto.roles=Admin |
| 774 # start at issue | 777 # start at issue |
| 775 curclass = cl | 778 curclass = cl |
| 776 lastprop = propname # handle case 'issue assignedto=admin' | 779 lastprop = propname # handle case 'issue assignedto=admin' |
| 777 if '.' in propname: | 780 if '.' in propname: |
| 778 # start splitting transitive prop into components | 781 # start splitting transitive prop into components |
| 779 # we end when we have no more links | 782 # we end when we have no more links |
| 780 for pn in propname.split('.'): | 783 for pn in propname.split('.'): |
| 781 try: | 784 try: |
| 782 lastprop=pn # get current component | 785 lastprop = pn # get current component |
| 783 # get classname for this link | 786 # get classname for this link |
| 784 try: | 787 try: |
| 785 curclassname = curclass.getprops()[pn].classname | 788 curclassname = curclass.getprops()[pn].classname |
| 786 except KeyError: | 789 except KeyError: |
| 787 raise UsageError(_("Class %(curclassname)s has " | 790 raise UsageError(_("Class %(curclassname)s has " |
| 800 | 803 |
| 801 # now do the filter | 804 # now do the filter |
| 802 try: | 805 try: |
| 803 id = [] | 806 id = [] |
| 804 designator = [] | 807 designator = [] |
| 805 props = { "filterspec": props } | 808 props = {"filterspec": props} |
| 806 | 809 |
| 807 if self.separator: | 810 if self.separator: |
| 808 if self.print_designator: | 811 if self.print_designator: |
| 809 id = cl.filter(None, **props) | 812 id = cl.filter(None, **props) |
| 810 for i in id: | 813 for i in id: |
| 988 | 991 |
| 989 # convert types | 992 # convert types |
| 990 for propname in props: | 993 for propname in props: |
| 991 try: | 994 try: |
| 992 props[propname] = hyperdb.rawToHyperdb(self.db, cl, None, | 995 props[propname] = hyperdb.rawToHyperdb(self.db, cl, None, |
| 993 propname, props[propname]) | 996 propname, props[propname]) |
| 994 except hyperdb.HyperdbValueError as message: | 997 except hyperdb.HyperdbValueError as message: |
| 995 raise UsageError(message) | 998 raise UsageError(message) |
| 996 | 999 |
| 997 # check for the key property | 1000 # check for the key property |
| 998 propname = cl.getkey() | 1001 propname = cl.getkey() |
| 999 if propname and propname not in props: | 1002 if propname and propname not in props: |
| 1000 raise UsageError(_('you must provide the "%(propname)s" ' | 1003 raise UsageError(_('you must provide the "%(propname)s" ' |
| 1001 'property.') % locals()) | 1004 'property.') % locals()) |
| 1002 | 1005 |
| 1003 # do the actual create | 1006 # do the actual create |
| 1004 try: | 1007 try: |
| 1005 sys.stdout.write(cl.create(**props) + '\n') | 1008 sys.stdout.write(cl.create(**props) + '\n') |
| 1006 except (TypeError, IndexError, ValueError) as message: | 1009 except (TypeError, IndexError, ValueError) as message: |
| 1120 props = [] | 1123 props = [] |
| 1121 for spec in prop_names: | 1124 for spec in prop_names: |
| 1122 if ':' in spec: | 1125 if ':' in spec: |
| 1123 name, width = spec.split(':') | 1126 name, width = spec.split(':') |
| 1124 if width == '': | 1127 if width == '': |
| 1125 # spec includes trailing :, use label/name width | 1128 # spec includes trailing :, use label/name width |
| 1126 props.append((name, len(name))) | 1129 props.append((name, len(name))) |
| 1127 else: | 1130 else: |
| 1128 try: | 1131 try: |
| 1129 props.append((name, int(width))) | 1132 props.append((name, int(width))) |
| 1130 except ValueError: | 1133 except ValueError: |
| 1144 print(' '.join([name.capitalize().ljust(width) | 1147 print(' '.join([name.capitalize().ljust(width) |
| 1145 for name, width in props])) | 1148 for name, width in props])) |
| 1146 | 1149 |
| 1147 # and the table data | 1150 # and the table data |
| 1148 for nodeid in cl.list(): | 1151 for nodeid in cl.list(): |
| 1149 l = [] | 1152 table_columns = [] |
| 1150 for name, width in props: | 1153 for name, width in props: |
| 1151 if name != 'id': | 1154 if name != 'id': |
| 1152 try: | 1155 try: |
| 1153 value = str(cl.get(nodeid, name)) | 1156 value = str(cl.get(nodeid, name)) |
| 1154 except KeyError: | 1157 except KeyError: |
| 1157 # value for it | 1160 # value for it |
| 1158 value = '' | 1161 value = '' |
| 1159 else: | 1162 else: |
| 1160 value = str(nodeid) | 1163 value = str(nodeid) |
| 1161 f = '%%-%ds' % width | 1164 f = '%%-%ds' % width |
| 1162 l.append(f % value[:width]) | 1165 table_columns.append(f % value[:width]) |
| 1163 print(' '.join(l)) | 1166 print(' '.join(table_columns)) |
| 1164 return 0 | 1167 return 0 |
| 1165 | 1168 |
| 1166 def do_history(self, args): | 1169 def do_history(self, args): |
| 1167 ''"""Usage: history designator [skipquiet] | 1170 ''"""Usage: history designator [skipquiet] |
| 1168 Show the history entries of a designator. | 1171 Show the history entries of a designator. |
| 1280 dbclass.restore(nodeid) | 1283 dbclass.restore(nodeid) |
| 1281 except KeyError as e: | 1284 except KeyError as e: |
| 1282 raise UsageError(e.args[0]) | 1285 raise UsageError(e.args[0]) |
| 1283 except IndexError: | 1286 except IndexError: |
| 1284 raise UsageError(_('no such %(classname)s node ' | 1287 raise UsageError(_('no such %(classname)s node ' |
| 1285 '" % (nodeid)s"')%locals()) | 1288 '" % (nodeid)s"') % locals()) |
| 1286 self.db_uncommitted = True | 1289 self.db_uncommitted = True |
| 1287 return 0 | 1290 return 0 |
| 1288 | 1291 |
| 1289 def do_export(self, args, export_files=True): | 1292 def do_export(self, args, export_files=True): |
| 1290 ''"""Usage: export [[-]class[,class]] export_dir | 1293 ''"""Usage: export [[-]class[,class]] export_dir |
| 1307 | 1310 |
| 1308 # get the list of classes to export | 1311 # get the list of classes to export |
| 1309 if len(args) == 2: | 1312 if len(args) == 2: |
| 1310 if args[0].startswith('-'): | 1313 if args[0].startswith('-'): |
| 1311 classes = [c for c in self.db.classes | 1314 classes = [c for c in self.db.classes |
| 1312 if c not in args[0][1:].split(',')] | 1315 if c not in args[0][1:].split(',')] |
| 1313 else: | 1316 else: |
| 1314 classes = args[0].split(',') | 1317 classes = args[0].split(',') |
| 1315 else: | 1318 else: |
| 1316 classes = self.db.classes | 1319 classes = self.db.classes |
| 1317 | 1320 |
| 1329 for classname in classes: | 1332 for classname in classes: |
| 1330 cl = self.get_class(classname) | 1333 cl = self.get_class(classname) |
| 1331 | 1334 |
| 1332 if not export_files and hasattr(cl, 'export_files'): | 1335 if not export_files and hasattr(cl, 'export_files'): |
| 1333 sys.stdout.write('Exporting %s WITHOUT the files\r\n' % | 1336 sys.stdout.write('Exporting %s WITHOUT the files\r\n' % |
| 1334 classname) | 1337 classname) |
| 1335 | 1338 |
| 1336 with open(os.path.join(dir, classname+'.csv'), 'w') as f: | 1339 with open(os.path.join(dir, classname+'.csv'), 'w') as f: |
| 1337 writer = csv.writer(f, colon_separated) | 1340 writer = csv.writer(f, colon_separated) |
| 1338 | 1341 |
| 1339 properties = cl.getprops() | |
| 1340 propnames = cl.export_propnames() | 1342 propnames = cl.export_propnames() |
| 1341 fields = propnames[:] | 1343 fields = propnames[:] |
| 1342 fields.append('is retired') | 1344 fields.append('is retired') |
| 1343 writer.writerow(fields) | 1345 writer.writerow(fields) |
| 1344 | 1346 |
| 1350 # _class.__retired__, _<class>._<keyname> | 1352 # _class.__retired__, _<class>._<keyname> |
| 1351 # on imports to rdbms. | 1353 # on imports to rdbms. |
| 1352 all_nodes = cl.getnodeids() | 1354 all_nodes = cl.getnodeids() |
| 1353 | 1355 |
| 1354 classkey = cl.getkey() | 1356 classkey = cl.getkey() |
| 1355 if classkey: # False sorts before True, so negate is_retired | 1357 if classkey: # False sorts before True, so negate is_retired |
| 1356 keysort = lambda i: (cl.get(i, classkey), | 1358 keysort = lambda i: (cl.get(i, classkey), |
| 1357 not cl.is_retired(i)) | 1359 not cl.is_retired(i)) |
| 1358 all_nodes.sort(key=keysort) | 1360 all_nodes.sort(key=keysort) |
| 1359 # if there is no classkey no need to sort | 1361 # if there is no classkey no need to sort |
| 1360 | 1362 |
| 1361 for nodeid in all_nodes: | 1363 for nodeid in all_nodes: |
| 1362 if self.verbose: | 1364 if self.verbose: |
| 1363 sys.stdout.write('\rExporting %s - %s' % | 1365 sys.stdout.write('\rExporting %s - %s' % |
| 1364 (classname, nodeid)) | 1366 (classname, nodeid)) |
| 1365 sys.stdout.flush() | 1367 sys.stdout.flush() |
| 1366 node = cl.getnode(nodeid) | 1368 node = cl.getnode(nodeid) |
| 1367 exp = cl.export_list(propnames, nodeid) | 1369 exp = cl.export_list(propnames, nodeid) |
| 1368 lensum = sum([len(repr_export(node[p])) for p in propnames]) | 1370 lensum = sum([len(repr_export(node[p])) for |
| 1371 p in propnames]) | |
| 1369 # for a safe upper bound of field length we add | 1372 # for a safe upper bound of field length we add |
| 1370 # difference between CSV len and sum of all field lengths | 1373 # difference between CSV len and sum of all field lengths |
| 1371 d = sum([len(x) for x in exp]) - lensum | 1374 d = sum([len(x) for x in exp]) - lensum |
| 1372 if not d > 0: | 1375 if not d > 0: |
| 1373 raise AssertionError("Bad assertion d > 0") | 1376 raise AssertionError("Bad assertion d > 0") |
| 1380 cl.export_files(dir, nodeid) | 1383 cl.export_files(dir, nodeid) |
| 1381 | 1384 |
| 1382 # export the journals | 1385 # export the journals |
| 1383 with open(os.path.join(dir, classname+'-journals.csv'), 'w') as jf: | 1386 with open(os.path.join(dir, classname+'-journals.csv'), 'w') as jf: |
| 1384 if self.verbose: | 1387 if self.verbose: |
| 1385 sys.stdout.write("\nExporting Journal for %s\n" % classname) | 1388 sys.stdout.write("\nExporting Journal for %s\n" % |
| 1389 classname) | |
| 1386 sys.stdout.flush() | 1390 sys.stdout.flush() |
| 1387 journals = csv.writer(jf, colon_separated) | 1391 journals = csv.writer(jf, colon_separated) |
| 1388 for row in cl.export_journals(): | 1392 for row in cl.export_journals(): |
| 1389 journals.writerow(row) | 1393 journals.writerow(row) |
| 1390 if max_len > self.db.config.CSV_FIELD_SIZE: | 1394 if max_len > self.db.config.CSV_FIELD_SIZE: |
| 1663 try: | 1667 try: |
| 1664 functions = self.commands.get(command) | 1668 functions = self.commands.get(command) |
| 1665 except KeyError: | 1669 except KeyError: |
| 1666 # not a valid command | 1670 # not a valid command |
| 1667 print(_('Unknown command "%(command)s" ("help commands" for a ' | 1671 print(_('Unknown command "%(command)s" ("help commands" for a ' |
| 1668 'list)') % locals()) | 1672 'list)') % locals()) |
| 1669 return 1 | 1673 return 1 |
| 1670 | 1674 |
| 1671 # check for multiple matches | 1675 # check for multiple matches |
| 1672 if len(functions) > 1: | 1676 if len(functions) > 1: |
| 1673 print(_('Multiple commands match "%(command)s": %(list)s') % \ | 1677 print(_('Multiple commands match "%(command)s": %(list)s') % |
| 1674 {'command': command, | 1678 {'command': command, |
| 1675 'list': ', '.join([i[0] for i in functions])}) | 1679 'list': ', '.join([i[0] for i in functions])}) |
| 1676 return 1 | 1680 return 1 |
| 1677 command, function = functions[0] | 1681 command, function = functions[0] |
| 1678 | 1682 |
| 1706 return 1 | 1710 return 1 |
| 1707 except NoConfigError as message: # noqa: F841 | 1711 except NoConfigError as message: # noqa: F841 |
| 1708 self.tracker_home = '' | 1712 self.tracker_home = '' |
| 1709 print(_("Error: Couldn't open tracker: %(message)s") % locals()) | 1713 print(_("Error: Couldn't open tracker: %(message)s") % locals()) |
| 1710 return 1 | 1714 return 1 |
| 1711 except ParsingOptionError as message: | 1715 except ParsingOptionError as message: # message used via locals |
| 1712 print("%(message)s" % locals()) | 1716 print("%(message)s" % locals()) |
| 1713 return 1 | 1717 return 1 |
| 1714 | 1718 |
| 1715 # only open the database once! | 1719 # only open the database once! |
| 1716 if not self.db: | 1720 if not self.db: |
| 1775 # handle command-line args | 1779 # handle command-line args |
| 1776 self.tracker_home = os.environ.get('TRACKER_HOME', '') | 1780 self.tracker_home = os.environ.get('TRACKER_HOME', '') |
| 1777 self.name = 'admin' | 1781 self.name = 'admin' |
| 1778 self.password = '' # unused | 1782 self.password = '' # unused |
| 1779 if 'ROUNDUP_LOGIN' in os.environ: | 1783 if 'ROUNDUP_LOGIN' in os.environ: |
| 1780 l = os.environ['ROUNDUP_LOGIN'].split(':') | 1784 login_env = os.environ['ROUNDUP_LOGIN'].split(':') |
| 1781 self.name = l[0] | 1785 self.name = login_env[0] |
| 1782 if len(l) > 1: | 1786 if len(login_env) > 1: |
| 1783 self.password = l[1] | 1787 self.password = login_env[1] |
| 1784 self.separator = None | 1788 self.separator = None |
| 1785 self.print_designator = 0 | 1789 self.print_designator = 0 |
| 1786 self.verbose = 0 | 1790 self.verbose = 0 |
| 1787 for opt, arg in opts: | 1791 for opt, arg in opts: |
| 1788 if opt == '-h': | 1792 if opt == '-h': |
| 1812 return 1 | 1816 return 1 |
| 1813 self.separator = ' ' | 1817 self.separator = ' ' |
| 1814 elif opt == '-d': | 1818 elif opt == '-d': |
| 1815 self.print_designator = 1 | 1819 self.print_designator = 1 |
| 1816 elif opt == '-u': | 1820 elif opt == '-u': |
| 1817 l = arg.split(':') | 1821 login_opt = arg.split(':') |
| 1818 self.name = l[0] | 1822 self.name = login_opt[0] |
| 1819 if len(l) > 1: | 1823 if len(login_opt) > 1: |
| 1820 self.password = l[1] | 1824 self.password = login_opt[1] |
| 1821 | 1825 |
| 1822 # if no command - go interactive | 1826 # if no command - go interactive |
| 1823 # wrap in a try/finally so we always close off the db | 1827 # wrap in a try/finally so we always close off the db |
| 1824 ret = 0 | 1828 ret = 0 |
| 1825 try: | 1829 try: |
