0006483: Listing the Family Trees can corrupt them. Changed get_dbdir_summary to exit if the bsddb_version is not the current bsddb and to return both BSDDB and schema version. Changed family_tree_summary to output both versions. Changed argparser and arghandler to additionally support -t (table) option to list family tree in tab delimited format.

svn: r21826
This commit is contained in:
Tim G L Lyons 2013-03-31 22:08:17 +00:00
parent 18f3824eca
commit 7a82cf5104
4 changed files with 74 additions and 21 deletions

View File

@ -162,6 +162,7 @@ class ArgHandler(object):
self.actions = parser.actions self.actions = parser.actions
self.list = parser.list self.list = parser.list
self.list_more = parser.list_more self.list_more = parser.list_more
self.list_table = parser.list_table
self.open_gui = parser.open_gui self.open_gui = parser.open_gui
self.imp_db_path = None self.imp_db_path = None
self.dbman = CLIDbManager(self.dbstate) self.dbman = CLIDbManager(self.dbstate)
@ -423,6 +424,27 @@ class ArgHandler(object):
encode(sys.getfilesystemencoding()) encode(sys.getfilesystemencoding())
sys.exit(0) 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.__open_action()
self.__import_action() self.__import_action()

View File

@ -71,6 +71,7 @@ Application options
-d, --debug=LOGGER_NAME Enable debug logs -d, --debug=LOGGER_NAME Enable debug logs
-l List Family Trees -l List Family Trees
-L List Family Trees in Detail -L List Family Trees in Detail
-t List Family Trees in tabular (tab delimited) form
-u, --force-unlock Force unlock of family tree -u, --force-unlock Force unlock of family tree
-s, --show Show config settings -s, --show Show config settings
-c, --config=[config.setting[:value]] Set config setting(s) and start Gramps -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.imp_db_path = None
self.list = False self.list = False
self.list_more = False self.list_more = False
self.list_table = False
self.help = False self.help = False
self.usage = False self.usage = False
self.force_unlock = False self.force_unlock = False
@ -289,6 +291,8 @@ class ArgParser(object):
self.list = True self.list = True
elif option in ('-L'): elif option in ('-L'):
self.list_more = True self.list_more = True
elif option in ('-t'):
self.list_table = True
elif option in ('-s','--show'): elif option in ('-s','--show'):
print "Gramps config settings from %s:" % \ print "Gramps config settings from %s:" % \
config.config.filename.encode(sys.getfilesystemencoding()) config.config.filename.encode(sys.getfilesystemencoding())
@ -343,7 +347,8 @@ class ArgParser(object):
del options[ind] del options[ind]
if len(options) > 0 and self.open is None and self.imports == [] \ 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. # Extract and convert to unicode the arguments in the list.
# The % operator replaces the list elements with repr() of # The % operator replaces the list elements with repr() of
# the list elements, which is OK for latin characters # 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 #errors in argument parsing ==> give cli error, no gui needed
return False 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 return False
if self.open_gui: if self.open_gui:

View File

@ -127,67 +127,91 @@ class CLIDbManager(object):
""" """
pass pass
def get_dbdir_summary(self, file_name): def get_dbdir_summary(self, dirpath, name):
""" """
Returns (people_count, version_number) of current DB. Returns (people_count, bsddb_version, schema_version) of
Returns ("Unknown", "Unknown") if invalid DB or other error. current DB.
Returns ("Unknown", "Unknown", "Unknown") if invalid DB or other error.
""" """
if config.get('preferences.use-bsddb3'): if config.get('preferences.use-bsddb3'):
from bsddb3 import dbshelve, db from bsddb3 import dbshelve, db
else: else:
from bsddb import dbshelve, db from bsddb import dbshelve, db
from gen.db import META, PERSON_TBL 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() env = db.DBEnv()
flags = db.DB_CREATE | db.DB_PRIVATE |\ flags = db.DB_CREATE | db.DB_PRIVATE |\
db.DB_INIT_MPOOL |\ db.DB_INIT_MPOOL |\
db.DB_INIT_LOG | db.DB_INIT_TXN db.DB_INIT_LOG | db.DB_INIT_TXN
try: try:
env.open(file_name, flags) env.open(dirpath, flags)
except: except Exception as msg:
return "Unknown", "Unknown" 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) dbmap1 = dbshelve.DBShelf(env)
fname = os.path.join(file_name, META + ".db") fname = os.path.join(dirpath, META + ".db")
try: try:
dbmap1.open(fname, META, db.DB_HASH, db.DB_RDONLY) dbmap1.open(fname, META, db.DB_HASH, db.DB_RDONLY)
except: except:
return "Unknown", "Unknown" env.close()
version = dbmap1.get('version', default=None) return "Unknown", bsddb_version, "Unknown"
schema_version = dbmap1.get('version', default=None)
dbmap1.close() dbmap1.close()
dbmap2 = dbshelve.DBShelf(env) dbmap2 = dbshelve.DBShelf(env)
fname = os.path.join(file_name, PERSON_TBL + ".db") fname = os.path.join(dirpath, PERSON_TBL + ".db")
try: try:
dbmap2.open(fname, PERSON_TBL, db.DB_HASH, db.DB_RDONLY) dbmap2.open(fname, PERSON_TBL, db.DB_HASH, db.DB_RDONLY)
except: except:
env.close() env.close()
return "Unknown", "Unknown" return "Unknown", bsddb_version, schema_version
count = len(dbmap2) count = len(dbmap2)
dbmap2.close() dbmap2.close()
env.close() env.close()
return (count, version) return (count, bsddb_version, schema_version)
def family_tree_summary(self): def family_tree_summary(self):
""" """
Return a list of dictionaries of the known family trees. Return a list of dictionaries of the known family trees.
""" """
# make the default directory if it does not exist # make the default directory if it does not exist
list = [] summary_list = []
for item in self.current_names: for item in self.current_names:
(name, dirpath, path_name, last, (name, dirpath, path_name, last,
tval, enable, stock_id) = item 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 = {}
retval[_("Number of people")] = count retval[_("Number of people")] = count
if enable: if enable:
retval[_("Locked?")] = _("yes") retval[_("Locked?")] = _("yes")
else: else:
retval[_("Locked?")] = _("no") 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[_("Family tree")] = name.encode(sys.getfilesystemencoding())
retval[_("Path")] = dirpath retval[_("Path")] = dirpath
retval[_("Last accessed")] = time.strftime('%x %X', retval[_("Last accessed")] = time.strftime('%x %X',
time.localtime(tval)) time.localtime(tval))
list.append( retval ) summary_list.append( retval )
return list return summary_list
def _populate_cli(self): def _populate_cli(self):
""" Get the list of current names in the database dir """ Get the list of current names in the database dir
@ -203,7 +227,9 @@ class CLIDbManager(object):
dirpath = os.path.join(dbdir, dpath) dirpath = os.path.join(dbdir, dpath)
path_name = os.path.join(dirpath, NAME_FILE) path_name = os.path.join(dirpath, NAME_FILE)
if os.path.isfile(path_name): 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) (tval, last) = time_val(dirpath)
(enable, stock_id) = self.icon_values(dirpath, self.active, (enable, stock_id) = self.icon_values(dirpath, self.active,

View File

@ -301,6 +301,6 @@ LONGOPTS = [
"qml", "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') GRAMPS_UUID = uuid.UUID('516cd010-5a41-470f-99f8-eb22f1098ad6')