Gramplets in Gramps Connect?

Welcome to the new Gramps Connect category! This is a place for discussing this new app (both a desktop and web app).

As we are getting closer to a 1.0 release, I have a question for you. First checkout the latest version 0.7.5:

This may look similar to Gramps desktop, and that is the goal. Take a look at the bottom, middle of the screen… what is that? Gramplets?

Yes, it is true: I have added Gramplets for Gramps Connect. You write in Python, using a familiar API. Here is the code for the Events gramplet:

if selected is None:
    html("<i>A person is not selected</i>")
else:
    person = selected
    name = person.primary_name
    full_name = f"{name.first_name} {' '.join(s.surname for s in name.surname_list)}".strip()
    html(f"<h3>Events for {full_name}</h3>")
    if person.event_ref_list:
        columns("Event", "Role", "Type", "Date", "Place")
        for event_ref in person.event_ref_list:
            event = db.get_event_from_handle(event_ref.ref)
            place = db.get_place_from_handle(event.place) if event.place else None
            row(event, str(event_ref.role), str(event.type), event.date, place)
    else:
        html("<i>No events exist for this person</i>")

I plan on having as many addon types as possible (at least gramplets, reports, and tools).

Now my question: should we call these “gramplets”? They have the same basic structure of a gpr.py file and Python code. But this code is different from normal Gramps’ Gramplets. I do plan having the same kind of 3rd-party repository (like an “app store”). Will calling them "gramplets cause confusion? Any ideas for a better name?

@emyoulation this task has your name all over it.

If you want to try out the desktop version, you can find it here for Mac, Windows, and Linux:

Hosted version instructions are available in the README. More details on how Gramps Connect runs Python code in the browser to follow.

I’m on a 2021 MacBook Pro M1 Max with the current stable Tahoe OS.

I get a series of malware warnings. First for gramps-connect-desktop, then for Python, then for one .so file, then another .so file.

Allowing each one via Privacy and Security settings gets me through that warning, but that just leads to the next warning.

I gave up after the warning for the second .so file.

1 Like

Same issues with my Tahoe M3 iMac.

1 Like

and:

Apparently, here’s what’s happening and the fix.

Why it cascades: the release .zip is a raw PyInstaller “onedir” folder (main executable + dozens of .so files), not a proper signed .app bundle. When Safari downloads the zip, macOS tags it with the com.apple.quarantine extended attribute, and unzipping propagates that tag to every extracted file. Since nothing in the bundle is code-signed or notarized, Tahoe’s Gatekeeper checks each Mach-O binary individually the first time it’s loaded — the main executable, then the embedded Python, then each .so as it gets dlopen’d at runtime — and flags each one separately as unverified. The README’s current advice (right-click → Open Anyway, or run from Terminal) only clears the quarantine flag on the top-level executable, not on every nested .so, so it doesn’t stop the cascade.

Fix: strip the quarantine attribute recursively from the whole extracted folder before running anything:

xattr -cr gramps-connect-desktop

(run in Terminal, from the parent of that folder — matching whatever it’s actually named once unzipped). That removes com.apple.quarantine from every file at once, so nothing triggers a warning at all — no per-file Allow-in-Settings loop.

Please try that, and I’ll update the README.

1 Like

I’ll also try to create a signed app.

I ran the xattr command.

Tried to run but it was not an executable. Set the exec bit and tried to run again. Below is the full log

gary$ ./gramps-connect-desktop 

zsh: permission denied: ./gramps-connect-desktop

gary$ file gramps-connect-desktop 

gramps-connect-desktop: Mach-O 64-bit executable arm64

gary$ chmod +x gramps-connect-desktop 

gary$ ./gramps-connect-desktop 

.gramps.gen.utils.grampslocale.WARNING: ICU not loaded because No module named 'PyICU'. Localization will be impaired. Use your package manager to install PyICU

Traceback (most recent call last):

  File "launcher.py", line 266, in <module>

  File "launcher.py", line 160, in main

  File "<frozen importlib._bootstrap>", line 1360, in _find_and_load

  File "<frozen importlib._bootstrap>", line 1331, in _find_and_load_unlocked

  File "<frozen importlib._bootstrap>", line 935, in _load_unlocked

  File "pyimod02_importers.py", line 457, in exec_module

  File "gramps_webapi/app.py", line 33, in <module>

  File "<frozen importlib._bootstrap>", line 1360, in _find_and_load

  File "<frozen importlib._bootstrap>", line 1331, in _find_and_load_unlocked

  File "<frozen importlib._bootstrap>", line 935, in _load_unlocked

  File "pyimod02_importers.py", line 457, in exec_module

  File "gramps/gen/config.py", line 43, in <module>

  File "<frozen importlib._bootstrap>", line 1360, in _find_and_load

  File "<frozen importlib._bootstrap>", line 1331, in _find_and_load_unlocked

  File "<frozen importlib._bootstrap>", line 935, in _load_unlocked

  File "pyimod02_importers.py", line 457, in exec_module

  File "gramps/gen/const.py", line 253, in <module>

  File "gramps/gen/utils/grampslocale.py", line 467, in __init__

  File "gramps/gen/utils/grampslocale.py", line 372, in __init_first_instance

AttributeError: module 'locale' has no attribute 'textdomain'

[PYI-2609:ERROR] Failed to execute script 'launcher' due to unhandled exception!

gary$ 
1 Like

Same PyICU module issue for me. I created an issue on GitHub.

dsblank, would you prefer to see details here, on GitHub, or both? (Or neither, I suppose :upside_down_face:)

Eventually I’d like to use github. But this is fine for now. I am building new download and it should be up shortly. There were two issues that you both found.

(I need to get a Mac. And a Windows machine. Otherwise I will wear you out :smiley: )

v0.7.6 is published:

Both fixes are in this release — the ad-hoc-signed .app bundle (should stop the Gatekeeper malware cascade) and the locale.textdomain startup-crash fix.

I hope this solves it, but if not I’ll keep trying!

Double-clicking gives this error:

Confirmed — this is a permission-loss bug in the release pipeline. Fixing…

I did the xattrs/chmod dance. Then the app seemed to start up (I got an icon in the dock), but then it went away with no errors. It didn’t seem to leave any processes around (but I didn’t look too hard).

1 Like

I tried v0.7.8

Icon appears, followed by “could not verify” warning.

Clearing extended attrs leads to the icon appearing briefly, then vanishing.

Progress of a sort…

Running v0.7.8 via command line presented a login window.

Logging in gave a 500 error with this detail:


Error on request:

Traceback (most recent call last):

  File "sqlalchemy/engine/base.py", line 1969, in \_exec_single_context

  File "sqlalchemy/engine/default.py", line 952, in do_execute

sqlite3.OperationalError: no such table: users

The above exception was the direct cause of the following exception:

Traceback (most recent call last):

  File "werkzeug/serving.py", line 371, in run_wsgi

  File "werkzeug/serving.py", line 332, in execute

  File "flask/app.py", line 1536, in \__call_\_

  File "flask/app.py", line 1514, in wsgi_app

  File "flask_cors/extension.py", line 206, in wrapped_function

  File "flask/app.py", line 1511, in wsgi_app

  File "flask/app.py", line 919, in full_dispatch_request

  File "flask_cors/extension.py", line 206, in wrapped_function

  File "flask/app.py", line 917, in full_dispatch_request

  File "flask/app.py", line 902, in dispatch_request

  File "flask/views.py", line 110, in view

  File "gramps_webapi/api/resources/\__init_\_.py", line 51, in dispatch_request

  File "flask_limiter/\_limits.py", line 326, in \__inner

  File "flask_smorest/response.py", line 89, in wrapper

  File "webargs/core.py", line 652, in wrapper

  File "flask_smorest/arguments.py", line 85, in wrapper

  File "gramps_webapi/api/resources/token.py", line 149, in post

  File "gramps_webapi/auth/\__init_\_.py", line 224, in authorized

  File "sqlalchemy/orm/query.py", line 2842, in scalar

  File "sqlalchemy/orm/query.py", line 2815, in one

  File "sqlalchemy/orm/query.py", line 2864, in \_iter

  File "sqlalchemy/orm/session.py", line 2373, in execute

  File "sqlalchemy/orm/session.py", line 2271, in \_execute_internal

  File "sqlalchemy/orm/context.py", line 306, in orm_execute_statement

  File "sqlalchemy/engine/base.py", line 1421, in execute

  File "sqlalchemy/sql/elements.py", line 526, in \_execute_on_connection

  File "sqlalchemy/engine/base.py", line 1643, in \_execute_clauseelement

  File "sqlalchemy/engine/base.py", line 1848, in \_execute_context

  File "sqlalchemy/engine/base.py", line 1988, in \_exec_single_context

  File "sqlalchemy/engine/base.py", line 2365, in \_handle_dbapi_exception

  File "sqlalchemy/engine/base.py", line 1969, in \_exec_single_context

  File "sqlalchemy/engine/default.py", line 952, in do_execute

sqlalchemy.exc.OperationalError: (sqlite3.OperationalError) no such table: users

and the following error report in the terminal:


Error on request:

Traceback (most recent call last):

  File "sqlalchemy/engine/base.py", line 1969, in \_exec_single_context

  File "sqlalchemy/engine/default.py", line 952, in do_execute

sqlite3.OperationalError: no such table: users

The above exception was the direct cause of the following exception:

Traceback (most recent call last):

  File "werkzeug/serving.py", line 371, in run_wsgi

  File "werkzeug/serving.py", line 332, in execute

  File "flask/app.py", line 1536, in \__call_\_

  File "flask/app.py", line 1514, in wsgi_app

  File "flask_cors/extension.py", line 206, in wrapped_function

  File "flask/app.py", line 1511, in wsgi_app

  File "flask/app.py", line 919, in full_dispatch_request

  File "flask_cors/extension.py", line 206, in wrapped_function

  File "flask/app.py", line 917, in full_dispatch_request

  File "flask/app.py", line 902, in dispatch_request

  File "flask/views.py", line 110, in view

  File "gramps_webapi/api/resources/\__init_\_.py", line 51, in dispatch_request

  File "flask_limiter/\_limits.py", line 326, in \__inner

  File "flask_smorest/response.py", line 89, in wrapper

  File "webargs/core.py", line 652, in wrapper

  File "flask_smorest/arguments.py", line 85, in wrapper

  File "gramps_webapi/api/resources/token.py", line 149, in post

  File "gramps_webapi/auth/\__init_\_.py", line 224, in authorized

  File "sqlalchemy/orm/query.py", line 2842, in scalar

  File "sqlalchemy/orm/query.py", line 2815, in one

  File "sqlalchemy/orm/query.py", line 2864, in \_iter

  File "sqlalchemy/orm/session.py", line 2373, in execute

  File "sqlalchemy/orm/session.py", line 2271, in \_execute_internal

  File "sqlalchemy/orm/context.py", line 306, in orm_execute_statement

  File "sqlalchemy/engine/base.py", line 1421, in execute

  File "sqlalchemy/sql/elements.py", line 526, in \_execute_on_connection

  File "sqlalchemy/engine/base.py", line 1643, in \_execute_clauseelement

  File "sqlalchemy/engine/base.py", line 1848, in \_execute_context

  File "sqlalchemy/engine/base.py", line 1988, in \_exec_single_context

  File "sqlalchemy/engine/base.py", line 2365, in \_handle_dbapi_exception

  File "sqlalchemy/engine/base.py", line 1969, in \_exec_single_context

  File "sqlalchemy/engine/default.py", line 952, in do_execute

sqlalchemy.exc.OperationalError: (sqlite3.OperationalError) no such table: users

But the server seemed to start, so: Progress!

Logging into the server also gives a 500 error with same detail as the app window.

1 Like

v0.7.10 is building with another fix. :crossed_fingers:

v0.7.10 is published: Release gramps-connect-desktop v0.7.10 · dsblank/gramps-connect · GitHub

Okay. v0.7.9 seems the same as 0.7.10. Can run only in terminal, and only after clearing xattrs.

Also, the app (both v0.7.8 and v0.7.9) creates 3 cache directories in the directory where I run it from:
persistent_cache
request_cache
thumbnail_cache

My earlier post omitted this error at startup (starting up via terminal):

./gramps-connect-desktop.app/Contents/MacOS/gramps-connect-desktop
.gramps.gen.utils.grampslocale.WARNING: ICU not loaded because No module named 'PyICU'. Localization will be impaired. Use your package manager to install PyICU
flask_limiter/_extension.py:364: UserWarning: Using the in-memory storage for tracking rate limits as no storage was explicitly specified. This is not recommended for production use. See: https://flask-limiter.readthedocs.io#configuring-a-storage-backend for documentation about configuring the storage backend.
 * Serving Flask app 'gramps_webapi.app'
 * Debug mode: off
WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
 * Running on http://127.0.0.1:5050
Press CTRL+C to quit
Gramps Connect Desktop running at http://127.0.0.1:5050
Log in as admin / admin
127.0.0.1 - - [28/Aug/2026 18:03:16] "GET / HTTP/1.1" 200 -
127.0.0.1 - - [28/Aug/2026 18:03:16] "GET /assets/index-DRITXtuv.js HTTP/1.1" 200 -
127.0.0.1 - - [28/Aug/2026 18:03:16] "GET /assets/index-CzEVQ9d_.css HTTP/1.1" 200 -
127.0.0.1 - - [28/Aug/2026 18:03:32] "POST /api/token/ HTTP/1.1" 500 -

Dinner calls. Back tomorrow.

1 Like

With a bit of help v0.7.10 starts, accepts logins via app and web, and imports my ~100 person tree.

It still needs the xattr fix and still gives the PyICU error, but it seems to be in a state that I can explore…

…tomorrow.

1 Like

I loaded 0.7.10 and it was a Mac app. I didnt need xattr. I just ran

gary$ cd gramps-connect-desktop.app/Contents/MacOS 
gary$ ./gramps-connect-desktop 

Imported my 18K tree with no issues. Lofs of logging messages. Some errors due to missing PyICU, cairo and Pango

One error that might need addressed when I went to the report tab.

127.0.0.1 - - [28/Aug/2026 19:36:25] "GET /api/transactions/history/?after_id=2&sort=id HTTP/1.1" 304 -

Plugin error (from 'gtkprint'): No module named 'cairo'

Plugin error (from 'cairodoc'): cannot import name 'Pango' from 'gi.repository' (unknown location)

Plugin error (from 'cairodoc'): cannot import name 'Pango' from 'gi.repository' (unknown location)

Plugin error (from 'cairodoc'): cannot import name 'Pango' from 'gi.repository' (unknown location)

Plugin error (from 'gvfamilylines'): cannot import name 'GdkPixbuf' from 'gi.repository' (unknown location)

127.0.0.1 - - [28/Aug/2026 19:36:27] "GET /api/reports/?include_help=false HTTP/1.1" 500 -

Error on request:

Traceback (most recent call last):

  File "werkzeug/serving.py", line 371, in run_wsgi

  File "werkzeug/serving.py", line 332, in execute

  File "flask/app.py", line 1536, in __call__

  File "flask/app.py", line 1514, in wsgi_app

  File "flask_cors/extension.py", line 206, in wrapped_function

  File "flask/app.py", line 1511, in wsgi_app

  File "flask/app.py", line 919, in full_dispatch_request

  File "flask_cors/extension.py", line 206, in wrapped_function

  File "flask/app.py", line 917, in full_dispatch_request

  File "flask/app.py", line 902, in dispatch_request

  File "gramps_webapi/api/auth.py", line 44, in wrapper

  File "flask/views.py", line 110, in view

  File "gramps_webapi/api/resources/__init__.py", line 51, in dispatch_request

  File "flask_smorest/response.py", line 89, in wrapper

  File "webargs/core.py", line 652, in wrapper

  File "flask_smorest/arguments.py", line 85, in wrapper

  File "gramps_webapi/api/resources/reports.py", line 68, in get

  File "gramps_webapi/api/report.py", line 134, in get_reports

  File "gramps_webapi/api/report.py", line 81, in get_report_profile

AttributeError: 'NoneType' object has no attribute 'FamilyLinesOptions'
1 Like

Ok, now we can get to actual bugs! I also did what you describe (wife’s laptop): ran the gramps-connect-desktop.app/Contents/MacOS/gramps-connect-desktop and it works the same!

If you want to try a “plugin” here are some: