Skip to content

Build failure due to strict cython == 3.1 pin in pyproject.toml (should this be ~=3.1 per PEP 440?) #530

@ryanwclark1

Description

@ryanwclark1
  1. What versions are you using?

    • python-oracledb commit: [2d9f577d75ed](2d9f577) (July 24, 2025)

    • Python: 3.13 (NixOS build environment)

    • Cython available: 3.1.3

    • pyproject.toml requires:

      [build-system]
      requires = [
        "setuptools >= 77.0.0",
        "wheel",
        "cython == 3.1",
      ]
    • Note: Before commit 2d9f577, the requirement was simply "cython" (unversioned).


  1. Is it an error or a hang or a crash?

    Build-time error (dependency resolution failure).


  1. What error(s) or behavior you are seeing?

    The NixOS build fails with:

    ERROR Missing dependencies:
            cython==3.1
    

    because the requirement cython == 3.1 (which, per PEP 440 normalization, matches exactly the 3.1.0 release) excludes other available 3.1.x patch releases (e.g., 3.1.3). In environments where only those patch versions are packaged, the build cannot proceed.

    Full Nixpkgs issue (with logs): [NixOS/nixpkgs#437487](Build failure: python313Packages.oracledb NixOS/nixpkgs#437487)


  1. Does your application call init_oracle_client()?

    N/A — this is not a runtime or client initialization issue.
    It is strictly a packaging/build-system metadata issue.


  1. Include a runnable Python script that shows the problem.

    Not applicable (build-time issue).

    Reproduction steps:

    1. Attempt to build python-oracledb from source in an environment that provides Cython 3.1.3 (but not 3.1.0).
    2. Build fails due to the strict == 3.1 pin.

Additional Context

  • The pinning to == 3.1 was introduced in commit [2d9f577](2d9f577).

  • In Unable to use python-oracledb with Cython 3.1.0 #493, a user suggested pinning to “3.1.x” (e.g., ~= 3.1.0) to avoid future breakage when 3.2 or 4.0 are released, and a maintainer replied that this would be done in 3.3. The current implementation, however, uses == 3.1, which effectively allows only 3.1.0 and excludes later 3.1.x patch releases.

  • Question (not assumption): Was the intent to support the entire 3.1 series (i.e., ~= 3.1 per PEP 440), or is there a deliberate reason to restrict to exactly 3.1.0?


Why ~= 3.1 might be preferable

  • ~= 3.1 is the PEP 440 compatible-release operator and is functionally equivalent to >= 3.1, < 3.2 (i.e., it permits bugfix releases in the 3.1 line).
  • Cython has shipped several 3.1.x patch releases, which typically contain bugfixes/compatibility updates.
  • This reduces downstream friction for curated ecosystems (NixOS, Debian, etc.) where a specific patch may be the packaged version.

Why pinning to a single exact version might have been intentional

  • Early 3.1.x releases (e.g., 3.1.0) introduced breaking changes for some projects; a strict pin can be a conservative safeguard during validation.
  • If specific 3.1.x patches are known-bad for python-oracledb, a guarded range may be more appropriate than a blanket compatible range.

Suggested Update (if compatible)

Option A (compatible range):

 [build-system]
 requires = [
   "setuptools >= 77.0.0",
   "wheel",
-  "cython == 3.1",
+  "cython ~= 3.1",  # i.e., >= 3.1, < 3.2 (allows 3.1.x)
 ]

(Explicit equivalent: "cython >= 3.1, < 3.2".)

Option B (guarded range—skip known-bad patch):

"cython != 3.1.0, >= 3.1, < 3.2"

If you have a known-good floor, we can also express it directly, e.g.:

"cython >= 3.1.2, < 3.2"

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions