Skip to content

Conversation

@encukou
Copy link
Contributor

@encukou encukou commented Jan 13, 2026

Since PEP 793, it's valid for modules to not have a PyInit function. Telling MSVC to export a nonexistent function will make it fail.

The function should be exported in code, using PyMODINIT_FUNC (which adds __declspec(dllexport), which is preferred over /EXPORT according to Microsoft docs.)

Fixes: #387

Since PEP 793, it's valid for modules to not have a PyInit function.
Telling MSVC to export a nonexistent function will make it fail.

The function should be exported in code, using `PyMODINIT_FUNC`
(which adds `__declspec(dllexport)`, which is preferred over
`/EXPORT` according to [Microsoft docs].)

Microsoft docs: https://learn.microsoft.com/en-us/cpp/build/reference/export-exports-a-function?view=msvc-170
Copy link

@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.

This implementation looks good to me, for now I only have a few very small suggestions for the docstring. I still need to do some testing with a few real-world packages.

For other reviewers: this relies on python/cpython#141672, which was merged only last week.

@rgommers
Copy link

I tested this change with the setuptools/c test case in https://github.com/Quansight-Labs/stable-abi-testing (side note: not yet fully polished, but it's usable enough to derive test cases from now; it contains test packages in a build-backends x binding-generators matrix).

With the latest released version of setuptools, that test package fails to build with 3.15.0a3 - which is the most recent build available in GHA's setup-python - with (CI log):

LINK : error LNK2001: unresolved external symbol PyInit_limited

After applying the patch in this PR to setuptools._distutils, that error goes away and the package builds and passes its tests (CI log).

That repo uses test packages with PyMODEXPORT_FUNC rather than PyMODINIT_FUNC, so that does not yet prove that this also works with the latter.

I then started with psutil, tested the patch with its existing wheel build CI matrix for completeness - that passed of course, since 3.15 wheels are not included yet (no cibuildwheel support), and this PR is a no-op on older Python versions.

I then also added a new psutil CI job for 3.15, before figuring out that psutil depends on pywin32 which doesn't have an sdist and doesn't build from source. So that's where I gave up.

Testing on 3.15-alpha is pretty cumbersome given the many packaging components and packages that don't yet support 3.15. That said, I'm confident that this PR works, and the testing I was able to do all worked as expected - so I'm +1 for merging this PR.

Co-authored-by: Ralf Gommers <ralf.gommers@gmail.com>
@mgorny
Copy link
Contributor

mgorny commented Jan 16, 2026

@encukou, could you do the reformatting, etc. to make CI pass?

@Avasam
Copy link
Contributor

Avasam commented Jan 23, 2026

@encukou
Copy link
Contributor Author

encukou commented Jan 26, 2026

There's also #371.

As far as I can see the failures are in code that this PR doesn't touch, due to updated mypy & ruff.
Should I pin the linters/checkers to a working version?

@Avasam
Copy link
Contributor

Avasam commented Jan 26, 2026

Should I pin the linters/checkers to a working version?

From my personal experience with maintainers (namely @jaraco ), I don't think that's necessary, but I'm also obviously not talking for them. They prefer to not pin unless absolutely necessary to see new failures as soon as they arrive and to not deal with micro-managing pins on many dozen of projects that could conflict with a shared base (https://github.com/jaraco/skeleton/). In the same vein, whilst annoying, unrelated failures not caused by the current changes are often not blocking.

IMO, it could make sense for you to pin in your PR if it helps you ensure you haven't broken stuff. I'll likely end up unpinning in my own PRs and/or a maintainer may end up asking you to remove the pin once they finally get to review 🤷‍♀️

Up to you really, I'm fairly certain the only thing blocking review of your PR is maintainers' free time.

@encukou
Copy link
Contributor Author

encukou commented Jan 27, 2026

I'm fairly certain the only thing blocking review of your PR is maintainers' free time.

That's my impression as well.

If there's anything I can help with, let me know.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Avoid passing /EXPORT:PyInit_* to MSVC for Python 3.15+ (PEP 793)

4 participants