Skip to content

MAINT: disable Cython bindings for Cython < 3.0.0.#30770

Merged
ngoldbaum merged 7 commits intonumpy:mainfrom
ngoldbaum:cython-30-minimum
Feb 10, 2026
Merged

MAINT: disable Cython bindings for Cython < 3.0.0.#30770
ngoldbaum merged 7 commits intonumpy:mainfrom
ngoldbaum:cython-30-minimum

Conversation

@ngoldbaum
Copy link
Copy Markdown
Member

@ngoldbaum ngoldbaum commented Feb 2, 2026

According to the cython docs, if there is a __init__cython-30.pxd, Cython > 3.0 will ignore a __init__.pxd.

In an attempt to give downstream users a useful error message, instead of just deleting __init__.pxd or renaming __init__cython-30.pxd, I left behind __init__.pxd but made it generate a build error if it is ever used.

I also updated the section on using the C API that covers Cython. The old content still talked about distutils, so I took the opportunity to update it to talk about meson.

@ngoldbaum
Copy link
Copy Markdown
Member Author

@da-woods I'm curious about your opinion on this. Is there a better way to drop support for building against the NumPy headers and older Cython versions that you might use instead of this?

@da-woods
Copy link
Copy Markdown
Contributor

da-woods commented Feb 2, 2026

Is there a better way to drop support for building against the NumPy headers and older Cython versions that you might use instead of this?

I think this is fine. But if I did it then I'd probably delete all of __init__.pxd except for the error. That'll hopefully avoid any possibility of people thinking that it's the real file my mistake. But that's just because I think it's clearer - the basic idea is fine I think.


The other thing you could do is to use CYTHON_HEX_VERSION. So just have one __init__.pxd but inject something like

#if !defined(CYTHON_HEX_VERSION) || CYTHON_HEX_VERSION < 0x03000000
#error "The Cython NumPy pxd wrappers require Cython 3.0.0 or newer"
#endif

With that said, I don't think Cython 0.29 would successfully compile the 3.0 pxd file so you might not even get far enough for people to see the error message. So it probably won't work for this case.

Comment thread numpy/__init__.pxd Outdated
@ngoldbaum
Copy link
Copy Markdown
Member Author

But if I did it then I'd probably delete all of init.pxd except for the error. That'll hopefully avoid any possibility of people thinking that it's the real file my mistake. But that's just because I think it's clearer - the basic idea is fine I think.

I tried this, but on a nontrivial project I end up seeing Cython compilation errors due to missing definitions in the cython headers. So to make compilation proceed to the point where the #error macro gets processed by a C compiler, I need to make sure all the cython compilation succeeds. That means keeping the content of __init__.pxd the same except for the new include that triggers the C compilation error.

I was hoping there's a way to do this in pure Cython so I can trigger this error in the Cython compilation step, but it sounds like there isn't.

@da-woods
Copy link
Copy Markdown
Contributor

da-woods commented Feb 2, 2026

You could do something like

DEF err = int('Cython minimum version is 3.0')

That immediately generates an error (i.e. it essentially just does eval on the right-hand side of the expression).

ddd.pyx:1:13: Error in compile-time expression: ValueError: invalid literal for int() with base 10: 'Cython minimum version is 3.0'

I couldn't quickly think of a version that generates a much nicer error message. But it at least moves the error message earlier.

@ngoldbaum
Copy link
Copy Markdown
Member Author

Thanks! I also opened cython/cython#7496 to track this feature upstream, IMO something like it would be nice to have in the future.

@ngoldbaum ngoldbaum marked this pull request as ready for review February 2, 2026 20:26
@ngoldbaum ngoldbaum added the Dependencies Pull requests that update a dependency file label Feb 2, 2026
@ngoldbaum ngoldbaum added this to the 2.5.0 Release milestone Feb 2, 2026
@ngoldbaum ngoldbaum added the 39 - free-threading PRs and issues related to support for free-threading CPython (a.k.a. no-GIL, PEP 703) label Feb 2, 2026
Comment thread doc/release/upcoming_changes/30770.compatibility.rst Outdated
Copy link
Copy Markdown
Member

@rgommers rgommers left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks Nathan! LGTM modulo some minor issues with the new example.

Comment thread doc/source/user/c-info.python-as-glue.rst Outdated
Comment thread doc/source/user/c-info.python-as-glue.rst Outdated
Comment thread doc/source/user/c-info.python-as-glue.rst Outdated
@ngoldbaum
Copy link
Copy Markdown
Member Author

@rgommers thanks for the suggestions! I went ahead and made sure the whole thing is end-to-end runnable, which required adding a __init__.py file. I think this is ready now.

Copy link
Copy Markdown
Member

@rgommers rgommers left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, but may need to hit the mailing list, so I won't hit the green button just yet.

@ngoldbaum
Copy link
Copy Markdown
Member Author

but may need to hit the mailing list

I sent a message to the mailing list to elicit more feedback. I also said I'd merge the PR next week if no one objects.

@ngoldbaum
Copy link
Copy Markdown
Member Author

No one objected, so I'm planning to merge this as soon as the CI passes.

If anyone in the future reads this because of the compiler error introduced in this PR, please open an issue if updating to use Cython 3.0.0 or newer is impossible for some reason.

@ngoldbaum ngoldbaum merged commit 169c995 into numpy:main Feb 10, 2026
77 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

03 - Maintenance 39 - free-threading PRs and issues related to support for free-threading CPython (a.k.a. no-GIL, PEP 703) Dependencies Pull requests that update a dependency file

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants