From a512c9d5ebf2f19f044aaa700e1fb78440b7abb9 Mon Sep 17 00:00:00 2001 From: Paul Franklin Date: Mon, 25 Jul 2016 12:56:56 -0700 Subject: [PATCH] improve pylint score on some CLI files cli/arghandler.py went from 8.30 to 9.52 cli/argparser.py went from 8.43 to 9.74 cli/grampscli.py went from 7.99 to 9.29 cli/plug/__init__.py went from 7.63 to 9.69 --- gramps/cli/arghandler.py | 185 ++++++++++++++------------- gramps/cli/argparser.py | 117 +++++++++-------- gramps/cli/grampscli.py | 68 +++++----- gramps/cli/plug/__init__.py | 247 ++++++++++++++++++++---------------- 4 files changed, 338 insertions(+), 279 deletions(-) diff --git a/gramps/cli/arghandler.py b/gramps/cli/arghandler.py index 407c4c605..23bd30418 100644 --- a/gramps/cli/arghandler.py +++ b/gramps/cli/arghandler.py @@ -117,7 +117,7 @@ def _split_options(options_str): #print char, "This character ends the list" in_list = False value += char - elif not in_quotes and ( char == '"' or char == "'"): + elif not in_quotes and (char == '"' or char == "'"): #print char, "This character starts a quoted string" in_quotes = True quote_type = char @@ -155,9 +155,9 @@ class ArgHandler: """ def __init__(self, dbstate, parser, sessionmanager, - errorfunc=None, gui=False): + errorfunc=None, gui=False): self.dbstate = dbstate - self.sm = sessionmanager + self.smgr = sessionmanager self.errorfunc = errorfunc self.gui = gui self.user = sessionmanager.user @@ -176,7 +176,7 @@ class ArgHandler: self.imp_db_path = None self.dbman = CLIDbManager(self.dbstate) self.force_unlock = parser.force_unlock - self.cl = 0 + self.cl_bool = False self.imports = [] self.exports = [] self.removes = parser.removes @@ -221,22 +221,25 @@ class ArgHandler: # We have a potential database path. # Check if it is good. if not self.check_db(db_path, self.force_unlock): - sys.exit(0) + sys.exit(1) if create: - self.__error( _("Error: Family Tree '%s' already exists.\n" - "The '-C' option cannot be used.") % value) - sys.exit(0) + self.__error(_("Error: Family Tree '%s' already exists.\n" + "The '-C' option cannot be used." + ) % value) + sys.exit(1) return db_path elif create: # create the tree here, and continue dbid = config.get('database.backend') - db_path, title = self.dbman.create_new_db_cli(title=value, dbid=dbid) + db_path, title = self.dbman.create_new_db_cli(title=value, + dbid=dbid) return db_path else: - self.__error( _('Error: Input Family Tree "%s" does not exist.\n' - "If GEDCOM, Gramps-xml or grdb, use the -i option " - "to import into a Family Tree instead.") % value) - sys.exit(0) + self.__error(_('Error: Input Family Tree "%s" does not exist.\n' + "If GEDCOM, Gramps-xml or grdb, use the -i option " + "to import into a Family Tree instead." + ) % value) + sys.exit(1) def __handle_import_option(self, value, family_tree_format): """ @@ -247,7 +250,7 @@ class ArgHandler: fullpath = os.path.abspath(os.path.expanduser(fname)) if fname != '-' and not os.path.exists(fullpath): self.__error(_('Error: Import file %s not found.') % fname) - sys.exit(0) + sys.exit(1) if family_tree_format is None: # Guess the file format based on the file extension. @@ -265,10 +268,10 @@ class ArgHandler: self.imports.append((fname, family_tree_format)) else: self.__error(_('Error: Unrecognized type: "%(format)s" for ' - 'import file: %(filename)s') % - {'format' : family_tree_format, - 'filename' : fname}) - sys.exit(0) + 'import file: %(filename)s' + ) % {'format' : family_tree_format, + 'filename' : fname}) + sys.exit(1) def __handle_export_option(self, value, family_tree_format): """ @@ -286,14 +289,15 @@ class ArgHandler: if os.path.exists(fullpath): message = _("WARNING: Output file already exists!\n" "WARNING: It will be overwritten:\n %s" - ) % fullpath + ) % fullpath accepted = self.user.prompt(_('OK to overwrite?'), message, - _('yes'), _('no'), default_label=_('yes')) + _('yes'), _('no'), + default_label=_('yes')) if accepted: - self.__error(_("Will overwrite the existing file: %s") - % fullpath) + self.__error(_("Will overwrite the existing file: %s" + ) % fullpath) else: - sys.exit(0) + sys.exit(1) if family_tree_format is None: # Guess the file format based on the file extension. @@ -310,9 +314,9 @@ class ArgHandler: if plugin_found: self.exports.append((fullpath, family_tree_format)) else: - self.__error(_("ERROR: Unrecognized format for export file %s") - % fname) - sys.exit(0) + self.__error(_("ERROR: Unrecognized format for export file %s" + ) % fname) + sys.exit(1) def __deduce_db_path(self, db_name_or_path): """ @@ -361,12 +365,13 @@ class ArgHandler: if not db_path: # Apparently it is not a database. See if it is a file that # can be imported. - db_path, title = self.dbman.import_new_db(self.open_gui, self.user) + db_path, title = self.dbman.import_new_db(self.open_gui, + self.user) if db_path: # Test if not locked or problematic if not self.check_db(db_path, self.force_unlock): - sys.exit(0) + sys.exit(1) # Add the file to the recent items title = self.dbstate.db.get_dbname() if not title: @@ -375,7 +380,7 @@ class ArgHandler: self.open = db_path self.__open_action() else: - sys.exit(0) + sys.exit(1) return db_path # if not open_gui, parse any command line args. We can only have one @@ -398,12 +403,13 @@ class ArgHandler: for name, dirname in sorted(self.dbman.family_tree_list(), key=lambda pair: pair[0].lower()): - if (self.database_names is None or - any([(re.match("^" + dbname + "$", name) or - dbname == name) - for dbname in self.database_names])): - print(_("%(full_DB_path)s with name \"%(f_t_name)s\"") - % {'full_DB_path' : dirname, 'f_t_name' : name}) + if (self.database_names is None + or any([(re.match("^" + dbname + "$", name) + or dbname == name) + for dbname in self.database_names])): + print(_('%(full_DB_path)s with name "%(f_t_name)s"' + ) % {'full_DB_path' : dirname, + 'f_t_name' : name}) return # Handle the "--remove" Family Tree @@ -427,11 +433,12 @@ class ArgHandler: # insertion of blank spaces when print on the same line is used line_list = [_("Family Tree")] for key in sorted(summary_list[0]): - if key != _("Family Tree"): + if key != _("Family Tree"): line_list += [key] print("\t".join(line_list)) for summary in sorted(summary_list, - key=lambda sum: sum[_("Family Tree")].lower()): + key=lambda + sum: sum[_("Family Tree")].lower()): line_list = [(_('"%s"') % summary[_("Family Tree")])] for item in sorted(summary): if item != _("Family Tree"): @@ -444,22 +451,27 @@ class ArgHandler: self.__import_action() for (action, op_string) in self.actions: - print(_("Performing action: %s.") % action, file=sys.stderr) + print(_("Performing action: %s." + ) % action, + file=sys.stderr) if op_string: - print(_("Using options string: %s") - % op_string, file=sys.stderr) + print(_("Using options string: %s" + ) % op_string, + file=sys.stderr) self.cl_action(action, op_string) for expt in self.exports: - print(_("Exporting: file %(filename)s, format %(format)s.") - % {'filename' : expt[0], - 'format' : expt[1]}, file=sys.stderr) + print(_("Exporting: file %(filename)s, format %(format)s." + ) % {'filename' : expt[0], + 'format' : expt[1]}, + file=sys.stderr) self.cl_export(expt[0], expt[1]) if cleanup: self.cleanup() def cleanup(self): + """ clean up any remaining files """ print(_("Cleaning up."), file=sys.stderr) # remove files in import db subdir after use self.dbstate.db.close() @@ -478,13 +490,14 @@ class ArgHandler: have happened that is now finished), if this is GUI, it is opened. """ if self.imports: - self.cl = bool(self.exports or self.actions or self.cl) + self.cl_bool = bool(self.exports or self.actions or self.cl_bool) if not self.open: # Create empty dir for imported database(s) if self.gui: dbid = config.get('database.backend') - self.imp_db_path, title = self.dbman.create_new_db_cli(dbid=dbid) + self.imp_db_path, title = self.dbman.create_new_db_cli( + dbid=dbid) else: self.imp_db_path = get_empty_tempdir("import_dbdir") dbid = config.get('database.backend') @@ -492,17 +505,18 @@ class ArgHandler: newdb.write_version(self.imp_db_path) try: - self.sm.open_activate(self.imp_db_path) + self.smgr.open_activate(self.imp_db_path) msg = _("Created empty Family Tree successfully") print(msg, file=sys.stderr) except: print(_("Error opening the file."), file=sys.stderr) print(_("Exiting..."), file=sys.stderr) - sys.exit(0) + sys.exit(1) for imp in self.imports: - msg = _("Importing: file %(filename)s, format %(format)s.") % \ - {'filename' : imp[0], 'format' : imp[1]} + msg = _("Importing: file %(filename)s, format %(format)s." + ) % {'filename' : imp[0], + 'format' : imp[1]} print(msg, file=sys.stderr) self.cl_import(imp[0], imp[1]) @@ -514,18 +528,18 @@ class ArgHandler: if self.open: # Family Tree to open was given. Open it # Then go on and process the rest of the command line arguments. - self.cl = bool(self.exports or self.actions) + self.cl_bool = bool(self.exports or self.actions) # we load this file for use try: - self.sm.open_activate(self.open) + self.smgr.open_activate(self.open) print(_("Opened successfully!"), file=sys.stderr) except: print(_("Error opening the file."), file=sys.stderr) print(_("Exiting..."), file=sys.stderr) - sys.exit(0) + sys.exit(1) - def check_db(self, dbpath, force_unlock = False): + def check_db(self, dbpath, force_unlock=False): """ Test a given family tree path if it can be opened. """ @@ -537,7 +551,7 @@ class ArgHandler: _(" Info: %s")) % find_locker_name(dbpath)) return False if self.dbman.needs_recovery(dbpath): - self.__error( _("Database needs recovery, cannot open it!")) + self.__error(_("Database needs recovery, cannot open it!")) return False return True @@ -589,7 +603,7 @@ class ArgHandler: except: options_str_dict = {} print(_("Ignoring invalid options string."), - file=sys.stderr) + file=sys.stderr) name = options_str_dict.pop('name', None) _cl_list = pmgr.get_reg_reports(gui=False) @@ -615,29 +629,30 @@ class ArgHandler: msg = _("Unknown report name.") else: msg = _("Report name not given. " - "Please use one of %(donottranslate)s=reportname") % \ - {'donottranslate' : '[-p|--options] name'} + "Please use one of %(donottranslate)s=reportname" + ) % {'donottranslate' : '[-p|--options] name'} print(_("%s\n Available names are:") % msg, file=sys.stderr) - for pdata in sorted(_cl_list, key= lambda pdata: pdata.id.lower()): + for pdata in sorted(_cl_list, key=lambda pdata: pdata.id.lower()): # Print cli report name ([item[0]), GUI report name (item[4]) if len(pdata.id) <= 25: - print(" %s%s- %s" - % ( pdata.id, " " * (26 - len(pdata.id)), - pdata.name), file=sys.stderr) + print(" %s%s- %s" % (pdata.id, + " " * (26 - len(pdata.id)), + pdata.name), + file=sys.stderr) else: - print(" %s\t- %s" - % (pdata.id, pdata.name), file=sys.stderr) + print(" %s\t- %s" % (pdata.id, pdata.name), + file=sys.stderr) elif action == "tool": from gramps.gui.plug import tool try: - options_str_dict = dict( [ tuple(chunk.split('=')) for - chunk in options_str.split(',') ] ) + options_str_dict = dict([tuple(chunk.split('=')) + for chunk in options_str.split(',')]) except: options_str_dict = {} print(_("Ignoring invalid options string."), - file=sys.stderr) + file=sys.stderr) name = options_str_dict.pop('name', None) _cli_tool_list = pmgr.get_reg_tools(gui=False) @@ -651,32 +666,32 @@ class ArgHandler: category = pdata.category tool_class = eval('mod.' + pdata.toolclass) options_class = eval('mod.' + pdata.optionclass) - tool.cli_tool( - dbstate=self.dbstate, - name=name, - category=category, - tool_class=tool_class, - options_class=options_class, - options_str_dict=options_str_dict, - user=self.user) + tool.cli_tool(dbstate=self.dbstate, + name=name, + category=category, + tool_class=tool_class, + options_class=options_class, + options_str_dict=options_str_dict, + user=self.user) return msg = _("Unknown tool name.") else: msg = _("Tool name not given. " - "Please use one of %(donottranslate)s=toolname.") % \ - {'donottranslate' : '[-p|--options] name'} + "Please use one of %(donottranslate)s=toolname." + ) % {'donottranslate' : '[-p|--options] name'} print(_("%s\n Available names are:") % msg, file=sys.stderr) for pdata in sorted(_cli_tool_list, key=lambda pdata: pdata.id.lower()): # Print cli report name ([item[0]), GUI report name (item[4]) if len(pdata.id) <= 25: - print(" %s%s- %s" - % ( pdata.id, " " * (26 - len(pdata.id)), - pdata.name), file=sys.stderr) + print(" %s%s- %s" % (pdata.id, + " " * (26 - len(pdata.id)), + pdata.name), + file=sys.stderr) else: - print(" %s\t- %s" - % (pdata.id, pdata.name), file=sys.stderr) + print(" %s\t- %s" % (pdata.id, pdata.name), + file=sys.stderr) elif action == "book": try: @@ -684,7 +699,7 @@ class ArgHandler: except: options_str_dict = {} print(_("Ignoring invalid options string."), - file=sys.stderr) + file=sys.stderr) name = options_str_dict.pop('name', None) book_list = BookList('books.xml', self.dbstate.db) @@ -696,8 +711,8 @@ class ArgHandler: msg = _("Unknown book name.") else: msg = _("Book name not given. " - "Please use one of %(donottranslate)s=bookname.") % \ - {'donottranslate' : '[-p|--options] name'} + "Please use one of %(donottranslate)s=bookname." + ) % {'donottranslate' : '[-p|--options] name'} print(_("%s\n Available names are:") % msg, file=sys.stderr) for name in sorted(book_list.get_book_names()): @@ -705,4 +720,4 @@ class ArgHandler: else: print(_("Unknown action: %s.") % action, file=sys.stderr) - sys.exit(0) + sys.exit(1) diff --git a/gramps/cli/argparser.py b/gramps/cli/argparser.py index 0ad747c68..5b51aec38 100644 --- a/gramps/cli/argparser.py +++ b/gramps/cli/argparser.py @@ -172,7 +172,7 @@ class ArgParser: If both input (-O or -i) and processing (-e or -a) options are given, interactive session will not be launched. - When using import ot export options (-i or -e), the -f option may be + When using import or export options (-i or -e), the -f option may be specified to indicate the family tree format. Possible values for ``ACTION`` are: 'report', 'book' and 'tool'. @@ -226,11 +226,13 @@ class ArgParser: """ try: options, leftargs = getopt.getopt(self.args[1:], - SHORTOPTS, LONGOPTS) + SHORTOPTS, LONGOPTS) except getopt.GetoptError as msg: # Extract the arguments in the list. - # The % operator replaces the list elements with repr() of the list elemements - # which is OK for latin characters, but not for non latin characters in list elements + # The % operator replaces the list elements + # with repr() of the list elements + # which is OK for latin characters, + # but not for non latin characters in list elements cliargs = "[ " for arg in range(len(self.args) - 1): cliargs += self.args[arg + 1] + " " @@ -238,10 +240,11 @@ class ArgParser: # Must first do str() of the msg object. msg = str(msg) self.errors += [(_('Error parsing the arguments'), - msg + '\n' + - _("Error parsing the arguments: %s \n" - "Type gramps --help for an overview of commands, or " - "read the manual pages.") % cliargs)] + msg + '\n' + + _("Error parsing the arguments: %s \n" + "Type gramps --help for an overview of " + "commands, or read the manual pages." + ) % cliargs)] return # Some args can work on a list of databases: @@ -256,8 +259,9 @@ class ArgParser: # if there were an argument without option, # use it as a file to open and return self.open_gui = leftargs[0] - print(_("Trying to open: %s ...") % leftargs[0], - file=sys.stderr) + print(_("Trying to open: %s ..." + ) % leftargs[0], + file=sys.stderr) #see if force open is on for opt_ix in range(len(options)): option, value = options[opt_ix] @@ -277,27 +281,28 @@ class ArgParser: self.create = value elif option in ['-i', '--import']: family_tree_format = None - if opt_ix < len(options) - 1 \ - and options[opt_ix + 1][0] in ( '-f', '--format'): + if (opt_ix < len(options) - 1 + and options[opt_ix + 1][0] in ('-f', '--format')): family_tree_format = options[opt_ix + 1][1] self.imports.append((value, family_tree_format)) elif option in ['-r', '--remove']: self.removes.append(value) elif option in ['-e', '--export']: family_tree_format = None - if opt_ix < len(options) - 1 \ - and options[opt_ix + 1][0] in ( '-f', '--format'): + if (opt_ix < len(options) - 1 + and options[opt_ix + 1][0] in ('-f', '--format')): family_tree_format = options[opt_ix + 1][1] self.exports.append((value, family_tree_format)) elif option in ['-a', '--action']: action = value if action not in ('report', 'tool', 'book'): - print(_("Unknown action: %s. Ignoring.") % action, - file=sys.stderr) + print(_("Unknown action: %s. Ignoring." + ) % action, + file=sys.stderr) continue options_str = "" - if opt_ix < len(options)-1 \ - and options[opt_ix+1][0] in ( '-p', '--options' ): + if (opt_ix < len(options)-1 + and options[opt_ix+1][0] in ('-p', '--options')): options_str = options[opt_ix+1][1] self.actions.append((action, options_str)) elif option in ['-d', '--debug']: @@ -311,17 +316,16 @@ class ArgParser: self.list_more = True elif option in ['-t']: self.list_table = True - elif option in ['-s','--show']: - print(_("Gramps config settings from %s:") - % config.filename) - for section in config.data: - for setting in config.data[section]: - print("%s.%s=%s" - % (section, setting, - repr(config.data[section][setting]))) + elif option in ['-s', '--show']: + print(_("Gramps config settings from %s:" + ) % config.filename) + for sect in config.data: + for setting in config.data[sect]: + print("%s.%s=%s" % (sect, setting, + repr(config.data[sect][setting]))) print() sys.exit(0) - elif option in ['-b','--databases']: + elif option in ['-b', '--databases']: default = config.data["behavior"]["database-backend"] pmgr = BasePluginManager.get_instance() pmgr.reg_plugins(PLUGINS_DIR, self, None) @@ -332,44 +336,46 @@ class ArgParser: if mod: database = getattr(mod, pdata.databaseclass) summary = database.get_class_summary() - print("Database backend ID:", pdata.id, "(default)" if pdata.id == default else "") + print("Database backend ID:", + pdata.id, + "(default)" if pdata.id == default else "") for key in sorted(summary.keys()): - print(" ", "%s:" % key, summary[key]) + print(" ", _("%s:") % key, summary[key]) sys.exit(0) elif option in ['-c', '--config']: - setting_name = value + cfg_name = value set_value = False - if setting_name: - if ":" in setting_name: - setting_name, new_value = setting_name.split(":", 1) + if cfg_name: + if ":" in cfg_name: + cfg_name, new_value = cfg_name.split(":", 1) set_value = True - if config.has_default(setting_name): - setting_value = config.get(setting_name) + if config.has_default(cfg_name): + setting_value = config.get(cfg_name) print(_("Current Gramps config setting: " - "%(name)s:%(value)s") - % {'name' : setting_name, - 'value' : repr(setting_value)}, + "%(name)s:%(value)s" + ) % {'name' : cfg_name, + 'value' : repr(setting_value)}, file=sys.stderr) if set_value: # does a user want the default config value? if new_value in ("DEFAULT", _("DEFAULT")): - new_value = config.get_default(setting_name) + new_value = config.get_default(cfg_name) else: converter = get_type_converter(setting_value) new_value = converter(new_value) - config.set(setting_name, new_value) + config.set(cfg_name, new_value) # translators: indent "New" to match "Current" print(_(" New Gramps config setting: " - "%(name)s:%(value)s") % - {'name' : setting_name, - 'value' : repr( - config.get(setting_name))}, + "%(name)s:%(value)s" + ) % {'name' : cfg_name, + 'value' : repr(config.get(cfg_name))}, file=sys.stderr) else: need_to_quit = True else: - print(_("Gramps: no such config setting: '%s'") - % setting_name, file=sys.stderr) + print(_("Gramps: no such config setting: '%s'" + ) % cfg_name, + file=sys.stderr) need_to_quit = True cleandbg += [opt_ix] elif option in ['-h', '-?', '--help']: @@ -388,10 +394,14 @@ class ArgParser: for ind in cleandbg: del options[ind] - if (len(options) > 0 and self.open is None and self.imports == [] - and self.removes == [] - and not (self.list or self.list_more or self.list_table or - self.help)): + if (len(options) > 0 + and self.open is None + and self.imports == [] + and self.removes == [] + and not (self.list + or self.list_more + or self.list_table + or self.help)): # Extract and convert to unicode the arguments in the list. # The % operator replaces the list elements with repr() of # the list elements, which is OK for latin characters @@ -403,7 +413,8 @@ class ArgParser: self.errors += [(_('Error parsing the arguments'), _("Error parsing the arguments: %s \n" "To use in the command-line mode, supply at " - "least one input file to process.") % cliargs)] + "least one input file to process." + ) % cliargs)] if need_to_quit: sys.exit(0) @@ -429,8 +440,8 @@ class ArgParser: return True # If we have data to work with: - if (self.open or self.imports): - if (self.exports or self.actions): + if self.open or self.imports: + if self.exports or self.actions: # have both data and what to do with it => no GUI return False elif self.create: diff --git a/gramps/cli/grampscli.py b/gramps/cli/grampscli.py index 3f1d5cb18..4e46c8661 100644 --- a/gramps/cli/grampscli.py +++ b/gramps/cli/grampscli.py @@ -99,12 +99,15 @@ class CLIDbLoader: .. note:: Inherit for GUI action """ - self._errordialog( '', _("Low level database corruption detected") + self._errordialog( + '', + _("Low level database corruption detected") + '\n' + _("Gramps has detected a problem in the underlying " "Berkeley database. This can be repaired from " "the Family Tree Manager. Select the database and " - 'click on the Repair button') + '\n\n' + str(msg)) + 'click on the Repair button' + ) + '\n\n' + str(msg)) def _begin_progress(self): """ @@ -146,8 +149,8 @@ class CLIDbLoader: if not os.access(filename, os.W_OK): mode = "r" self._warn(_('Read only database'), - _('You do not have write access ' - 'to the selected file.')) + _('You do not have write access ' + 'to the selected file.')) else: mode = "w" else: @@ -155,8 +158,8 @@ class CLIDbLoader: dbid_path = os.path.join(filename, DBBACKEND) if os.path.isfile(dbid_path): - with open(dbid_path) as fp: - dbid = fp.read().strip() + with open(dbid_path) as file: + dbid = file.read().strip() else: dbid = "bsddb" @@ -172,31 +175,31 @@ class CLIDbLoader: self.dbstate.db.set_save_path(filename) except DbEnvironmentError as msg: self.dbstate.no_database() - self._errordialog( _("Cannot open database"), str(msg)) + self._errordialog(_("Cannot open database"), str(msg)) except BsddbUpgradeRequiredError as msg: self.dbstate.no_database() - self._errordialog( _("Cannot open database"), str(msg)) + self._errordialog(_("Cannot open database"), str(msg)) except BsddbDowngradeRequiredError as msg: self.dbstate.no_database() - self._errordialog( _("Cannot open database"), str(msg)) + self._errordialog(_("Cannot open database"), str(msg)) except BsddbDowngradeError as msg: self.dbstate.no_database() - self._errordialog( _("Cannot open database"), str(msg)) + self._errordialog(_("Cannot open database"), str(msg)) except DbUpgradeRequiredError as msg: self.dbstate.no_database() - self._errordialog( _("Cannot open database"), str(msg)) + self._errordialog(_("Cannot open database"), str(msg)) except PythonDowngradeError as msg: self.dbstate.no_database() - self._errordialog( _("Cannot open database"), str(msg)) + self._errordialog(_("Cannot open database"), str(msg)) except PythonUpgradeRequiredError as msg: self.dbstate.no_database() - self._errordialog( _("Cannot open database"), str(msg)) + self._errordialog(_("Cannot open database"), str(msg)) except DbVersionError as msg: self.dbstate.no_database() - self._errordialog( _("Cannot open database"), str(msg)) + self._errordialog(_("Cannot open database"), str(msg)) except DbPythonError as msg: self.dbstate.no_database() - self._errordialog( _("Cannot open database"), str(msg)) + self._errordialog(_("Cannot open database"), str(msg)) except OSError as msg: self.dbstate.no_database() self._errordialog( @@ -217,8 +220,9 @@ class CLIDbLoader: class CLIManager: """ - Sessionmanager for Gramps. This is in effect a reduced :class:`.ViewManager` - instance (see gui/viewmanager), suitable for CLI actions. + Sessionmanager for Gramps. + This is in effect a reduced :class:`.ViewManager` instance + (see gui/viewmanager), suitable for CLI actions. Aim is to manage a dbstate on which to work (load, unload), and interact with the plugin session """ @@ -249,20 +253,21 @@ class CLIManager: """ Called when a file needs to be loaded """ - # A recent database should already have a directory If not, do nothing, - # just return. This can be handled better if family tree delete/rename - # also updated the recent file menu info in displaystate.py + # A recent database should already have a directory. + # If not, do nothing, just return. + # This can be handled better if family tree delete/rename + # also updated the recent file menu info in displaystate.py if not os.path.isdir(filename): self._errordialog( - _("Could not load a recent Family Tree."), - _("Family Tree does not exist, as it has been deleted.")) + _("Could not load a recent Family Tree."), + _("Family Tree does not exist, as it has been deleted.")) return if os.path.isfile(os.path.join(filename, "lock")): self._errordialog( - _("The database is locked."), - _("Use the --force-unlock option if you are sure " - "that the database is not in use.")) + _("The database is locked."), + _("Use the --force-unlock option if you are sure " + "that the database is not in use.")) return if self.db_loader.read_file(filename): @@ -308,7 +313,9 @@ class CLIManager: # If the DB Owner Info is empty and # [default] Researcher is not empty and # database is empty, then copy default researcher to DB owner - if res.is_empty() and not owner.is_empty() and self.dbstate.db.is_empty(): + if (res.is_empty() + and not owner.is_empty() + and self.dbstate.db.is_empty()): self.dbstate.db.set_researcher(owner) name_displayer.set_name_format(self.dbstate.db.name_formats) @@ -346,8 +353,8 @@ def startcli(errors, argparser): sys.exit(1) if argparser.errors: - errmsg = _('Error encountered in argument parsing: %s') \ - % argparser.errors[0][0] + errmsg = _('Error encountered in argument parsing: %s' + ) % argparser.errors[0][0] print(errmsg, file=sys.stderr) errmsg = _(' Details: %s') % argparser.errors[0][1] print(errmsg, file=sys.stderr) @@ -358,9 +365,8 @@ def startcli(errors, argparser): #we need a manager for the CLI session from .user import User - user=User(auto_accept=argparser.auto_accept, - quiet=argparser.quiet) - climanager = CLIManager(dbstate, setloader=True, user=user) + user = User(auto_accept=argparser.auto_accept, quiet=argparser.quiet) + climanager = CLIManager(dbstate, True, user) #load the plugins climanager.do_reg_plugins(dbstate, uistate=None) diff --git a/gramps/cli/plug/__init__.py b/gramps/cli/plug/__init__.py index 8c247cef8..62d2db26c 100644 --- a/gramps/cli/plug/__init__.py +++ b/gramps/cli/plug/__init__.py @@ -26,6 +26,7 @@ # cli.plug.__init__ # +""" Enable report generation from the command line interface (CLI) """ #------------------------------------------------------------------------- # @@ -37,7 +38,7 @@ import os import sys import logging -log = logging.getLogger(".") +LOG = logging.getLogger(".") #------------------------------------------------------------------------- # @@ -46,11 +47,12 @@ log = logging.getLogger(".") #------------------------------------------------------------------------- from gramps.gen.plug import BasePluginManager from gramps.gen.plug.docgen import (StyleSheet, StyleSheetList, PaperStyle, - PAPER_PORTRAIT, PAPER_LANDSCAPE, graphdoc) + PAPER_PORTRAIT, PAPER_LANDSCAPE, graphdoc) from gramps.gen.plug.menu import (FamilyOption, PersonOption, NoteOption, - MediaOption, PersonListOption, NumberOption, - BooleanOption, DestinationOption, StringOption, - TextOption, EnumeratedListOption, Option) + MediaOption, PersonListOption, NumberOption, + BooleanOption, DestinationOption, Option, + TextOption, EnumeratedListOption, + StringOption) from gramps.gen.display.name import displayer as name_displayer from gramps.gen.errors import ReportError, FilterError from gramps.gen.plug.report import (CATEGORY_TEXT, CATEGORY_DRAW, CATEGORY_BOOK, @@ -77,8 +79,8 @@ def _convert_str_to_match_type(str_val, type_val): ret_type = type(type_val) if isinstance(type_val, str): - if ( str_val.startswith("'") and str_val.endswith("'") ) or \ - ( str_val.startswith('"') and str_val.endswith('"') ): + if ((str_val.startswith("'") and str_val.endswith("'")) + or (str_val.startswith('"') and str_val.endswith('"'))): # Remove enclosing quotes return str(str_val[1:-1]) else: @@ -109,7 +111,7 @@ def _convert_str_to_match_type(str_val, type_val): elif ret_type == list: ret_val = [] - if not ( str_val.startswith("[") and str_val.endswith("]") ): + if not (str_val.startswith("[") and str_val.endswith("]")): print("'%s' is not a list-- try: [%s]" % (str_val, str_val)) return ret_val @@ -166,7 +168,7 @@ def _validate_options(options, dbase): person = dbase.get_person_from_handle(phandle) if not person: print(_("ERROR: Please specify a person"), - file=sys.stderr) + file=sys.stderr) if person: option.set_value(person.get_gramps_id()) @@ -214,15 +216,30 @@ class CommandLineReport: self.__textdoc_plugins.append(plugin) if plugin.get_draw_support() and plugin.get_extension(): self.__drawdoc_plugins.append(plugin) - if plugin.get_text_support() and \ - plugin.get_draw_support() and \ - plugin.get_extension(): + if (plugin.get_extension() + and plugin.get_text_support() + and plugin.get_draw_support()): self.__bookdoc_plugins.append(plugin) self.database = database self.category = category + + self.options_dict = None # keep pylint happy + self.options_help = None + self.paper = None + self.orien = None + self.marginl = None + self.marginr = None + self.margint = None + self.marginb = None + self.doc_options = None + self.doc_option_class = None + self.selected_style = None + self.style_list = None + self.css_filename = None self.format = None self.raw_name = name + self.option_class = option_class(name, database) if category == CATEGORY_GRAPHVIZ: # Need to include Graphviz options @@ -231,11 +248,12 @@ class CommandLineReport: self.__gvoptions.add_menu_options(menu) for name in menu.get_all_option_names(): if name not in self.option_class.options_dict: - self.option_class.options_dict[name] = \ - menu.get_option_by_name(name).get_value() + self.option_class.options_dict[ + name] = menu.get_option_by_name(name).get_value() self.option_class.load_previous_values() _validate_options(self.option_class, database) self.show = options_str_dict.pop('show', None) + self.options_str_dict = options_str_dict self.init_standard_options(noopt) self.init_report_options() @@ -250,8 +268,8 @@ class CommandLineReport: self.options_dict = { 'of' : self.option_class.handler.module_name, 'off' : self.option_class.handler.get_format_name(), - 'style' : \ - self.option_class.handler.get_default_stylesheet_name(), + 'style' : + self.option_class.handler.get_default_stylesheet_name(), 'papers' : self.option_class.handler.get_paper_name(), 'papero' : self.option_class.handler.get_orientation(), 'paperml' : self.option_class.handler.get_margins()[0], @@ -262,21 +280,22 @@ class CommandLineReport: } self.options_help = { - 'of' : [_("=filename"), _("Output file name. MANDATORY"),""], + 'of' : [_("=filename"), + _("Output file name. MANDATORY"), ""], 'off' : [_("=format"), _("Output file format."), []], 'style' : [_("=name"), _("Style name."), ""], 'papers' : [_("=name"), _("Paper size name."), ""], 'papero' : [_("=number"), _("Paper orientation number."), ""], - 'paperml' : [_("=number"), _("Left paper margin"), - _("Size in cm")], - 'papermr' : [_("=number"), _("Right paper margin"), - _("Size in cm")], - 'papermt' : [_("=number"), _("Top paper margin"), - _("Size in cm")], - 'papermb' : [_("=number"), _("Bottom paper margin"), - _("Size in cm")], - 'css' : [_("=css filename"), _("CSS filename to use, " - "html format only"), ""], + 'paperml' : [_("=number"), + _("Left paper margin"), _("Size in cm")], + 'papermr' : [_("=number"), + _("Right paper margin"), _("Size in cm")], + 'papermt' : [_("=number"), + _("Top paper margin"), _("Size in cm")], + 'papermb' : [_("=number"), + _("Bottom paper margin"), _("Size in cm")], + 'css' : [_("=css filename"), + _("CSS filename to use, html format only"), ""], } if noopt: @@ -288,29 +307,28 @@ class CommandLineReport: if self.category == CATEGORY_TEXT: for plugin in self.__textdoc_plugins: self.options_help['off'][2].append( - plugin.get_extension() + "\t" + plugin.get_description() ) + plugin.get_extension() + "\t" + plugin.get_description()) elif self.category == CATEGORY_DRAW: for plugin in self.__drawdoc_plugins: self.options_help['off'][2].append( - plugin.get_extension() + "\t" + plugin.get_description() ) + plugin.get_extension() + "\t" + plugin.get_description()) elif self.category == CATEGORY_BOOK: for plugin in self.__bookdoc_plugins: self.options_help['off'][2].append( - plugin.get_extension() + "\t" + plugin.get_description() ) + plugin.get_extension() + "\t" + plugin.get_description()) elif self.category == CATEGORY_GRAPHVIZ: for graph_format in graphdoc.FORMATS: self.options_help['off'][2].append( - graph_format["type"] + "\t" + graph_format["descr"] ) + graph_format["type"] + "\t" + graph_format["descr"]) else: self.options_help['off'][2] = "NA" - self.options_help['papers'][2] = \ - [ paper.get_name() for paper in paper_sizes - if paper.get_name() != 'Custom Size' ] + self.options_help['papers'][2] = [ + paper.get_name() for paper in paper_sizes + if paper.get_name() != 'Custom Size'] - self.options_help['papero'][2] = [ - "%d\tPortrait" % PAPER_PORTRAIT, - "%d\tLandscape" % PAPER_LANDSCAPE ] + self.options_help['papero'][2] = ["%d\tPortrait" % PAPER_PORTRAIT, + "%d\tLandscape" % PAPER_LANDSCAPE] self.options_help['css'][2] = os.path.join(USER_HOME, "whatever_name.css") @@ -333,8 +351,8 @@ class CommandLineReport: if self.category == CATEGORY_BOOK: # a Book Report has no "menu" for key in self.option_class.options_dict: self.options_dict[key] = self.option_class.options_dict[key] - self.options_help[key] = \ - self.option_class.options_help[key][:3] + self.options_help[ + key] = self.option_class.options_help[key][:3] # a Book Report can't have HTML output so "css" is meaningless self.options_dict.pop('css') @@ -355,15 +373,15 @@ class CommandLineReport: menu = self.option_class.menu for name in menu.get_all_option_names(): option = menu.get_option_by_name(name) - self.options_help[name] = [ "", option.get_help() ] + self.options_help[name] = ["", option.get_help()] if isinstance(option, PersonOption): id_list = [] for person_handle in self.database.get_person_handles(True): person = self.database.get_person_from_handle(person_handle) - id_list.append("%s\t%s" % ( - person.get_gramps_id(), - name_displayer.display(person))) + id_list.append("%s\t%s" + % (person.get_gramps_id(), + name_displayer.display(person))) self.options_help[name].append(id_list) elif isinstance(option, FamilyOption): id_list = [] @@ -380,8 +398,8 @@ class CommandLineReport: father = self.database.get_person_from_handle(fhandle) if father: fname = name_displayer.display(father) - text = "%s:\t%s, %s" % \ - (family.get_gramps_id(), fname, mname) + text = "%s:\t%s, %s" % (family.get_gramps_id(), + fname, mname) id_list.append(text) self.options_help[name].append(id_list) elif isinstance(option, NoteOption): @@ -409,7 +427,7 @@ class CommandLineReport: elif isinstance(option, TextOption): self.options_help[name].append( "A list of text values. Each entry in the list " - "represents one line of text." ) + "represents one line of text.") elif isinstance(option, EnumeratedListOption): ilist = [] for (value, description) in option.get_items(): @@ -427,11 +445,11 @@ class CommandLineReport: print(_("Unknown option: %s") % option, file=sys.stderr) print(_(" Valid options are:") + ", ".join(list(self.options_dict.keys())), - file=sys.stderr) + file=sys.stderr) print(_(" Use '%(donottranslate)s' to see description " - "and acceptable values") - % {'donottranslate' : "show=option"}, - file=sys.stderr) + "and acceptable values" + ) % {'donottranslate' : "show=option"}, + file=sys.stderr) def parse_options(self): """ @@ -460,9 +478,9 @@ class CommandLineReport: elif self.category == CATEGORY_BOOK: plugins = self.__bookdoc_plugins for plugin in plugins: - if plugin.get_extension() == self.options_dict['off']: - self.format = plugin.get_basedoc() - self.doc_option_class = plugin.get_doc_option_class() + if plugin.get_extension() == self.options_dict['off']: + self.format = plugin.get_basedoc() + self.doc_option_class = plugin.get_doc_option_class() if self.format is None: # Pick the first one as the default. plugin = plugins[0] @@ -482,24 +500,23 @@ class CommandLineReport: self.format = None if _chosen_format and _format_str: print(_("Ignoring '%(notranslate1)s=%(notranslate2)s' " - "and using '%(notranslate1)s=%(notranslate3)s'.") - % {'notranslate1' : "off", - 'notranslate2' : self.options_dict['off'], - 'notranslate3' : _chosen_format}, - file=sys.stderr) - print(_("Use '%(notranslate)s' to see valid values.") - % {'notranslate' : "show=off"}, file=sys.stderr) + "and using '%(notranslate1)s=%(notranslate3)s'." + ) % {'notranslate1' : "off", + 'notranslate2' : self.options_dict['off'], + 'notranslate3' : _chosen_format}, + file=sys.stderr) + print(_("Use '%(notranslate)s' to see valid values." + ) % {'notranslate' : "show=off"}, file=sys.stderr) self.do_doc_options() for opt in self.options_str_dict: if opt in self.options_dict: - self.options_dict[opt] = \ - _convert_str_to_match_type(self.options_str_dict[opt], - self.options_dict[opt]) + self.options_dict[opt] = _convert_str_to_match_type( + self.options_str_dict[opt], self.options_dict[opt]) - self.option_class.handler.options_dict[opt] = \ - self.options_dict[opt] + self.option_class.handler.options_dict[ + opt] = self.options_dict[opt] if menu and opt in menu_opt_names: option = menu.get_option_by_name(opt) @@ -509,10 +526,11 @@ class CommandLineReport: print(_("Ignoring unknown option: %s") % opt, file=sys.stderr) print(_(" Valid options are:"), ", ".join(list(self.options_dict.keys())), - file=sys.stderr) + file=sys.stderr) print(_(" Use '%(donottranslate)s' to see description " - "and acceptable values") % - {'donottranslate' : "show=option"}, file=sys.stderr) + "and acceptable values" + ) % {'donottranslate' : "show=option"}, + file=sys.stderr) self.option_class.handler.output = self.options_dict['of'] @@ -542,6 +560,9 @@ class CommandLineReport: self.selected_style = self.style_list.get_style_sheet(style_name) def do_doc_options(self): + """ + Process docgen options, if any (options for the backend, e.g. AsciiDoc) + """ self.doc_options = None if not self.doc_option_class: return # this docgen type has no options @@ -558,9 +579,8 @@ class CommandLineReport: for oname in docgen_menu.get_option_names('Document Options'): docgen_opt = docgen_menu.get_option('Document Options', oname) if oname in self.options_str_dict and oname in doc_options_dict: - doc_options_dict[oname] = \ - _convert_str_to_match_type(self.options_str_dict[oname], - doc_options_dict[oname]) + doc_options_dict[oname] = _convert_str_to_match_type( + self.options_str_dict[oname], doc_options_dict[oname]) self.options_str_dict.pop(oname) if oname in doc_options_dict: docgen_opt.set_value(doc_options_dict[oname]) @@ -588,8 +608,8 @@ class CommandLineReport: _('(no help available)')) print(optmsg) print(_(" Use '%(donottranslate)s' to see description " - "and acceptable values") - % {'donottranslate' : "show=option"}) + "and acceptable values" + ) % {'donottranslate' : "show=option"}) elif self.show in self.options_help: opt = self.options_help[self.show] tabs = '\t\t' if len(self.show) < 10 else '\t' @@ -605,10 +625,10 @@ class CommandLineReport: else: #there was a show option given, but the option is invalid print(_("option '%(optionname)s' not valid. " - "Use '%(donottranslate)s' to see all valid options.") - % {'optionname' : self.show, - 'donottranslate' : "show=all"}, - file=sys.stderr) + "Use '%(donottranslate)s' to see all valid options." + ) % {'optionname' : self.show, + 'donottranslate' : "show=all"}, + file=sys.stderr) #------------------------------------------------------------------------ # @@ -617,6 +637,9 @@ class CommandLineReport: #------------------------------------------------------------------------ def cl_report(database, name, category, report_class, options_class, options_str_dict): + """ + function to actually run the selected report + """ err_msg = _("Failed to write report. ") clr = CommandLineReport(database, name, category, options_class, @@ -631,38 +654,38 @@ def cl_report(database, name, category, report_class, options_class, if category in [CATEGORY_TEXT, CATEGORY_DRAW, CATEGORY_BOOK]: if clr.doc_options: clr.option_class.handler.doc = clr.format( - clr.selected_style, - PaperStyle(clr.paper,clr.orien,clr.marginl, - clr.marginr,clr.margint,clr.marginb), - clr.doc_options) + clr.selected_style, + PaperStyle(clr.paper, clr.orien, clr.marginl, + clr.marginr, clr.margint, clr.marginb), + clr.doc_options) else: clr.option_class.handler.doc = clr.format( - clr.selected_style, - PaperStyle(clr.paper,clr.orien,clr.marginl, - clr.marginr,clr.margint,clr.marginb)) + clr.selected_style, + PaperStyle(clr.paper, clr.orien, clr.marginl, + clr.marginr, clr.margint, clr.marginb)) elif category == CATEGORY_GRAPHVIZ: clr.option_class.handler.doc = clr.format( - clr.option_class, - PaperStyle(clr.paper,clr.orien,clr.marginl, - clr.marginr,clr.margint,clr.marginb)) - if clr.css_filename is not None and \ - hasattr(clr.option_class.handler.doc, 'set_css_filename'): + clr.option_class, + PaperStyle(clr.paper, clr.orien, clr.marginl, + clr.marginr, clr.margint, clr.marginb)) + if (clr.css_filename is not None + and hasattr(clr.option_class.handler.doc, 'set_css_filename')): clr.option_class.handler.doc.set_css_filename(clr.css_filename) - MyReport = report_class(database, clr.option_class, User()) - MyReport.doc.init() - MyReport.begin_report() - MyReport.write_report() - MyReport.end_report() + my_report = report_class(database, clr.option_class, User()) + my_report.doc.init() + my_report.begin_report() + my_report.write_report() + my_report.end_report() return clr except ReportError as msg: - (m1, m2) = msg.messages() + (msg1, msg2) = msg.messages() print(err_msg, file=sys.stderr) - print(m1, file=sys.stderr) - if m2: - print(m2, file=sys.stderr) + print(msg1, file=sys.stderr) + if msg2: + print(msg2, file=sys.stderr) except: - if len(log.handlers) > 0: - log.error(err_msg, exc_info=True) + if len(LOG.handlers) > 0: + LOG.error(err_msg, exc_info=True) else: print(err_msg, file=sys.stderr) ## Something seems to eat the exception above. @@ -694,7 +717,7 @@ def run_report(db, name, **options_str_dict): filename in clr.option_class.get_output() """ dbstate = DbState() - climanager = CLIManager(dbstate, setloader=False, user=User()) # don't load db + climanager = CLIManager(dbstate, False, User()) # don't load db climanager.do_reg_plugins(dbstate, None) pmgr = BasePluginManager.get_instance() cl_list = pmgr.get_reg_reports() @@ -724,6 +747,10 @@ def run_report(db, name, **options_str_dict): # #------------------------------------------------------------------------ def cl_book(database, name, book, options_str_dict): + """ + function to actually run the selected book, + which in turn runs whatever reports the book has in it + """ clr = CommandLineReport(database, name, CATEGORY_BOOK, ReportOptions, options_str_dict) @@ -773,11 +800,11 @@ def cl_book(database, name, book, options_str_dict): rpt.write_report() doc.close() except ReportError as msg: - (m1, m2) = msg.messages() + (msg1, msg2) = msg.messages() print(err_msg % name, file=sys.stderr) # which report has the error? - print(m1, file=sys.stderr) - if m2: - print(m2, file=sys.stderr) + print(msg1, file=sys.stderr) + if msg2: + print(msg2, file=sys.stderr) #------------------------------------------------------------------------ # @@ -790,11 +817,11 @@ def write_book_item(database, report_class, options, user): try: return report_class(database, options, user) except ReportError as msg: - (m1, m2) = msg.messages() - print("ReportError", m1, m2, file=sys.stderr) + (msg1, msg2) = msg.messages() + print("ReportError", msg1, msg2, file=sys.stderr) except FilterError as msg: - (m1, m2) = msg.messages() - print("FilterError", m1, m2, file=sys.stderr) + (msg1, msg2) = msg.messages() + print("FilterError", msg1, msg2, file=sys.stderr) except: - log.error("Failed to write book item.", exc_info=True) + LOG.error("Failed to write book item.", exc_info=True) return None