Sync addons-source@maintenance/gramps60 with upstream (2026-05-27) - #21
Merged
eduralph merged 31 commits intoMay 29, 2026
Merged
Conversation
`RebuildTypes/RebuildTypes.gpr.py` declares `include_in_listing=False`, `status=UNSTABLE`, `category=TOOL_DBFIX` and `authors=["Nick Hall"]` - it is not published to users and is flagged as a database-modifying tool that may corrupt data. The addon also carried two stale Gramps-3 era pre-namespace imports (`from gui.plug import tool`, `from QuestionDialog import OkDialog`) that broke plugin registration on Python 3, so a load-time fix would have been needed to revive it. On PR gramps-project#877 (closed 2026-05-15, the prior port attempt) the addon's author and the project maintainer agreed to drop it rather than port: Nick-Hall: "The RebuildTypes addon was either just an example or written for a particular person to fix a bug. An export followed by an import will achieve the same result. The Type Cleanup tool may also be a better option. I am happy for this addon to be deleted." GaryGriffin: "Seeing TOOL_DBFIX and UNSTABLE together is scary for a released addon." Replace the dead/dangerous addon with its absence. Users needing the same outcome have two supported alternatives Nick named: - export / re-import (rebuilds the type catalogue as a side effect of the round-trip) - the Type Cleanup tool (which is published and maintained) No listing impact - the addon was already `include_in_listing=False`, so `addons/gramps*/listings/addons-*.json` did not reference it; no other tree references it either (`grep -rn RebuildTypes` on `upstream/maintenance/gramps60` returns hits only inside the `RebuildTypes/` directory itself). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The four ngettext() counter calls embedded a trailing \n in the plural form but not the singular. gettext requires a msgid and its msgid_plural to agree on the trailing newline, so msgfmt rejected every catalog that translated these strings and `make.py build lxml` aborted with fatal errors (Mantis bug 14234). Append the layout newline in code instead -- as the pre-39fbcdd version did -- so it is no longer part of the translatable string. The singular case (count == 1) still gets its line break. The per-language catalogs are not touched here: make.py extract-po regenerates them from the corrected template, so the stale \n drops out of de/hr/nl/pt_PT/sk through the normal Weblate pipeline rather than by hand-editing build output. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Provides nine filter rules (Person, Family, Event, Place, Source, Citation, Repository, Media, Note) that match objects whose tag names contain a given substring (case-insensitive). Uses the selected_handles optimizer pattern with find_backlink_handles so only objects of the target namespace are fetched from the database. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Closing a family tree emits 'database-changed'; change_db() clears the history and calls redraw(), which -- finding no active person -- calls change_object(None). That returned immediately, before the code that rebuilds header/stack, so the view kept showing the closed tree's people. Their edit buttons still held handles from the closed database, and clicking one raised gramps.gen.errors.HandleError inside get_person_from_handle() (Mantis bug 12572; the underlying stale-view symptom is Mantis bug 14226). On the no-active-object path, clear header/stack and disable the per-page actions instead of returning early, mirroring the built-in RelationshipView whose change_db() clears its container directly. edit_active() is guarded against the now-possible active_page is None. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…10512)
## Root cause
The Sandclock Genealogy Tree report rendered only one page of an
arbitrarily-large tree. The LaTeX `genealogytree` package's default
`database` template lays the tree out so widely that big sandclocks
clip off the page; the package itself does not support multi-page
output for that layout (confirmed by SNoiraud in note ~0046612 on
the Mantis ticket).
## Fix
Expose SNoiraud's 2018-12-20 workaround as a user-facing report option.
A new "Compact tree layout" boolean on the Sandclock report appends
`template=database pole reduced` to the `\genealogytree[…]` parameter
list when enabled, giving ~4x more space per page at the cost of
denser per-node formatting.
The directive is appended last so it overrides any node-spacing
defaults that `gramps/gen/plug/docgen/treedoc.py`'s built-in keys
(`level distance`, `node size`, `level size`) set earlier in the
parameter list — pgfkeys is order-sensitive, so a later `template=`
re-sets the keys the template controls.
Option-list assembly was extracted into a `_build_tree_options()`
method so the option-construction logic can be unit-tested without
driving a full report run.
## Verified against
- `GenealogyTree/gt_sandclock.py:148` — `_build_tree_options` body
- `GenealogyTree/gt_sandclock.py:96-128` — `write_report` calls into it
- `GenealogyTree/treeplugins.gpr.py` — unchanged; per addons-source
convention the maintainer manages the `.gpr.py` version, not the
contributor
## Test
`GenealogyTree/tests/test_sandclock_compact_template.py` — five focused
unit tests exercising the new option-list builder via
`SandclockTree.__new__(...)` skeleton (no Gramps GUI, no LaTeX, no DB).
Cover:
* Default layout omits any `template=` directive.
* `compact=True` appends exactly `template=database pole reduced`.
* Directive lands LAST in the option list (pgfkeys order).
* Other default options (`pref code=`, `list separators hang`,
`place text=`, `box=`) remain intact when compact is on.
* `include_images` and `compact` coexist without either suppressing
the other.
All 5 pass via `gramps-testbed/scripts/ubuntu/run-addon-unit.sh
GenealogyTree`.
Fixes #10512
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
main() reads `self.uistate.viewmanager.active_page.bottombar` unguarded, but the gramplet framework keeps stepping the generator via `_updater` → `next(self._generator)` after the family tree is closed. At that point `active_page` is None, so the read raises AttributeError: 'NoneType' object has no attribute 'bottombar'. Pull active_page into a local, return early if it's None, then proceed with the existing bottombar/db-open/count<3 short-circuit chain. No behaviour change while a tree is open. Regression test exercises main() with a stub uistate whose active_page is None and asserts the generator exits cleanly (StopIteration) instead of raising. Two further cases lock the existing dashboard / non-dashboard short-circuit paths so the new guard does not regress them. Fixes #13966
… off The pre-pass guarded by `if self.dubperson:` in write_report() is the only path that fills `self.report_app_ref`. When that option is off but Index of Dates / Places / Names is on, append_event still runs from write_person_info / __write_family_events for every event and raises against the empty / missing table — KeyError on the current handle (this report), or AttributeError on older addon versions before the partial fix for 12857/12859 added the unconditional init. Fall back inside append_event to the current writing-pass coordinates (report_count, generation+1, dnumber[phandle], person's name). That is the natural Ref for an index entry anyway — the location in the document where the event is being narrated. When report_app_ref is populated (the omit-duplicates path), the original `[0]` read is preserved, so behaviour there is unchanged. Regression test exercises append_event in isolation with an empty report_app_ref and asserts (a) it does not raise and (b) the index entry references current state. Fixes #14051
Refines the previous commit. The earlier fallback computed the Ref tuple from the CURRENT writing-pass coordinates each time append_event ran. With omit-duplicates off and a person appearing in multiple per-ascendant reports, append_event runs once per encounter, and `self.index_of_dates[year][date]` / index_of_places overwrites on every call — so the surviving entry ended up tagged with the LAST encounter's coordinates, not the first. The omit-duplicates path emits the FIRST-encounter coordinates (report_app_ref[phandle][0]). Populating that entry on first call in append_event — rather than re-deriving on every call — pins the Ref to the first encounter and makes the two paths semantically equivalent. Verified empirically on example.gramps (I00016): 1365 / 1372 common (place, date) index entries have identical Ref tuples between omit-duplicates ON and OFF; the 7 mismatches all carry `date="0000-00-00"`, a pre-existing key collision in index_of_places[place][date] where unrelated empty-date events overwrite each other (independent of this fix). Place coverage in OFF is slightly higher (658 vs 656) because OFF doesn't early-return duplicates, so events on duplicated people are indexed too. New test TestRefSemanticsParityWithOmitDuplicates locks first- encounter semantics by simulating a multi-encounter scenario.
PluginStatus.__info iterates Requirements().info(addon) as [label, table] pairs and joins the first row with " ".join(req_lst[0]). If the addon listing carries a present-but-empty requires key - e.g. PostgreSQL Enhanced's gpr.py declares `requires_exe=[]`, which ends up as `"re": []` in addons-<lang>.json - gramps core's Requirements.info still emits an "Executables" label paired with an empty table, and the join raises `IndexError: list index out of range`. Skip empty tables cleanly: indexing fails on them and there is nothing useful to render anyway. PostgreSQL Enhanced is currently the only addon in gramps61 listings with a present-but-empty requires key, which matches the reported "only the PostgreSQL Enhanced row crashes" symptom. Resolves #13979.
Running `make.py <ver> listing <Addon>` against an addon whose .gpr.py declares `include_in_listing=False` (or whose .addon.tgz has not been built yet) caused the listings file to be overwritten with `[]`, wiping every previously listed addon for that language. The single-addon update path builds `listings` per language, then either replaces the file (for "listing all") or merges entries from the existing file with the new ones. When the targeted addon yielded no eligible plugin, `listings` was empty, the merge loop did not iterate, and `output` was written as `[]`. Guard the single-addon path: when `listings` is empty and a listings file already exists, skip the write and tell the user that the targeted addon is not eligible and how to remove an existing entry on purpose (`make.py <ver> unlist <Addon>`). Resolves #13694.
GaryGriffin flagged on PR 915 that the listings file still corrupts for addons that ship multiple .gpr.py files (or multiple register() calls per .gpr.py). The Form addon is the canonical example: running `make.py gramps61 listing Form` ballooned addons-en.json from 170 entries to 510 - every existing addon appearing three times, one per Form-registered plugin. Root cause: the merge path's outer `for plugin in sorted(listings, ...)` loop re-read the entire existing listings file on each iteration while accumulating into a shared `output`. With N new plugins for cmd_arg the existing N-1 unrelated entries got appended N times. Replace the per-plugin re-read with a single-pass merge: read the existing file once, drop every row that belongs to cmd_arg (matched by .z) or whose (t, i) collides with one of the fresh plugins, then merge the kept rows with the new plugins in sorted (t, i) order. This also tightens behaviour in two ways: - Stale entries for cmd_arg (e.g. a register() removed from a gpr.py since the last build) are dropped, not preserved. - The "first match wins" ambiguity of the old z+t matcher is gone; matching is per-plugin by (t, i). Tests in `tests/test_make_listing.py` now cover both the 13694 case (include_in_listing=False addon) and a multi-gpr addon shaped like the real Form. The multi-gpr test fails on the pre-fix code with "14 != 6" - exactly the symptom Gary saw - and passes after. Resolves #13694.
The Geneanet entry in WEBSITES (FRWebPack.py:45) pointed at the deprecated `https://search.geneanet.org/result.php?lang=fr&name=...` URL, which no longer returns useful results, and the template only carried the surname. Replace with the current individus search the reporter on Mantis 14145 supplied: https://www.geneanet.org/fonds/individus/?go=1&nom=%(surname)s&prenom=%(given)s The two `%(...)s` placeholders match the file's existing convention (see lines 41, 46, 48) and the libwebconnect URL builder at libwebconnect/libwebconnect.py:182, which formats the pattern with the dict returned by make_person_dict — both `surname` and `given` keys are populated there. callmedave's note 4 on the tracker recommends the WebSearch Gramplet as a longer-term replacement for the Web Connect Pack family of addons, BUT his note 5 explicitly confirms the bug for FrWebConnectPack — so the live addon is still in scope and this is not a wontfix. Add a regression test in `FRWebConnectPack/tests/` that pulls the Geneanet pattern from WEBSITES and applies the same `pattern % dict` formatting libwebconnect uses. Pure string assertion — no network, no display, no Gtk. The test covers both halves of the fix: the URL must include both name parts (the given name was discarded pre-fix) and must target the current host/path/params (the old `search.geneanet.org/result.php` form is asserted absent). Verified via the testbed's `run-addon-unit.sh FRWebConnectPack`: Before fix: FAILED (failures=2) After fix: 2 tests, OK Fixes #14145 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Add IE 1926 Form and reference
B/M/D forms from https://gramps-project.org/bugs/view.php?id=13977 Removed Marriage/Signed field
Added new headings for additional attributes in the form. Added new headings and reordered them.
eduralph
force-pushed
the
sync/upstream-maintenance-gramps60-auto
branch
from
May 28, 2026 07:45
320d9d5 to
7aa8a9a
Compare
eduralph
force-pushed
the
sync/upstream-maintenance-gramps60-auto
branch
from
May 29, 2026 07:45
7aa8a9a to
7b06efa
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Automated nightly sync from
gramps-project/addons-source@maintenance/gramps60. Generated by .github/workflows/upstream-sync.yml on the testbed.