Skip to content

Sync addons-source@maintenance/gramps60 with upstream (2026-05-19) - #18

Merged
eduralph merged 13 commits into
maintenance/gramps60from
sync/upstream-maintenance-gramps60-auto
May 24, 2026
Merged

Sync addons-source@maintenance/gramps60 with upstream (2026-05-19)#18
eduralph merged 13 commits into
maintenance/gramps60from
sync/upstream-maintenance-gramps60-auto

Conversation

@eduralph

Copy link
Copy Markdown
Owner

Automated nightly sync from gramps-project/addons-source@maintenance/gramps60. Generated by .github/workflows/upstream-sync.yml on the testbed.

eduralph and others added 7 commits May 18, 2026 09:56
`PostgreSQLEnhanced/postgresqlenhanced.py:2102` calls `time.time()`
when stamping new tree metadata, but the file never imports `time`.
Ruff (F821) flags it:

    F821 Undefined name `time`
       --> PostgreSQLEnhanced/postgresqlenhanced.py:2102:44

Add `import time` alongside the other stdlib imports. Without it,
the tree-creation path raises `NameError` instead of recording the
timestamp.

Verified via `ruff check --select=E9,F63,F7,F82 --no-fix
--exclude='*.gpr.py' PostgreSQLEnhanced/` (now passes) and `python3 -m
py_compile`.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
`lxml/lxmlGramplet.py:400` and `:758` both use:

    if os.name is 'nt':

Python 3.12+ emits a SyntaxWarning on this idiom:

    SyntaxWarning: "is" with 'str' literal. Did you mean "=="?

`is` checks object identity, not equality. The expression happens to
evaluate as expected on CPython today only because short strings get
interned during compilation, so `os.name` and the literal `'nt'` end
up pointing at the same object — but that's an implementation detail
of the interpreter and not guaranteed by the language. The right test
is value equality.

Two other call sites in the same file already use `==` for the same
comparison (`lxmlGramplet.py:161` and `:181`), so this also brings the
file's style into self-consistency.

Verified via `python3 -W error::SyntaxWarning -m py_compile
lxml/lxmlGramplet.py` (exits 0).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
`lxml/lxmlGramplet.py:72,94` reference `self.uistate.window` at
module top level — both inside `except ImportError:` branches that
guard `import gzip` and `from lxml import etree, objectify`. `self`
is undefined at module-load time (the gramplet instance does not
exist yet), so when either import actually failed the addon module
crashed with:

    NameError: name 'self' is not defined

…instead of showing the intended ErrorDialog. Ruff (F821) flags
both:

    F821 Undefined name `self`
       --> lxml/lxmlGramplet.py:72:69
       --> lxml/lxmlGramplet.py:94:104

PR gramps-project#820's body listed this as one of the "Real bugs":
"stray `parent=self.uistate.window` at module level in
lxmlGramplet".

Drop `parent=self.uistate.window` from both `ErrorDialog` calls.
The dialogs render with no parent window — not ideal aesthetically,
but at module-load there genuinely is no UI parent to anchor to (the
alternative — moving these checks into the gramplet's `__init__` —
is a larger restructuring outside this PR's scope).

In practice the gzip branch is dead code (gzip is in the Python
stdlib and never raises ImportError); the lxml branch is the
user-visible win — when a user installs the addon without the lxml
package present, they now get the intended "Missing python3 lxml"
dialog instead of an opaque NameError that masks the underlying
cause.

No regression test is added for this fix:

  - The bug only fires when `from lxml import ...` raises
    ImportError, which requires either an unusual install or
    subprocess-isolated sys.modules tampering to simulate.
  - The natural location for the test would be `lxml/tests/`, but
    the addon directory name (`lxml`) collides with the third-party
    `lxml` package — Python's import system treats the latter
    (regular package, /usr/lib/python3/dist-packages/lxml) as taking
    precedence over the namespace-package addon directory, so
    `python3 -m unittest lxml.tests.test_*` cannot reach the
    addon's tests subtree on any system that has `lxml` installed
    (which the CI image always does).
  - Ruff F821 catches future regressions of this exact pattern,
    which is the same gate that surfaced the bug in the first
    place.

Verified via `ruff check --select=E9,F63,F7,F82 --no-fix
--exclude='*.gpr.py' lxml/` (both F821 sites on `self` removed —
the remaining F632 sites at lines 400/758 are in-flight via PR gramps-project#837)
and `python3 -m py_compile lxml/lxmlGramplet.py`.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@eduralph
eduralph force-pushed the sync/upstream-maintenance-gramps60-auto branch from d53dc47 to fd7fdd6 Compare May 20, 2026 07:34
eduralph and others added 2 commits May 20, 2026 12:17
Bug 0014056-style symptom, this one tracked as bug 0012913. When a
family in the descent chain has only one parent defined,
``family.get_mother_handle()`` returns ``None``, and the existing
``spouse_handle = mother if mother != handle else
family.get_father_handle()`` resolves to ``None`` too. The code
then called ``self.database.get_person_from_handle(None)``, which
raises ``HandleError: Handle is None`` and aborts the entire
report -- exactly the reporter's traceback.

The very next line already had a defensive ``if spouse: ... else:
spouse_name = 'N.N.'`` block, anticipating the missing-spouse case,
but the lookup right above it bypassed that branch by raising
before ``spouse`` was even bound.

Reproduction (per the reporter, against example.gramps):
  * Active person: Boucher, David (I0801)
  * Ancestor:      Boucher, David (I0801)
  * Descendant:    Boucher, Mary Cecilia (I0055)
  * In Family F0037, remove Reeves, Maria (I0052) as mother.
  * Run Reports → Text → Lines of Descendancy → crash before the
    fix; "N.N." in place of the missing spouse after the fix.

Fix: guard the get_person_from_handle call with ``if
spouse_handle:`` and fall back to ``spouse = None`` on the no-handle
path, so the existing ``'N.N.'`` fallback handles the rest.
Minimal-delta change; preserves existing user-visible behaviour for
the case where the spouse object itself is missing but the handle
isn't.

Test: extend the existing
LinesOfDescendency/tests/test_linesofdescendency_guards.py with a
TestWritePathMissingSpouse class that drives ``write_path``
directly via ``__new__``-bypass (mirrors the gramps-core test style
for guard regressions) and asserts: (1) the call completes without
HandleError, (2) get_person_from_handle is never called with None,
and (3) the rendered output still contains the existing 'N.N.'
fallback for the missing-spouse case.

Closes 12913 (MantisBT).
@eduralph
eduralph force-pushed the sync/upstream-maintenance-gramps60-auto branch from fd7fdd6 to 7630945 Compare May 21, 2026 07:40
@eduralph
eduralph force-pushed the sync/upstream-maintenance-gramps60-auto branch 2 times, most recently from 0281a4c to c1103b4 Compare May 23, 2026 06:27
@eduralph
eduralph force-pushed the sync/upstream-maintenance-gramps60-auto branch from c1103b4 to 9c03337 Compare May 24, 2026 06:53
@eduralph
eduralph merged commit ce0449d into maintenance/gramps60 May 24, 2026
6 of 7 checks passed
@eduralph
eduralph deleted the sync/upstream-maintenance-gramps60-auto branch May 24, 2026 10:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants