gedcomkit 0.1.17__tar.gz → 0.1.19__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {gedcomkit-0.1.17 → gedcomkit-0.1.19}/CHANGELOG.md +211 -0
- {gedcomkit-0.1.17 → gedcomkit-0.1.19}/Cargo.lock +1 -1
- {gedcomkit-0.1.17 → gedcomkit-0.1.19}/Cargo.toml +1 -1
- {gedcomkit-0.1.17 → gedcomkit-0.1.19}/PKG-INFO +1 -1
- {gedcomkit-0.1.17 → gedcomkit-0.1.19}/README.md +3 -0
- {gedcomkit-0.1.17 → gedcomkit-0.1.19}/bindings/gedcomkit-py/Cargo.lock +2 -2
- {gedcomkit-0.1.17 → gedcomkit-0.1.19}/bindings/gedcomkit-py/Cargo.toml +1 -1
- {gedcomkit-0.1.17 → gedcomkit-0.1.19}/bindings/gedcomkit-py/gedcomkit.pyi +32 -3
- {gedcomkit-0.1.17 → gedcomkit-0.1.19}/bindings/gedcomkit-py/src/lib.rs +7 -2
- {gedcomkit-0.1.17 → gedcomkit-0.1.19}/src/convert.rs +412 -7
- {gedcomkit-0.1.17 → gedcomkit-0.1.19}/src/dates.rs +574 -77
- gedcomkit-0.1.19/src/validate.rs +3508 -0
- {gedcomkit-0.1.17 → gedcomkit-0.1.19}/src/view.rs +42 -1
- {gedcomkit-0.1.17 → gedcomkit-0.1.19}/tests/typescript.rs +1 -0
- gedcomkit-0.1.17/src/validate.rs +0 -855
- {gedcomkit-0.1.17 → gedcomkit-0.1.19}/LICENSE +0 -0
- {gedcomkit-0.1.17 → gedcomkit-0.1.19}/bindings/gedcomkit-py/LICENSE +0 -0
- {gedcomkit-0.1.17 → gedcomkit-0.1.19}/bindings/gedcomkit-py/README.md +0 -0
- {gedcomkit-0.1.17 → gedcomkit-0.1.19}/fixtures/vendored/gedcom-spec/LICENSE +0 -0
- {gedcomkit-0.1.17 → gedcomkit-0.1.19}/fixtures/vendored/gedcom-spec/README.md +0 -0
- {gedcomkit-0.1.17 → gedcomkit-0.1.19}/fixtures/vendored/gedcom-spec/cardinalities.tsv +0 -0
- {gedcomkit-0.1.17 → gedcomkit-0.1.19}/fixtures/vendored/gedcom-spec/enumerations.tsv +0 -0
- {gedcomkit-0.1.17 → gedcomkit-0.1.19}/fixtures/vendored/gedcom-spec/enumerationsets.tsv +0 -0
- {gedcomkit-0.1.17 → gedcomkit-0.1.19}/fixtures/vendored/gedcom-spec/grammar.abnf +0 -0
- {gedcomkit-0.1.17 → gedcomkit-0.1.19}/fixtures/vendored/gedcom-spec/grammar.gedstruct +0 -0
- {gedcomkit-0.1.17 → gedcomkit-0.1.19}/fixtures/vendored/gedcom-spec/payloads.tsv +0 -0
- {gedcomkit-0.1.17 → gedcomkit-0.1.19}/fixtures/vendored/gedcom-spec/substructures.tsv +0 -0
- {gedcomkit-0.1.17 → gedcomkit-0.1.19}/fixtures/vendored/gedcom7code/5/age-invalid.ged +0 -0
- {gedcomkit-0.1.17 → gedcomkit-0.1.19}/fixtures/vendored/gedcom7code/5/age-valid.ged +0 -0
- {gedcomkit-0.1.17 → gedcomkit-0.1.19}/fixtures/vendored/gedcom7code/5/atsign.ged +0 -0
- {gedcomkit-0.1.17 → gedcomkit-0.1.19}/fixtures/vendored/gedcom7code/5/char_ascii_1.ged +0 -0
- {gedcomkit-0.1.17 → gedcomkit-0.1.19}/fixtures/vendored/gedcom7code/5/char_ascii_2.ged +0 -0
- {gedcomkit-0.1.17 → gedcomkit-0.1.19}/fixtures/vendored/gedcom7code/5/char_utf16be-1.ged +0 -0
- {gedcomkit-0.1.17 → gedcomkit-0.1.19}/fixtures/vendored/gedcom7code/5/char_utf16be-2.ged +0 -0
- {gedcomkit-0.1.17 → gedcomkit-0.1.19}/fixtures/vendored/gedcom7code/5/char_utf16le-1.ged +0 -0
- {gedcomkit-0.1.17 → gedcomkit-0.1.19}/fixtures/vendored/gedcom7code/5/char_utf16le-2.ged +0 -0
- {gedcomkit-0.1.17 → gedcomkit-0.1.19}/fixtures/vendored/gedcom7code/5/char_utf8-1.ged +0 -0
- {gedcomkit-0.1.17 → gedcomkit-0.1.19}/fixtures/vendored/gedcom7code/5/char_utf8-2.ged +0 -0
- {gedcomkit-0.1.17 → gedcomkit-0.1.19}/fixtures/vendored/gedcom7code/5/char_utf8-3.ged +0 -0
- {gedcomkit-0.1.17 → gedcomkit-0.1.19}/fixtures/vendored/gedcom7code/5/date-all.ged +0 -0
- {gedcomkit-0.1.17 → gedcomkit-0.1.19}/fixtures/vendored/gedcom7code/5/date-dual-invalid.ged +0 -0
- {gedcomkit-0.1.17 → gedcomkit-0.1.19}/fixtures/vendored/gedcom7code/5/date-dual-valid.ged +0 -0
- {gedcomkit-0.1.17 → gedcomkit-0.1.19}/fixtures/vendored/gedcom7code/5/enum-ext.ged +0 -0
- {gedcomkit-0.1.17 → gedcomkit-0.1.19}/fixtures/vendored/gedcom7code/5/filename-1.ged +0 -0
- {gedcomkit-0.1.17 → gedcomkit-0.1.19}/fixtures/vendored/gedcom7code/5/lang-all.ged +0 -0
- {gedcomkit-0.1.17 → gedcomkit-0.1.19}/fixtures/vendored/gedcom7code/5/notes-1.ged +0 -0
- {gedcomkit-0.1.17 → gedcomkit-0.1.19}/fixtures/vendored/gedcom7code/5/obje-1.ged +0 -0
- {gedcomkit-0.1.17 → gedcomkit-0.1.19}/fixtures/vendored/gedcom7code/5/obsolete-1.ged +0 -0
- {gedcomkit-0.1.17 → gedcomkit-0.1.19}/fixtures/vendored/gedcom7code/5/pedi-1.ged +0 -0
- {gedcomkit-0.1.17 → gedcomkit-0.1.19}/fixtures/vendored/gedcom7code/5/rela_1.ged +0 -0
- {gedcomkit-0.1.17 → gedcomkit-0.1.19}/fixtures/vendored/gedcom7code/5/sour-1.ged +0 -0
- {gedcomkit-0.1.17 → gedcomkit-0.1.19}/fixtures/vendored/gedcom7code/5/tiny-1.ged +0 -0
- {gedcomkit-0.1.17 → gedcomkit-0.1.19}/fixtures/vendored/gedcom7code/5/xref-case.ged +0 -0
- {gedcomkit-0.1.17 → gedcomkit-0.1.19}/fixtures/vendored/gedcom7code/7/age-invalid.ged +0 -0
- {gedcomkit-0.1.17 → gedcomkit-0.1.19}/fixtures/vendored/gedcom7code/7/age-valid.ged +0 -0
- {gedcomkit-0.1.17 → gedcomkit-0.1.19}/fixtures/vendored/gedcom7code/7/atsign.ged +0 -0
- {gedcomkit-0.1.17 → gedcomkit-0.1.19}/fixtures/vendored/gedcom7code/7/char_ascii_1.ged +0 -0
- {gedcomkit-0.1.17 → gedcomkit-0.1.19}/fixtures/vendored/gedcom7code/7/char_ascii_2.ged +0 -0
- {gedcomkit-0.1.17 → gedcomkit-0.1.19}/fixtures/vendored/gedcom7code/7/char_utf16be-1.ged +0 -0
- {gedcomkit-0.1.17 → gedcomkit-0.1.19}/fixtures/vendored/gedcom7code/7/char_utf16be-2.ged +0 -0
- {gedcomkit-0.1.17 → gedcomkit-0.1.19}/fixtures/vendored/gedcom7code/7/char_utf16le-1.ged +0 -0
- {gedcomkit-0.1.17 → gedcomkit-0.1.19}/fixtures/vendored/gedcom7code/7/char_utf16le-2.ged +0 -0
- {gedcomkit-0.1.17 → gedcomkit-0.1.19}/fixtures/vendored/gedcom7code/7/char_utf8-1.ged +0 -0
- {gedcomkit-0.1.17 → gedcomkit-0.1.19}/fixtures/vendored/gedcom7code/7/char_utf8-2.ged +0 -0
- {gedcomkit-0.1.17 → gedcomkit-0.1.19}/fixtures/vendored/gedcom7code/7/char_utf8-3.ged +0 -0
- {gedcomkit-0.1.17 → gedcomkit-0.1.19}/fixtures/vendored/gedcom7code/7/date-all.ged +0 -0
- {gedcomkit-0.1.17 → gedcomkit-0.1.19}/fixtures/vendored/gedcom7code/7/date-dual-invalid.ged +0 -0
- {gedcomkit-0.1.17 → gedcomkit-0.1.19}/fixtures/vendored/gedcom7code/7/enum-ext.ged +0 -0
- {gedcomkit-0.1.17 → gedcomkit-0.1.19}/fixtures/vendored/gedcom7code/7/filename-1.ged +0 -0
- {gedcomkit-0.1.17 → gedcomkit-0.1.19}/fixtures/vendored/gedcom7code/7/lang-all.ged +0 -0
- {gedcomkit-0.1.17 → gedcomkit-0.1.19}/fixtures/vendored/gedcom7code/7/notes-1.ged +0 -0
- {gedcomkit-0.1.17 → gedcomkit-0.1.19}/fixtures/vendored/gedcom7code/7/obje-1.ged +0 -0
- {gedcomkit-0.1.17 → gedcomkit-0.1.19}/fixtures/vendored/gedcom7code/7/obsolete-1.ged +0 -0
- {gedcomkit-0.1.17 → gedcomkit-0.1.19}/fixtures/vendored/gedcom7code/7/pedi-1.ged +0 -0
- {gedcomkit-0.1.17 → gedcomkit-0.1.19}/fixtures/vendored/gedcom7code/7/rela_1.ged +0 -0
- {gedcomkit-0.1.17 → gedcomkit-0.1.19}/fixtures/vendored/gedcom7code/7/sour-1.ged +0 -0
- {gedcomkit-0.1.17 → gedcomkit-0.1.19}/fixtures/vendored/gedcom7code/7/tiny-1.ged +0 -0
- {gedcomkit-0.1.17 → gedcomkit-0.1.19}/fixtures/vendored/gedcom7code/7/xref-case.ged +0 -0
- {gedcomkit-0.1.17 → gedcomkit-0.1.19}/fixtures/vendored/gedcom7code/LICENSE +0 -0
- {gedcomkit-0.1.17 → gedcomkit-0.1.19}/fixtures/vendored/gedcom7code/UPSTREAM-README.md +0 -0
- {gedcomkit-0.1.17 → gedcomkit-0.1.19}/fixtures/vendored/zip-interop/README.md +0 -0
- {gedcomkit-0.1.17 → gedcomkit-0.1.19}/fixtures/vendored/zip-interop/python-zip64.gdz +0 -0
- {gedcomkit-0.1.17 → gedcomkit-0.1.19}/fixtures/vendored/zip-interop/python-zipfile.gdz +0 -0
- {gedcomkit-0.1.17 → gedcomkit-0.1.19}/pyproject.toml +0 -0
- {gedcomkit-0.1.17 → gedcomkit-0.1.19}/src/build.rs +0 -0
- {gedcomkit-0.1.17 → gedcomkit-0.1.19}/src/decode.rs +0 -0
- {gedcomkit-0.1.17 → gedcomkit-0.1.19}/src/family.rs +0 -0
- {gedcomkit-0.1.17 → gedcomkit-0.1.19}/src/gedzip.rs +0 -0
- {gedcomkit-0.1.17 → gedcomkit-0.1.19}/src/lib.rs +0 -0
- {gedcomkit-0.1.17 → gedcomkit-0.1.19}/src/names.rs +0 -0
- {gedcomkit-0.1.17 → gedcomkit-0.1.19}/src/schema.rs +0 -0
- {gedcomkit-0.1.17 → gedcomkit-0.1.19}/src/synthetic.rs +0 -0
- {gedcomkit-0.1.17 → gedcomkit-0.1.19}/src/tags.rs +0 -0
- {gedcomkit-0.1.17 → gedcomkit-0.1.19}/tests/endurance.rs +0 -0
- {gedcomkit-0.1.17 → gedcomkit-0.1.19}/tests/external_charset.rs +0 -0
- {gedcomkit-0.1.17 → gedcomkit-0.1.19}/tests/properties.rs +0 -0
- {gedcomkit-0.1.17 → gedcomkit-0.1.19}/tests/requirement_corpus.rs +0 -0
- {gedcomkit-0.1.17 → gedcomkit-0.1.19}/tests/spec_conformance.rs +0 -0
- {gedcomkit-0.1.17 → gedcomkit-0.1.19}/tests/vendored_corpus.rs +0 -0
- {gedcomkit-0.1.17 → gedcomkit-0.1.19}/tests/version_conversion.rs +0 -0
|
@@ -5,6 +5,217 @@ format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and
|
|
|
5
5
|
the project uses semantic versioning within the usual pre-1.0 compatibility
|
|
6
6
|
rules.
|
|
7
7
|
|
|
8
|
+
## [Unreleased]
|
|
9
|
+
|
|
10
|
+
## [0.1.19] - 2026-10-17
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- `view::EventView::date_phrase` (`datePhrase` in the serialized view, so
|
|
15
|
+
in both bindings and the TypeScript definitions): the `PHRASE` beneath an
|
|
16
|
+
event's `DATE`, exactly as written. A GEDCOM 7 date with an empty payload
|
|
17
|
+
and a `PHRASE`, or a date with a phrase beside it, showed nothing of the
|
|
18
|
+
phrase before. A 5.5.1 phrase is written inside the payload, which `date`
|
|
19
|
+
already holds. The Python stub gains an `EventView` typed dict naming
|
|
20
|
+
every key of an event.
|
|
21
|
+
- The date reader reads ISO 8601's year and month: `1834-02` is February
|
|
22
|
+
1834, as `1834-02-10` was already 10 February 1834. Only four digits, a
|
|
23
|
+
hyphen and two digits are read, and only when the month is no more than
|
|
24
|
+
the year's last two digits: `1808-10`, `1711-12` and `2010-11` are as
|
|
25
|
+
often a span of years or a dual year as a month, and stay unparsed. So
|
|
26
|
+
does every month of a year ending in 00 (`1800-01` to `1800-12`), and
|
|
27
|
+
the later months of a year ending in 01 to 11 (`2005-06` to `2005-12`).
|
|
28
|
+
|
|
29
|
+
### Changed
|
|
30
|
+
|
|
31
|
+
- `validate::inspect` no longer reports two events out of order when an
|
|
32
|
+
approximate date's leeway could put them in order, which is how
|
|
33
|
+
`conflicting-vitals` already read them. A birth `ABT 1854` with a
|
|
34
|
+
christening in 1853 was a `christened-before-born` question; it is now
|
|
35
|
+
no finding. The same holds for `died-before-born`, `buried-before-died`,
|
|
36
|
+
`event-after-death`, `event-before-birth`, `married-before-born`,
|
|
37
|
+
`married-after-died` and `child-born-after-mother-died`, each of which
|
|
38
|
+
now reports only what is out of order beyond the leeway, as a
|
|
39
|
+
contradiction (a question for an `EVEN` or `FACT`, as before). Within the
|
|
40
|
+
leeway no other check fires in its place: a marriage in 1849 for somebody
|
|
41
|
+
born about 1850 is not `married-as-a-child`. Bounds (`BEF`, `AFT`, `BET`)
|
|
42
|
+
are read as the ranges they admit, unchanged.
|
|
43
|
+
- `convert::to_version_5_5_1` turns a name type back into 5.5.1's
|
|
44
|
+
spelling: `OTHER` with a one-line `PHRASE` becomes the phrase's words,
|
|
45
|
+
and an enumerated value is written in lower case (`BIRTH` becomes
|
|
46
|
+
`birth`). `OTHER` whose words are themselves an enumerated value (the
|
|
47
|
+
phrase `birth`) stays `other`, its `PHRASE` kept and reported, since the
|
|
48
|
+
words alone would convert back up as `BIRTH`. A `PHRASE` beside any other
|
|
49
|
+
value is kept and reported.
|
|
50
|
+
- `DatePoint::from_ymd` refuses a day its month never has (30 February,
|
|
51
|
+
31 April, day 0). The point is written with no calendar escape, which
|
|
52
|
+
makes it Gregorian, so 29 February is taken only in a Gregorian leap
|
|
53
|
+
year: 2000, not 1900.
|
|
54
|
+
|
|
55
|
+
### Fixed
|
|
56
|
+
|
|
57
|
+
- A range with an end the date reader cannot read is no longer read in
|
|
58
|
+
part. `FROM ABT 1924 TO 1959` was read as `TO 1959`, dropping the start
|
|
59
|
+
without a word, and `BET 1950 AND JULIAN DEC 302` as a range with only
|
|
60
|
+
its first end; `FROM Infant` was a period with neither end. Each is now
|
|
61
|
+
`DateKind::Unparsed`, keeps its text as the phrase, and still offers its
|
|
62
|
+
year to sort by; `to_version_7` keeps it whole as an empty `DATE` with a
|
|
63
|
+
`PHRASE`. A range whose ends are both dates reads as before.
|
|
64
|
+
- The date reader no longer accepts a day its month does not have.
|
|
65
|
+
`1834-02-30` and `30 FEB 1834` were read as 30 February 1834; they are
|
|
66
|
+
now unparsed, as is `29 FEB 1834`. Leap years follow the payload's
|
|
67
|
+
calendar: `@#DJULIAN@ 29 FEB 1900` is read and `@#DGREGORIAN@ 29 FEB
|
|
68
|
+
1900` is not. A payload with no calendar escape keeps the Julian leap
|
|
69
|
+
day, since files often leave the escape off a Julian date, so
|
|
70
|
+
`29 FEB 1900` is still read; ISO 8601's `1900-02-29` is not, since ISO
|
|
71
|
+
8601 is Gregorian by definition. A dual year's leap day is its second
|
|
72
|
+
year's, so `29 FEB 1711/12` and `@#DJULIAN@ 29 FEB 1711/12` are read. A
|
|
73
|
+
Roman or unrecognized calendar is held to the Julian month lengths, and
|
|
74
|
+
no Hebrew or French Republican month has more than 30 days. A numeric
|
|
75
|
+
date with a month or day out of range (`1834-13-05`, `13/05/1834`) is
|
|
76
|
+
unparsed too; before, the piece out of range was dropped and the rest
|
|
77
|
+
read (`1834-13-05` as the year 1834).
|
|
78
|
+
- `convert::to_version_5_5_1` no longer writes `INT (…)`, an interpreted
|
|
79
|
+
date with no date, for a version 7 `DATE` that is empty beside its
|
|
80
|
+
`PHRASE`; 5.5.1 does not allow it. The phrase is written as 5.5.1's date
|
|
81
|
+
phrase, `(FROM ABT 1924 TO 1959)`, or as the date itself when it is
|
|
82
|
+
already one in 5.5.1's grammar that version 7 cannot spell, so a dual
|
|
83
|
+
year (`1740/41`) comes back as the date it was.
|
|
84
|
+
- `convert::to_version_7` / `to_version_7_with` convert a personal name's
|
|
85
|
+
type (`INDI`.`NAME`.`TYPE`), which 5.5.1 writes as free text and version
|
|
86
|
+
7 as an enumeration. A value that is one of version 7's words in any case
|
|
87
|
+
(`aka`, `birth`, `immigrant`, `maiden`, `married`, `professional`,
|
|
88
|
+
`other`) becomes that word in upper case; any other becomes `OTHER`, with
|
|
89
|
+
the text kept verbatim as a `PHRASE`, the way a role has been converted
|
|
90
|
+
since 0.1.13. Before, `TYPE aka` was carried into the 7.0 document as it
|
|
91
|
+
stood, where it is not valid. A type that already has a `PHRASE`, is
|
|
92
|
+
empty, or has a continuation line with substructures is kept and
|
|
93
|
+
reported.
|
|
94
|
+
|
|
95
|
+
## [0.1.18] - 2026-10-16
|
|
96
|
+
|
|
97
|
+
### Added
|
|
98
|
+
|
|
99
|
+
- `validate::inspect` runs nine more checks. Each has a stable name, and
|
|
100
|
+
the module documentation now lists every check with its severity:
|
|
101
|
+
- `married-after-died` (contradiction): a family's first `MARR` wholly
|
|
102
|
+
after a partner's death, or, failing a dated death, their burial. A
|
|
103
|
+
burial before the wedding beside a death after it is no finding here:
|
|
104
|
+
the death says when the life ended, and the burial is
|
|
105
|
+
`buried-before-died`'s.
|
|
106
|
+
- `child-born-long-after-father-died`: a child born more than 300 days
|
|
107
|
+
after the death of the family's `HUSB`. A contradiction when both dates
|
|
108
|
+
name a day; a question otherwise, since a bare year is often a guess.
|
|
109
|
+
- `christened-before-born` (contradiction): a `CHR`, `CHRA` or `BAPM`
|
|
110
|
+
wholly before the birth.
|
|
111
|
+
- `event-before-birth`: the mirror of `event-after-death`, for any other
|
|
112
|
+
event or attribute wholly before the birth year. A burial or cremation
|
|
113
|
+
is left to `died-before-born` and `buried-before-died` when the person
|
|
114
|
+
has a dated death.
|
|
115
|
+
- `buried-long-after-died` (question): a burial more than 365 days after
|
|
116
|
+
the death, counted from the latest day the death allows to the earliest
|
|
117
|
+
the burial does.
|
|
118
|
+
- `children-too-close`: two children of one mother born 2 to 270 days
|
|
119
|
+
apart. A contradiction when both dates name a day and are under 150
|
|
120
|
+
days apart; a question otherwise, since a very early birth makes the
|
|
121
|
+
longer gaps possible. A mother's children are taken from every family
|
|
122
|
+
she is the `WIFE` in; a family with no `WIFE` is compared alone.
|
|
123
|
+
- `possible-duplicate-child` (question): two children of one mother with
|
|
124
|
+
one given name (one name may be the start of the other: `Mira` and
|
|
125
|
+
`Mira Elowen`, but not `Mira Elowen` and `Mira Rose`), born on one
|
|
126
|
+
date, or on one day and month of different years.
|
|
127
|
+
- `conflicting-vitals` (question): two `BIRT`, or two `DEAT`, events of
|
|
128
|
+
one person that cannot both be true, even with an approximate date
|
|
129
|
+
allowed a year either way (`BIRT 1851` and `BIRT ABT 1850` are not in
|
|
130
|
+
conflict). GEDCOM lets a file record alternatives with the preferred
|
|
131
|
+
first, which is the one the other checks read, so this asks rather
|
|
132
|
+
than accuses.
|
|
133
|
+
- `own-ancestor` (contradiction): a loop in the parent links, read from
|
|
134
|
+
both directions of the family link as `FamilyGraph` reads them. One
|
|
135
|
+
finding per loop, on the person in it the file lists first, naming the
|
|
136
|
+
shortest way round: in full up to six steps, and past that its first
|
|
137
|
+
five and how many more, so a loop through 20,000 people is one short
|
|
138
|
+
message.
|
|
139
|
+
|
|
140
|
+
The three checks that compare pairs are bounded, so a hostile file cannot
|
|
141
|
+
make the report as large as the square of its people. `children-too-close`
|
|
142
|
+
and `possible-duplicate-child` report at most ten pairs for one mother,
|
|
143
|
+
and `conflicting-vitals` ten for one person's births and ten for their
|
|
144
|
+
deaths, the first in the order the file lists them; one more finding under
|
|
145
|
+
the same check, as serious as the most serious pair it stands for, then
|
|
146
|
+
says how many more pairs there are and how many in all (`4059990 more
|
|
147
|
+
pairs of children born 2 to 270 days apart, 4060000 in all`). The work is
|
|
148
|
+
bounded too: births and deaths are counted by sorting rather than compared
|
|
149
|
+
pair by pair; children who share a span of birth days, or a given name,
|
|
150
|
+
are compared as one group; and one mother's children are compared at most
|
|
151
|
+
100,000 times for each check, past which the summary gives its counts as
|
|
152
|
+
lower bounds. A family of 3,000 children of one name born in one month,
|
|
153
|
+
which made 4.5 million sibling findings, makes 22; a person with 5,000
|
|
154
|
+
births, which made 12.5 million `conflicting-vitals` findings, makes 11.
|
|
155
|
+
|
|
156
|
+
### Changed
|
|
157
|
+
|
|
158
|
+
- PyPI gets one wheel, Linux x86_64, beside the source distribution. The
|
|
159
|
+
macOS and Windows wheels are no longer cross-built; on those platforms pip
|
|
160
|
+
builds from the sdist, which needs a Rust toolchain.
|
|
161
|
+
- `died-before-born`, `buried-before-died`, `christened-before-born`,
|
|
162
|
+
`married-after-died` and `conflicting-vitals` compare as finely as both
|
|
163
|
+
dates allow: a burial on 12 September before a death on 14 September of
|
|
164
|
+
one year is now found. Julian and Gregorian dates are put on one count of days first.
|
|
165
|
+
An approximate date (`ABT`, `CAL`, `EST`) still vouches for its year and
|
|
166
|
+
nothing finer, and a bound (`BEF`, `AFT`, `BET`) admits its own day. A
|
|
167
|
+
finding the years alone decide keeps its wording (`born 1900 and died
|
|
168
|
+
1880`); one only a finer comparison finds names the dates in full
|
|
169
|
+
(`died 14 September 1862 and buried 12 September 1862`).
|
|
170
|
+
- An approximate date (`ABT`, `CAL`, `EST`) may be a year out. A finding
|
|
171
|
+
that two events are out of order is a question, not a contradiction, when
|
|
172
|
+
moving each approximate date a year either way could put them in order:
|
|
173
|
+
`BIRT ABT 1850` with `CHR 1849` or `CENS 1849`, or `DEAT ABT 1850` with a
|
|
174
|
+
burial in 1849. Two years out it is still a contradiction. This holds for
|
|
175
|
+
`died-before-born`, `buried-before-died`, `event-after-death`,
|
|
176
|
+
`married-before-born` and `child-born-after-mother-died`, and for the new
|
|
177
|
+
`christened-before-born`, `event-before-birth` and `married-after-died`;
|
|
178
|
+
the checks about an age or an interval take an approximate year as
|
|
179
|
+
written. Their messages say an approximate date is one: `born about 1850,
|
|
180
|
+
and Christening is dated 1849`.
|
|
181
|
+
- `event-after-death` is a question, not a contradiction, for an `EVEN` or
|
|
182
|
+
`FACT`. Such an event is whatever its free-text `TYPE` says — a land
|
|
183
|
+
entry completed, a patent issued, an estate settled — and many of those
|
|
184
|
+
are done in a dead person's name. The other events keep their severity.
|
|
185
|
+
- `by` is read as a `BEF` qualifier: `by 5 October 1752` is
|
|
186
|
+
`BEF 5 OCT 1752`, where it was read as 5 May 1752. The qualifiers the
|
|
187
|
+
reader already knew (`abt`, `about`, `c.`, `ca.`, `bef`, `before`, `aft`,
|
|
188
|
+
`after`, and the others) are unchanged.
|
|
189
|
+
|
|
190
|
+
### Fixed
|
|
191
|
+
|
|
192
|
+
- The date reader no longer shifts the pieces of a four-word date around a
|
|
193
|
+
word it does not know. `chr 10 Nov 1788` read as 10 October 1788,
|
|
194
|
+
`b 9 Jun 1750` as 9 September, `bapt. 3 May 1801` as 3 March: the leading
|
|
195
|
+
word was tried as a month, failed, and the day number was taken as the
|
|
196
|
+
month instead. Four pieces are now read only as a day, its ordinal ending
|
|
197
|
+
and a month written as a word, in either order (`Feb 11 th 1809`,
|
|
198
|
+
`11 th Feb 1809`, `1er janvier 1800`, `5te Januar 1800`); anything else is
|
|
199
|
+
`DateKind::Unparsed`, keeps its text as the phrase, and still offers its
|
|
200
|
+
year to sort by, so `to_gedcom_5_5_1` and `to_gedcom_7` return `None` and
|
|
201
|
+
the caller writes it as a date phrase. A month given only as a number never
|
|
202
|
+
decides the order of four pieces.
|
|
203
|
+
- A dual year (`10 JAN 1731/32`) admits both its years in every check, not
|
|
204
|
+
only where days are compared. The checks that compare years read it as
|
|
205
|
+
its first year alone, so `BIRT 1732` with `DEAT 10 JAN 1731/32` was
|
|
206
|
+
`died-before-born` ("born 1732 and died 1731"); it is now no finding, and
|
|
207
|
+
a death past both years says `died between 1731 and 1732`. Where the days
|
|
208
|
+
of two dates are compared, they alone decide the order, so a burial in the
|
|
209
|
+
Julian year 1700, which runs eleven days into the Gregorian 1701, is no
|
|
210
|
+
longer wholly before a death in the Gregorian 1701.
|
|
211
|
+
- `child-listed-twice` keeps the children it has seen in a set rather than
|
|
212
|
+
a list, so a family listing tens of thousands of children is checked in
|
|
213
|
+
time proportional to their number, not its square.
|
|
214
|
+
- The checks on an individual's own record read that record's dates when it
|
|
215
|
+
has no identifier, or shares one with another record. Before, such a
|
|
216
|
+
record was checked against no dates, or against those of the last record
|
|
217
|
+
with its identifier.
|
|
218
|
+
|
|
8
219
|
## [0.1.17] - 2026-10-16
|
|
9
220
|
|
|
10
221
|
### Changed
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
# was checked on crates.io, npm, and PyPI before the initial release.
|
|
4
4
|
[package]
|
|
5
5
|
name = "gedcomkit"
|
|
6
|
-
version = "0.1.
|
|
6
|
+
version = "0.1.19"
|
|
7
7
|
description = "A byte-preserving GEDCOM document model: decoding, parsing, readings, version conversion, plausibility checks, and the GEDZIP container, for GEDCOM 5.5 through 7.x."
|
|
8
8
|
edition = "2024"
|
|
9
9
|
# The true minimum, not the workspace's toolchain: a parser library is a leaf
|
|
@@ -35,7 +35,7 @@ dependencies = [
|
|
|
35
35
|
|
|
36
36
|
[[package]]
|
|
37
37
|
name = "gedcomkit"
|
|
38
|
-
version = "0.1.
|
|
38
|
+
version = "0.1.19"
|
|
39
39
|
dependencies = [
|
|
40
40
|
"flate2",
|
|
41
41
|
"serde",
|
|
@@ -43,7 +43,7 @@ dependencies = [
|
|
|
43
43
|
|
|
44
44
|
[[package]]
|
|
45
45
|
name = "gedcomkit-py"
|
|
46
|
-
version = "0.1.
|
|
46
|
+
version = "0.1.19"
|
|
47
47
|
dependencies = [
|
|
48
48
|
"gedcomkit",
|
|
49
49
|
"pyo3",
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
# abi3 keeps it to one wheel per platform across Python versions.
|
|
3
3
|
[package]
|
|
4
4
|
name = "gedcomkit-py"
|
|
5
|
-
version = "0.1.
|
|
5
|
+
version = "0.1.19"
|
|
6
6
|
description = "Python bindings for gedcomkit: an archival-grade GEDCOM library — byte-preserving round-trip, encoding detection, GEDCOM 5.5 through 7.x, GEDZIP."
|
|
7
7
|
edition = "2024"
|
|
8
8
|
rust-version = "1.88"
|
|
@@ -19,6 +19,29 @@ class RecordSpec(TypedDict):
|
|
|
19
19
|
value: NotRequired[str | None]
|
|
20
20
|
children: NotRequired[list[RecordSpec]]
|
|
21
21
|
|
|
22
|
+
class EventView(TypedDict):
|
|
23
|
+
"""One entry of an individual's or a family's ``events``.
|
|
24
|
+
|
|
25
|
+
``date`` is the DATE payload exactly as written. ``datePhrase`` is the
|
|
26
|
+
GEDCOM 7 PHRASE beneath that DATE, or ``None``: beside a date, or the
|
|
27
|
+
only text an empty 7.0 DATE has. A 5.5.1 phrase is part of ``date``.
|
|
28
|
+
"""
|
|
29
|
+
|
|
30
|
+
tag: str
|
|
31
|
+
label: str
|
|
32
|
+
date: str | None
|
|
33
|
+
datePhrase: str | None
|
|
34
|
+
dateDisplay: str | None
|
|
35
|
+
year: int | None
|
|
36
|
+
sortKey: int | None
|
|
37
|
+
place: str | None
|
|
38
|
+
age: str | None
|
|
39
|
+
cause: str | None
|
|
40
|
+
attribute: bool
|
|
41
|
+
value: str | None
|
|
42
|
+
citations: list[str]
|
|
43
|
+
path: list[int]
|
|
44
|
+
|
|
22
45
|
class WrappedLine(TypedDict):
|
|
23
46
|
record: str
|
|
24
47
|
path: list[int]
|
|
@@ -42,9 +65,15 @@ class Gedcom:
|
|
|
42
65
|
def content_records(self) -> int: ...
|
|
43
66
|
def records(self) -> list[dict[str, Any]]: ...
|
|
44
67
|
def record(self, xref: str) -> dict[str, Any]: ...
|
|
45
|
-
def individuals(self) -> list[dict[str, Any]]:
|
|
46
|
-
|
|
47
|
-
def
|
|
68
|
+
def individuals(self) -> list[dict[str, Any]]:
|
|
69
|
+
"""Every individual's view; each of its ``events`` is an ``EventView``."""
|
|
70
|
+
def families(self) -> list[dict[str, Any]]:
|
|
71
|
+
"""Every family's view; each of its ``events`` is an ``EventView``."""
|
|
72
|
+
def validate(self) -> list[dict[str, Any]]:
|
|
73
|
+
"""Plausibility findings, each with ``record``, ``check``, ``severity``
|
|
74
|
+
and ``message``. ``check`` is the core's stable rule name, such as
|
|
75
|
+
``died-before-born`` or ``own-ancestor``; the core's ``validate``
|
|
76
|
+
module documentation lists every one with its severity."""
|
|
48
77
|
def unresolved_pointers(self) -> list[dict[str, Any]]: ...
|
|
49
78
|
def parents_of(self, xref: str) -> list[str]: ...
|
|
50
79
|
def children_of(self, xref: str) -> list[str]: ...
|
|
@@ -224,6 +224,8 @@ impl Gedcom {
|
|
|
224
224
|
}
|
|
225
225
|
|
|
226
226
|
/// Every individual, read for display: names, events, families, IDs.
|
|
227
|
+
/// Each event has its `date` payload as written and, beside it,
|
|
228
|
+
/// `datePhrase`: the GEDCOM 7 `PHRASE` under the date, or `None`.
|
|
227
229
|
fn individuals(&self, py: Python<'_>) -> PyResult<Vec<Py<PyAny>>> {
|
|
228
230
|
self.document
|
|
229
231
|
.records_of("INDI")
|
|
@@ -231,7 +233,7 @@ impl Gedcom {
|
|
|
231
233
|
.collect()
|
|
232
234
|
}
|
|
233
235
|
|
|
234
|
-
/// Every family record's view.
|
|
236
|
+
/// Every family record's view, its events shaped as `individuals`' are.
|
|
235
237
|
fn families(&self, py: Python<'_>) -> PyResult<Vec<Py<PyAny>>> {
|
|
236
238
|
self.document
|
|
237
239
|
.records_of("FAM")
|
|
@@ -240,7 +242,10 @@ impl Gedcom {
|
|
|
240
242
|
}
|
|
241
243
|
|
|
242
244
|
/// Plausibility findings: contradictions, questions, and what cites
|
|
243
|
-
/// nothing — reported with the numbers they were drawn from.
|
|
245
|
+
/// nothing — reported with the numbers they were drawn from. Each has
|
|
246
|
+
/// `record`, `check`, `severity` and `message`; `check` is the core's
|
|
247
|
+
/// stable rule name (`died-before-born`, `own-ancestor`, …), listed with
|
|
248
|
+
/// its severity in the core's `validate` module documentation.
|
|
244
249
|
fn validate(&self, py: Python<'_>) -> PyResult<Vec<Py<PyAny>>> {
|
|
245
250
|
gedcomkit::validate::inspect(&self.document)
|
|
246
251
|
.iter()
|