Skip to main content

GBIF scientific name parser — Rust core, Python binding

Project description

nameparser-py — native Python binding

import nameparser gives you the Rust nameparser core's parse() directly, as a PyO3 extension module. Unlike bindings/java (which crosses the JVM/native boundary via java.lang.foreign, either JSON or a flat struct on the wire), there is no C-ABI or marshalling floor here: PyO3 wraps the core nameparser::model::ParsedName struct directly, with one getter per field mapping it straight to its idiomatic Python type — no JVM, no JSON round-trip, no separately-installed native library to locate at runtime.

Field parity with the core is validated over this repo's full ~11,302-name test corpus, cross-checked against the independent Java name-parser oracle: 0 diffs (see crates/nameparser-py/python/tests/test_parity.py and docs/superpowers/findings/2026-07-11-phase4a-python-status.md).

Install

Not yet published to PyPI. Until then, build from source with maturin inside this repo's project-local venv:

python3 -m venv .venv && . .venv/bin/activate
pip install maturin
maturin develop --release -m crates/nameparser-py/Cargo.toml

maturin develop compiles the Rust cdylib and installs it into the active virtualenv as an editable nameparser package (including the nameparser.pyi type stub and a py.typed marker — this package is fully typed; see Editors / type checkers below). Once published, the same package will install with:

pip install gbif-name-parser   # → import nameparser

(The PyPI distribution name is gbif-name-parser — matching the Rust core crate on crates.io, so it's one name across both registries — but the importable module stays nameparser either way; see pyproject.toml.)

Usage

import nameparser

pn = nameparser.parse("Vulpes vulpes silaceus Miller, 1907")
print(pn.rank, pn.genus, pn.specific_epithet, pn.infraspecific_epithet)   # SUBSPECIES Vulpes vulpes silaceus
print(pn.combination_authorship.authors, pn.combination_authorship.year)  # ['Miller'] 1907
print(pn.to_dict()["type"])                                               # SCIENTIFIC — full dict, wire (JSON/Java) field names

results = nameparser.parse_all(["Abies alba", "Tobacco mosaic virus"])    # batch: never raises
print(results)                                                            # [ParsedName(...), None]

try:
    nameparser.parse("Tobacco mosaic virus")
except nameparser.UnparsableNameError as e:
    print(e.name_type, e.code, e.name)   # OTHER VIRUS Tobacco mosaic virus
    print(str(e))                        # Unparsable OTHER name: Tobacco mosaic virus

Every one of ParsedName's 30 core fields is exposed as a Python property (snake_case, e.g. specific_epithet, combination_authorship, published_in_year); enum-typed fields (rank, code, type, state, and each element of notho) come across as plain SCREAMING_SNAKE_CASE strings ("SPECIES", "ZOOLOGICAL", …) — the same convention the JSON/Java wire format uses — not a Python enum.Enum. rank/code inputs to parse()/parse_all() accept those same strings (or None). to_dict() (on both ParsedName and the nested Authorship) returns the complete structure straight from the core's own serde::Serialize impl, keyed by the JSON/Java wire field names (specificEpithet, not specific_epithet) — the escape hatch for anything a typed getter doesn't surface, and the parity oracle the corpus test itself diffs against.

UnparsableNameError.name_type/.code/.name mirror Java's org.gbif.nameparser.api.UnparsableNameException's getType()/getCode()/getName(); str(e) is still exactly the core's own message, unchanged.

Editors / type checkers

nameparser.pyi (shipped inside the package, alongside a py.typed marker) gives Pyright/mypy/ your editor full attribute-level types for parse/parse_all/ParsedName/Authorship/ UnparsableNameError — no more "unknown attribute" noise on pn.specific_epithet or e.name_type. It's hand-written (the compiled extension has no Python source for a stub generator to read) and kept in sync by hand with src/lib.rs's getters; see its own module docstring.

Native, no JDK required

This binding never starts a JVM and needs no java/JAVA_HOME on the machine that runs it — unlike bindings/java (which requires JDK 22+ for java.lang.foreign) — because it compiles directly against the Rust core, in-process, with PyO3 doing the Rust↔Python marshalling at the Rust/CPython C-API level rather than crossing a JVM boundary at all. Performance-wise it inherits the native CLI's batch-throughput profile (see the root BENCHMARKS.md): there is no per-call FFM downcall or JSON re-serialization step the way the Java binding's NameParserRust has, since parse()/parse_all() call nameparser::parse directly.

Development

. .venv/bin/activate
maturin develop --release -m crates/nameparser-py/Cargo.toml
pytest crates/nameparser-py/python/tests/ -v

Three test files under python/tests/:

  • test_api.py — unit tests for the binding surface itself (getters, to_dict(), parse_all()'s none-on-unparsable contract, UnparsableNameError's structured attributes).
  • test_getter_consistency.py — checks every #[getter] agrees with to_dict() over a representative sample (a path test_parity.py alone can't exercise, since it only ever calls to_dict()).
  • test_parity.py — the corpus parity gate: diffs nameparser.parse(name).to_dict(), and UnparsableNameError's message/name_type/code, against an independent Java-oracle (or Rust-CLI-fallback) row for every one of the ~11,302 corpus names. Needs a JDK on PATH (falls back to the release nameparser-cli binary if the Java shaded jar isn't available).

Build a wheel (not published) with:

maturin build --release -m crates/nameparser-py/Cargo.toml   # → target/wheels/*.whl (git-ignored)

The wheel is abi3 (built against the stable Python C ABI, py39 floor) — one wheel per platform, working across Python 3.9+, not one per Python minor version.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

gbif_name_parser-0.1.0.tar.gz (403.0 kB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

gbif_name_parser-0.1.0-cp39-abi3-win_amd64.whl (1.2 MB view details)

Uploaded CPython 3.9+Windows x86-64

gbif_name_parser-0.1.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.4 MB view details)

Uploaded CPython 3.9+manylinux: glibc 2.17+ x86-64

gbif_name_parser-0.1.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (1.4 MB view details)

Uploaded CPython 3.9+manylinux: glibc 2.17+ ARM64

gbif_name_parser-0.1.0-cp39-abi3-macosx_11_0_arm64.whl (1.3 MB view details)

Uploaded CPython 3.9+macOS 11.0+ ARM64

File details

Details for the file gbif_name_parser-0.1.0.tar.gz.

File metadata

  • Download URL: gbif_name_parser-0.1.0.tar.gz
  • Upload date:
  • Size: 403.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for gbif_name_parser-0.1.0.tar.gz
Algorithm Hash digest
SHA256 3e5b6eb446fb170f383bc09f12d728bb589c2b21b5a8017bd8f78af291cfb706
MD5 730afba8c021d76828450971763d42a9
BLAKE2b-256 53a1790df64b343bc44e09b2e1e0b570c3b19f9f76d8638edab03234900c334c

See more details on using hashes here.

Provenance

The following attestation bundles were made for gbif_name_parser-0.1.0.tar.gz:

Publisher: python-release.yml on gbif/name-parser-rust

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file gbif_name_parser-0.1.0-cp39-abi3-win_amd64.whl.

File metadata

File hashes

Hashes for gbif_name_parser-0.1.0-cp39-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 dcca09cf18c2408098c7d0e22e1f2f02c767ccd6641d86d00f0c75c93126ae3a
MD5 2295fdcd26e12624577777c3f7f23ba5
BLAKE2b-256 e757fc525fbfd4e812fc375f4e3c9093adc11f33a8db64873b6b486722a3507d

See more details on using hashes here.

Provenance

The following attestation bundles were made for gbif_name_parser-0.1.0-cp39-abi3-win_amd64.whl:

Publisher: python-release.yml on gbif/name-parser-rust

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file gbif_name_parser-0.1.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for gbif_name_parser-0.1.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 6d9980de675a7cfb0d4c96a8b2c184ec68a6663eba265ec8ccf27feff3ba54ac
MD5 fff3561f5e322e1eca9245fa77ae3477
BLAKE2b-256 79fd0e550dd4562935b367e724d6a0c72c02d9529b36fb7a44abe1a6ef726933

See more details on using hashes here.

Provenance

The following attestation bundles were made for gbif_name_parser-0.1.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:

Publisher: python-release.yml on gbif/name-parser-rust

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file gbif_name_parser-0.1.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for gbif_name_parser-0.1.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 343a1b72c286e22eaf22978ce4fa9b270e4a6b0d8c5d882e0bad147c2c90b255
MD5 78bb6b8c0d734c1000331a500c996834
BLAKE2b-256 52be50db10c11507b8fff1d612a07753961071ec5c96ab2776cc0a3586df82c7

See more details on using hashes here.

Provenance

The following attestation bundles were made for gbif_name_parser-0.1.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl:

Publisher: python-release.yml on gbif/name-parser-rust

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file gbif_name_parser-0.1.0-cp39-abi3-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for gbif_name_parser-0.1.0-cp39-abi3-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 15247940bc024b9b53da0b1db9da79352f056adcbb3b32e5f936dbd214a97e43
MD5 83f1048a554fd0a8137036c2a32c518c
BLAKE2b-256 1d248844ea9798705f1b28ca7e8b3f08be1aa3d1d96d207b655984231b490c97

See more details on using hashes here.

Provenance

The following attestation bundles were made for gbif_name_parser-0.1.0-cp39-abi3-macosx_11_0_arm64.whl:

Publisher: python-release.yml on gbif/name-parser-rust

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page