From 63bb36ea4473e9ebbdffb0a754f881825dfdfad2 Mon Sep 17 00:00:00 2001 From: Nick Hall Date: Fri, 28 Jul 2017 23:42:55 +0100 Subject: [PATCH] Reorganise DBAPI plugins Add SQLite and PostgreSQL plugins. Remove DBAPI and InMemoryDb plugins. --- gramps/gen/db/generic.py | 5 ++ gramps/gen/db/utils.py | 4 +- gramps/gui/dbman.py | 2 +- gramps/plugins/db/dbapi/dbapi.py | 42 +------------- gramps/plugins/db/dbapi/inmemorydb.py | 58 ------------------- .../{inmemorydb.gpr.py => postgresql.gpr.py} | 20 +++---- gramps/plugins/db/dbapi/postgresql.py | 45 +++++++++++++- .../db/dbapi/{dbapi.gpr.py => sqlite.gpr.py} | 20 +++---- gramps/plugins/db/dbapi/sqlite.py | 27 +++++++-- gramps/plugins/db/dbapi/test/db_test.py | 12 ++-- .../plugins/test/db_undo_and_signals_test.py | 2 +- po/POTFILES.in | 4 +- po/POTFILES.skip | 4 -- 13 files changed, 105 insertions(+), 140 deletions(-) delete mode 100644 gramps/plugins/db/dbapi/inmemorydb.py rename gramps/plugins/db/dbapi/{inmemorydb.gpr.py => postgresql.gpr.py} (73%) rename gramps/plugins/db/dbapi/{dbapi.gpr.py => sqlite.gpr.py} (74%) diff --git a/gramps/gen/db/generic.py b/gramps/gen/db/generic.py index 06593dfdc..48681f4f1 100644 --- a/gramps/gen/db/generic.py +++ b/gramps/gen/db/generic.py @@ -601,6 +601,11 @@ class DbGeneric(DbWriteBase, DbReadBase, UpdateCallback, Callback): # run backend-specific code: self._initialize(directory) + # We use the existence of the person table as a proxy for the database + # being new + if not self.dbapi.table_exists("person"): + self._create_schema() + # Load metadata self.name_formats = self._get_metadata('name_formats') self.owner = self._get_metadata('researcher', default=Researcher()) diff --git a/gramps/gen/db/utils.py b/gramps/gen/db/utils.py index 10cfe7c3d..29a2a7c52 100644 --- a/gramps/gen/db/utils.py +++ b/gramps/gen/db/utils.py @@ -129,8 +129,8 @@ def import_as_dict(filename, user, skp_imp_adds=True): """ Import the filename into a InMemoryDB and return it. """ - db = make_database("inmemorydb") - db.load(None) + db = make_database("sqlite") + db.load(":memory:") db.set_feature("skip-import-additions", skp_imp_adds) status = import_from_filename(db, filename, user) return db if status else None diff --git a/gramps/gui/dbman.py b/gramps/gui/dbman.py index 150314289..3f612cefd 100644 --- a/gramps/gui/dbman.py +++ b/gramps/gui/dbman.py @@ -809,7 +809,7 @@ class DbManager(CLIDbManager, ManagedWindow): new_text = "%s %s" % (name, _("(Converted #%d)") % count) new_path, newname = self._create_new_db(new_text, edit_entry=False) ## Create a new database of correct type: - dbase = make_database("dbapi") + dbase = make_database(config.get('database.backend')) dbase.write_version(new_path) dbase.load(new_path) ## import from XML diff --git a/gramps/plugins/db/dbapi/dbapi.py b/gramps/plugins/db/dbapi/dbapi.py index 7a963cfcd..d0730944c 100644 --- a/gramps/plugins/db/dbapi/dbapi.py +++ b/gramps/plugins/db/dbapi/dbapi.py @@ -79,48 +79,12 @@ class DBAPI(DbGeneric): version_file.write(str(self.VERSION[0])) versionpath = os.path.join(directory, str(DBBACKEND)) - _LOG.debug("Write database backend file to 'dbapi'") + _LOG.debug("Write database backend file") with open(versionpath, "w") as version_file: - version_file.write("dbapi") + version_file.write(self.__class__.__name__.lower()) def _initialize(self, directory): - # Run code from directory - from gramps.gen.utils.configmanager import ConfigManager - config_file = os.path.join(directory, 'settings.ini') - config_mgr = ConfigManager(config_file) - config_mgr.register('database.dbtype', 'sqlite') - config_mgr.register('database.dbname', 'gramps') - config_mgr.register('database.host', 'localhost') - config_mgr.register('database.user', 'user') - config_mgr.register('database.password', 'password') - config_mgr.register('database.port', 'port') - config_mgr.load() # load from settings.ini - - dbtype = config_mgr.get('database.dbtype') - - if dbtype == "sqlite": - from gramps.plugins.db.dbapi.sqlite import Sqlite - path_to_db = os.path.join(directory, 'sqlite.db') - self.dbapi = Sqlite(path_to_db) - else: - dbkwargs = {} - for key in config_mgr.get_section_settings('database'): - # Use all parameters except dbtype as keyword arguments - if key == 'dbtype': - continue - dbkwargs[key] = config_mgr.get('database.' + key) - if dbtype == "postgresql": - from gramps.plugins.db.dbapi.postgresql import Postgresql - self.dbapi = Postgresql(**dbkwargs) - else: - raise AttributeError(("invalid DB-API dbtype: '%s'. " + - "Should be 'sqlite' or 'postgresql'") - % dbtype) - - # We use the existence of the person table as a proxy for the database - # being new - if not self.dbapi.table_exists("person"): - self._create_schema() + raise NotImplementedError def _create_schema(self): """ diff --git a/gramps/plugins/db/dbapi/inmemorydb.py b/gramps/plugins/db/dbapi/inmemorydb.py deleted file mode 100644 index b975a245c..000000000 --- a/gramps/plugins/db/dbapi/inmemorydb.py +++ /dev/null @@ -1,58 +0,0 @@ -# -# Gramps - a GTK+/GNOME based genealogy program -# -# Copyright (C) 2016 Douglas S. Blank -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -# - -from gramps.plugins.db.dbapi.dbapi import DBAPI -from gramps.plugins.db.dbapi.sqlite import Sqlite -from gramps.gen.db import DBBACKEND -from gramps.gen.db.generic import DbGeneric, LOG -import os -import glob - -class InMemoryDB(DBAPI): - """ - A DB-API 2.0 In-memory SQL database. - """ - def _initialize(self, directory): - """ - Create an in-memory sqlite database. - """ - self.dbapi = Sqlite(":memory:") - self._create_schema() - - def write_version(self, directory): - """Write files for a newly created DB.""" - versionpath = os.path.join(directory, DBBACKEND) - LOG.debug("Write database backend file to 'inmemorydb'") - with open(versionpath, "w") as version_file: - version_file.write("inmemorydb") - - def load(self, directory, callback=None, mode=None, - force_schema_upgrade=False, - force_bsddb_upgrade=False, - force_bsddb_downgrade=False, - force_python_upgrade=False, - update=True): - DbGeneric.load(self, directory, - callback, - mode, - force_schema_upgrade, - force_bsddb_upgrade, - force_bsddb_downgrade, - force_python_upgrade) diff --git a/gramps/plugins/db/dbapi/inmemorydb.gpr.py b/gramps/plugins/db/dbapi/postgresql.gpr.py similarity index 73% rename from gramps/plugins/db/dbapi/inmemorydb.gpr.py rename to gramps/plugins/db/dbapi/postgresql.gpr.py index 3db80b507..c881c0905 100644 --- a/gramps/plugins/db/dbapi/inmemorydb.gpr.py +++ b/gramps/plugins/db/dbapi/postgresql.gpr.py @@ -22,15 +22,15 @@ from gramps.gen.const import GRAMPS_LOCALE as glocale _ = glocale.translation.gettext register(DATABASE, - id = 'inmemorydb', - name = _("In-Memory"), - name_accell = _("In-_Memory Database"), - description = _("In-Memory Database"), - version = '1.0.0', - gramps_target_version = "5.0", - status = STABLE, - fname = 'inmemorydb.py', - databaseclass = 'InMemoryDB', + id='postgresql', + name=_('PostgreSQL'), + name_accell=_('_PostgreSQL Database'), + description=_('PostgreSQL Database'), + version='1.0.0', + gramps_target_version='5.0', + status=STABLE, + fname='postgresql.py', + databaseclass='PostgreSQL', authors=['Doug Blank'], - authors_email=["doug.blank@gmail.com"], + authors_email=['doug.blank@gmail.com'] ) diff --git a/gramps/plugins/db/dbapi/postgresql.py b/gramps/plugins/db/dbapi/postgresql.py index 63019b13a..af4888c07 100644 --- a/gramps/plugins/db/dbapi/postgresql.py +++ b/gramps/plugins/db/dbapi/postgresql.py @@ -2,7 +2,7 @@ # Gramps - a GTK+/GNOME based genealogy program # # Copyright (C) 2015-2016 Douglas S. Blank -# Copyright (C) 2016 Nick Hall +# Copyright (C) 2016-2017 Nick Hall # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -19,12 +19,17 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # +""" +Backend for PostgreSQL database. +""" + #------------------------------------------------------------------------- # # Standard python modules # #------------------------------------------------------------------------- import psycopg2 +import os import re #------------------------------------------------------------------------- @@ -32,12 +37,43 @@ import re # Gramps modules # #------------------------------------------------------------------------- +from gramps.plugins.db.dbapi.dbapi import DBAPI +from gramps.gen.utils.configmanager import ConfigManager from gramps.gen.db.dbconst import ARRAYSIZE from gramps.gen.const import GRAMPS_LOCALE as glocale psycopg2.paramstyle = 'format' -class Postgresql: +#------------------------------------------------------------------------- +# +# PostgreSQL class +# +#------------------------------------------------------------------------- +class PostgreSQL(DBAPI): + + def _initialize(self, directory): + config_file = os.path.join(directory, 'settings.ini') + config_mgr = ConfigManager(config_file) + config_mgr.register('database.dbname', 'gramps') + config_mgr.register('database.host', 'localhost') + config_mgr.register('database.user', 'user') + config_mgr.register('database.password', 'password') + config_mgr.register('database.port', 'port') + config_mgr.load() + + dbkwargs = {} + for key in config_mgr.get_section_settings('database'): + dbkwargs[key] = config_mgr.get('database.' + key) + + self.dbapi = Connection(**dbkwargs) + + +#------------------------------------------------------------------------- +# +# Connection class +# +#------------------------------------------------------------------------- +class Connection: @classmethod def get_summary(cls): """ @@ -140,6 +176,11 @@ class Postgresql: return Cursor(self.__connection) +#------------------------------------------------------------------------- +# +# Cursor class +# +#------------------------------------------------------------------------- class Cursor: def __init__(self, connection): self.__connection = connection diff --git a/gramps/plugins/db/dbapi/dbapi.gpr.py b/gramps/plugins/db/dbapi/sqlite.gpr.py similarity index 74% rename from gramps/plugins/db/dbapi/dbapi.gpr.py rename to gramps/plugins/db/dbapi/sqlite.gpr.py index ef442cfe9..e107db8dd 100644 --- a/gramps/plugins/db/dbapi/dbapi.gpr.py +++ b/gramps/plugins/db/dbapi/sqlite.gpr.py @@ -22,15 +22,15 @@ from gramps.gen.const import GRAMPS_LOCALE as glocale _ = glocale.translation.gettext register(DATABASE, - id = 'dbapi', - name = _("DB-API"), - name_accell = _("DB-_API Database"), - description = _("DB-API Database"), - version = '1.0.32', - gramps_target_version = "5.0", - status = STABLE, - fname = 'dbapi.py', - databaseclass = 'DBAPI', + id='sqlite', + name=_('SQLite'), + name_accell=_('_SQLite Database'), + description=_('SQLite Database'), + version='1.0.0', + gramps_target_version='5.0', + status=STABLE, + fname='sqlite.py', + databaseclass='SQLite', authors=['Doug Blank'], - authors_email=["doug.blank@gmail.com"], + authors_email=['doug.blank@gmail.com'] ) diff --git a/gramps/plugins/db/dbapi/sqlite.py b/gramps/plugins/db/dbapi/sqlite.py index 5a4a0e934..15280d61d 100644 --- a/gramps/plugins/db/dbapi/sqlite.py +++ b/gramps/plugins/db/dbapi/sqlite.py @@ -2,7 +2,7 @@ # Gramps - a GTK+/GNOME based genealogy program # # Copyright (C) 2015-2016 Douglas S. Blank -# Copyright (C) 2016 Nick Hall +# Copyright (C) 2016-2017 Nick Hall # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -20,7 +20,7 @@ # """ -Backend for sqlite database. +Backend for SQLite database. """ #------------------------------------------------------------------------- @@ -29,14 +29,16 @@ Backend for sqlite database. # #------------------------------------------------------------------------- import sqlite3 -import logging +import os import re +import logging #------------------------------------------------------------------------- # # Gramps modules # #------------------------------------------------------------------------- +from gramps.plugins.db.dbapi.dbapi import DBAPI from gramps.gen.db.dbconst import ARRAYSIZE from gramps.gen.const import GRAMPS_LOCALE as glocale @@ -44,10 +46,25 @@ sqlite3.paramstyle = 'qmark' #------------------------------------------------------------------------- # -# Sqlite class +# SQLite class # #------------------------------------------------------------------------- -class Sqlite: +class SQLite(DBAPI): + + def _initialize(self, directory): + if directory == ':memory:': + path_to_db = ':memory:' + else: + path_to_db = os.path.join(directory, 'sqlite.db') + self.dbapi = Connection(path_to_db) + + +#------------------------------------------------------------------------- +# +# Connection class +# +#------------------------------------------------------------------------- +class Connection: """ The Sqlite class is an interface between the DBAPI class which is the Gramps backend for the DBAPI interface and the sqlite3 python module. diff --git a/gramps/plugins/db/dbapi/test/db_test.py b/gramps/plugins/db/dbapi/test/db_test.py index 82a79d7d9..7204a046c 100644 --- a/gramps/plugins/db/dbapi/test/db_test.py +++ b/gramps/plugins/db/dbapi/test/db_test.py @@ -47,8 +47,8 @@ class DbRandomTest(unittest.TestCase): @classmethod def setUpClass(cls): - cls.db = make_database("inmemorydb") - cls.db.load(None) + cls.db = make_database("sqlite") + cls.db.load(":memory:") def setUp(self): self.handles = {'Person': [], 'Family': [], 'Event': [], 'Place': [], @@ -709,8 +709,8 @@ class DbEmptyTest(unittest.TestCase): @classmethod def setUpClass(cls): - cls.db = make_database("inmemorydb") - cls.db.load(None) + cls.db = make_database("sqlite") + cls.db.load(":memory:") ################################################################ # @@ -806,8 +806,8 @@ class DbPersonTest(unittest.TestCase): @classmethod def setUpClass(cls): - cls.db = make_database("inmemorydb") - cls.db.load(None) + cls.db = make_database("sqlite") + cls.db.load(":memory:") def __add_person(self, gender, first_name, surname, trans): person = Person() diff --git a/gramps/plugins/test/db_undo_and_signals_test.py b/gramps/plugins/test/db_undo_and_signals_test.py index 233f9ca5f..3ab25fb87 100644 --- a/gramps/plugins/test/db_undo_and_signals_test.py +++ b/gramps/plugins/test/db_undo_and_signals_test.py @@ -361,7 +361,7 @@ class DbTestClassBase(object): msg="Callback Manager disconnect cb check") -params = [('BsdDb', 'bsddb'), ('DbApi', 'dbapi')] +params = [('BsdDb', 'bsddb'), ('SQLite', 'sqlite')] for name, param in params: cls_name = "TestMyTestClass_%s" % (name, ) diff --git a/po/POTFILES.in b/po/POTFILES.in index 001b6f8c0..4e0104285 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -552,13 +552,13 @@ gramps/gui/widgets/reorderfam.py gramps/gui/widgets/styledtextbuffer.py gramps/gui/widgets/styledtexteditor.py gramps/gui/widgets/validatedmaskedentry.py -gramps/plugins/db/dbapi/dbapi.gpr.py gramps/plugins/db/bsddb/bsddb.gpr.py gramps/plugins/db/bsddb/read.py gramps/plugins/db/bsddb/undoredo.py gramps/plugins/db/bsddb/upgrade.py gramps/plugins/db/bsddb/write.py -gramps/plugins/db/dbapi/inmemorydb.gpr.py +gramps/plugins/db/dbapi/postgresql.gpr.py +gramps/plugins/db/dbapi/sqlite.gpr.py gramps/plugins/docgen/asciidoc.py gramps/plugins/docgen/docgen.gpr.py gramps/plugins/docgen/gtkprint.glade diff --git a/po/POTFILES.skip b/po/POTFILES.skip index 88bbfcb2e..494d4d737 100644 --- a/po/POTFILES.skip +++ b/po/POTFILES.skip @@ -378,10 +378,6 @@ gramps/gui/widgets/valuetoolitem.py # gramps/plugins/__init__.py # -# plugins/db directory -# -gramps/plugins/db/dbapi/inmemorydb.py -# # plugins/docgen directory # gramps/plugins/docgen/__init__.py