Sync addons-source@maintenance/gramps61 with upstream (2026-06-30)#59
Sync addons-source@maintenance/gramps61 with upstream (2026-06-30)#59eduralph wants to merge 62 commits into
Conversation
In both make.py and setup.py, the function extracting addon translation languages contained dead code: a fixed-width slice assignment that immediately gets overwritten. The `locale = po[length-11:length-9]` statement (make.py:165, setup.py:787) extracts only 2 characters, which would mangle locales like `pt_BR` or `zh_CN`. However, the very next line (make.py:166, setup.py:788) overwrites `locale` using `po.rsplit()`, and the derived locale (make.py:167, setup.py:789) strips only the suffix `-local.po`, yielding the full code for any length. The slice never reaches any output; removing it clarifies the code path without changing behavior, confirmed by end-to-end testing with multi-char locales. Fixes #7344 Signed-off-by: Eduard Ralph <eduard@ralphovi.net>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: c2000d6b19
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| r'(?P<nad>SE/\w+/\d+/[^,]+)\s*' | ||
| r'\((?P<years>\d{4}(?:-\d{4})?)\),\s*' | ||
| r'bildid[^_]*_(?P<bildid>\d+)' | ||
| r'(?P<nad>[^\(]+)*' |
There was a problem hiding this comment.
Remove the nested quantifier from NAD parsing
When the user pastes a partial Riksarkivet-like string with two comma-separated fields but no following ( year section, (?P<nad>[^\(]+)* can repartition the same NAD text exponentially while trying to satisfy the next group, so the GTK click handler can freeze on short invalid input; in addition, the outer * lets nad be None before the later .strip(). Make the NAD portion required without the outer repetition, or fail before dereferencing it.
Useful? React with 👍 / 👎.
c2000d6 to
7fc72c9
Compare
When the Deep Connections path search finds the active/target person,
it reports the connection path and pauses for user interaction. On
resume ("Continue"), the search was falling through and expanding the
target itself as a regular node, queuing the target's own relatives;
those relatives then re-reach the target, causing the search to
re-emit the same connection (now with the target re-entered as an
interior step). This repeat happens with every "Continue" press while
undiscovered distinct paths remain.
The fix skips the target expansion by adding a `continue` statement
after the pause/yield in the found-target branch, advancing directly
to the next queued candidate. Genuinely distinct connections already
queued before the target was first found remain reachable, preserving
all independent paths the user should see.
Verified by regression test driving the production path-search
generator on a fixture with two node-disjoint Home→target connections
plus a target child that triggered the bounce-back repeat; the test
asserts no path re-enters the target, both independent paths remain
reachable, and consecutive paths never repeat.
Fixes #10628
Signed-off-by: Eduard Ralph <eduard@ralphovi.net>
The DescendantsLines report derives the graphic's output filename solely from its persisted "Destination" option, which retains the previous session's value across Gramps sessions. The graphic lands on that stale name rather than the filename chosen for the current run in the standard report dialog's "Document Options", ignoring the user's current selection entirely. Extract the filename derivation into a pure helper module (descendantslines_output.py, free of gi imports so it can be tested headlessly) and route production through derive_output_filename, which sources the current run's destination instead. Fall back to the persisted option only when no current destination is given (e.g. CLI without -O). When the derived name would equal the document's own output path, add a -chart suffix to avoid clobbering by the document's close(). Fixes #5965 Signed-off-by: Eduard Ralph <eduard@ralphovi.net>
…amps 6.1 - Add evaluate_expression() method — runs code in full scope and returns stdout - Fix save_script crash when no filename set (fall through to Save As) - Fix get_columns() returning None instead of [] when no match found - Add database variable to script execution scope - Update gramps_target_version to 6.1 - Add tests/: DataDict2/DataList2/NoneData unit tests and get_columns tests Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…arget gramps 6.1#959
be63620 to
adcaf2b
Compare
…nd patronymic names
…tions, add E2E tests
…iven and patronymic names#941
The Dynamic Web Report (DWR) tree SVG view rewrites hyphens inside names to spaces — "Jan-Åke" renders as "Jan Åke" in the tree only, while every other DWR surface (indexes, tabs, mouse-over) shows the hyphen faithfully. The rewrite lives in dwr_svg.js:2939, where the tree-node name is split for line-wrapping using the regex /[ \-]+/g, which treats hyphens exactly like spaces. The fragments are then rejoined with a space (dwr_svg.js:2862), silently converting the hyphen to a space. The Python name export path (dynamicweb.py:1052–1055, 923–924) is faithful and is not the cause — only the tree passes the name through this splitter. Fix: split on spaces only (/ +/g), so hyphens become ordinary characters inside words and render intact. A hyphenated name is no longer a multi-word token and cannot wrap at its hyphen, but that layout nicety is explicitly out of scope, and preserving the name character outranks an internal wrap opportunity. Includes a regression test (DynamicWeb/tests/test_dwr_tree_names.py) that reads the production splitter regex live from dwr_svg.js and reproduces the tree's same-line join logic, asserting the hyphen survives for hyphenated names. The test fails red with the buggy regex and passes green with the fix. Fixes #11437 Signed-off-by: Eduard Ralph <eduard@ralphovi.net>
* GrampsAssistant: AI assistant addon for Gramps Adds the GrampsAssistant tool, which provides an AI-powered chat interface for querying and exploring a Gramps family tree database. Features: - Anthropic and OpenAI-compatible backend support, plus local model support - Tool registry with 20+ Gramps-specific tools (person lookup, navigation, filtering, relationship finding, statistics, GrampyScript integration) - evaluate_expression tool for immediate introspection of the database - execute_script tool for staging GrampyScript code for user execution - Comprehensive docstrings describing the GrampyScript execution environment (iterators, object properties, null-safe chaining, database access) - Test suite: tool registry, backend (SSE parsing, tool-call handling, message conversion), and Gramps tool integration tests Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * Apply suggestion from @dsblank * Apply suggestion from @dsblank * Update GrampsAssistant/grampsassistant.py * Update GrampsAssistant/tools.py * GrampsAssistant: convert tests from pytest to unittest Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * GrampsAssistant: skip live API tests when key is unavailable or unreachable Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * GrampyScript: add _instance singleton and return STDOUT from execute_code Needed by GrampsAssistant's execute_script and evaluate_expression tools, which look up the running GrampyScript instance via GrampyScript._instance and capture output via the return value of execute_code. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * GrampyScript: remove GrampyScript.py changes that belong in PR gramps-project#959 The _instance singleton and return STDOUT from execute_code belong in the GrampyScript PR (gramps-project#959), not the GrampsAssistant PR (gramps-project#960). GrampsAssistant depends on those features landing via gramps-project#959 first. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Currently translated at 42.6% (2333 of 5472 strings) Translation: Gramps/Addons Translate-URL: https://hosted.weblate.org/projects/gramps-project/addons/ru/
Currently translated at 60.5% (3311 of 5472 strings) Translation: Gramps/Addons Translate-URL: https://hosted.weblate.org/projects/gramps-project/addons/es/
Currently translated at 60.5% (3311 of 5472 strings) Translation: Gramps/Addons Translate-URL: https://hosted.weblate.org/projects/gramps-project/addons/es/
Currently translated at 5.6% (310 of 5472 strings) Translation: Gramps/Addons Translate-URL: https://hosted.weblate.org/projects/gramps-project/addons/pt_BR/
Currently translated at 1.9% (107 of 5472 strings) Translation: Gramps/Addons Translate-URL: https://hosted.weblate.org/projects/gramps-project/addons/zh_Hans/
Currently translated at 75.2% (4119 of 5472 strings) Translation: Gramps/Addons Translate-URL: https://hosted.weblate.org/projects/gramps-project/addons/fr/
Currently translated at 23.7% (1302 of 5472 strings) Translation: Gramps/Addons Translate-URL: https://hosted.weblate.org/projects/gramps-project/addons/tr/
Currently translated at 3.7% (204 of 5472 strings) Translation: Gramps/Addons Translate-URL: https://hosted.weblate.org/projects/gramps-project/addons/en_GB/
Currently translated at 31.6% (1733 of 5472 strings) Translation: Gramps/Addons Translate-URL: https://hosted.weblate.org/projects/gramps-project/addons/tr/
Updated by "Update PO files to match POT (msgmerge)" add-on in Weblate. Translation: Gramps/Addons Translate-URL: https://hosted.weblate.org/projects/gramps-project/addons/
Currently translated at 100.0% (5522 of 5522 strings) Translation: Gramps/Addons Translate-URL: https://hosted.weblate.org/projects/gramps-project/addons/pt_PT/
adcaf2b to
ea7c4be
Compare
ea7c4be to
584e2ca
Compare
* first working version of excludesubtree person filter * Add boolean option to include the matched persons themselves * fix d63958f exception upon filter building > File "/usr/lib/python3/dist-packages/gramps/gui/editors/filtereditor.py", line 594, in init > t = v1 > TypeError: init() missing 2 required positional arguments: 'uistate' and 'track' * fix #1 proper implementation of boolean filter parameter * add debug logging, slightly optimize runtime * gramps 6.0 compat: rename function apply -> apply_to_one * chore: rename filter result to self.selected_handles as requested in PR * fix issues noted by review in PR gramps-project#933 2. Missing type imports 3. Mutable class-level attribute 4. reset() never tears down the sub-filter 5. Potential AttributeError when Gramps ID is not found 6. Progress counter can exceed its declared total 7. Name/description mismatch between gpr.py and the class 8. Both .py files are missing the required GPL-2.0-or-later license header block. 9. Import sections need the standard comment headers 10. Each class needs a navigation header comment: 11. The ExcludeSubtree class has no docstring. 12. set([]) → set(). (14) get_relatives yields None handles (missing father/mother); filtering inside the generator rather than at the call site would be cleaner. * feat: pass "include matched" param as enum to avoid GUI imports Instead of adding a checkbox-widget for the boolean parameter, avoid GUI code in this non-GUI addon by receiving a generic string and using empty/false as "include" and any other content (e.g. "exclude") as true * chore: run `black` formatter * fix: copy gettext(translation) boilerplate from howto; bump plugin version * fix type annotations & possible AttributeError on None * fix: add `from __future__ import annotations` for backward compatibility * fix: guard log.debug statements to only evaluate when logging enabled * feat: remove "include_stopfilter_matches:bool", default to "exclude" stringly-typed enums / magic values are bad UX. Include can simply be realized by adding the MatchesFilter to the containing Filter, too * remove initialization of class variable selected_handles "confusing" according to review. I still think initializing the empty set is correct: should `apply_to_one` ever be called before `prepare` this will raise an AttributeError.
f3e6a77 to
92887d6
Compare
callback() called db._table(), which doesn't exist on the db API, instead of db._get_table_func(), causing any script that edits data (e.g. via begin_changes()) to crash with: AttributeError: 'SQLite' object has no attribute '_table'
…mily has no parents
92887d6 to
41ec6fc
Compare
Automated nightly sync from
gramps-project/addons-source@maintenance/gramps61. Generated by .github/workflows/upstream-sync.yml on the testbed.