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
This commit is contained in:
Paul Franklin 2016-07-25 12:56:56 -07:00
parent 6efe71d303
commit a512c9d5eb
4 changed files with 338 additions and 279 deletions

View File

@ -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)

View File

@ -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:

View File

@ -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)

View File

@ -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