diff --git a/gramps/cli/grampscli.py b/gramps/cli/grampscli.py index 7f665d20d..30f8cdc3c 100644 --- a/gramps/cli/grampscli.py +++ b/gramps/cli/grampscli.py @@ -53,6 +53,7 @@ from gramps.gen.dbstate import DbState from gramps.gen.db.exceptions import (DbUpgradeRequiredError, BsddbDowngradeError, DbVersionError, + DbPythonError, DbEnvironmentError, BsddbUpgradeRequiredError, BsddbDowngradeRequiredError, @@ -193,6 +194,9 @@ class CLIDbLoader(object): except DbVersionError as msg: self.dbstate.no_database() self._errordialog( _("Cannot open database"), str(msg)) + except DbPythonError as msg: + self.dbstate.no_database() + self._errordialog( _("Cannot open database"), str(msg)) except OSError as msg: self.dbstate.no_database() self._errordialog( diff --git a/gramps/gen/db/exceptions.py b/gramps/gen/db/exceptions.py index 324a51639..c3a3ac490 100644 --- a/gramps/gen/db/exceptions.py +++ b/gramps/gen/db/exceptions.py @@ -99,6 +99,29 @@ class DbVersionError(Exception): 'min_vers': self.min_vers, 'max_vers': self.max_vers} +class DbPythonError(Exception): + """ + Error used to report that a file could not be read because it is written + in an unsupported version of the Python format. + """ + def __init__(self, tree_vers, min_vers, max_vers): + Exception.__init__(self) + self.tree_vers = tree_vers + self.min_vers = min_vers + self.max_vers = max_vers + + def __str__(self): + return _('The Python version is not supported by this version of ' + 'Gramps.\n\n' + 'This Family Tree is Python version %(tree_vers)s, and this ' + 'version of Gramps supports versions %(min_vers)s to ' + '%(max_vers)s\n\n' + 'Please upgrade to the corresponding version or use ' + 'XML for porting data between different schema versions.') %\ + {'tree_vers': self.tree_vers, + 'min_vers': self.min_vers, + 'max_vers': self.max_vers} + class BsddbDowngradeError(Exception): """ Error used to report that the Berkeley database used to create the family diff --git a/gramps/gen/db/generic.py b/gramps/gen/db/generic.py index 17f658e74..25a219c28 100644 --- a/gramps/gen/db/generic.py +++ b/gramps/gen/db/generic.py @@ -56,6 +56,7 @@ from gramps.gen.db.base import QuerySet from gramps.gen.utils.callback import Callback from gramps.gen.updatecallback import UpdateCallback from gramps.gen.db.dbconst import * +from gramps.gen.db import exceptions from gramps.gen.utils.id import create_id from gramps.gen.lib.researcher import Researcher @@ -755,6 +756,18 @@ class DbGeneric(DbWriteBase, DbReadBase, UpdateCallback, Callback): """ If update is False: then don't update any files """ + db_python_version = self.get_python_version(directory) + current_python_version = sys.version_info[0] + if db_python_version != current_python_version: + raise exceptions.DbPythonError(str(db_python_version), + str(current_python_version), + str(current_python_version)) + db_schema_version = self.get_schema_version(directory) + current_schema_version = self.VERSION[0] + if db_schema_version != current_schema_version: + raise exceptions.DbVersionError(str(db_schema_version), + str(current_schema_version), + str(current_schema_version)) # run backend-specific code: self.initialize_backend(directory) diff --git a/gramps/gui/dbloader.py b/gramps/gui/dbloader.py index b556ddbf8..868a251d3 100644 --- a/gramps/gui/dbloader.py +++ b/gramps/gui/dbloader.py @@ -59,6 +59,7 @@ from gramps.gen.config import config from gramps.gen.db.exceptions import (DbUpgradeRequiredError, BsddbDowngradeError, DbVersionError, + DbPythonError, DbEnvironmentError, BsddbUpgradeRequiredError, BsddbDowngradeRequiredError, @@ -401,6 +402,9 @@ class DbLoader(CLIDbLoader): except DbVersionError as msg: self.dbstate.no_database() self._errordialog( _("Cannot open database"), str(msg)) + except DbPythonError as msg: + self.dbstate.no_database() + self._errordialog( _("Cannot open database"), str(msg)) except DbEnvironmentError as msg: self.dbstate.no_database() self._errordialog( _("Cannot open database"), str(msg)) diff --git a/gramps/plugins/database/dbapi.py b/gramps/plugins/database/dbapi.py index 9ca8fd879..ef62ee4f4 100644 --- a/gramps/plugins/database/dbapi.py +++ b/gramps/plugins/database/dbapi.py @@ -30,6 +30,7 @@ _ = glocale.translation.gettext import dbapi_support import time +import sys import pickle from operator import itemgetter @@ -54,6 +55,42 @@ class DBAPI(DbGeneric): """ pass + def get_python_version(self, directory=None): + """ + Get the version of python that the database was created + under. Assumes 3, if not found. + """ + if directory is None: + directory = self._directory + version = 3 + if directory: + versionpath = os.path.join(directory, "pythonversion.txt") + if os.path.exists(versionpath): + with open(versionpath, "r") as version_file: + version = version_file.read() + version = int(version) + else: + LOG.info("Missing '%s'. Assuming version 3.", versionpath) + return version + + def get_schema_version(self, directory=None): + """ + Get the version of the schema that the database was created + under. Assumes 18, if not found. + """ + if directory is None: + directory = self._directory + version = 18 + if directory: + versionpath = os.path.join(directory, "schemaversion.txt") + if os.path.exists(versionpath): + with open(versionpath, "r") as version_file: + version = version_file.read() + version = int(version) + else: + LOG.info("Missing '%s'. Assuming version 18.", versionpath) + return version + def write_version(self, directory): """Write files for a newly created DB.""" versionpath = os.path.join(directory, str(DBBACKEND)) @@ -63,6 +100,15 @@ class DBAPI(DbGeneric): versionpath = os.path.join(directory, "bdbversion.txt") with open(versionpath, "w") as version_file: version_file.write(str(self.VERSION)) + versionpath = os.path.join(directory, "pickleupgrade.txt") + with open(versionpath, "w") as version_file: + version_file.write("YES") + versionpath = os.path.join(directory, "pythonversion.txt") + with open(versionpath, "w") as version_file: + version_file.write(str(sys.version_info[0])) + versionpath = os.path.join(directory, "schemaversion.txt") + with open(versionpath, "w") as version_file: + version_file.write(str(self.VERSION[0])) # Write default_settings, sqlite.db defaults = os.path.join(os.path.dirname(os.path.abspath(__file__)), "dbapi_support", "defaults")