Example #1
0
    def create_new_db_cli(self, title=None, create_db=True, dbid=None):
        """
        Create a new database.
        """
        new_path = find_next_db_dir()

        os.mkdir(new_path)
        path_name = os.path.join(new_path, NAME_FILE)

        if title is None:
            name_list = [name[0] for name in self.current_names]
            title = find_next_db_name(name_list)

        with open(path_name, "w", encoding='utf8') as name_file:
            name_file.write(title)

        if create_db:
            if dbid is None:
                dbid = config.get('database.backend')
            newdb = make_database(dbid)

        backend_path = os.path.join(new_path, DBBACKEND)
        with open(backend_path, "w", encoding='utf8') as backend_file:
            backend_file.write(dbid)

        (tval, last) = time_val(new_path)

        self.current_names.append((title, new_path, path_name,
                                   last, tval, False, "", dbid))
        return new_path, title
Example #2
0
    def create_new_db_cli(self, title=None, create_db=True, dbid=None):
        """
        Create a new database.
        """
        new_path = find_next_db_dir()

        os.mkdir(new_path)
        path_name = os.path.join(new_path, NAME_FILE)

        if title is None:
            name_list = [name[0] for name in self.current_names]
            title = find_next_db_name(name_list)

        with open(path_name, "w", encoding='utf8') as name_file:
            name_file.write(title)

        if create_db:
            if dbid is None:
                dbid = config.get('database.backend')
            newdb = make_database(dbid)

        backend_path = os.path.join(new_path, DBBACKEND)
        with open(backend_path, "w", encoding='utf8') as backend_file:
            backend_file.write(dbid)

        (tval, last) = time_val(new_path)

        self.current_names.append(
            (title, new_path, path_name, last, tval, False, "", dbid))
        return new_path, title
Example #3
0
    def read_file(self, filename, mode: str, username: str, password: str):
        """Open a database from a file."""
        if (
            mode == DBMODE_W
            and os.path.exists(filename)
            and not os.access(filename, os.W_OK)
        ):
            mode = DBMODE_R
            LOG.warning(
                "%s. %s",
                _("Read only database"),
                _("You do not have write access " "to the selected file."),
            )

        dbid_path = os.path.join(filename, DBBACKEND)
        with open(dbid_path) as file_handle:
            dbid = file_handle.read().strip()

        db = make_database(dbid)

        self.dbstate.change_database(db)
        self.dbstate.db.disable_signals()

        self.dbstate.db.load(
            filename, callback=None, mode=mode, username=username, password=password,
        )
Example #4
0
    def create_new_db_cli(self, title=None, create_db=True, dbid=None):
        """
        Create a new database.
        """
        new_path = find_next_db_dir()

        os.mkdir(new_path)
        path_name = os.path.join(new_path, NAME_FILE)

        if title is None:
            name_list = [name[0] for name in self.current_names]
            title = find_next_db_name(name_list)

        with open(path_name, "w", encoding='utf8') as name_file:
            name_file.write(title)

        if create_db:
            # write the version number into metadata
            if dbid is None:
                dbid = "bsddb"
            newdb = make_database(dbid)
            newdb.write_version(new_path)

        (tval, last) = time_val(new_path)

        self.current_names.append(
            (title, new_path, path_name, last, tval, False, "", dbid))
        return new_path, title
Example #5
0
    def create_new_db_cli(self, title=None, create_db=True, dbid=None):
        """
        Create a new database.
        """
        new_path = find_next_db_dir()

        os.mkdir(new_path)
        path_name = os.path.join(new_path, NAME_FILE)

        if title is None:
            name_list = [name[0] for name in self.current_names]
            title = find_next_db_name(name_list)

        with open(path_name, "w", encoding='utf8') as name_file:
            name_file.write(title)

        if create_db:
            # write the version number into metadata
            if dbid is None:
                dbid = "bsddb"
            newdb = make_database(dbid)
            newdb.write_version(new_path)

        (tval, last) = time_val(new_path)

        self.current_names.append((title, new_path, path_name,
                                   last, tval, False, "", dbid))
        return new_path, title
 def setUpClass(cls):
     # print("doing setup with", cls.param)
     set_det_id(True)  # handles must be deterministic for this test
     cls.dbstate = DbState()
     cls.dbman = CLIDbManager(cls.dbstate)
     dirpath, _name = cls.dbman.create_new_db_cli("Test: %s" % cls.param,
                                                  dbid=cls.param)
     cls.db = make_database(cls.param)
     cls.db.load(dirpath, None)
Example #7
0
    def setUp(self):
        self.database1 = make_database("bsddb")
        try:
            os.mkdir("/tmp/bsddb_exportsql_1")
        except:
            pass
        self.database1.load("/tmp/bsddb_exportsql_1")

        importXML(self.database1, gramps_path + "/example/gramps/example.gramps", User())
        exportSQL(self.database1, "/tmp/exported1.sql")

        self.database2 = make_database("bsddb")
        try:
            os.mkdir("/tmp/bsddb_exportsql_2")
        except:
            pass

        self.database2.load("/tmp/bsddb_exportsql_2")
 def setUpClass(cls):
     # print("doing setup with", cls.param)
     set_det_id(True)  # handles must be deterministic for this test
     cls.dbstate = DbState()
     cls.dbman = CLIDbManager(cls.dbstate)
     dirpath, _name = cls.dbman.create_new_db_cli("Test: %s" % cls.param,
                                                  dbid=cls.param)
     cls.db = make_database(cls.param)
     cls.db.load(dirpath, None)
Example #9
0
    def setUp(self):
        def dummy_callback(dummy):
            pass

        self.dbstate = DbState()
        self.dbman = CLIDbManager(self.dbstate)
        dirpath, name = self.dbman.create_new_db_cli("Test: bsddb", dbid="bsddb")
        self._db = make_database("bsddb")
        self._db.load(dirpath, None)
Example #10
0
    def setUp(self):
        def dummy_callback(dummy):
            pass

        self.dbstate = DbState()
        self.dbman = CLIDbManager(self.dbstate)
        dirpath, name = self.dbman.create_new_db_cli("Test: bsddb", dbid="bsddb")
        self._db = make_database("bsddb")
        self._db.load(dirpath, None)
Example #11
0
 def __init__(self):
     """
     Initalize the state with an empty (and useless) DummyDb. This is just a
     place holder until a real DB is assigned.
     """
     Callback.__init__(self)
     self.db = make_database("dummydb")
     self.open = False  #  Deprecated - use DbState.is_open()
     self.stack = []
Example #12
0
 def __convert_db(self, name, dirname):
     """
     Actually convert the family tree into the default database backend.
     """
     try:
         db = open_database(name)
     except:
         ErrorDialog(_("Opening the '%s' database") % name,
                     _("An attempt to convert the database failed. "
                       "Perhaps it needs updating."),
                     parent=self.top)
         return
     plugin_manager = GuiPluginManager.get_instance()
     export_function = None
     for plugin in plugin_manager.get_export_plugins():
         if plugin.get_extension() == "gramps":
             export_function = plugin.get_export_function()
             break
     ## Next, get an XML dump:
     if export_function is None:
         ErrorDialog(_("Converting the '%s' database") % name,
                     _("An attempt to export the database failed."),
                     parent=self.top)
         db.close(user=self.user)
         return
     self.__start_cursor(_("Converting data..."))
     xml_file = os.path.join(dirname, "backup.gramps")
     export_function(db, xml_file, self.user)
     db.close(user=self.user)
     count = 1
     new_text = "%s %s" % (name, _("(Converted #%d)") % count)
     while self.existing_name(new_text):
         count += 1
         new_text = "%s %s" % (name, _("(Converted #%d)") % count)
     dbid = config.get('database.backend')
     new_path, newname = self._create_new_db(new_text,
                                             dbid=dbid,
                                             edit_entry=False)
     ## Create a new database of correct type:
     dbase = make_database(dbid)
     dbase.load(new_path)
     ## import from XML
     import_function = None
     for plugin in plugin_manager.get_import_plugins():
         if plugin.get_extension() == "gramps":
             import_function = plugin.get_import_function()
     if import_function is None:
         ErrorDialog(_("Converting the '%s' database") % name,
                     _("An attempt to import into the database failed."),
                     parent=self.top)
     else:
         import_function(dbase, xml_file, self.user)
     self.__end_cursor()
     dbase.close(user=self.user)
     self.__populate()
     self._select_default()
Example #13
0
 def no_database(self):
     """
     Closes the database without a new database (except for the DummyDb)
     """
     self.emit('no-database', ())
     if self.is_open():
         self.db.close()
     self.db = make_database("dummydb")
     self.open = False
     self.emit('database-changed', (self.db, ))
Example #14
0
    def test_mediapath(self):
        """
        Test media path variables.
        """

        # Create database
        db = make_database("bsddb")
        path = get_empty_tempdir("utils_file_test")
        db.write_version(path)
        db.load(path)

        # Test without db.mediapath set
        self.assertEqual(media_path(db), os.path.normcase(os.path.normpath(
            os.path.abspath(USER_HOME))))
        self.assertTrue(os.path.exists(media_path(db)))

        # Test with absolute db.mediapath
        db.set_mediapath(os.path.abspath(USER_HOME) + "/test_abs")
        self.assertEqual(media_path(db), os.path.normcase(os.path.normpath(
            os.path.abspath(USER_HOME + "/test_abs"))))

        # Test with relative db.mediapath
        db.set_mediapath("test_rel")
        self.assertEqual(media_path(db), os.path.normcase(os.path.normpath(
            os.path.abspath(TEMP_DIR + "/utils_file_test/test_rel"))))

        # Test with environment variable
        db.set_mediapath("/test/{VERSION}/test_var")
        self.assertEqual(media_path(db), os.path.normcase(os.path.normpath(
            os.path.abspath("/test/" + VERSION + "/test_var"))))
        db.set_mediapath("{USER_PLUGINS}/test_var")
        self.assertEqual(media_path(db), os.path.normcase(os.path.normpath(
            os.path.abspath(USER_PLUGINS + "/test_var"))))
        db.set_mediapath("{VERSION}/test_var")
        self.assertEqual(media_path(db), os.path.normcase(os.path.normpath(
            os.path.abspath(TEMP_DIR + "/utils_file_test/" + VERSION +
                            "/test_var"))))

        # Test with $GRAMPSHOME environment variable not set
        old_env = os.environ.copy()
        if 'GRAMPSHOME' in os.environ:
            del os.environ['GRAMPSHOME']
        db.set_mediapath("{GRAMPSHOME}/test_var")
        self.assertEqual(media_path(db), os.path.normcase(os.path.normpath(
            os.path.abspath(USER_HOME + "/test_var"))))

        # Test with $GRAMPSHOME environment variable set
        os.environ['GRAMPSHOME'] = "/this/is/a/test"
        db.set_mediapath("{GRAMPSHOME}/test_var")
        self.assertEqual(media_path(db), os.path.normcase(os.path.normpath(
            os.path.abspath("/this/is/a/test/test_var"))))

        # Restore environment
        os.environ = old_env
Example #15
0
 def __convert_db(self, name, dirname):
     """
     Actually convert the family tree into the default database backend.
     """
     try:
         db = open_database(name)
     except:
         ErrorDialog(_("Opening the '%s' database") % name,
                     _("An attempt to convert the database failed. "
                       "Perhaps it needs updating."), parent=self.top)
         return
     plugin_manager = GuiPluginManager.get_instance()
     export_function = None
     for plugin in plugin_manager.get_export_plugins():
         if plugin.get_extension() == "gramps":
             export_function = plugin.get_export_function()
             break
     ## Next, get an XML dump:
     if export_function is None:
         ErrorDialog(_("Converting the '%s' database") % name,
                     _("An attempt to export the database failed."),
                     parent=self.top)
         db.close(user=self.user)
         return
     self.__start_cursor(_("Converting data..."))
     xml_file = os.path.join(dirname, "backup.gramps")
     export_function(db, xml_file, self.user)
     db.close(user=self.user)
     count = 1
     new_text = "%s %s" % (name, _("(Converted #%d)") % count)
     while self.existing_name(new_text):
         count += 1
         new_text = "%s %s" % (name, _("(Converted #%d)") % count)
     dbid = config.get('database.backend')
     new_path, newname = self._create_new_db(new_text, dbid=dbid,
                                             edit_entry=False)
     ## Create a new database of correct type:
     dbase = make_database(dbid)
     dbase.load(new_path)
     ## import from XML
     import_function = None
     for plugin in plugin_manager.get_import_plugins():
         if plugin.get_extension() == "gramps":
             import_function = plugin.get_import_function()
     if import_function is None:
         ErrorDialog(_("Converting the '%s' database") % name,
                     _("An attempt to import into the database failed."),
                     parent=self.top)
     else:
         import_function(dbase, xml_file, self.user)
     self.__end_cursor()
     dbase.close(user=self.user)
     self.__populate()
     self._select_default()
Example #16
0
    def __checkout_copy(self, parent_name, name, revision, db_path):
        """
        Create a new database, then extracts a revision from RCS and
        imports it into the db
        """
        new_path, newname = self._create_new_db("%s : %s" % (parent_name, name))

        self.__start_cursor(_("Extracting archive..."))

        dbase = make_database("bsddb")
        dbase.load(new_path)

        self.__start_cursor(_("Importing archive..."))
        check_out(dbase, revision, db_path, self.user)
        self.__end_cursor()
        dbase.close(user=self.user)
Example #17
0
    def __checkout_copy(self, parent_name, name, revision, db_path):
        """
        Create a new database, then extracts a revision from RCS and
        imports it into the db
        """
        new_path, newname = self._create_new_db("%s : %s" % (parent_name, name))

        self.__start_cursor(_("Extracting archive..."))

        dbase = make_database("bsddb")
        dbase.load(new_path)

        self.__start_cursor(_("Importing archive..."))
        check_out(dbase, revision, db_path, self.user)
        self.__end_cursor()
        dbase.close(user=self.user)
Example #18
0
    def __import_action(self):
        """
        Take action for all given import files.

        .. note:: Family trees are not supported.

        If a family tree is open, the import happens on top of it. If not
        open, a new family tree is created, and the import done. If this
        is CLI, the created tree is deleted at the end (as some action will
        have happened that is now finished), if this is GUI, it is opened.
        """
        if self.imports:
            self.cl_bool = bool(self.exports or self.actions or self.cl_bool)

            if not self.open:
                # Create empty dir for imported database(s)
                if self.gui:
                    dbid = config.get('database.backend')
                    self.imp_db_path, title = self.dbman.create_new_db_cli(
                        dbid=dbid)
                else:
                    self.imp_db_path = get_empty_tempdir("import_dbdir")
                    dbid = config.get('database.backend')
                    newdb = make_database(dbid)
                    versionpath = os.path.join(self.imp_db_path,
                                               str(DBBACKEND))
                    with open(versionpath, "w") as version_file:
                        version_file.write(dbid)

                try:
                    self.smgr.open_activate(self.imp_db_path, self.username,
                                            self.password)
                    msg = _("Created empty Family Tree successfully")
                    print(msg, file=sys.stderr)
                except:
                    print(_("Error opening the file."), file=sys.stderr)
                    print(_("Exiting..."), file=sys.stderr)
                    sys.exit(1)

            for imp in self.imports:
                msg = _("Importing: file %(filename)s, format %(format)s.") % {
                    'filename': imp[0],
                    'format': imp[1]
                }
                print(msg, file=sys.stderr)
                self.cl_import(imp[0], imp[1])
Example #19
0
    def setUp(self):
        db = make_database("inmemorydb")
        db.load(None)
        with DbTxn("Test", db) as trans:
            # Add some people:
            person1 = Person()
            person1.primary_name = Name()
            person1.primary_name.surname_list.append(Surname())
            person1.primary_name.surname_list[0].surname = "Smith"
            person1.gramps_id = "I0001"
            db.add_person(person1, trans) # person gets a handle

            # Add some families:
            family1 = Family()
            family1.father_handle = person1.handle
            family1.gramps_id = "F0001"
            db.add_family(family1, trans)
        self.db = db
Example #20
0
 def test_editreference(self):
     dbstate = DbState()
     db = make_database("bsddb")
     path = "/tmp/edit_ref_test"
     try:
         os.mkdir(path)
     except:
         pass
     db.load(path)
     dbstate.change_database(db)
     source = Place()
     source.gramps_id = "P0001"
     dbstate.db.place_map[source.handle] = source.serialize()
     editor = MockEditReference(dbstate, uistate=None, track=[],
                                source=source, source_ref=None, update=None)
     with patch('gramps.gui.editors.editreference.ErrorDialog') as MockED:
         editor.check_for_duplicate_id("Place")
         self.assertTrue(MockED.called)
Example #21
0
    def get_dbdir_summary(self, dirpath, name):
        """
        dirpath: full path to database
        name: proper name of family tree

        Returns dictionary of summary item.
        Should include at least, if possible:

        _("Path")
        _("Family Tree")
        _("Last accessed")
        _("Database")
        _("Locked?")

        and these details:

        _("Number of people")
        _("Version")
        _("Schema version")
        """
        dbid = "bsddb"
        dbid_path = os.path.join(dirpath, "database.txt")
        if os.path.isfile(dbid_path):
            with open(dbid_path) as file:
                dbid = file.read().strip()
        if not self.is_locked(dirpath):
            try:
                database = make_database(dbid)
                database.load(dirpath, None, update=False)
                retval = database.get_summary()
                database.close(update=False)
            except Exception as msg:
                retval = {_("Unavailable"): str(msg)[:74] + "..."}
        else:
            retval = {_("Unavailable"): "locked"}
        retval.update({
            _("Family Tree"): name,
            _("Path"): dirpath,
            _("Database"): dbid,
            _("Last accessed"): time_val(dirpath)[1],
            _("Locked?"): self.is_locked(dirpath),
        })
        return retval
Example #22
0
    def get_dbdir_summary(self, dirpath, name):
        """
        dirpath: full path to database
        name: proper name of family tree

        Returns dictionary of summary item.
        Should include at least, if possible:

        _("Path")
        _("Family Tree")
        _("Last accessed")
        _("Database")
        _("Locked?")

        and these details:

        _("Number of people")
        _("Version")
        _("Schema version")
        """
        dbid = "bsddb"
        dbid_path = os.path.join(dirpath, "database.txt")
        if os.path.isfile(dbid_path):
            with open(dbid_path) as file:
                dbid = file.read().strip()
        if not self.is_locked(dirpath):
            try:
                database = make_database(dbid)
                database.load(dirpath, None, update=False)
                retval = database.get_summary()
                database.close(update=False)
            except Exception as msg:
                retval = {_("Unavailable"): str(msg)[:74] + "..."}
        else:
            retval = {_("Unavailable"): "locked"}
        retval.update({_("Family Tree"): name,
                       _("Path"): dirpath,
                       _("Database"): self.get_backend_name_from_dbid(dbid),
                       _("Last accessed"): time_val(dirpath)[1],
                       _("Locked?"): self.is_locked(dirpath),
                      })
        return retval
Example #23
0
    def __import_action(self):
        """
        Take action for all given import files.

        .. note:: Family trees are not supported.

        If a family tree is open, the import happens on top of it. If not
        open, a new family tree is created, and the import done. If this
        is CLI, the created tree is deleted at the end (as some action will
        have happened that is now finished), if this is GUI, it is opened.
        """
        if self.imports:
            self.cl_bool = bool(self.exports or self.actions or self.cl_bool)

            if not self.open:
                # Create empty dir for imported database(s)
                if self.gui:
                    dbid = config.get('database.backend')
                    self.imp_db_path, title = self.dbman.create_new_db_cli(
                        dbid=dbid)
                else:
                    self.imp_db_path = get_empty_tempdir("import_dbdir")
                    dbid = config.get('database.backend')
                    newdb = make_database(dbid)
                    newdb.write_version(self.imp_db_path)

                try:
                    self.smgr.open_activate(self.imp_db_path)
                    msg = _("Created empty Family Tree successfully")
                    print(msg, file=sys.stderr)
                except:
                    print(_("Error opening the file."), file=sys.stderr)
                    print(_("Exiting..."), file=sys.stderr)
                    sys.exit(1)

            for imp in self.imports:
                msg = _("Importing: file %(filename)s, format %(format)s."
                       ) % {'filename' : imp[0],
                            'format'   : imp[1]}
                print(msg, file=sys.stderr)
                self.cl_import(imp[0], imp[1])
Example #24
0
 def test_editreference(self):
     dbstate = DbState()
     db = make_database("bsddb")
     path = "/tmp/edit_ref_test"
     try:
         os.mkdir(path)
     except:
         pass
     db.load(path)
     dbstate.change_database(db)
     source = Place()
     source.gramps_id = "P0001"
     dbstate.db.place_map[source.handle] = source.serialize()
     editor = MockEditReference(dbstate,
                                uistate=None,
                                track=[],
                                source=source,
                                source_ref=None,
                                update=None)
     with patch('gramps.gui.editors.editreference.ErrorDialog') as MockED:
         editor.check_for_duplicate_id("Place")
         self.assertTrue(MockED.called)
Example #25
0
    def import_new_db(self, filename, user):
        """
        Attempt to import the provided file into a new database.
        A new database will only be created if an appropriate importer was
        found.

        :param filename: a fully-qualified path, filename, and
                         extension to open.

        :param user: a :class:`.cli.user.User` or :class:`.gui.user.User`
                     instance for managing user interaction.

        :returns: A tuple of (new_path, name) for the new database
                  or (None, None) if no import was performed.
        """
        pmgr = BasePluginManager.get_instance()
        # check to see if it isn't a filename directly:
        if not os.path.isfile(filename):
            # Allow URL names here; make temp file if necessary
            url = urlparse(filename)
            if url.scheme != "":
                if url.scheme == "file":
                    filename = url2pathname(filename[7:])
                else:
                    url_fp = urlopen(filename)  # open URL
                    # make a temp local file:
                    ext = os.path.splitext(url.path)[1]
                    fd, filename = tempfile.mkstemp(suffix=ext)
                    temp_fp = os.fdopen(fd, "w")
                    # read from URL:
                    data = url_fp.read()
                    # write locally:
                    temp_fp.write(data)
                    url_fp.close()
                    temp_fp.close()

        (name, ext) = os.path.splitext(os.path.basename(filename))
        format = ext[1:].lower()

        for plugin in pmgr.get_import_plugins():
            if format == plugin.get_extension():

                dbid = config.get('database.backend')
                new_path, name = self._create_new_db(name,
                                                     dbid=dbid,
                                                     edit_entry=False)

                # Create a new database
                self.__start_cursor(_("Importing data..."))

                dbase = make_database(dbid)
                dbase.load(new_path, user.callback)

                import_function = plugin.get_import_function()
                import_function(dbase, filename, user)

                # finish up
                self.__end_cursor()
                dbase.close()

                return new_path, name
        return None, None
Example #26
0
 def setUpClass(cls):
     cls.db = make_database("inmemorydb")
     cls.db.load(None)
Example #27
0
    def read_file(self, filename, username=None, password=None):
        """
        This method takes care of changing database, and loading the data.
        In 3.0 we only allow reading of real databases of filetype
        'x-directory/normal'

        This method should only return on success.
        Returning on failure makes no sense, because we cannot recover,
        since database has already been changed.
        Therefore, any errors should raise exceptions.

        On success, return with the disabled signals. The post-load routine
        should enable signals, as well as finish up with other UI goodies.
        """

        if os.path.exists(filename):
            if not os.access(filename, os.W_OK):
                mode = "r"
                self._warn(
                    _('Read only database'),
                    _('You do not have write access '
                      'to the selected file.'))
            else:
                mode = "w"
        else:
            mode = 'w'

        self.dbstate.no_database()

        self.uistate.progress.show()
        self.uistate.pulse_progressbar(0)

        force_schema_upgrade = False
        try:
            while True:
                dbid_path = os.path.join(filename, DBBACKEND)
                if os.path.isfile(dbid_path):
                    with open(dbid_path) as fp:
                        dbid = fp.read().strip()
                else:
                    dbid = "bsddb"

                db = make_database(dbid)
                db.disable_signals()
                if db.requires_login() and username is None:
                    login = GrampsLoginDialog(self.uistate)
                    credentials = login.run()
                    if credentials is None:
                        return
                    username, password = credentials

                try:
                    db.load(filename,
                            self.uistate.pulse_progressbar,
                            mode,
                            force_schema_upgrade,
                            username=username,
                            password=password)
                    if self.dbstate.is_open():
                        self.dbstate.db.close(
                            user=User(callback=self.uistate.pulse_progressbar,
                                      uistate=self.uistate,
                                      dbstate=self.dbstate))
                    self.dbstate.change_database(db)
                    break
                except (DbSupportedError, DbUpgradeRequiredError) as msg:
                    if (force_schema_upgrade or QuestionDialog2(
                            _("Are you sure you want "
                              "to upgrade this Family Tree?"),
                            str(msg),
                            _("I have made a backup,\n"
                              "please upgrade my Family Tree"),
                            _("Cancel"),
                            parent=self.uistate.window).run()):
                        force_schema_upgrade = True
                        make_zip_backup(filename)
                    else:
                        self.dbstate.no_database()
                        break
        # Get here is there is an exception the while loop does not handle
        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 DbConnectionError as msg:
            self.dbstate.no_database()
            self._warn(_("Cannot open database"), str(msg))
        except OSError as msg:
            self.dbstate.no_database()
            self._errordialog(
                _("Could not open file: %s") % filename, str(msg))
        except DbError as msg:
            self.dbstate.no_database()
            self._dberrordialog(msg)
        except Exception as newerror:
            self.dbstate.no_database()
            self._dberrordialog(str(newerror))

        self.uistate.progress.hide()
        return True
Example #28
0
    def read_file(self, filename, username, password):
        """
        This method takes care of changing database, and loading the data.
        In 3.0 we only allow reading of real databases of filetype
        'x-directory/normal'

        This method should only return on success.
        Returning on failure makes no sense, because we cannot recover,
        since database has already been changed.
        Therefore, any errors should raise exceptions.

        On success, return with the disabled signals. The post-load routine
        should enable signals, as well as finish up with other UI goodies.
        """

        if os.path.exists(filename):
            if not os.access(filename, os.W_OK):
                mode = "r"
                self._warn(_('Read only database'),
                           _('You do not have write access '
                             'to the selected file.'))
            else:
                mode = "w"
        else:
            mode = 'w'

        dbid_path = os.path.join(filename, DBBACKEND)
        if os.path.isfile(dbid_path):
            with open(dbid_path) as file:
                dbid = file.read().strip()
        else:
            dbid = "bsddb"

        db = make_database(dbid)

        self.dbstate.change_database(db)
        self.dbstate.db.disable_signals()

        self._begin_progress()

        try:
            self.dbstate.db.load(filename, self._pulse_progress, mode,
                                 username=username, password=password)
        except DbEnvironmentError as msg:
            self.dbstate.no_database()
            self._errordialog(_("Cannot open database"), str(msg))
        except BsddbUpgradeRequiredError as msg:
            self.dbstate.no_database()
            self._errordialog(_("Cannot open database"), str(msg))
        except BsddbDowngradeRequiredError as msg:
            self.dbstate.no_database()
            self._errordialog(_("Cannot open database"), str(msg))
        except BsddbDowngradeError as msg:
            self.dbstate.no_database()
            self._errordialog(_("Cannot open database"), str(msg))
        except DbUpgradeRequiredError as msg:
            self.dbstate.no_database()
            self._errordialog(_("Cannot open database"), str(msg))
        except PythonDowngradeError as msg:
            self.dbstate.no_database()
            self._errordialog(_("Cannot open database"), str(msg))
        except PythonUpgradeRequiredError as msg:
            self.dbstate.no_database()
            self._errordialog(_("Cannot open database"), str(msg))
        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 DbConnectionError as msg:
            self.dbstate.no_database()
            self._errordialog(_("Cannot open database"), str(msg))
        except OSError as msg:
            self.dbstate.no_database()
            self._errordialog(
                _("Could not open file: %s") % filename, str(msg))
        except DbError as msg:
            self.dbstate.no_database()
            self._dberrordialog(msg)
        except Exception:
            self.dbstate.no_database()
            LOG.error("Failed to open database.", exc_info=True)
        return True
Example #29
0
    def __repair_db(self, obj):
        """
        Start the repair process by calling the start_editing option on
        the line with the cursor.
        """
        store, node = self.selection.get_selected()
        dirname = store[node][1]

        #First ask user if he is really sure :-)
        yes_no = QuestionDialog2(
            _("Repair Family Tree?"),
            _("If you click %(bold_start)sProceed%(bold_end)s, Gramps will "
              "attempt to recover your Family Tree from the last good "
              "backup. There are several ways this can cause unwanted "
              "effects, so %(bold_start)sbackup%(bold_end)s the "
              "Family Tree first.\nThe Family Tree you have selected "
              "is stored in %(dirname)s.\n\n"
              "Before doing a repair, verify that the Family Tree can "
              "really no longer be opened, as the database back-end can "
              "recover from some errors automatically.\n\n"
              "%(bold_start)sDetails:%(bold_end)s Repairing a Family Tree "
              "actually uses the last backup of the Family Tree, which "
              "Gramps stored on last use. If you have worked for "
              "several hours/days without closing Gramps, then all "
              "this information will be lost! If the repair fails, then "
              "the original Family Tree will be lost forever, hence "
              "a backup is needed. If the repair fails, or too much "
              "information is lost, you can fix the original "
              "Family Tree manually. For details, see the webpage\n"
              "%(gramps_wiki_recover_url)s\n"
              "Before doing a repair, try to open the Family Tree "
              "in the normal manner. Several errors that trigger the "
              "repair button can be fixed automatically. "
              "If this is the case, you can disable the repair button "
              "by removing the file %(recover_file)s in the "
              "Family Tree directory.") % {
                  'bold_start': '<b>',
                  'bold_end': '</b>',
                  'recover_file': '<i>need_recover</i>',
                  'gramps_wiki_recover_url':
                  URL_WIKISTRING + 'Recover_corrupted_family_tree',
                  'dirname': dirname
              },
            _("Proceed, I have taken a backup"),
            _("Stop"),
            parent=self.top)
        prompt = yes_no.run()
        if not prompt:
            return

        opened = store[node][OPEN_COL]
        if opened:
            self.dbstate.no_database()

        # delete files that are not backup files or the .txt file
        for filename in os.listdir(dirname):
            if os.path.splitext(filename)[1] not in (".gbkp", ".txt"):
                fname = os.path.join(dirname, filename)
                os.unlink(fname)

        dbase = make_database("bsddb")
        dbase.load(dirname, None)

        self.__start_cursor(_("Rebuilding database from backup files"))

        try:
            dbase.restore()
        except DbException as msg:
            ErrorDialog(_("Error restoring backup data"), msg, parent=self.top)

        self.__end_cursor()

        dbase.close(user=self.user)
        self.dbstate.no_database()
        self.__populate()
        self._select_default()
Example #30
0
    def import_new_db(self, filename, user):
        """
        Attempt to import the provided file into a new database.
        A new database will only be created if an appropriate importer was
        found.

        :param filename: a fully-qualified path, filename, and
                         extension to open.

        :param user: a :class:`.cli.user.User` or :class:`.gui.user.User`
                     instance for managing user interaction.

        :returns: A tuple of (new_path, name) for the new database
                  or (None, None) if no import was performed.
        """
        pmgr = BasePluginManager.get_instance()
        # check to see if it isn't a filename directly:
        if not os.path.isfile(filename):
            # Allow URL names here; make temp file if necessary
            url = urlparse(filename)
            if url.scheme != "":
                if url.scheme == "file":
                    filename = url2pathname(filename[7:])
                else:
                    url_fp = urlopen(filename) # open URL
                    # make a temp local file:
                    ext = os.path.splitext(url.path)[1]
                    fd, filename = tempfile.mkstemp(suffix=ext)
                    temp_fp = os.fdopen(fd, "w")
                    # read from URL:
                    data = url_fp.read()
                    # write locally:
                    temp_fp.write(data)
                    url_fp.close()
                    from  gramps.gen.db.dbconst import BDBVERSFN
                    # name not set
                    (name, ext) = os.path.splitext(os.path.basename(filename))
                    versionpath = os.path.join(name, BDBVERSFN)
                    # dbase not set
                    dbase = make_database("bsddb")
                    _LOG.debug("Write bsddb version %s", str(dbase.version()))
                    with open(versionpath, "w") as version_file:
                        version_file.write(str(dbase.version()))
                    temp_fp.close()

        (name, ext) = os.path.splitext(os.path.basename(filename))
        format = ext[1:].lower()

        for plugin in pmgr.get_import_plugins():
            if format == plugin.get_extension():

                new_path, name = self._create_new_db(name, edit_entry=False)

                # Create a new database
                self.__start_cursor(_("Importing data..."))

                ## Use bsddb, for now, because we assumed that above.
                dbid = "bsddb" ## config.get('database.backend')
                dbase = make_database(dbid)
                dbase.load(new_path, user.callback)

                import_function = plugin.get_import_function()
                import_function(dbase, filename, user)

                # finish up
                self.__end_cursor()
                dbase.close()

                return new_path, name
        return None, None
Example #31
0
    def read_file(self, filename):
        """
        This method takes care of changing database, and loading the data.
        In 3.0 we only allow reading of real databases of filetype
        'x-directory/normal'

        This method should only return on success.
        Returning on failure makes no sense, because we cannot recover,
        since database has already been changed.
        Therefore, any errors should raise exceptions.

        On success, return with the disabled signals. The post-load routine
        should enable signals, as well as finish up with other UI goodies.
        """

        if os.path.exists(filename):
            if not os.access(filename, os.W_OK):
                mode = "r"
                self._warn(_('Read only database'),
                                             _('You do not have write access '
                                               'to the selected file.'))
            else:
                mode = "w"
        else:
            mode = 'w'

        dbid_path = os.path.join(filename, DBBACKEND)
        if os.path.isfile(dbid_path):
            with open(dbid_path) as fp:
                dbid = fp.read().strip()
        else:
            dbid = "bsddb"

        db = make_database(dbid)
        db.disable_signals()
        self.dbstate.no_database()

        self._begin_progress()

        force_schema_upgrade = False
        force_bsddb_upgrade = False
        force_bsddb_downgrade = False
        force_python_upgrade = False
        try:
            while True:
                try:
                    db.load(filename, self._pulse_progress,
                            mode, force_schema_upgrade,
                            force_bsddb_upgrade,
                            force_bsddb_downgrade,
                            force_python_upgrade)
                    db.set_save_path(filename)
                    if self.dbstate.is_open():
                        self.dbstate.db.close(
                            user=User(callback=self._pulse_progress,
                                      uistate=self.uistate,
                                      dbstate=self.dbstate))
                    self.dbstate.change_database(db)
                    break
                except DbUpgradeRequiredError as msg:
                    if QuestionDialog2(_("Are you sure you want "
                                         "to upgrade this Family Tree?"),
                                       str(msg),
                                       _("I have made a backup,\n"
                                         "please upgrade my Family Tree"),
                                       _("Cancel"),
                                       parent=self.uistate.window).run():
                        force_schema_upgrade = True
                        force_bsddb_upgrade = False
                        force_bsddb_downgrade = False
                        force_python_upgrade = False
                    else:
                        self.dbstate.no_database()
                        break
                except BsddbUpgradeRequiredError as msg:
                    if QuestionDialog2(_("Are you sure you want "
                                         "to upgrade this Family Tree?"),
                                       str(msg),
                                       _("I have made a backup,\n"
                                         "please upgrade my Family Tree"),
                                       _("Cancel"),
                                       parent=self.uistate.window).run():
                        force_schema_upgrade = False
                        force_bsddb_upgrade = True
                        force_bsddb_downgrade = False
                        force_python_upgrade = False
                    else:
                        self.dbstate.no_database()
                        break
                except BsddbDowngradeRequiredError as msg:
                    if QuestionDialog2(_("Are you sure you want "
                                         "to downgrade this Family Tree?"),
                                       str(msg),
                                       _("I have made a backup,\n"
                                         "please downgrade my Family Tree"),
                                       _("Cancel"),
                                       parent=self.uistate.window).run():
                        force_schema_upgrade = False
                        force_bsddb_upgrade = False
                        force_bsddb_downgrade = True
                        force_python_upgrade = False
                    else:
                        self.dbstate.no_database()
                        break
                except PythonUpgradeRequiredError as msg:
                    if QuestionDialog2(_("Are you sure you want "
                                         "to upgrade this Family Tree?"),
                                       str(msg),
                                       _("I have made a backup,\n"
                                         "please upgrade my Family Tree"),
                                       _("Cancel"),
                                       parent=self.uistate.window).run():
                        force_schema_upgrade = False
                        force_bsddb_upgrade = False
                        force_bsddb_downgrade = False
                        force_python_upgrade = True
                    else:
                        self.dbstate.no_database()
                        break
        # Get here is there is an exception the while loop does not handle
        except BsddbDowngradeError as msg:
            self.dbstate.no_database()
            self._warn( _("Cannot open database"), str(msg))
        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))
        except PythonDowngradeError as msg:
            self.dbstate.no_database()
            self._warn( _("Cannot open database"), str(msg))
        except OSError as msg:
            self.dbstate.no_database()
            self._errordialog(
                _("Could not open file: %s") % filename, str(msg))
        except DbError as msg:
            self.dbstate.no_database()
            self._dberrordialog(msg)
        except Exception as newerror:
            self.dbstate.no_database()
            self._dberrordialog(str(newerror))
        self._end_progress()
        return True
Example #32
0
    def __repair_db(self, obj):
        """
        Start the repair process by calling the start_editing option on
        the line with the cursor.
        """
        store, node = self.selection.get_selected()
        dirname = store[node][1]

        #First ask user if he is really sure :-)
        yes_no = QuestionDialog2(
            _("Repair Family Tree?"),
            _("If you click %(bold_start)sProceed%(bold_end)s, Gramps will "
              "attempt to recover your Family Tree from the last good "
              "backup. There are several ways this can cause unwanted "
              "effects, so %(bold_start)sbackup%(bold_end)s the "
              "Family Tree first.\nThe Family Tree you have selected "
              "is stored in %(dirname)s.\n\n"
              "Before doing a repair, verify that the Family Tree can "
              "really no longer be opened, as the database back-end can "
              "recover from some errors automatically.\n\n"
              "%(bold_start)sDetails:%(bold_end)s Repairing a Family Tree "
              "actually uses the last backup of the Family Tree, which "
              "Gramps stored on last use. If you have worked for "
              "several hours/days without closing Gramps, then all "
              "this information will be lost! If the repair fails, then "
              "the original Family Tree will be lost forever, hence "
              "a backup is needed. If the repair fails, or too much "
              "information is lost, you can fix the original "
              "Family Tree manually. For details, see the webpage\n"
              "%(gramps_wiki_recover_url)s\n"
              "Before doing a repair, try to open the Family Tree "
              "in the normal manner. Several errors that trigger the "
              "repair button can be fixed automatically. "
              "If this is the case, you can disable the repair button "
              "by removing the file %(recover_file)s in the "
              "Family Tree directory."
             ) % {'bold_start': '<b>',
                  'bold_end': '</b>',
                  'recover_file': '<i>need_recover</i>',
                  'gramps_wiki_recover_url':
                      URL_WIKISTRING + 'Recover_corrupted_family_tree',
                  'dirname': dirname},
            _("Proceed, I have taken a backup"),
            _("Stop"),
            parent=self.top)
        prompt = yes_no.run()
        if not prompt:
            return

        opened = store[node][OPEN_COL]
        if opened:
            self.dbstate.no_database()

        # delete files that are not backup files or the .txt file
        for filename in os.listdir(dirname):
            if os.path.splitext(filename)[1] not in (".gbkp", ".txt"):
                fname = os.path.join(dirname, filename)
                os.unlink(fname)

        newdb = make_database("bsddb")
        newdb.write_version(dirname)

        dbase = make_database("bsddb")
        dbase.set_save_path(dirname)
        dbase.load(dirname, None)

        self.__start_cursor(_("Rebuilding database from backup files"))

        try:
            dbase.restore()
        except DbException as msg:
            ErrorDialog(_("Error restoring backup data"), msg,
                        parent=self.top)

        self.__end_cursor()

        dbase.close(user=self.user)
        self.dbstate.no_database()
        self.__populate()
        self._select_default()
Example #33
0
 def setUpClass(cls):
     cls.db = make_database("sqlite")
     cls.db.load(":memory:")
Example #34
0
    def read_file(self, filename):
        """
        This method takes care of changing database, and loading the data.
        In 3.0 we only allow reading of real databases of filetype
        'x-directory/normal'

        This method should only return on success.
        Returning on failure makes no sense, because we cannot recover,
        since database has already been changed.
        Therefore, any errors should raise exceptions.

        On success, return with the disabled signals. The post-load routine
        should enable signals, as well as finish up with other UI goodies.
        """

        if os.path.exists(filename):
            if not os.access(filename, os.W_OK):
                mode = "r"
                self._warn(
                    _('Read only database'),
                    _('You do not have write access '
                      'to the selected file.'))
            else:
                mode = "w"
        else:
            mode = 'w'

        dbid_path = os.path.join(filename, DBBACKEND)
        if os.path.isfile(dbid_path):
            with open(dbid_path) as file:
                dbid = file.read().strip()
        else:
            dbid = "bsddb"

        db = make_database(dbid)

        self.dbstate.change_database(db)
        self.dbstate.db.disable_signals()

        self._begin_progress()

        try:
            self.dbstate.db.load(filename, self._pulse_progress, mode)
            self.dbstate.db.set_save_path(filename)
        except DbEnvironmentError as msg:
            self.dbstate.no_database()
            self._errordialog(_("Cannot open database"), str(msg))
        except BsddbUpgradeRequiredError as msg:
            self.dbstate.no_database()
            self._errordialog(_("Cannot open database"), str(msg))
        except BsddbDowngradeRequiredError as msg:
            self.dbstate.no_database()
            self._errordialog(_("Cannot open database"), str(msg))
        except BsddbDowngradeError as msg:
            self.dbstate.no_database()
            self._errordialog(_("Cannot open database"), str(msg))
        except DbUpgradeRequiredError as msg:
            self.dbstate.no_database()
            self._errordialog(_("Cannot open database"), str(msg))
        except PythonDowngradeError as msg:
            self.dbstate.no_database()
            self._errordialog(_("Cannot open database"), str(msg))
        except PythonUpgradeRequiredError as msg:
            self.dbstate.no_database()
            self._errordialog(_("Cannot open database"), str(msg))
        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(
                _("Could not open file: %s") % filename, str(msg))
        except DbError as msg:
            self.dbstate.no_database()
            self._dberrordialog(msg)
        except Exception:
            self.dbstate.no_database()
            LOG.error("Failed to open database.", exc_info=True)
        return True
Example #35
0
 def setUpClass(cls):
     cls.name = "Test Web Db Manager"
     cls.dbman = CLIDbManager(DbState())
     dirpath, _name = cls.dbman.create_new_db_cli(cls.name, dbid="sqlite")
     cls.db = make_database("sqlite")
Example #36
0
def print_db_content(db):
    for h in db.get_person_handles():
        print("DB contains: person %s" % h)
    for h in db.get_source_handles():
        print("DB contains: source %s" % h)

tmpdir = tempfile.mkdtemp()
try:
    filename1 = os.path.join(tmpdir,'test1.grdb')
    filename2 = os.path.join(tmpdir,'test2.grdb')
    print("\nUsing Database file: %s" % filename1)
    dbstate = DbState()
    dbman = CLIDbManager(dbstate)
    dirpath, name = dbman.create_new_db_cli(filename1, dbid="bsddb")
    db = make_database("bsddb")
    db.load(dirpath, None)
    print("Add person 1")
    add_person( db,"Anton", "Albers",True,False)
    print("Add source")
    add_source( db,"A short test",True,False)
    print("Add person 2 without commit")
    add_person( db,"Bernd","Beta",False,False)
    print("Add source")
    add_source( db,"A short test",True,False)
    print("Add person 3")
    add_person( db,"Chris","Connor",True,False)
    print_db_content( db)
    print("Closing Database file: %s" % filename1)
    db.close()
    tran = None
Example #37
0
def print_db_content(db):
    for h in db.get_person_handles():
        print("DB contains: person %s" % h)
    for h in db.get_source_handles():
        print("DB contains: source %s" % h)


tmpdir = tempfile.mkdtemp()
try:
    filename1 = os.path.join(tmpdir, 'test1.grdb')
    filename2 = os.path.join(tmpdir, 'test2.grdb')
    print("\nUsing Database file: %s" % filename1)
    dbstate = DbState()
    dbman = CLIDbManager(dbstate)
    dirpath, name = dbman.create_new_db_cli(filename1, dbid="bsddb")
    db = make_database("bsddb")
    db.load(dirpath, None)
    print("Add person 1")
    add_person(db, "Anton", "Albers", True, False)
    print("Add source")
    add_source(db, "A short test", True, False)
    print("Add person 2 without commit")
    add_person(db, "Bernd", "Beta", False, False)
    print("Add source")
    add_source(db, "A short test", True, False)
    print("Add person 3")
    add_person(db, "Chris", "Connor", True, False)
    print_db_content(db)
    print("Closing Database file: %s" % filename1)
    db.close()
    tran = None
Example #38
0
 def setUpClass(cls):
     cls.db = make_database("inmemorydb")
     cls.db.load(None)
Example #39
0
 def setUpClass(cls):
     cls.db = make_database("sqlite")
     cls.db.load(":memory:")