Skip to content

PersonRelationshipFilter#987

Open
dsblank wants to merge 3 commits into
gramps-project:maintenance/gramps61from
dsblank:dsb/person-relationship-filter-fixes
Open

PersonRelationshipFilter#987
dsblank wants to merge 3 commits into
gramps-project:maintenance/gramps61from
dsblank:dsb/person-relationship-filter-fixes

Conversation

@dsblank

@dsblank dsblank commented Jul 17, 2026

Copy link
Copy Markdown
Member

A new gramplet, Relationship Filter (previously called Flat Filter), that drops into the Person view's Gramplet bar as a sidebar-style filter. Unlike the built-in Person filter (which only matches on the active person's own attributes), this one searches by the names of relatives:

  • the person's own name
  • father's / mother's name
  • spouse's name
  • up to two named siblings
  • up to two named children
  • a "probably alive on date" filter

Each name field is split into given-name and surname boxes searched independently (substring or regex), and results combine into a single GenericFilter applied to the Person view.

Motivation

The stock Person sidebar filter can't answer "find people whose mother is named X" or "find the children of someone named Y" — you have to know the target person's own name or ID. In a large tree, it's often the relative's name you remember, not the person you're actually looking for. This gramplet lets you search on that relationship directly instead of navigating the tree by hand.

History and bugs fixed here

This is a new addon for addons-source, based on earlier work by Paul Womack (BugBear, 2024). While bringing it up to date for Gramps 6.1, I found and fixed two correctness bugs in that original code:

  • IsSiblingofNamedSibling crashed with HandleError whenever applied to a person with no recorded parents (any root ancestor, immigrant, etc.). Person.get_main_parents_family_handle() returns None when there's no parent family, but the code passed that straight into get_family_from_handle(), which raises rather than returning None on a None handle. Fixed with a guard, matching the pattern used elsewhere in this file and in core (e.g. persondetails.py).
  • RegExpPersonal/RegExpFamily searched mismatched Name fields. The personal (given-name) field list listed title twice instead of including the call name, so a personal-name search never matched a person's call name. The family/surname field list included title and call name — both personal-name fields — so a surname search could false-positive on an unrelated title or call name. Split the field lists to match the Given/Family grouping in the Name Editor.

Also:

  • Renamed a variable shadowing the all builtin.
  • Reformatted with black; added a type annotation so mypy is clean.
  • Added tests/test_person_relationship_filter_rules.py — builds a small family tree directly in an in-memory database and exercises every rule (RegExpPersonal/RegExpFamily field matching, HasNamedFather/Mother/Child/Spouse, IsSiblingofNamedSibling, HasName), including both regressions above. tests/__init__.py is left empty, matching the convention used by the rest of the repo's per-addon test suites (only RepositoriesReport pins GTK/GDK at the package level; every other addon's tests/__init__.py is empty and each test module self-guards, which this one does too).

Test plan

  • python3 -m pytest PersonRelationshipFilter/tests/ -v — 19 passed
  • Verified both regression tests fail against the pre-fix code (HandleError for the sibling crash, AssertionError for the call-name mismatch) and pass again with the fix
  • black --check PersonRelationshipFilter/ — clean
  • mypy --ignore-missing-imports PersonRelationshipFilter/PersonRelationshipFilter.py PersonRelationshipFilter/tests/ — clean

🤖 Generated with Claude Code

…ields

IsSiblingofNamedSibling crashed with HandleError whenever applied to a
person with no recorded parents, because get_family_from_handle(None)
raises rather than returning None. RegExpPersonal/RegExpFamily also
searched mismatched Name fields (title was listed twice in the
personal list, and call name was searched by the family/surname rule
instead), so personal search never matched a person's call name and
surname search could false-positive on an unrelated title or call
name. Adds unit tests covering both regressions plus the general
relationship-matching rules, and brings the addon up to date with
black/mypy.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@dsblank dsblank changed the title PersonRelationshipFilter: fix HandleError crash and mismatched name fields PersonRelationshipFilter Jul 17, 2026
…wiki page

help_url pointed at Addon:AdvancedPersonFilter, a different addon name
left over from this addon's origin, instead of Addon:PersonRelationshipFilter.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@GaryGriffin

Copy link
Copy Markdown
Member

Don't need the pinning of Gtk and Gdk to 3.0 in the test.

Comment thread PersonRelationshipFilter/tests/test_person_relationship_filter_rules.py Outdated
@GaryGriffin

Copy link
Copy Markdown
Member

Running unittest failed

python3 -m unittest PersonRelationshipFilter.tests.test_person_relationship_filter_rules
Traceback (most recent call last):
File "/Volumes/Storage/Development/addons-source/PersonRelationshipFilter/tests/test_person_relationship_filter_rules.py", line 71, in
from PersonRelationshipFilter import (
...<8 lines>...
)
ImportError: cannot import name 'HasName' from 'PersonRelationshipFilter' (unknown location)

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "", line 198, in _run_module_as_main
File "", line 88, in _run_code
File "/Users/GrampsTest61/gtk/inst/lib/python3.14/unittest/main.py", line 18, in
main(module=None)
~~~~^^^^^^^^^^^^^
File "/Users/GrampsTest61/gtk/inst/lib/python3.14/unittest/main.py", line 103, in init
self.parseArgs(argv)
~~~~~~~~~~~~~~^^^^^^
File "/Users/GrampsTest61/gtk/inst/lib/python3.14/unittest/main.py", line 142, in parseArgs
self.createTests()
~~~~~~~~~~~~~~~~^^
File "/Users/GrampsTest61/gtk/inst/lib/python3.14/unittest/main.py", line 153, in createTests
self.test = self.testLoader.loadTestsFromNames(self.testNames,
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^
self.module)
^^^^^^^^^^^^
File "/Users/GrampsTest61/gtk/inst/lib/python3.14/unittest/loader.py", line 207, in loadTestsFromNames
suites = [self.loadTestsFromName(name, module) for name in names]
~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^
File "/Users/GrampsTest61/gtk/inst/lib/python3.14/unittest/loader.py", line 137, in loadTestsFromName
module = import(module_name)
File "/Volumes/Storage/Development/addons-source/PersonRelationshipFilter/tests/test_person_relationship_filter_rules.py", line 82, in
raise unittest.SkipTest("PersonRelationshipFilter module unavailable: %s" % err)
unittest.case.SkipTest: PersonRelationshipFilter module unavailable: cannot import name 'HasName' from 'PersonRelationshipFilter' (unknown location)

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.

2 participants