Skip to content

Add sniff_function support to ImportPlugin for version-aware dispatch - #2251

Closed
dsblank wants to merge 1 commit into
masterfrom
feature/sniff-function-importer-dispatch
Closed

Add sniff_function support to ImportPlugin for version-aware dispatch#2251
dsblank wants to merge 1 commit into
masterfrom
feature/sniff-function-importer-dispatch

Conversation

@dsblank

@dsblank dsblank commented Apr 18, 2026

Copy link
Copy Markdown
Member

Summary

  • Adds an optional sniff_function attribute to PluginData and ImportPlugin so multiple importers can share a file extension and be selected by file content.
  • Updates both GUI (dbloader.py) and CLI (arghandler.py) dispatch to prefer a sniff-matched plugin over the first-match fallback.
  • Adds 10 unit tests covering all dispatch paths.

Motivation

The .ged extension is currently mapped to a single GEDCOM importer.
The GEDCOM 7 addon (PR #744) needs to register a second importer for .ged files and have it chosen automatically when the file header identifies the file as GEDCOM 7. GEDCOM 7 requires a version string in the header, so detection is trivial — the only missing piece was a hook in core.

How it works

A plugin declares a sniff_function by name in its .gpr.py:

plg.sniff_function = "sniffData"

The function accepts a filename and returns True when the plugin should handle it:

def sniffData(filename):
    with open(filename, "rb") as f:
        for line in itertools.islice(f, 20):
            if b"VERS 7." in line:
                return True
    return False

Plugins without a sniff_function continue to work exactly as before.

Test plan

  • GRAMPS_RESOURCES=. python3 -m unittest discover -p "*_test.py" gramps/gen/plug/test — all 10 tests pass
  • black run on all changed files — no reformatting needed (except minor spacing in _import.py)
  • Manual smoke test: import a GEDCOM 5.5 file and verify the built-in importer is still selected
  • Manual smoke test: install GEDCOM 7 addon and verify a GEDCOM 7 file routes to it

🤖 Generated with Claude Code

Previously, Gramps mapped each file extension to a single importer.
This change adds an optional sniff_function attribute to ImportPlugin
and PluginData so that multiple importers can register for the same
file extension and be distinguished by file content rather than
extension alone.

When the importer for a file is selected, plugins that declare a
sniff_function are tested first.  The first plugin whose sniff
function returns True for the file wins.  Plugins without a sniff
function continue to work as before, acting as a fallback.

This makes it possible for an addon to register a GEDCOM 7 importer
alongside the built-in GEDCOM 5.5 importer: the addon's sniff
function checks for the VERS 7.x header and claims the file when
present, leaving all other GEDCOM files to the existing importer.

The same dispatch logic is applied in both the GUI (dbloader.py) and
the CLI (arghandler.py).
@Nick-Hall

Copy link
Copy Markdown
Member

@dsblank Please don't create branches in origin. Use you own fork when creating pull requests.

@dsblank

dsblank commented Apr 18, 2026

Copy link
Copy Markdown
Member Author

Please don't create branches in origin. Use you own fork when creating pull requests.

I'll add that to AGENTS.md

@dsblank dsblank closed this Apr 18, 2026
@dsblank
dsblank deleted the feature/sniff-function-importer-dispatch branch April 18, 2026 16:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants