Visitar URL original
Proposal: optional native parser backend with pure-Python fallback · Issue #474 · python-semver/python-semver · GitHub
Skip to content

Proposal: optional native parser backend with pure-Python fallback #474

Closed

Description

@lowmiaq-gmail

Problem

Version.parse() is used repeatedly by workloads that normalize and sort
large version datasets. The pure-Python parser is correct, but a bounded OSV
fixture workload shows measurable wall-time cost. This proposal is limited to
that parse-heavy path; it does not claim a general speedup for all users.

Proposal

Add an optional native extra to python-semver that uses the separate
fast-semver-rs-backend package for parsing when installed:

python-semver[native]

The default installation remains unchanged: pure Python, no compiler, no Rust
toolchain, and no native dependency. If the backend is absent, the existing
Python parser is used automatically.

The proposed adapter is intentionally small (41 changed lines): it calls the
backend only at the parser boundary and reconstructs the existing public
Version behavior in python-semver.

Compatibility and verification

  • Tested against upstream main at 99d2032c8f7ef4895df25053ddcdcb85d5460326.
  • Official suite: 342 passed with the backend; 341 passed, 1 skipped
    without it.
  • Latest-main differential corpus: 10,000 cases, 0 mismatches.
  • OSV consumer fixtures: 3/3 in both paths with identical result digest.
  • The backend wheel has no top-level semver package and coexists with
    official python-semver.
  • Backend CI: 10/10 jobs passed across Linux x86_64/arm64, macOS
    x86_64/arm64, and Windows x86_64 on CPython 3.10 and 3.14:
    https://github.com/lowmiaq-gmail/fast-semver-rs/actions/runs/33139994365
  • Standalone fast-semver-rs root CI remains green, including its frozen
    public 3.0.4 contract:
    https://github.com/lowmiaq-gmail/fast-semver-rs/actions/runs/33139994368

Performance evidence

On a bounded 20,000-item OSV-style workload, with identical output digests:

Workload Pure Python p50 Native p50 Speedup Absolute saving
normalize 52.519875 ms 43.107625 ms 1.22x 9.412250 ms
sort 55.471375 ms 46.013959 ms 1.21x 9.457416 ms

These are bounded consumer measurements, not a claim of external adoption.

Maintenance and failure isolation

  • python-semver would maintain only the thin optional extra and adapter.
  • We would maintain the Rust backend wheels and implementation.
  • The backend is CPython-only; PyPy continues to use the pure-Python path.
  • No compatible native wheel means the base package still works unchanged;
    only users explicitly selecting native depend on backend availability.
  • The backend distribution owns no semver namespace and does not replace
    upstream files.

Prototype

If this direction is acceptable, I can turn the public adapter branch into a
PR after maintainer feedback on the optional dependency and ownership model.

Activity

  1. tomschr commented on Aug 30, 2026

    @tomschr
    Member

    Thank you, @lowmiaq-gmail, for your proposal! 👍 The performance are compelling, and I appreciate your idea.

    My primary goal is to ensure the project remains simple and has a very low maintenance footprint. It's just a hobby for me and I do this in my free time. This is especially important as I don't know Rust, so if you were to step away, I couldn't maintain the native backend myself.😉 While I appreciate your offer, I'm cautious about adding a native component as it introduces long-term complexity and risk that would fall to me.

    However, I am open to the idea if we can establish a clear framework to address these concerns. To feel comfortable moving forward, how do you think we could best address the following points?

    I'd like to discuss the following principles:

    1. Maintenance & Ownership: How do you see the maintenance of the Rust backend working long-term? To keep the main python-semver repository simple and pure Python, my preference would be to keep the Rust code in a separate repository. This could be hosted under the python-semver organization or at a location of your choice. How would you see the ownership of that package working to ensure it's sustainable if you're no longer involved?

    2. Integration & Safety: What's the best way to integrate the two parsers to guarantee they always produce the exact same results? How can we ensure that a bug fix in one implementation is always mirrored in the other?

    3. Packaging & Distribution: What would the release process for the native wheels look like? How can we ensure it's fully automated and doesn't add a manual burden for project maintainers for each new release?

    Thanks, looking forward to discuss this with you!

  2. lowmiaq-gmail commented on Sep 1, 2026

    @lowmiaq-gmail
    ContributorAuthor
  3. tomschr commented on Sep 1, 2026

    @tomschr
    Member

    My preference would be to keep it under my account initially.

    I'm fine with that too. 👍

    I wouldn’t claim that two independent implementations can never contain a bug.

    In that case, we have both issue tracker to record a bug. 🙂

    If that model addresses the concerns you had in mind, I’m happy to turn the prototype into the smallest possible PR so you can review the actual maintenance footprint rather than committing to a larger design up front.


    Ok, to summarize what we have:

    • Isolated Maintenance & Zero Risk

      The Rust project lives in a separate repository managed by you, requiring only a minimal integration hook in python-semver. The pure-Python implementation remains the default, ensuring python-semver stays fully functional even if the Rust backend is abandoned.

    • Python as Source of Truth

      The Python implementation defines all parsing behavior and semantics. Automated CI in the Rust repository will continuously test against python-semver test suites and run differential corpus comparisons to detect divergence.

    • Zero Packaging Overhead

      Cross-platform native wheel creationand PyPI publishing will be fully automated in the backend repository. Core maintainers will not need to build, test, or manage native binaries.

    • Decoupled Releases

      Both projects maintain independent release schedules, meaning python-semver updates do not require synchronized Rust releases unless parser contracts change.

    • Immediate Next Steps

      You propose submitting a minimal pull request so maintainers can evaluate the footprint of the code changes before making any formal commitments.

    Is that correct? If yes, then let's make it possible! 😁

  4. lowmiaq-gmail commented on Sep 2, 2026

    @lowmiaq-gmail
    ContributorAuthor

    Hi Tom,

    Yes, that’s exactly right. Thanks for putting it together so clearly.

    I’ll go ahead and prepare a minimal PR next, so you can review the actual maintenance footprint without any larger design commitment up front.

    Just let me know if you’d like me to adjust anything before I open it.

  5. lowmiaq-gmail commented on Sep 2, 2026

    @lowmiaq-gmail
    ContributorAuthor

    Hi Tom,

    Minimal adapter PR is up for the footprint review:

    #476

    Happy to adjust the shape if anything looks heavier than you’d like.

  6. tomschr commented on Oct 5, 2026

    @tomschr
    Member

    Forgot to close this issue. This is all implemented in #476.
    Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    SIze

    None yet

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions