gedcomtools — GEDCOM 5/7/X toolkit (alpha)
Project description
gedcomtools
A comprehensive Python toolkit for parsing, converting, validating, and analyzing genealogical data using the GEDCOM 5.x, GEDCOM 7, and GEDCOM X data models.
BETA SOFTWARE — v0.8.0b4
gedcomtoolsis under active development. Public APIs and serialization should be considered stable. Data models and formats *may change between releases without notice. It is not yet recommended for production use. Feedback and bug reports are welcome.
What's New in v0.8.0b4
Cross-platform GEDCOM loading
- Fixed GEDCOM 7 loading on Windows and Linux for legacy Windows-encoded bytes
such as
0xb7. GEDCOM 7 data is still decoded as UTF-8 first, but CP-1252 and Latin-1 compatibility fallbacks now produce anon_utf8_encodingvalidation warning instead of crashing. - Added a shared
Gedcom7.parse_bytes()path used by local files, URLs, and.gdzarchive entries, so zipped GEDCOM 7 files behave the same as regular.gedfiles. - Added regression tests for UTF-8 BOM files, Windows CP-1252 GEDCOM 7 files,
and CP-1252
.gdzarchive entries. - Made GedcomX JSON CLI loading byte-based so Windows default text encodings do not affect JSON imports.
Release cleanup
- Removed
.envfrom git tracking and added it to.gitignore. - Made GEDCOM version sniffing and the legacy
_gedcom5xhelper more tolerant of non-UTF-8 input bytes. - Made spec cache text reads and writes explicit UTF-8.
- Consolidated release history into
CHANGES.md;UPDATES.mdhas been folded into that changelog.
Release packaging
- Bumped the package and docs version to
0.8.0b4. - Verified the release with
pyright, the full pytest suite,python -m build,twine check, and an artifact scan for local env/sample/log/cache files.
Previous Development Updates
Updates from 2026-03-31
- Refactored code quality hotspots across the codebase by replacing silent bare
except Exceptionblocks with narrower exception handling and debug logging in the GEDCOM 5 converter, GedcomX conversion layer,gctool, andgxcli. - Split the large
gxcli.pyimplementation into focused modules for output helpers, command mixins, schema tools, and REPL core, while preserving the existing publicShellandmain()entry points. - Moved GEDCOM
EVENtag lookup helpers out ofschemas.pyand into the conversion layer, keeping compatibility stubs for external callers. - Added a shared
GxConverterBaseabstract base class so GEDCOM 5 and GEDCOM 7 converters now expose a commonconvert()interface. - Cleaned up circular-import model rebuild handling for GedcomX
eventandrelationshipmodels so rebuild workarounds are explicit and do not leakPersoninto module namespaces.
Updates from 2026-03-29
- Fixed
GedcomX.validate()relationship cross-reference checking so bothresourceIdreferences andResource(resource=URI(fragment="..."))references are validated correctly. - Fixed
GedcomX.from_dict()round-trips so root-levelattributionandgroupsare no longer dropped during deserialization. - Fixed
Serialization.serialize(dict)so empty-list andNonevalues do not leak into output as unwantednullfields. - Updated
GedcomZipnaming to usegenealogy.jsoninstead oftree.json, and added collision-safe archive naming for repeated top-level resources. - Fixed
TypeCollection.append()and ZIP path handling so same-document resource references serialize as#P1when appropriate, while explicit path-based URIs still preserve directory structure inside the archive.
GML graph export
A new gml.py module exports a GedcomX object graph to GML (Graph Modelling Language),
readable by Gephi, yEd, NetworkX, and other graph tools. Persons become nodes; Couple and
ParentChild relationships become directed edges.
from gedcomtools.gedcomx.gml import to_gml
gml_text = to_gml(gx)
with open("family.gml", "w") as f:
f.write(gml_text)
Node attributes: id, label (primary name), gender, birth_year, birth_place,
death_year, death_place, living. Edge attributes: source, target, label
(relationship type), rel_type.
Expanded gxcli interactive shell
The gxcli REPL was significantly expanded with new commands:
| Command | Description |
|---|---|
ahnentafel / ahnen |
Ancestor numbering — set, add, tree, export (decimal/binary/GEDCOM formats) |
grep PATTERN |
Recursive regex search across entire object tree |
schema |
Browse schema: here, class, find, where, bases, toplevel, json, diff |
bookmark / bm |
Named bookmarks for quick navigation |
dump |
Serialize current node to JSON |
resolve |
Resolve resource references at current node |
write FORMAT |
Export to gx, zip, jsonl, or adbg format |
log LEVEL |
Set runtime log level |
cfg |
Persistent configuration (set/get/tree/import/export) |
ext |
Load, unload, and trust plugins |
OBJE multimedia support
GEDCOM OBJE (multimedia object) records are now handled in both the G5→GX and G7→GX
converters. OBJE records produce SourceDescription(resourceType=DigitalArtifact) with
MIME type detection from the file extension.
PEDI and ABBR tag support
PEDI(pedigree linkage type:adopted,birth,foster,sealing) is now preserved as a qualifier onParentChildrelationships in both the G7→GX and G5→GX paths.ABBR(source abbreviation) is stored as a note onSourceDescription.
Improved date parsing (G5 → G7)
The GEDCOM 5 → GEDCOM 7 date converter (g5tog7.py) now handles a wider range of
date formats including approximate dates (ABT, CAL, EST), date ranges
(BEF, AFT, BET … AND …), and French Republican / Hebrew calendar indicators.
Model correctness fixes
Agent.__eq__redesigned: person reference takes priority (if set, equality is determined entirely by person match); falls back to case-insensitive name overlap when person isNone.Agent.__hash__ = None— mutable objects are no longer accidentally hashable.Conclusion.__hash__ = None— consistent with value-based__eq__and mutable list fields (sources,notes).Identifier.values— mutable default[]replaced withField(default_factory=list). Previously allIdentifierinstances without an explicitvaluesargument shared the same list.Agent.sorted_names— new read-only property returning names sorted alphabetically (case-insensitive).names[0]primary-name order is preserved in the stored list.
Type annotation improvements
Forward-reference circular imports resolved via TYPE_CHECKING guards and
model_rebuild() calls, replacing several Optional[Any] fields with proper types:
| Field | Before | After |
|---|---|---|
Relationship.person1 / .person2 |
Optional[Any] |
Optional[Union[Person, Resource]] |
EventRole.person |
Optional[Any] |
Optional[Union[Person, Resource]] |
PlaceDescription.jurisdiction |
Optional[Any] |
Optional[Union[Resource, PlaceDescription]] |
PlaceDescription.spatialDescription |
Optional[Any] |
Optional[PlaceReference] |
Event conversion bug fix
handle_even in conversion.py used the wrong object_map index (record.level
instead of record.level-1) when creating an EventRole for an unknown EVEN type,
silently assigning the wrong object (e.g. a Note) as the person. The fix adds the
same parent-type guards (Person / SourceDescription) that the known-type branches
already used.
What's New in v0.7.2
GEDCOM 7 → GedcomX converter
A new Gedcom7Converter converts a parsed GEDCOM 7 file directly to GedcomX.
It uses the pre-assembled Detail objects from gedcom7/models.py so no
level-tracking stack is needed.
from gedcomtools.gedcom7.gedcom7 import Gedcom7
g7 = Gedcom7("family.ged")
gx = g7.to_gedcomx() # returns GedcomX
with open("family.json", "wb") as f:
f.write(gx.json)
Or use the converter directly:
from gedcomtools.gedcom7.g7togx import Gedcom7Converter
gx = Gedcom7Converter().convert(g7)
What is converted:
| GEDCOM 7 | GedcomX |
|---|---|
INDI |
Person (id = xref) |
INDI.NAME + parts |
Name / NameForm / NamePart (Given, Surname, Prefix, Suffix) |
INDI.NAME.TRAN |
additional NameForm with lang |
INDI.SEX M/F/X/U |
Gender (Male/Female/Intersex/Unknown) |
INDI.BIRT/DEAT/BURI/… |
Fact with Date, PlaceReference, source citations |
INDI.OCCU/TITL/RELI/NATI |
attribute Fact with value |
FAM (HUSB + WIFE) |
Relationship(type=Couple) with marriage/divorce facts |
FAM.CHIL |
Relationship(type=ParentChild) per parent × child |
SOUR |
SourceDescription with title, notes, repository link |
REPO |
Agent with name, address, phone, email, homepage |
SUBM |
Agent with name, address, contact info |
OBJE |
SourceDescription(resourceType=DigitalArtifact) |
SNOTE |
SourceDescription(resourceType=Record) carrying the note text |
HEAD.DATE / HEAD.SUBM |
GedcomX.attribution |
| Place names | deduplicated PlaceDescription; facts reference via {"resource": "#id"} |
Facade conversion methods
All three parsers now expose conversion methods that return the correct high-level type — not a raw list, not a dict:
# Gedcom5
g5 = Gedcom5("family.ged")
g7 = g5.to_gedcom7() # → Gedcom7
gx = g5.to_gedcomx() # → GedcomX
# Gedcom7
g7 = Gedcom7("family.ged")
gx = g7.to_gedcomx() # → GedcomX
# Full chain
gx = Gedcom5("family.ged").to_gedcom7().to_gedcomx()
to_gedcom7() previously returned a raw List[GedcomStructure]. It now
returns a fully constructed Gedcom7 object (with tag index), so all
Gedcom7 accessors (individuals(), validate(), write(), etc.) work
immediately on the result.
Return-type test suite
A new tests/test_conversion_return_types.py module verifies that every
conversion method returns the correct type. Each test includes both a positive
isinstance check and a negative check (not a list, not a dict) so
regressions like the to_gedcom7() list-return bug are caught immediately.
What's New in v0.7.1
GEDCOM 5 → GEDCOM 7 converter
A new Gedcom5to7 converter translates GEDCOM 5.x files to GEDCOM 7 format.
The converter is available via the gedcomtools convert CLI or directly in Python:
from gedcomtools.gedcom5.gedcom5 import Gedcom5
from gedcomtools.gedcom5.g5tog7 import Gedcom5to7
from gedcomtools.gedcom7.writer import Gedcom7Writer
g5 = Gedcom5("family.ged")
conv = Gedcom5to7(unknown_tags="convert") # or "drop"
records = conv.convert(g5)
for w in conv.warnings:
print(f" warning: {w}")
Gedcom7Writer().write(records, "family7.ged")
The unknown_tags option controls vendor and non-standard G5 tags
(RIN, FSID, AFN, WWW, ADR4–ADR6):
| Value | Behaviour |
|---|---|
"drop" (default) |
Tags are silently discarded |
"convert" |
Tags are renamed to _TAG extension tags and declared in HEAD.SCHMA |
Unified gedcomtools convert CLI
A single entry-point replaces the previous format-specific CLI tools:
# GEDCOM 5 → GEDCOM X JSON
gedcomtools convert family.ged family.json -gx
# GEDCOM 5 → GEDCOM 7
gedcomtools convert family.ged family7.ged -g7
# Preserve vendor tags as extension tags during G5→G7
gedcomtools convert family.ged family7.ged -g7 --on-unknown convert
Source format is detected automatically from file content (the 2 VERS header
tag) and extension. The --on-unknown flag only applies to the G5→G7 path.
Pydantic migration: broken resource references — and the fix
The v0.7.0 Pydantic migration introduced a serialization regression in the
GEDCOM X layer. Cross-references that should have been written as compact
{"resource": "#id"} pointers were instead being inlined as full copies of the
referenced object — causing output JSON files to be an order of magnitude larger
than expected and breaking the spec-required reference model.
Root causes:
-
_GXModelshort-circuit placed too early.Serialization.serializedetected pydantic models and immediately calledmodel_dump(), bypassing the field-type lookup that was responsible for deciding when to emit a resource reference instead of an inline object. Any field typedOptional[Any](a common migration escape-hatch) also lost its union type information at runtime, so the lookup silently fell through. -
GedcomX._serializer/_as_dictbypassed the serializer. The container object had its own serialization path that calledmodel_dump()recursively, never reachingResource._of_object. -
IdentifierList._serializerused Python-modemodel_dump(). URIs were returned as Python objects instead of JSON-compatible strings, causingTypeError: Type is not JSON serializable: URIdownstream.
Fixes applied:
_RESOURCE_REF_FIELDS— an explicit table of{class_name: {field_names}}that must always serialize as resource references, regardless of annotation. The full MRO is walked so inherited fields (e.g.Conclusion.analysisonPerson) are covered._normalize_field_type— stripsOptional[X]wrappers and resolves union types (preferringResourcewhen it appears) before the field-type dispatch.- Short-circuit removed — the
_GXModelfast-path now sits after the field-type loop as a fallback for pydantic models with no registered schema fields, not before it. GedcomX._to_dict()— replaces_serializer/_as_dict; callsSerialization.serialize()for each item in every collection so the full resource-ref path is always taken.IdentifierList._serializer— fixed tomodel_dump(mode="json")so URIs are serialized to strings.Resource._of_objecthardened — now handlesdictinputs (already- serialized refs that appear on a second round-trip) and objects with noidattribute (logs a warning and continues instead of raisingAttributeError).
A regression test (TestConversionLarge.test_json_size_within_expected_range)
was added: it serializes the Royal92 large real-world file and asserts the output
stays under 5 MB. Inlining all objects instead of using resource references
pushes the same file above 40 MB, making size a reliable canary for this class
of bug.
What's New in v0.7.0
Migration to Pydantic v2
The entire GEDCOM X object model (gedcomtools.gedcomx) has been rewritten on
Pydantic v2. The previous implementation used plain Python classes with manual
__init__ and to_dict methods. Pydantic brings:
- Automatic validation — type errors and structural violations are caught at assignment time, not silently at serialization.
- Zero type errors — the full model passes Pyright strict-mode with 0 errors.
model_validate/model_dump— standard round-trip serialization replaces bespokefrom_dict/to_dictplumbing.model_post_init— replaces fragile__post_init__patterns and ensures computed fields (e.g. URI fragments) are always in sync.- Pydantic
Fielddefaults — mutable defaults (lists, dicts) are now safe; no more shared-state bugs fromdefault=[]. model_validator(mode="before")— input normalization (e.g. URI parsing) runs before field assignment, keeping models clean.ConfigDict— fine-grained control over immutability, extra fields, and arbitrary types where needed (e.g.TypeCollection).
The migration also cleaned up a large amount of dead code, removed private file
references from git history, and consolidated the logging layer into glog.py.
New functionality in v0.7.0
TRAN (Translation / Transliteration) support
GEDCOM 5.5.1 TRAN tags are now converted to GEDCOM X:
NAME TRAN→ additionalNameFormwithlangset from theLANGchild tagNOTE TRAN→ siblingNotewith translated text andlangTITL TRAN→ translatedTextValueFORMunderTRAN(script hint) is preserved onNameForm.fullText
GedcomZip packaging
GEDCOM X objects can be packaged into a standard zip archive:
from gedcomtools.gedcomx.zip import GedcomZip
with GedcomZip("export.zip") as gz:
gz.add_object_as_resource(gx)
O(1) collection lookups
TypeCollection now maintains three indexes (_id_index, _uri_index,
_name_index) so by_id(), by_uri(), and by_name() are constant-time
regardless of collection size. The name index uses dict[str, dict[int, T]]
(keyed by id(item)) to avoid requiring pydantic models to be hashable.
ResolveStats telemetry
Reference resolution now returns a ResolveStats dataclass with counters for
total refs, cache hits/misses, successes, failures, and timing:
from gedcomtools.gedcomx.serialization import Serialization, ResolveStats
stats = ResolveStats()
Serialization._resolve_structure(gx, gx._resolve, stats=stats)
print(stats.resolved_ok, stats.resolved_fail)
Flexible date/coordinate types
Several fields that GEDCOM populates with human-readable strings are now typed to accept both structured objects and raw strings:
| Field | Previous type | Now |
|---|---|---|
Attribution.modified / .created |
datetime |
Union[datetime, str] |
SourceDescription.published / .created / .modified |
Date |
Union[Date, str] |
PlaceDescription.latitude / .longitude |
float |
Union[float, str] |
This eliminates serialization warnings from GEDCOM files that store dates like
"23 Jun 2008" or coordinates like "N40.896".
Expanded test suite — 884 tests
New test modules added this release:
| File | Coverage |
|---|---|
tests/gedcom5/test_gedcom5_official.py |
All 6 local 555*.GED sample files; UTF-16 BE/LE encoding; live download from gedcom.org |
tests/test_gedcom5_individual.py |
IndividualRecord API: names, gender, birth/death data, flags |
tests/test_gedcomx_roundtrip.py |
GEDCOM 5 → GedcomX → JSON → GedcomX round-trip; double round-trip stability; reference resolution |
tests/test_gedcomx_validation_rules.py |
Pydantic mirror-model validation rules for Person, Name, Relationship, Resource |
tests/test_zip.py |
GedcomZip archive structure, content validity, context manager |
Features
- ✅ GEDCOM 5.x parser (
gedcom5) - ✅ GEDCOM 7 parser, 18-phase validator, serializer, and high-level models (
gedcom7) - ✅ GEDCOM X Pydantic v2 object model (
gedcomx) — complete, 0 Pyright errors - ✅ GEDCOM X per-property validation (
validate()on every model) - ✅ Converter — GEDCOM 5.x → GEDCOM X (including TRAN, FONE, multi-language names)
- ✅ Converter — GEDCOM 5.x → GEDCOM 7 (vendor tag drop/convert via
--on-unknown) - ✅ Converter — GEDCOM 7 → GedcomX (
Gedcom7Converter/g7.to_gedcomx()) - ✅ Facade conversion methods on all parsers —
to_gedcom7(),to_gedcomx()return correct types - ✅ Full conversion chain:
Gedcom5 → Gedcom7 → GedcomXin one expression - ✅
gedcomtools convertunified CLI — auto-detects source format, supports g5→gx and g5→g7 - ✅
GedcomZip— package a GEDCOM X graph into a portable zip archive - ✅ O(1) collection lookups by id, URI, and name
- ✅
ResolveStats— reference resolution telemetry - ✅ Correct
{"resource": "#id"}pointer serialization — resource references are never inlined - ✅ CLI tools (
gedcomtools,gxcli,g7cli,validate7) - ✅ Structured logging (
glog) withGEDCOMTOOLS_DEBUGenv var support - ✅ Sub-loggers (conversion, parser, io, etc.)
- ✅ Extensible schema / extension system with TrustLevel plugin security
- ✅ Source, person, family, relationship modeling
- ✅ Place and event normalization with multi-language translation support
- ✅ Metadata and attribution handling
- ✅ OBJE multimedia record support (G5→GX and G7→GX)
- ✅ PEDI pedigree linkage and ABBR abbreviation tag support
- ✅ GML graph export — Gephi / yEd / NetworkX compatible
- ✅ Expanded
gxcli— ahnentafel, grep, schema browser, bookmarks, plugin manager - ✅ Correct
Agent.__eq__— person-reference priority with name-overlap fallback - ✅ ~1145 tests, 0 failures
- 🔧 GEDCOM X → GEDCOM 7 converter — planned
Project Structure
gedcomtools/
├── gedcom5/ # GEDCOM 5.x parsing layer
│ ├── gedcom5.py # High-level facade (Gedcom5)
│ ├── parser.py # Low-level parser engine (Gedcom5x)
│ ├── elements.py # Typed element/record classes
│ ├── helpers.py # Element query helpers
│ ├── tags.py # GEDCOM 5.x tag constants
│ └── source.py # Source record helpers
├── gedcom7/ # GEDCOM 7 parsing, validation, and serialization
│ ├── gedcom7.py # Parser + Gedcom7 class
│ ├── structure.py # In-memory tree node (GedcomStructure)
│ ├── validator.py # 18-phase structural/semantic validator
│ ├── writer.py # GEDCOM 7 serializer
│ ├── models.py # High-level detail dataclasses
│ ├── specification.py # Tag rules, cardinality, enumerations
│ ├── g7interop.py # Tag ↔ URI mapping
│ ├── exceptions.py # Exception hierarchy
│ ├── g7cli.py # Interactive browser/editor shell
│ └── validate7.py # validate7 CLI entry point
├── gedcomx/ # GEDCOM X object model (Pydantic v2)
│ ├── gedcomx.py # GedcomX root object + TypeCollection
│ ├── conversion.py # GEDCOM 5 → GEDCOM X converter
│ ├── serialization.py # JSON serialize / deserialize + ResolveStats
│ ├── zip.py # GedcomZip archive packaging
│ ├── person.py # Person model
│ ├── relationship.py # Relationship model
│ ├── name.py # Name / NameForm / NamePart
│ ├── fact.py # Fact / FactType
│ ├── source_description.py
│ ├── agent.py
│ ├── place_description.py
│ ├── attribution.py
│ └── ... # date, note, identifier, uri, resource, ...
├── glog.py # Structured logging (loguru-based)
├── cli.py # gedcomtools CLI entry point
└── utils/ # Shared utilities
Installation
pip install gedcomtools
Or from source:
git clone https://github.com/cartwrightdj/gedcomtools.git
cd gedcomtools
pip install -e .
Quick Start
Parse GEDCOM 5.x
from gedcomtools.gedcom5 import Gedcom5
g = Gedcom5("family.ged")
for person in g.individual_details():
print(person.full_name, person.birth_year, person.death_year)
for family in g.family_details():
print(family.husband_xref, family.wife_xref, family.marriage_year)
Parse and validate GEDCOM 7
from gedcomtools.gedcom7 import Gedcom7
g = Gedcom7("family.ged")
issues = g.validate()
for issue in issues:
print(f"[{issue.severity}] {issue.code}: {issue.message}")
# Write back out
g.write("family_out.ged")
Convert between formats
All parsers expose to_gedcom7() and to_gedcomx() convenience methods
that return the correct high-level type:
from gedcomtools.gedcom5.gedcom5 import Gedcom5
from gedcomtools.gedcom7.gedcom7 import Gedcom7
# GEDCOM 5 → GEDCOM 7
g5 = Gedcom5("family.ged")
g7 = g5.to_gedcom7() # returns Gedcom7
g7.write("family7.ged")
# GEDCOM 5 → GedcomX
gx = g5.to_gedcomx() # returns GedcomX
with open("family.json", "wb") as f:
f.write(gx.json)
# GEDCOM 7 → GedcomX
g7 = Gedcom7("family7.ged")
gx = g7.to_gedcomx() # returns GedcomX
# Full chain in one expression
gx = Gedcom5("family.ged").to_gedcom7().to_gedcomx()
Round-trip JSON serialization
import json
from gedcomtools.gedcomx.gedcomx import GedcomX
from gedcomtools.gedcomx.serialization import Serialization
data = json.loads(gx.json)
gx2 = Serialization.deserialize(data, GedcomX)
print(len(gx2.persons), "persons restored")
Package as a GEDCOM X zip archive
from gedcomtools.gedcomx.zip import GedcomZip
with GedcomZip("export.zip") as gz:
gz.add_object_as_resource(gx)
Validate a GEDCOM X object graph
Every model supports recursive validation with type and completeness checks:
result = gx.validate()
for issue in result.errors:
print(f"[error] {issue.path}: {issue.message}")
for issue in result.warnings:
print(f"[warn] {issue.path}: {issue.message}")
Access GEDCOM 7 high-level models
from gedcomtools.gedcom7 import Gedcom7
from gedcomtools.gedcom7.models import individual_detail
g = Gedcom7("family.ged")
for indi_node in g["INDI"]:
p = individual_detail(indi_node)
print(p.full_name, p.birth_year, p.death_year)
# Access place translations (PLAC.TRAN)
if p.birth and p.birth.place_translations:
print(p.birth.place_translations.get("de"))
# Access name translations (NAME.TRAN)
for tran in (p.name.translations if p.name else []):
print(f" [{tran.lang}] {tran.display}")
CLI Tools
gedcomtools convert — format converter
# GEDCOM 5 → GEDCOM X JSON (auto-detects source format)
gedcomtools convert family.ged output.json -gx
# GEDCOM 5 → GEDCOM 7
gedcomtools convert family.ged output.ged -g7
# Drop vendor/non-standard tags during G5→G7 (default)
gedcomtools convert family.ged output.ged -g7 --on-unknown drop
# Rename vendor tags to _TAG extension tags instead of dropping them
gedcomtools convert family.ged output.ged -g7 --on-unknown convert
| Exit code | Meaning |
|---|---|
| 0 | Success |
| 1 | Source file not found |
| 2 | Cannot determine source format |
| 3 | Conversion not supported for this format pair |
| 4 | Conversion failed (parse or transform error) |
| 5 | I/O error writing output |
validate7 — GEDCOM 7 validator
validate7 family.ged
validate7 --lenient family.ged # suppress undeclared extension tag errors
| Exit code | Meaning |
|---|---|
| 0 | Clean (warnings may still be printed) |
| 1 | One or more validation errors |
| 2 | Not a GEDCOM 7 file |
| 3 | File not found or cannot be read |
g7cli — interactive GEDCOM 7 browser/editor
g7cli family.ged
Commands: load, reload, write, validate, info, ls, cd, pwd,
show, find, set, add, rm, help, quit.
gxcli — GEDCOM X CLI
gxcli convert input.ged output.json
Logging
The project uses glog (loguru-based) for structured logging.
from gedcomtools.glog import get_logger
log = get_logger("conversion")
log.info("Starting conversion")
Set GEDCOMTOOLS_DEBUG=1 in your environment to enable debug output.
Design Goals
- Pydantic v2 throughout GEDCOM X — validation at the boundary, not at serialization
- Centralized logging control — no side effects on import
- Extensible schema support
- Accurate GEDCOM X modeling against the published specification
- Robust error reporting at every layer
- CLI + API parity
- Clear separation of concerns between parsing, conversion, and serialization
Roadmap
- GEDCOM X → GEDCOM 7 converter
- JSON-LD export
- RAG pipeline integration
License
MIT License
Author
David J. Cartwright
Build genealogy tooling like infrastructure: structured, observable, extensible.
Changes Since v0.7.3-dev
Note: there is no Git tag named 0.7.3-dev in this repository. This summary is based on changes since commit a8f2f57, which introduced the v0.7.3-dev version marker in this README.
- Integrated the dedicated
gxcliMarkdown guide into the Sphinx documentation as a subsection of the CLI docs. - Cleaned up the Sphinx configuration and docs dependencies so the HTML documentation build completes cleanly.
- Removed the accidentally tracked
test/andtest (2)/ZIP artifact remnants from the repository and added ignore rules to keep them out going forward.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file gedcomtools-0.8.0b4.tar.gz.
File metadata
- Download URL: gedcomtools-0.8.0b4.tar.gz
- Upload date:
- Size: 407.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
06b65234aeb735ebd3b87f35f57bfd78fac6d27c39d9c397ea8accbf220541f7
|
|
| MD5 |
3558cb89c30fc95087409679cf055d2f
|
|
| BLAKE2b-256 |
62478bb0d7ba8da56a3576c28933e0c83d0e0eaf9b9b6cccf217652f66f40f80
|
File details
Details for the file gedcomtools-0.8.0b4-py3-none-any.whl.
File metadata
- Download URL: gedcomtools-0.8.0b4-py3-none-any.whl
- Upload date:
- Size: 394.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b242b28d6ecfaf87bd8355ead4a24139f93dd989ebd2bfb9121bf9b7aa024e2b
|
|
| MD5 |
54b28ee7e213adf6826a91b3940e6fc4
|
|
| BLAKE2b-256 |
f7b0e48c68556d388104cbb4c1b156030b91711424f020627aef1d1032c7239c
|