diff --git a/src/cli/arghandler.py b/src/cli/arghandler.py index ab420e6f7..939eda594 100644 --- a/src/cli/arghandler.py +++ b/src/cli/arghandler.py @@ -162,6 +162,7 @@ class ArgHandler(object): self.actions = parser.actions self.list = parser.list self.list_more = parser.list_more + self.list_table = parser.list_table self.open_gui = parser.open_gui self.imp_db_path = None self.dbman = CLIDbManager(self.dbstate) @@ -423,6 +424,27 @@ class ArgHandler(object): encode(sys.getfilesystemencoding()) sys.exit(0) + if self.list_table: + print _('Gramps Family Trees:').encode(sys.getfilesystemencoding()) + summary_list = self.dbman.family_tree_summary() + print _("Family Tree").encode(sys.getfilesystemencoding()), + for key in sorted(summary_list[0]): + if key != _("Family tree"): + print "\t ", + print key.encode(sys.getfilesystemencoding()), + print + for summary in sorted(summary_list, + key=lambda sum: sum[_("Family tree")].lower()): + print '"%s"'.\ + encode(sys.getfilesystemencoding()) % summary[_("Family tree")], + for item in sorted(summary): + if item != _("Family tree"): + print "\t ", + print ('"%s"' % summary[item]).\ + encode(sys.getfilesystemencoding()), + print + sys.exit(0) + self.__open_action() self.__import_action() diff --git a/src/cli/argparser.py b/src/cli/argparser.py index 647da9fc9..67050f02d 100644 --- a/src/cli/argparser.py +++ b/src/cli/argparser.py @@ -71,6 +71,7 @@ Application options -d, --debug=LOGGER_NAME Enable debug logs -l List Family Trees -L List Family Trees in Detail + -t List Family Trees in tabular (tab delimited) form -u, --force-unlock Force unlock of family tree -s, --show Show config settings -c, --config=[config.setting[:value]] Set config setting(s) and start Gramps @@ -174,6 +175,7 @@ class ArgParser(object): self.imp_db_path = None self.list = False self.list_more = False + self.list_table = False self.help = False self.usage = False self.force_unlock = False @@ -289,6 +291,8 @@ class ArgParser(object): self.list = True elif option in ('-L'): self.list_more = True + elif option in ('-t'): + self.list_table = True elif option in ('-s','--show'): print "Gramps config settings from %s:" % \ config.config.filename.encode(sys.getfilesystemencoding()) @@ -343,7 +347,8 @@ class ArgParser(object): del options[ind] if len(options) > 0 and self.open is None and self.imports == [] \ - and not (self.list or self.list_more or self.help or self.runqml): + and not (self.list or self.list_more or self.list_table or + self.help or self.runqml): # 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 @@ -370,7 +375,7 @@ class ArgParser(object): #errors in argument parsing ==> give cli error, no gui needed return False - if self.list or self.list_more or self.help: + if self.list or self.list_more or self.list_table or self.help: return False if self.open_gui: diff --git a/src/cli/clidbman.py b/src/cli/clidbman.py index 24dc74462..a4de93538 100644 --- a/src/cli/clidbman.py +++ b/src/cli/clidbman.py @@ -127,67 +127,91 @@ class CLIDbManager(object): """ pass - def get_dbdir_summary(self, file_name): + def get_dbdir_summary(self, dirpath, name): """ - Returns (people_count, version_number) of current DB. - Returns ("Unknown", "Unknown") if invalid DB or other error. + Returns (people_count, bsddb_version, schema_version) of + current DB. + Returns ("Unknown", "Unknown", "Unknown") if invalid DB or other error. """ if config.get('preferences.use-bsddb3'): from bsddb3 import dbshelve, db else: from bsddb import dbshelve, db + from gen.db import META, PERSON_TBL + from gen.db.dbconst import BDBVERSFN + + bdbversion_file = os.path.join(dirpath, BDBVERSFN) + if os.path.isfile(bdbversion_file): + vers_file = open(bdbversion_file) + bsddb_version = vers_file.readline().strip() + else: + return "Unknown", "Unknown", "Unknown" + + current_bsddb_version = str(db.version()) + if bsddb_version != current_bsddb_version: + return "Unknown", bsddb_version, "Unknown" + env = db.DBEnv() flags = db.DB_CREATE | db.DB_PRIVATE |\ db.DB_INIT_MPOOL |\ db.DB_INIT_LOG | db.DB_INIT_TXN try: - env.open(file_name, flags) - except: - return "Unknown", "Unknown" + env.open(dirpath, flags) + except Exception as msg: + LOG.warning("Error opening db environment for '%s': %s" % + (name, str(msg))) + try: + env.close() + except Exception as msg: + LOG.warning("Error closing db environment for '%s': %s" % + (name, str(msg))) + return "Unknown", bsddb_version, "Unknown" dbmap1 = dbshelve.DBShelf(env) - fname = os.path.join(file_name, META + ".db") + fname = os.path.join(dirpath, META + ".db") try: dbmap1.open(fname, META, db.DB_HASH, db.DB_RDONLY) except: - return "Unknown", "Unknown" - version = dbmap1.get('version', default=None) + env.close() + return "Unknown", bsddb_version, "Unknown" + schema_version = dbmap1.get('version', default=None) dbmap1.close() dbmap2 = dbshelve.DBShelf(env) - fname = os.path.join(file_name, PERSON_TBL + ".db") + fname = os.path.join(dirpath, PERSON_TBL + ".db") try: dbmap2.open(fname, PERSON_TBL, db.DB_HASH, db.DB_RDONLY) except: env.close() - return "Unknown", "Unknown" + return "Unknown", bsddb_version, schema_version count = len(dbmap2) dbmap2.close() env.close() - return (count, version) + return (count, bsddb_version, schema_version) def family_tree_summary(self): """ Return a list of dictionaries of the known family trees. """ # make the default directory if it does not exist - list = [] + summary_list = [] for item in self.current_names: (name, dirpath, path_name, last, tval, enable, stock_id) = item - count, version = self.get_dbdir_summary(dirpath) + count, bsddb_version, schema_version = self.get_dbdir_summary(dirpath, name) retval = {} retval[_("Number of people")] = count if enable: retval[_("Locked?")] = _("yes") else: retval[_("Locked?")] = _("no") - retval[_("DB version")] = version + retval[_("Bsddb version")] = bsddb_version + retval[_("Schema version")] = schema_version retval[_("Family tree")] = name.encode(sys.getfilesystemencoding()) retval[_("Path")] = dirpath retval[_("Last accessed")] = time.strftime('%x %X', time.localtime(tval)) - list.append( retval ) - return list + summary_list.append( retval ) + return summary_list def _populate_cli(self): """ Get the list of current names in the database dir @@ -203,7 +227,9 @@ class CLIDbManager(object): dirpath = os.path.join(dbdir, dpath) path_name = os.path.join(dirpath, NAME_FILE) if os.path.isfile(path_name): - name = file(path_name).readline().strip() + f = open(path_name) + name = f.readline().strip() + f.close() (tval, last) = time_val(dirpath) (enable, stock_id) = self.icon_values(dirpath, self.active, diff --git a/src/const.py.in b/src/const.py.in index f796f914e..314c21d88 100644 --- a/src/const.py.in +++ b/src/const.py.in @@ -301,6 +301,6 @@ LONGOPTS = [ "qml", ] -SHORTOPTS = "O:C:i:e:f:a:p:d:c:lLhuv?s" +SHORTOPTS = "O:C:i:e:f:a:p:d:c:lLthuv?s" GRAMPS_UUID = uuid.UUID('516cd010-5a41-470f-99f8-eb22f1098ad6')