9383: the Family Tree Manager dialog should show the database type

This commit is contained in:
Doug Blank 2016-04-22 07:52:34 -04:00
parent 0a3b05f156
commit 048151f447
11 changed files with 143 additions and 33 deletions

View File

@ -43,7 +43,8 @@ import logging
# gramps modules # gramps modules
# #
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
from gramps.gen.const import LONGOPTS, SHORTOPTS from gramps.gen.const import LONGOPTS, SHORTOPTS, PLUGINS_DIR, USER_PLUGINS
from gramps.gen.plug import BasePluginManager
from gramps.gen.config import config from gramps.gen.config import config
from gramps.gen.utils.cast import get_type_converter from gramps.gen.utils.cast import get_type_converter
from gramps.gen.const import GRAMPS_LOCALE as glocale from gramps.gen.const import GRAMPS_LOCALE as glocale
@ -76,6 +77,7 @@ Application options
-y, --yes Don't ask to confirm dangerous actions (non-GUI mode only) -y, --yes Don't ask to confirm dangerous actions (non-GUI mode only)
-q, --quiet Suppress progress indication output (non-GUI mode only) -q, --quiet Suppress progress indication output (non-GUI mode only)
-v, --version Show versions -v, --version Show versions
-b, --databases Show available database backends
""") """)
_USAGE = _(""" _USAGE = _("""
@ -152,6 +154,7 @@ class ArgParser(object):
-y, --yes Don't ask to confirm dangerous actions -y, --yes Don't ask to confirm dangerous actions
-q, --quiet Suppress progress indication output -q, --quiet Suppress progress indication output
-v, --version Show versions -v, --version Show versions
-b, --databases Show available database backends
-h, --help Display the help -h, --help Display the help
--usage Display usage information --usage Display usage information
@ -206,7 +209,6 @@ class ArgParser(object):
self.usage = False self.usage = False
self.force_unlock = False self.force_unlock = False
self.create = None self.create = None
self.runqml = False
self.quiet = False self.quiet = False
self.auto_accept = False self.auto_accept = False
@ -319,6 +321,20 @@ class ArgParser(object):
repr(config.data[section][setting]))) repr(config.data[section][setting])))
print() print()
sys.exit(0) sys.exit(0)
elif option in ['-b','--databases']:
default = config.data["behavior"]["database-backend"]
pmgr = BasePluginManager.get_instance()
pmgr.reg_plugins(PLUGINS_DIR, self, None)
pmgr.reg_plugins(USER_PLUGINS, self, None, load_on_reg=True)
for plugin in pmgr.get_reg_databases():
pdata = pmgr.get_plugin(plugin.id)
mod = pmgr.load_plugin(pdata)
database = getattr(mod, pdata.databaseclass)
summary = database.get_class_summary()
print("Database backend ID:", pdata.id, "(default)" if pdata.id == default else "")
for key in sorted(summary.keys()):
print(" ", "%s:" % key, summary[key])
sys.exit(0)
elif option in ['-c', '--config']: elif option in ['-c', '--config']:
setting_name = value setting_name = value
set_value = False set_value = False
@ -361,8 +377,6 @@ class ArgParser(object):
self.force_unlock = True self.force_unlock = True
elif option in ['--usage']: elif option in ['--usage']:
self.usage = True self.usage = True
elif option in ['--qml']:
self.runqml = True
elif option in ['-y', '--yes']: elif option in ['-y', '--yes']:
self.auto_accept = True self.auto_accept = True
elif option in ['-q', '--quiet']: elif option in ['-q', '--quiet']:
@ -376,7 +390,7 @@ class ArgParser(object):
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 self.removes == [] and self.removes == []
and not (self.list or self.list_more or self.list_table or and not (self.list or self.list_more or self.list_table or
self.help or self.runqml)): self.help)):
# 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

View File

@ -143,7 +143,7 @@ class CLIDbManager(object):
_("Path") _("Path")
_("Family Tree") _("Family Tree")
_("Last accessed") _("Last accessed")
_("Database backend") _("Database")
_("Locked?") _("Locked?")
and these details: and these details:
@ -168,7 +168,7 @@ class CLIDbManager(object):
retval = {_("Unavailable"): "locked"} retval = {_("Unavailable"): "locked"}
retval.update({_("Family Tree"): name, retval.update({_("Family Tree"): name,
_("Path"): dirpath, _("Path"): dirpath,
_("Database backend"): dbid, _("Database"): dbid,
_("Last accessed"): time_val(dirpath)[1], _("Last accessed"): time_val(dirpath)[1],
_("Locked?"): self.is_locked(dirpath), _("Locked?"): self.is_locked(dirpath),
}) })

View File

@ -258,30 +258,12 @@ ARABIC_SEMICOLON = "؛"
# #
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
# Note: Make sure to edit argparser.py _help string too!
# (longName, shortName, type , default, flags, descrip , argDescrip)
POPT_TABLE = [
("config", 'c', str, None, 0, "Set config setting(s) and start Gramps", ""),
("open", 'O', str, None, 0, "Open family tree", "FAMILY_TREE"),
("create", 'C', str, None, 0, "Create or Open family tree", "FAMILY_TREE"),
("import", 'i', str, None, 0, "Import file", "FILENAME"),
("export", 'e', str, None, 0, "Export file", "FILENAME"),
("format", 'f', str, None, 0, 'Specify format', "FORMAT"),
("action", 'a', str, None, 0, 'Specify action', "ACTION"),
("options", 'p', str, None, 0, 'Specify options', "OPTIONS_STRING"),
("debug", 'd', str, None, 0, 'Enable debug logs', "LOGGER_NAME"),
("", 'l', None, None, 0, 'List Family Trees', ""),
("", 'L', None, None, 0, 'List Family Tree Details', ""),
("show", 's', None, None, 0, "Show config settings", ""),
("force-unlock", 'u', None, None, 0, 'Force unlock of family tree', ""),
("version", 'v', None, None, 0, 'Show versions', ""),
]
LONGOPTS = [ LONGOPTS = [
"action=", "action=",
"class=", "class=",
"config=", "config=",
"debug=", "debug=",
"databases",
"display=", "display=",
"disable-sound", "disable-sound",
"disable-crash-dialog", "disable-crash-dialog",
@ -321,7 +303,7 @@ LONGOPTS = [
"quiet", "quiet",
] ]
SHORTOPTS = "O:C:i:e:f:a:p:d:c:r:lLthuv?syq" SHORTOPTS = "O:C:i:e:f:a:p:d:c:r:blLthuv?syq"
GRAMPS_UUID = uuid.UUID('516cd010-5a41-470f-99f8-eb22f1098ad6') GRAMPS_UUID = uuid.UUID('516cd010-5a41-470f-99f8-eb22f1098ad6')

View File

@ -1990,7 +1990,7 @@ class DbGeneric(DbWriteBase, DbReadBase, UpdateCallback, Callback):
_("Number of people") _("Number of people")
_("Version") _("Version")
_("Schema version") _("Data version")
""" """
return { return {
_("Number of people"): self.get_number_of_people(), _("Number of people"): self.get_number_of_people(),
@ -2003,7 +2003,7 @@ class DbGeneric(DbWriteBase, DbReadBase, UpdateCallback, Callback):
_("Number of repositories"): self.get_number_of_repositories(), _("Number of repositories"): self.get_number_of_repositories(),
_("Number of notes"): self.get_number_of_notes(), _("Number of notes"): self.get_number_of_notes(),
_("Number of tags"): self.get_number_of_tags(), _("Number of tags"): self.get_number_of_tags(),
_("Schema version"): ".".join([str(v) for v in self.VERSION]), _("Data version"): ".".join([str(v) for v in self.VERSION]),
} }
def get_dbname(self): def get_dbname(self):

View File

@ -280,9 +280,19 @@ def show_settings():
bsddb_str = bsddb.__version__ bsddb_str = bsddb.__version__
bsddb_db_str = str(bsddb.db.version()).replace(', ', '.')\ bsddb_db_str = str(bsddb.db.version()).replace(', ', '.')\
.replace('(', '').replace(')', '') .replace('(', '').replace(')', '')
bsddb_location_str = bsddb.__file__
except: except:
bsddb_str = 'not found' bsddb_str = 'not found'
bsddb_db_str = 'not found' bsddb_db_str = 'not found'
bsddb_location_str = 'not found'
try:
import sqlite3
sqlite3_version_str = sqlite3.version
sqlite3_location_str = sqlite3.__file__
except:
sqlite3_version_str = 'not found'
sqlite3_location_str = 'not found'
try: try:
from .gen.const import VERSION from .gen.const import VERSION
@ -335,8 +345,6 @@ def show_settings():
print(' gtk++ : %s' % gtkver_str) print(' gtk++ : %s' % gtkver_str)
print(' pygobject : %s' % pygobjectver_str) print(' pygobject : %s' % pygobjectver_str)
print(' pango : %s' % pangover_str) print(' pango : %s' % pangover_str)
print(' bsddb : %s' % bsddb_str)
print(' bsddb.db : %s' % bsddb_db_str)
print(' cairo : %s' % cairover_str) print(' cairo : %s' % cairover_str)
print(' pycairo : %s' % pycairover_str) print(' pycairo : %s' % pycairover_str)
print(' osmgpsmap : %s' % osmgpsmap_str) print(' osmgpsmap : %s' % osmgpsmap_str)
@ -368,6 +376,16 @@ def show_settings():
for folder in os_path: for folder in os_path:
print(" ", folder) print(" ", folder)
print('') print('')
print("Databases:")
print("-------------------------")
print(' bsddb :')
print(' version : %s' % bsddb_str)
print(' db version : %s' % bsddb_db_str)
print(' location : %s' % bsddb_location_str)
print(' sqlite3 :')
print(' version : %s' % sqlite3_version_str)
print(' location : %s' % sqlite3_location_str)
print('')
def run(): def run():
error = [] error = []

View File

@ -38,6 +38,7 @@ import bisect
from functools import wraps from functools import wraps
import logging import logging
from sys import maxsize, getfilesystemencoding, version_info from sys import maxsize, getfilesystemencoding, version_info
from ast import literal_eval as safe_eval
from bsddb3 import dbshelve, db from bsddb3 import dbshelve, db
from bsddb3.db import DB_CREATE, DB_AUTO_COMMIT, DB_DUP, DB_DUPSORT, DB_RDONLY from bsddb3.db import DB_CREATE, DB_AUTO_COMMIT, DB_DUP, DB_DUPSORT, DB_RDONLY
@ -208,6 +209,27 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback):
Gramps database write access object. Gramps database write access object.
""" """
@classmethod
def get_class_summary(cls):
"""
Return a diction of information about this database.
"""
try:
import bsddb3 as bsddb
bsddb_str = bsddb.__version__
bsddb_db_str = str(bsddb.db.version()).replace(', ', '.')\
.replace('(', '').replace(')', '')
except:
bsddb_str = 'not found'
bsddb_db_str = 'not found'
summary = {
"DB-API version": "n/a",
"Database type": cls.__name__,
'Database version': bsddb_str,
'Database db version': bsddb_db_str
}
return summary
# Set up dictionary for callback signal handler # Set up dictionary for callback signal handler
# --------------------------------------------- # ---------------------------------------------
# 1. Signals for primary objects # 1. Signals for primary objects
@ -2517,9 +2539,11 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback):
if os.path.isfile(bdbversion_file): if os.path.isfile(bdbversion_file):
vers_file = open(bdbversion_file) vers_file = open(bdbversion_file)
bsddb_version = vers_file.readline().strip() bsddb_version = vers_file.readline().strip()
bsddb_version = ".".join([str(v) for v in safe_eval(bsddb_version)])
else: else:
bsddb_version = _("Unknown") bsddb_version = _("Unknown")
return { return {
_("DB-API version"): "n/a",
_("Number of people"): self.get_number_of_people(), _("Number of people"): self.get_number_of_people(),
_("Number of families"): self.get_number_of_families(), _("Number of families"): self.get_number_of_families(),
_("Number of sources"): self.get_number_of_sources(), _("Number of sources"): self.get_number_of_sources(),
@ -2530,8 +2554,8 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback):
_("Number of repositories"): self.get_number_of_repositories(), _("Number of repositories"): self.get_number_of_repositories(),
_("Number of notes"): self.get_number_of_notes(), _("Number of notes"): self.get_number_of_notes(),
_("Number of tags"): self.get_number_of_tags(), _("Number of tags"): self.get_number_of_tags(),
_("Schema version"): schema_version, _("Data version"): schema_version,
_("Version"): bsddb_version, _("Database db version"): bsddb_version,
} }
def mk_backup_name(database, base): def mk_backup_name(database, base):

View File

@ -40,6 +40,13 @@ class DBAPI(DbGeneric):
""" """
Database backends class for DB-API 2.0 databases Database backends class for DB-API 2.0 databases
""" """
@classmethod
def get_class_summary(cls):
summary = {
"DB-API version": "2.0",
"Database type": cls.__name__,
}
return summary
def restore(self): def restore(self):
""" """
@ -1873,3 +1880,16 @@ class DBAPI(DbGeneric):
else: else:
obj = self.get_table_func(table,"class_func").create(pickle.loads(row[0])) obj = self.get_table_func(table,"class_func").create(pickle.loads(row[0]))
yield obj yield obj
def get_summary(self):
"""
Returns dictionary of summary item.
Should include, if possible:
_("Number of people")
_("Version")
_("Schema version")
"""
summary = super().get_summary()
summary.update(self.dbapi.__class__.get_summary())
return summary

View File

@ -3,6 +3,21 @@ import MySQLdb
MySQLdb.paramstyle = 'qmark' ## Doesn't work MySQLdb.paramstyle = 'qmark' ## Doesn't work
class MySQL(object): class MySQL(object):
@classmethod
def get_summary(cls):
"""
Return a diction of information about this database
backend.
"""
summary = {
"DB-API version": "2.0",
"Database SQL type": cls.__name__,
"Database SQL module": "MySQLdb",
"Database SQL module version": ".".join([str(v) for v in MySQLdb.version_info]),
"Database SQL module location": MySQLdb.__file__,
}
return summary
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
self.connection = MySQLdb.connect(*args, **kwargs) self.connection = MySQLdb.connect(*args, **kwargs)
self.cursor = self.connection.cursor() self.cursor = self.connection.cursor()

View File

@ -3,6 +3,21 @@ import pg8000
pg8000.paramstyle = 'qmark' pg8000.paramstyle = 'qmark'
class Postgresql(object): class Postgresql(object):
@classmethod
def get_summary(cls):
"""
Return a diction of information about this database
backend.
"""
summary = {
"DB-API version": "2.0",
"Database SQL type": cls.__name__,
"Database SQL module": "pg8000",
"Database SQL module version": pg8000.__version__,
"Database SQL module location": pg8000.__file__,
}
return summary
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
self.connection = pg8000.connect(*args, **kwargs) self.connection = pg8000.connect(*args, **kwargs)
self.cursor = self.connection.cursor() self.cursor = self.connection.cursor()

View File

@ -6,6 +6,21 @@ import re
sqlite3.paramstyle = 'qmark' sqlite3.paramstyle = 'qmark'
class Sqlite(object): class Sqlite(object):
@classmethod
def get_summary(cls):
"""
Return a diction of information about this database
backend.
"""
summary = {
"DB-API version": "2.0",
"Database SQL type": cls.__name__,
"Database SQL module": "sqlite3",
"Database SQL module version": sqlite3.version,
"Database SQL module location": sqlite3.__file__,
}
return summary
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
self.log = logging.getLogger(".sqlite") self.log = logging.getLogger(".sqlite")
self.connection = sqlite3.connect(*args, **kwargs) self.connection = sqlite3.connect(*args, **kwargs)

View File

@ -28,6 +28,13 @@ class InMemoryDB(DBAPI):
""" """
A DB-API 2.0 In-memory SQL database. A DB-API 2.0 In-memory SQL database.
""" """
@classmethod
def get_class_summary(cls):
summary = DBAPI.get_class_summary()
summary.update({
"Database location": "in memory",
})
return summary
def initialize_backend(self, directory): def initialize_backend(self, directory):
""" """