Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions ImportGedcom7/MANIFEST
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ImportGedcom7/README.md
37 changes: 37 additions & 0 deletions ImportGedcom7/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# GEDCOM 7 Import

Imports [GEDCOM 7](https://gedcom.io/) files into Gramps.

GEDCOM 7 is a substantial revision of the GEDCOM standard and is not backwards
compatible with GEDCOM 5.5.1, so it needs an importer of its own. Gramps' built-in
GEDCOM importer continues to handle 5.5.1 and earlier files.

## Requirements

This addon requires the [gramps-gedcom7](https://github.com/DavidMStraub/gramps-gedcom7)
Python library, which does the actual parsing and conversion:

```bash
pip install gramps-gedcom7
```

The Plugin Manager can also install it for you when you install this addon.

## File extension

The addon registers the `.ged7` extension. GEDCOM 7 files produced by other
applications usually carry the same `.ged` extension as GEDCOM 5.5.1 files,
which Gramps routes to its built-in GEDCOM 5.5.1 importer — so **rename a
GEDCOM 7 file to `.ged7` before importing it**.

GEDCOM ZIP packages (`.gdz`) are not supported yet; unpack them and import the
GEDCOM file they contain.

## Status

The underlying conversion covers the vast majority of GEDCOM 7 and has been
tested against real-world files. The addon itself is registered as beta because
it is new; as with any conversion tool, check the results after importing.

Please report problems, ideally with a sample file, at the
[gramps-gedcom7 issue tracker](https://github.com/DavidMStraub/gramps-gedcom7/issues).
116 changes: 116 additions & 0 deletions ImportGedcom7/import_gedcom7.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2025 David Straub
#
# 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.
#

"""Import a GEDCOM 7 file into Gramps."""

# -------------------------------------------------------------------------
#
# Standard Python modules
#
# -------------------------------------------------------------------------
import logging

# -------------------------------------------------------------------------
#
# Gramps modules
#
# -------------------------------------------------------------------------
from gramps.gen.const import GRAMPS_LOCALE as glocale
from gramps.gen.errors import DbError
from gramps.gen.utils.libformatting import ImportInfo

# -------------------------------------------------------------------------
#
# GEDCOM 7 library
#
# -------------------------------------------------------------------------
from gramps_gedcom7 import ImportSettings, import_gedcom

try:
_trans = glocale.get_addon_translator(__file__)
except ValueError:
_trans = glocale.translation
_ = _trans.gettext

LOG = logging.getLogger(".ImportGedcom7")


def _object_counts(database):
"""Return the number of objects of each type, keyed by display label."""
return {
label: getattr(database, method)()
for label, method in (
(_("People"), "get_number_of_people"),
(_("Families"), "get_number_of_families"),
(_("Events"), "get_number_of_events"),
(_("Places"), "get_number_of_places"),
(_("Sources"), "get_number_of_sources"),
(_("Citations"), "get_number_of_citations"),
(_("Repositories"), "get_number_of_repositories"),
(_("Media"), "get_number_of_media"),
(_("Notes"), "get_number_of_notes"),
(_("Tags"), "get_number_of_tags"),
)
}


def _import_statistics(before, after):
"""Return the number of objects added, omitting types with no additions."""
added = {
label: after[label] - before[label]
for label in after
if after[label] > before[label]
}
return added or {_("Results"): _("No objects were imported")}


def import_data(database, filename, user):
"""Import a GEDCOM 7 file into a Gramps database.

:returns: an :class:`ImportInfo` with the object counts, or None if the
file could not be imported. Gramps treats None as a failure.
"""
# A fresh ImportSettings per import: the library records HEAD.PLAC.FORM on
# it, so a shared instance would leak that default into the next import.
settings = ImportSettings()
before = _object_counts(database)
try:
import_gedcom(input_file=filename, db=database, settings=settings)
except OSError as err:
user.notify_error(_("%s could not be opened") % filename, str(err))
return None
except ValueError as err:
# raised for invalid UTF-8 and for GEDCOM 7 parse errors
user.notify_error(
_("Invalid GEDCOM 7 file"),
_("%s could not be imported") % filename + "\n" + str(err),
)
return None
except DbError as err:
user.notify_db_error(str(err.value))
return None
except Exception as err:
LOG.error("Failed to import GEDCOM 7 file.", exc_info=True)
user.notify_error(
_("Error reading GEDCOM 7 file"),
_("%s could not be imported") % filename + "\n" + str(err),
)
return None
return ImportInfo(_import_statistics(before, _object_counts(database)))
34 changes: 34 additions & 0 deletions ImportGedcom7/importgedcom7.gpr.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# Copyright (C) 2025 David Straub
#
# 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.
#

"""Import a Gedcom 7 file into Gramps."""

register(
IMPORT,
id="im_ged7",
name=_("GEDCOM 7"),
description=_("Import GEDCOM 7 files"),
version = "0.1.0",
gramps_target_version="6.0",
status=BETA,
fname="import_gedcom7.py",
import_function="import_data",
extension="ged7",
requires_mod=["gramps_gedcom7"],
authors=["David Straub"],
authors_email=["straub@protonmail.com"],
)
92 changes: 92 additions & 0 deletions ImportGedcom7/po/template.pot
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2026-08-12 22:55+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"

#: ImportGedcom7/importgedcom7.gpr.py:23
msgid "GEDCOM 7"
msgstr ""

#: ImportGedcom7/importgedcom7.gpr.py:24
msgid "Import GEDCOM 7 files"
msgstr ""

#: ImportGedcom7/import_gedcom7.py:60
msgid "People"
msgstr ""

#: ImportGedcom7/import_gedcom7.py:61
msgid "Families"
msgstr ""

#: ImportGedcom7/import_gedcom7.py:62
msgid "Events"
msgstr ""

#: ImportGedcom7/import_gedcom7.py:63
msgid "Places"
msgstr ""

#: ImportGedcom7/import_gedcom7.py:64
msgid "Sources"
msgstr ""

#: ImportGedcom7/import_gedcom7.py:65
msgid "Citations"
msgstr ""

#: ImportGedcom7/import_gedcom7.py:66
msgid "Repositories"
msgstr ""

#: ImportGedcom7/import_gedcom7.py:67
msgid "Media"
msgstr ""

#: ImportGedcom7/import_gedcom7.py:68
msgid "Notes"
msgstr ""

#: ImportGedcom7/import_gedcom7.py:69
msgid "Tags"
msgstr ""

#: ImportGedcom7/import_gedcom7.py:81
msgid "Results"
msgstr ""

#: ImportGedcom7/import_gedcom7.py:81
msgid "No objects were imported"
msgstr ""

#: ImportGedcom7/import_gedcom7.py:97
#, python-format
msgid "%s could not be opened"
msgstr ""

#: ImportGedcom7/import_gedcom7.py:102
msgid "Invalid GEDCOM 7 file"
msgstr ""

#: ImportGedcom7/import_gedcom7.py:103 ImportGedcom7/import_gedcom7.py:113
#, python-format
msgid "%s could not be imported"
msgstr ""

#: ImportGedcom7/import_gedcom7.py:112
msgid "Error reading GEDCOM 7 file"
msgstr ""
Empty file added ImportGedcom7/tests/__init__.py
Empty file.
Loading