Script 'mail_helper' called by obssrc
Hello community,
here is the log from the commit of package python-extension-helpers for
openSUSE:Factory checked in at 2026-11-09 16:03:56
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-extension-helpers (Old)
and /work/SRC/openSUSE:Factory/.python-extension-helpers.new.3759290 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-extension-helpers"
Mon Nov 9 16:03:56 2026 rev:7 rq:1396183 version:1.5.0
Changes:
--------
---
/work/SRC/openSUSE:Factory/python-extension-helpers/python-extension-helpers.changes
2026-02-11 18:48:50.205350251 +0100
+++
/work/SRC/openSUSE:Factory/.python-extension-helpers.new.3759290/python-extension-helpers.changes
2026-11-09 16:04:31.519514962 +0100
@@ -1,0 +2,15 @@
+Sun Nov 8 20:45:57 UTC 2026 - Dirk Müller <[email protected]>
+
+- update to 1.5.0:
+ * Fix support for src/ layout even without ``setup.py``
+ * Fix incorrect path to _compiler.c for 'src' layout packages
+ * Look for setup.cfg in current directory, not srcdir
+ * TST: fixup skip condition on limited-api test
+ * TST: Replace macos-13 with macos-14
+ * MNT: drop deprecated License classifier, update related
+ metadata (PEP 639)
+ * Fix test with recent versions of pip/build
+ * Switch to two-phase module initialization
+ * Define COVERAGE_FILE to try and fix coverage reporting
+
+-------------------------------------------------------------------
Old:
----
extension_helpers-1.4.0.tar.gz
New:
----
extension_helpers-1.5.0.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-extension-helpers.spec ++++++
--- /var/tmp/diff_new_pack.H1fxDP/_old 2026-11-09 16:04:32.404552066 +0100
+++ /var/tmp/diff_new_pack.H1fxDP/_new 2026-11-09 16:04:32.406552149 +0100
@@ -17,16 +17,16 @@
Name: python-extension-helpers
-Version: 1.4.0
+Version: 1.5.0
Release: 0
-Summary: Utilities for building and installing packages wuth compiled
extensions
+Summary: Utilities for building and installing packages with compiled
extensions
License: BSD-3-Clause
URL: https://github.com/astropy/extension-helpers
Source:
https://files.pythonhosted.org/packages/source/e/extension_helpers/extension_helpers-%{version}.tar.gz
Source100: python-extension-helpers-rpmlintrc
BuildRequires: %{python_module base >= 3.10}
BuildRequires: %{python_module pip}
-BuildRequires: %{python_module setuptools >= 64}
+BuildRequires: %{python_module setuptools >= 77.0.1}
BuildRequires: %{python_module setuptools_scm >= 6.2}
BuildRequires: %{python_module wheel}
BuildRequires: fdupes
@@ -37,11 +37,11 @@
BuildRequires: %{python_module devel}
BuildRequires: %{python_module numpy-devel}
BuildRequires: %{python_module pytest}
-BuildRequires: %{python_module tomli if %python-base < 3.11}
+BuildRequires: %{python_module tomli >= 1.0.0 if %python-base < 3.11}
BuildRequires: %{python_module wheel}
# /SECTION
Requires: python-setuptools >= 64
-Requires: (python-tomli if python-base < 3.11)
+Requires: (python-tomli >= 1.0.0 if python-base < 3.11)
BuildArch: noarch
%python_subpackages
++++++ extension_helpers-1.4.0.tar.gz -> extension_helpers-1.5.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/extension_helpers-1.4.0/.github/dependabot.yml
new/extension_helpers-1.5.0/.github/dependabot.yml
--- old/extension_helpers-1.4.0/.github/dependabot.yml 2025-06-09
14:25:36.000000000 +0200
+++ new/extension_helpers-1.5.0/.github/dependabot.yml 2026-09-15
13:59:44.284224000 +0200
@@ -8,3 +8,5 @@
actions:
patterns:
- "*"
+ cooldown:
+ default-days: 7
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/extension_helpers-1.4.0/.github/release.yml
new/extension_helpers-1.5.0/.github/release.yml
--- old/extension_helpers-1.4.0/.github/release.yml 2025-06-09
14:25:36.000000000 +0200
+++ new/extension_helpers-1.5.0/.github/release.yml 2026-09-15
13:59:44.285530300 +0200
@@ -1,7 +1,8 @@
changelog:
exclude:
authors:
- - pre-commit-ci
+ - dependabot[bot]
+ - pre-commit-ci[bot]
categories:
- title: New Features
labels:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/extension_helpers-1.4.0/.github/workflows/main.yml
new/extension_helpers-1.5.0/.github/workflows/main.yml
--- old/extension_helpers-1.4.0/.github/workflows/main.yml 2025-06-09
14:25:36.000000000 +0200
+++ new/extension_helpers-1.5.0/.github/workflows/main.yml 2026-09-15
13:59:44.285530300 +0200
@@ -11,14 +11,13 @@
jobs:
tests:
- uses:
OpenAstronomy/github-actions-workflows/.github/workflows/tox.yml@8c0fde6f7e926df6ed7057255d29afa9c1ad5320
# v1.16.0
+ permissions:
+ id-token: write
+ uses:
OpenAstronomy/github-actions-workflows/.github/workflows/tox.yml@22ddf09dfabb443adddfb9f861b7d41a787d6b1a
# v3.0.3
with:
posargs: --openmp-expected=True
- coverage: codecov
+ coverage: codecov-oidc
envs: |
- # Code style
- - linux: style
-
# Standard tests
- linux: py310-test-oldestdeps
@@ -37,17 +36,18 @@
# Test with more compilers, for the OpenMP helpers
- macos: py313-test-osxclang-conda
- runs-on: macos-13
+ runs-on: macos-14
coverage: ''
- linux: py310-test-linuxgcc-conda
coverage: ''
# Test downstream packages
- linux: py313-downstream
+ coverage: ''
publish:
needs: tests
- uses:
OpenAstronomy/github-actions-workflows/.github/workflows/publish_pure_python.yml@8c0fde6f7e926df6ed7057255d29afa9c1ad5320
# v1.16.0
+ uses:
OpenAstronomy/github-actions-workflows/.github/workflows/publish_pure_python.yml@22ddf09dfabb443adddfb9f861b7d41a787d6b1a
# v3.0.3
with:
test_extras: test
test_command: pytest --pyargs extension_helpers
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/extension_helpers-1.4.0/.github/workflows/update-changelog.yml
new/extension_helpers-1.5.0/.github/workflows/update-changelog.yml
--- old/extension_helpers-1.4.0/.github/workflows/update-changelog.yml
2025-06-09 14:25:36.000000000 +0200
+++ new/extension_helpers-1.5.0/.github/workflows/update-changelog.yml
2026-09-15 13:59:44.285682700 +0200
@@ -14,7 +14,7 @@
steps:
- name: Checkout code
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 #
v4.2.2
+ uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 #
v7.0.1
with:
ref: main
@@ -26,7 +26,7 @@
path-to-changelog: CHANGES.md
- name: Commit updated CHANGELOG
- uses:
stefanzweifel/git-auto-commit-action@b863ae1933cb653a53c021fe36dbb774e1fb9403
# v5.2.0
+ uses:
stefanzweifel/git-auto-commit-action@4a55954c782fc1ea30b9056cd3e7a2b40ca8887d
# v7.2.0
with:
branch: main
commit_message: Update CHANGELOG
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/extension_helpers-1.4.0/.pre-commit-config.yaml
new/extension_helpers-1.5.0/.pre-commit-config.yaml
--- old/extension_helpers-1.4.0/.pre-commit-config.yaml 2025-06-09
14:25:36.000000000 +0200
+++ new/extension_helpers-1.5.0/.pre-commit-config.yaml 2026-09-15
13:59:44.285682700 +0200
@@ -1,6 +1,11 @@
+ci:
+ autofix_prs: false
+ autoupdate_schedule: monthly
+ autofix_commit_msg: "style: pre-commit fixes"
+
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
- rev: v5.0.0
+ rev: v6.0.0
hooks:
- id: check-added-large-files
- id: check-case-conflict
@@ -12,17 +17,17 @@
exclude: ".*(data.*|extern.*|licenses.*|.*.fits)$"
- repo: https://github.com/psf/black-pre-commit-mirror
- rev: 25.1.0
+ rev: 26.5.1
hooks:
- id: black
- repo: https://github.com/scientific-python/cookie
- rev: 2025.05.02
+ rev: 2026.06.18
hooks:
- id: sp-repo-review
- repo: https://github.com/codespell-project/codespell
- rev: v2.4.1
+ rev: v2.4.3
hooks:
- id: codespell
args: ["--write-changes"]
@@ -30,10 +35,7 @@
- tomli
- repo: https://github.com/astral-sh/ruff-pre-commit
- rev: "v0.11.12"
+ rev: "v0.16.1"
hooks:
- - id: ruff
+ - id: ruff-check
args: ["--fix", "--show-fixes"]
-
-ci:
- autofix_prs: false
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/extension_helpers-1.4.0/CHANGES.md
new/extension_helpers-1.5.0/CHANGES.md
--- old/extension_helpers-1.4.0/CHANGES.md 2025-06-09 14:25:36.000000000
+0200
+++ new/extension_helpers-1.5.0/CHANGES.md 2026-09-15 13:59:44.285682700
+0200
@@ -1,3 +1,14 @@
+## v1.4.0 - 2025-06-09
+
+<!-- Release notes generated using configuration in .github/release.yml at
main -->
+### What's Changed
+
+#### New Features
+
+* Allow opting in to limited API builds with EXTENSION_HELPERS_PY_LIMITED_API
by @astrofrog in https://github.com/astropy/extension-helpers/pull/110
+
+**Full Changelog**:
https://github.com/astropy/extension-helpers/compare/v1.3.0...v1.4.0
+
## v1.3.0 - 2025-05-27
<!-- Release notes generated using configuration in .github/release.yml at
main -->
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/extension_helpers-1.4.0/MANIFEST.in
new/extension_helpers-1.5.0/MANIFEST.in
--- old/extension_helpers-1.4.0/MANIFEST.in 2025-06-09 14:25:36.000000000
+0200
+++ new/extension_helpers-1.5.0/MANIFEST.in 2026-09-15 13:59:44.285682700
+0200
@@ -1,7 +1,5 @@
include README.rst
include CHANGES.rst
-include LICENSE.rst
-recursive-include licenses *
include ah_bootstrap.py
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/extension_helpers-1.4.0/PKG-INFO
new/extension_helpers-1.5.0/PKG-INFO
--- old/extension_helpers-1.4.0/PKG-INFO 2025-06-09 14:25:44.286327000
+0200
+++ new/extension_helpers-1.5.0/PKG-INFO 2026-09-15 13:59:56.814056400
+0200
@@ -1,14 +1,13 @@
Metadata-Version: 2.4
Name: extension-helpers
-Version: 1.4.0
+Version: 1.5.0
Summary: Utilities for building and installing packages with compiled
extensions
Author-email: The Astropy Developers <[email protected]>
-License: BSD 3-Clause License
+License-Expression: BSD-3-Clause
Project-URL: Homepage, https://github.com/astropy/extension-helpers
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: Framework :: Setuptools Plugin
-Classifier: License :: OSI Approved :: BSD License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 3
@@ -19,6 +18,7 @@
Requires-Python: >=3.10
Description-Content-Type: text/x-rst
License-File: LICENSE.rst
+License-File: licenses/LICENSE_ASTROSCRAPPY.rst
Requires-Dist: setuptools>=64
Requires-Dist: tomli>=1.0.0; python_version < "3.11"
Provides-Extra: test
@@ -53,4 +53,4 @@
the Astropy project but is intended to be general and usable by any Python
package.
-For more information, see the documentation at
http://extension-helpers.readthedocs.io
+For more information, see the documentation at
https://extension-helpers.readthedocs.io
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/extension_helpers-1.4.0/README.rst
new/extension_helpers-1.5.0/README.rst
--- old/extension_helpers-1.4.0/README.rst 2025-06-09 14:25:36.000000000
+0200
+++ new/extension_helpers-1.5.0/README.rst 2026-09-15 13:59:44.285682700
+0200
@@ -19,4 +19,4 @@
the Astropy project but is intended to be general and usable by any Python
package.
-For more information, see the documentation at
http://extension-helpers.readthedocs.io
+For more information, see the documentation at
https://extension-helpers.readthedocs.io
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/extension_helpers-1.4.0/docs/conf.py
new/extension_helpers-1.5.0/docs/conf.py
--- old/extension_helpers-1.4.0/docs/conf.py 2025-06-09 14:25:36.000000000
+0200
+++ new/extension_helpers-1.5.0/docs/conf.py 2026-09-15 13:59:44.286129000
+0200
@@ -1,11 +1,11 @@
-from pkg_resources import get_distribution
+from importlib.metadata import version as get_version
project = "extension-helpers"
copyright = "2019, The Astropy Developers"
author = "The Astropy Developers"
# We need to get the version number from the package
-version = release = get_distribution("extension-helpers").version
+version = release = get_version("extension-helpers")
extensions = [
"sphinx.ext.autodoc",
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/extension_helpers-1.4.0/docs/using.rst
new/extension_helpers-1.5.0/docs/using.rst
--- old/extension_helpers-1.4.0/docs/using.rst 2025-06-09 14:25:36.000000000
+0200
+++ new/extension_helpers-1.5.0/docs/using.rst 2026-09-15 13:59:44.286129000
+0200
@@ -66,6 +66,29 @@
For backwards compatibility, the setting of ``use_extension_helpers`` in
``setup.cfg`` will override any setting of it in ``pyproject.toml``.
+If your package uses a `src layout
+<https://setuptools.pypa.io/en/latest/userguide/package_discovery.html#src-layout>`_,
+extension-helpers will look for extensions in the source directory declared
+using the standard setuptools options, either in ``setup.cfg``::
+
+ [options]
+ package_dir =
+ = src
+
+ [options.packages.find]
+ where = src
+
+or in ``pyproject.toml``::
+
+ [tool.setuptools.packages.find]
+ where = ["src"]
+
+If no packages configuration is given at all, extension-helpers mirrors
+`automatic discovery
+<https://setuptools.pypa.io/en/latest/userguide/package_discovery.html#automatic-discovery>`_
+in setuptools and uses the ``src`` directory if it exists, falling back to the
+project root otherwise.
+
Python limited API
------------------
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/extension_helpers-1.4.0/extension_helpers/__init__.py
new/extension_helpers-1.5.0/extension_helpers/__init__.py
--- old/extension_helpers-1.4.0/extension_helpers/__init__.py 2025-06-09
14:25:36.000000000 +0200
+++ new/extension_helpers-1.5.0/extension_helpers/__init__.py 2026-09-15
13:59:44.286129000 +0200
@@ -1,3 +1,4 @@
+import os
import sys
from configparser import ConfigParser
@@ -7,12 +8,42 @@
from .version import version as __version__ # noqa: F401
+def _auto_srcdir():
+ # Mimic setuptools automatic discovery, which prefers src layout if src/
exists
+ return "src" if os.path.isdir("src") else "."
+
+
+def _get_srcdir_from_setup_cfg(cfg):
+ # The source root is the path mapped to the root package, e.g. "= src"
+ if cfg.has_option("options", "package_dir"):
+ for mapping in cfg.get("options", "package_dir").replace(",",
"\n").splitlines():
+ package, sep, path = mapping.partition("=")
+ if sep and package.strip() == "":
+ return path.strip()
+ # Any explicit packages configuration disables automatic discovery
+ if cfg.has_option("options", "packages"):
+ return "."
+ return _auto_srcdir()
+
+
+def _get_srcdir_from_pyproject(pyproject_cfg):
+ setuptools_cfg = pyproject_cfg.get("tool", {}).get("setuptools", {})
+ if "" in setuptools_cfg.get("package-dir", {}):
+ return setuptools_cfg["package-dir"][""]
+ packages = setuptools_cfg.get("packages", {})
+ if isinstance(packages, dict) and packages.get("find", {}).get("where"):
+ return packages["find"]["where"][0]
+ # Any explicit packages configuration disables automatic discovery
+ if "packages" in setuptools_cfg or "package-dir" in setuptools_cfg:
+ return "."
+ return _auto_srcdir()
+
+
def _finalize_distribution_hook(distribution):
"""
Entry point for setuptools which allows extension-helpers to be enabled
from setup.cfg without the need for setup.py.
"""
- import os
from pathlib import Path
if sys.version_info >= (3, 11):
@@ -29,7 +60,7 @@
if cfg.has_option("extension-helpers", "use_extension_helpers"):
found_config = True
if cfg.get("extension-helpers", "use_extension_helpers").lower()
== "true":
- distribution.ext_modules = get_extensions()
+ distribution.ext_modules =
get_extensions(_get_srcdir_from_setup_cfg(cfg))
pyproject = Path(distribution.src_root or os.curdir, "pyproject.toml")
if pyproject.exists() and not found_config:
@@ -41,4 +72,4 @@
and "use_extension_helpers" in
pyproject_cfg["tool"]["extension-helpers"]
and
pyproject_cfg["tool"]["extension-helpers"]["use_extension_helpers"]
):
- distribution.ext_modules = get_extensions()
+ distribution.ext_modules =
get_extensions(_get_srcdir_from_pyproject(pyproject_cfg))
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/extension_helpers-1.4.0/extension_helpers/_openmp_helpers.py
new/extension_helpers-1.5.0/extension_helpers/_openmp_helpers.py
--- old/extension_helpers-1.4.0/extension_helpers/_openmp_helpers.py
2025-06-09 14:25:36.000000000 +0200
+++ new/extension_helpers-1.5.0/extension_helpers/_openmp_helpers.py
2026-09-15 13:59:44.286451600 +0200
@@ -143,7 +143,7 @@
# Compile program
ccompiler.compile(["test_icx.c"], output_dir="objects")
- except Exception:
+ except Exception: # noqa: BLE001
is_icx = False
else:
is_icx = True
@@ -266,7 +266,7 @@
else:
log.warning("Unexpected output from test OpenMP program
(output was %s)", output)
is_openmp_supported = False
- except Exception:
+ except Exception: # noqa: BLE001
is_openmp_supported = False
finally:
@@ -323,9 +323,7 @@
Determine whether this package was built with OpenMP support.
\"\"\"
return {return_bool}
-"""[
- 1:
-]
+"""[1:]
def generate_openmp_enabled_py(packagename, srcdir=".", disable_openmp=None):
@@ -339,7 +337,7 @@
if sys.version_info >= (3, 11):
timestamp = datetime.datetime.fromtimestamp(epoch, datetime.UTC)
else:
- timestamp = datetime.datetime.utcfromtimestamp(epoch)
+ timestamp = datetime.datetime.utcfromtimestamp(epoch) # noqa: DTZ004
if disable_openmp is not None:
import builtins
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/extension_helpers-1.4.0/extension_helpers/_setup_helpers.py
new/extension_helpers-1.5.0/extension_helpers/_setup_helpers.py
--- old/extension_helpers-1.4.0/extension_helpers/_setup_helpers.py
2025-06-09 14:25:36.000000000 +0200
+++ new/extension_helpers-1.5.0/extension_helpers/_setup_helpers.py
2026-09-15 13:59:44.286451600 +0200
@@ -61,6 +61,9 @@
# Use the find_packages tool to locate all packages and modules
packages = find_packages(srcdir)
+ if not packages:
+ log.warning(f"No packages found in srcdir={srcdir!r}, so no extensions
will be collected")
+
# Update package_dir if the package lies in a subdirectory
if srcdir != ".":
package_dir[""] = srcdir
@@ -105,7 +108,8 @@
os.path.join(srcdir, main_package_dir, "_compiler.c"),
)
ext = Extension(
- main_package_dir + ".compiler_version",
[os.path.join(main_package_dir, "_compiler.c")]
+ main_package_dir + ".compiler_version",
+ [os.path.join(srcdir, main_package_dir, "_compiler.c")],
)
ext_modules.append(ext)
@@ -140,7 +144,8 @@
extension.sources = sources
- abi = get_limited_api_option(srcdir=srcdir)
+ # setup.cfg and pyproject.toml are in the current directory, not in srcdir
+ abi = get_limited_api_option(srcdir=".")
if abi:
version_info, version_hex = abi_to_versions(abi)
@@ -204,7 +209,7 @@
break # Don't recurse into subdirectories
-def get_cython_extensions(srcdir, packages, prevextensions=tuple(),
extincludedirs=None):
+def get_cython_extensions(srcdir, packages, prevextensions=(),
extincludedirs=None):
"""
Looks for Cython files and generates Extensions if needed.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/extension_helpers-1.4.0/extension_helpers/_utils.py
new/extension_helpers-1.5.0/extension_helpers/_utils.py
--- old/extension_helpers-1.4.0/extension_helpers/_utils.py 2025-06-09
14:25:36.000000000 +0200
+++ new/extension_helpers-1.5.0/extension_helpers/_utils.py 2026-09-15
13:59:44.286451600 +0200
@@ -15,7 +15,7 @@
import tomli as tomllib
-__all__ = ["write_if_different", "import_file", "get_limited_api_option",
"abi_to_versions"]
+__all__ = ["abi_to_versions", "get_limited_api_option", "import_file",
"write_if_different"]
if sys.platform == "win32":
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/extension_helpers-1.4.0/extension_helpers/src/compiler.c
new/extension_helpers-1.5.0/extension_helpers/src/compiler.c
--- old/extension_helpers-1.4.0/extension_helpers/src/compiler.c
2025-06-09 14:25:36.000000000 +0200
+++ new/extension_helpers-1.5.0/extension_helpers/src/compiler.c
2026-09-15 13:59:44.286451600 +0200
@@ -75,13 +75,20 @@
#endif
};
+static int m_exec(PyObject *module) {
+ return PyModule_AddStringConstant(module, "compiler", COMPILER);
+}
+
static struct PyModuleDef moduledef = {
PyModuleDef_HEAD_INIT,
"compiler_version",
NULL,
sizeof(struct module_state),
NULL,
- NULL,
+ (PyModuleDef_Slot []) {
+ {Py_mod_exec, m_exec},
+ {/* terminal element, all NULL */}
+ },
NULL,
NULL,
NULL
@@ -94,14 +101,5 @@
{
- PyObject* m;
-
- m = PyModule_Create(&moduledef);
-
- if (m == NULL)
- INITERROR;
-
- PyModule_AddStringConstant(m, "compiler", COMPILER);
-
- return m;
+ return PyModuleDef_Init(&moduledef);
}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/extension_helpers-1.4.0/extension_helpers/tests/test_setup_helpers.py
new/extension_helpers-1.5.0/extension_helpers/tests/test_setup_helpers.py
--- old/extension_helpers-1.4.0/extension_helpers/tests/test_setup_helpers.py
2025-06-09 14:25:36.000000000 +0200
+++ new/extension_helpers-1.5.0/extension_helpers/tests/test_setup_helpers.py
2026-09-15 13:59:44.286991000 +0200
@@ -2,7 +2,9 @@
import os
import subprocess
import sys
+import sysconfig
import uuid
+import zipfile
from textwrap import dedent
import pytest
@@ -15,9 +17,7 @@
else:
from .py311_backports import chdir
-extension_helpers_PATH = os.path.abspath(
- os.path.join(os.path.dirname(__file__), "..", "..")
-) # noqa
+extension_helpers_PATH =
os.path.abspath(os.path.join(os.path.dirname(__file__), "..", ".."))
def teardown_module(module):
@@ -38,6 +38,7 @@
def _extension_test_package(
tmp_path,
request=None,
+ src_layout=False,
extension_type="c",
include_numpy=False,
include_setup_py=True,
@@ -45,17 +46,16 @@
"""Creates a simple test package with an extension module."""
test_pkg = tmp_path / "test_pkg"
- os.makedirs(test_pkg / "helpers_test_package")
- (test_pkg / "helpers_test_package" / "__init__.py").touch()
+ src_dir = test_pkg / "src" if src_layout else test_pkg
+ os.makedirs(src_dir / "helpers_test_package")
+ (src_dir / "helpers_test_package" / "__init__.py").touch()
# TODO: It might be later worth making this particular test package into a
# reusable fixture for other build_ext tests
if extension_type in ("c", "both"):
# A minimal C extension for testing
- (test_pkg / "helpers_test_package" / "unit01.c").write_text(
- dedent(
- """\
+ (src_dir / "helpers_test_package" / "unit01.c").write_text(dedent("""\
#include <Python.h>
static struct PyModuleDef moduledef = {
@@ -69,19 +69,13 @@
PyInit_unit01(void) {
return PyModule_Create(&moduledef);
}
- """
- )
- )
+ """))
if extension_type in ("pyx", "both"):
# A minimal Cython extension for testing
- (test_pkg / "helpers_test_package" / "unit02.pyx").write_text(
- dedent(
- """\
+ (src_dir / "helpers_test_package" /
"unit02.pyx").write_text(dedent("""\
print("Hello cruel angel.")
- """
- )
- )
+ """))
if extension_type == "c":
extensions = ["unit01.c"]
@@ -92,30 +86,30 @@
include_dirs = ["numpy"] if include_numpy else []
+ pkg_dir = "'src', 'helpers_test_package'" if src_layout else
"'helpers_test_package'"
+
extensions_list = [
f"Extension('helpers_test_package.{os.path.splitext(extension)[0]}', "
- f"[join('helpers_test_package', '{extension}')], "
+ f"[join({pkg_dir}, '{extension}')], "
f"{include_dirs=})"
for extension in extensions
]
- (test_pkg / "helpers_test_package" / "setup_package.py").write_text(
- dedent(
- """\
+ (src_dir / "helpers_test_package" /
"setup_package.py").write_text(dedent("""\
from setuptools import Extension
from os.path import join
def get_extensions():
return [{}]
- """.format(
- ", ".join(extensions_list)
- )
- )
- )
+ """.format(", ".join(extensions_list))))
if include_setup_py:
- (test_pkg / "setup.py").write_text(
- dedent(
- f"""\
+ if src_layout:
+ packages_args = "packages=find_packages('src'), package_dir={'':
'src'}"
+ extensions_args = "get_extensions('src')"
+ else:
+ packages_args = "packages=find_packages()"
+ extensions_args = "get_extensions()"
+ (test_pkg / "setup.py").write_text(dedent(f"""\
import sys
from os.path import join
from setuptools import setup, find_packages
@@ -125,12 +119,10 @@
setup(
name='helpers_test_package',
version='0.1',
- packages=find_packages(),
- ext_modules=get_extensions()
+ {packages_args},
+ ext_modules={extensions_args}
)
- """
- )
- )
+ """))
if "" in sys.path:
sys.path.remove("")
@@ -237,9 +229,7 @@
simple_c = test_pkg / package_name / "simple.c"
- simple_c.write_text(
- dedent(
- """\
+ simple_c.write_text(dedent("""\
#include <Python.h>
static struct PyModuleDef moduledef = {
@@ -253,38 +243,26 @@
PyInit_simple(void) {
return PyModule_Create(&moduledef);
}
- """
- )
- )
+ """))
- (test_pkg / package_name / "setup_package.py").write_text(
- dedent(
- f"""\
+ (test_pkg / package_name / "setup_package.py").write_text(dedent(f"""\
from setuptools import Extension
from os.path import join
def get_extensions():
return [Extension('{package_name}.simple', [join('{package_name}',
'simple.c')])]
- """
- )
- )
+ """))
if use_extension_helpers is None:
- (test_pkg / "setup.cfg").write_text(
- dedent(
- f"""\
+ (test_pkg / "setup.cfg").write_text(dedent(f"""\
[metadata]
name = {package_name}
version = 0.1
[options]
packages = find:
- """
- )
- )
+ """))
else:
- (test_pkg / "setup.cfg").write_text(
- dedent(
- f"""\
+ (test_pkg / "setup.cfg").write_text(dedent(f"""\
[metadata]
name = {package_name}
version = 0.1
@@ -294,25 +272,17 @@
[extension-helpers]
use_extension_helpers = {str(use_extension_helpers).lower()}
- """
- )
- )
+ """))
if pyproject_use_helpers is None:
- (test_pkg / "pyproject.toml").write_text(
- dedent(
- """\
+ (test_pkg / "pyproject.toml").write_text(dedent("""\
[build-system]
requires = ["setuptools>=43.0.0",
"wheel"]
build-backend = 'setuptools.build_meta'
- """
- )
- )
+ """))
else:
- (test_pkg / "pyproject.toml").write_text(
- dedent(
- f"""\
+ (test_pkg / "pyproject.toml").write_text(dedent(f"""\
[build-system]
requires = ["setuptools>=43.0.0",
"wheel"]
@@ -320,9 +290,7 @@
[tool.extension-helpers]
use_extension_helpers = {str(pyproject_use_helpers).lower()}
- """
- )
- )
+ """))
install_temp = test_pkg / "install_temp"
os.mkdir(install_temp)
@@ -377,29 +345,21 @@
os.makedirs(test_pkg / package_name)
(test_pkg / package_name / "__init__.py").touch()
simple_pyx = test_pkg / package_name / "simple.pyx"
- simple_pyx.write_text(
- dedent(
- """\
+ simple_pyx.write_text(dedent("""\
def test():
pass
- """
- )
- )
+ """))
if pyproject_use_helpers is None:
extension_helpers_option = ""
else:
- extension_helpers_option = dedent(
- f"""
+ extension_helpers_option = dedent(f"""
[tool.extension-helpers]
use_extension_helpers = {str(pyproject_use_helpers).lower()}
- """
- )
+ """)
buildtime_requirements = ["setuptools>=43.0.0", "wheel", "Cython"]
- (test_pkg / "pyproject.toml").write_text(
- dedent(
- f"""\
+ (test_pkg / "pyproject.toml").write_text(dedent(f"""\
[project]
name = "{package_name}"
version = "0.1"
@@ -411,10 +371,7 @@
requires = [{', '.join(f'"{_}"' for _ in buildtime_requirements)}]
build-backend = 'setuptools.build_meta'
- """
- )
- + extension_helpers_option
- )
+ """) + extension_helpers_option)
install_temp = test_pkg / "install_temp"
os.mkdir(install_temp)
@@ -468,36 +425,49 @@
# Tests to make sure that limited API support works correctly
[email protected]("config", ("setup.cfg", "pyproject.toml"))
[email protected]("config", ("setup.cfg", "setup.py", "pyproject.toml"))
@pytest.mark.parametrize("envvar", (False, True))
@pytest.mark.parametrize("limited_api", (None, "cp310"))
@pytest.mark.parametrize("extension_type", ("c", "pyx", "both"))
-def test_limited_api(tmp_path, config, envvar, limited_api, extension_type):
-
- if sys.version_info < (3, 11):
- pytest.skip(
- "This test requires setuptools>=65.4 which is only available for
Python 3.11 and later"
- )
[email protected]("src_layout", (False, True))
+def test_limited_api(tmp_path, config, envvar, limited_api, extension_type,
src_layout):
+ pytest.importorskip("setuptools", minversion="65.4")
package = _extension_test_package(
- tmp_path, extension_type=extension_type, include_numpy=True,
include_setup_py=False
+ tmp_path,
+ extension_type=extension_type,
+ include_numpy=True,
+ include_setup_py=(config == "setup.py"),
+ src_layout=src_layout,
)
- if config == "setup.cfg":
+ if config == "setup.py":
- setup_cfg = dedent(
- """\
+ if limited_api and not envvar:
+ (package /
"setup.cfg").write_text(f"[bdist_wheel]\npy_limited_api={limited_api}")
+ elif envvar:
+ # Make sure if we are using the environment variable that it takes
+ # precedence over this setting (this only works for setup.cfg)
+ (package /
"setup.cfg").write_text("[bdist_wheel]\npy_limited_api=cp35")
+
+ elif config == "setup.cfg":
+
+ setup_cfg = dedent(f"""\
[metadata]
name = helpers_test_package
version = 0.1
[options]
packages = find:
+ package_dir =
+ = {'src' if src_layout else '.'}
+
+ [options.packages.find]
+ where = {'src' if src_layout else '.'}
[extension-helpers]
use_extension_helpers = true
- """
- )
+ """)
if limited_api and not envvar:
setup_cfg += f"\n[bdist_wheel]\npy_limited_api={limited_api}"
@@ -508,26 +478,9 @@
(package / "setup.cfg").write_text(setup_cfg)
- # Still require a minimal pyproject.toml file if no setup.py file
-
- (package / "pyproject.toml").write_text(
- dedent(
- """
- [build-system]
- requires = ["setuptools>=43.0.0",
- "wheel"]
- build-backend = 'setuptools.build_meta'
-
- [tool.extension-helpers]
- use_extension_helpers = true
- """
- )
- )
-
elif config == "pyproject.toml":
- pyproject_toml = dedent(
- """\
+ pyproject_toml = dedent(f"""\
[build-system]
requires = ["setuptools>=43.0.0",
"wheel"]
@@ -537,19 +490,28 @@
name = "helpers_test_package"
version = "0.1"
- [tool.setuptools.packages]
- find = {namespaces = false}
+ [tool.setuptools.packages.find]
+ where = ["{'src' if src_layout else '.'}"]
+ namespaces = false
[tool.extension-helpers]
use_extension_helpers = true
- """
- )
+ """)
if limited_api and not envvar:
pyproject_toml += f'\n[tool.distutils.bdist_wheel]\npy-limited-api
= "{limited_api}"'
(package / "pyproject.toml").write_text(pyproject_toml)
+ if config != "pyproject.toml":
+ # A minimal pyproject.toml file is still required
+ (package / "pyproject.toml").write_text(dedent("""
+ [build-system]
+ requires = ["setuptools>=43.0.0",
+ "wheel"]
+ build-backend = 'setuptools.build_meta'
+ """))
+
env = os.environ.copy()
if envvar:
@@ -568,6 +530,55 @@
assert len(wheels) == 1
assert ("abi3" in wheels[0]) == (limited_api is not None)
+ # The wheel tag above only reflects the bdist_wheel option, so also check
+ # that the extensions themselves were built for the limited API, in which
+ # case they don't use the default (version-specific) extension suffix
+ ext_suffix = sysconfig.get_config_var("EXT_SUFFIX")
+ with zipfile.ZipFile(package / "dist" / wheels[0]) as wheel:
+ ext_files = [f for f in wheel.namelist() if f.endswith((".so",
".pyd"))]
+ assert ext_files
+ for filename in ext_files:
+ assert filename.endswith(ext_suffix) == (limited_api is None)
+
+
[email protected]("src_layout", (False, True))
+def test_automatic_layout_discovery(tmp_path, src_layout):
+ """
+ Test building a package with no explicit packages configuration, relying
+ on setuptools automatic discovery of flat and src layouts.
+ """
+
+ pytest.importorskip("setuptools", minversion="61.0")
+
+ package = _extension_test_package(
+ tmp_path,
+ extension_type="c",
+ include_numpy=True,
+ include_setup_py=False,
+ src_layout=src_layout,
+ )
+
+ (package / "pyproject.toml").write_text(dedent("""\
+ [build-system]
+ requires = ["setuptools>=61.0", "wheel"]
+ build-backend = 'setuptools.build_meta'
+
+ [project]
+ name = "helpers_test_package"
+ version = "0.1"
+
+ [tool.extension-helpers]
+ use_extension_helpers = true
+ """))
+
+ with chdir(package):
+ subprocess.run([sys.executable, "-m", "build", "--wheel",
"--no-isolation"], check=True)
+
+ wheels = os.listdir(package / "dist")
+ assert len(wheels) == 1
+ with zipfile.ZipFile(package / "dist" / wheels[0]) as wheel:
+ assert [f for f in wheel.namelist() if f.endswith((".so", ".pyd"))]
+
def test_limited_api_invalid_abi(tmp_path, capsys):
@@ -575,9 +586,7 @@
tmp_path, extension_type="c", include_numpy=True,
include_setup_py=False
)
- (package / "setup.cfg").write_text(
- dedent(
- """\
+ (package / "setup.cfg").write_text(dedent("""\
[metadata]
name = helpers_test_package
version = 0.1
@@ -590,26 +599,20 @@
[bdist_wheel]
py_limited_api=invalid
- """
- )
- )
+ """))
- (package / "pyproject.toml").write_text(
- dedent(
- """
+ (package / "pyproject.toml").write_text(dedent("""
[build-system]
requires = ["setuptools>=43.0.0",
"wheel"]
build-backend = 'setuptools.build_meta'
- """
- )
- )
+ """))
with chdir(package):
result = subprocess.run(
- [sys.executable, "-m", "build", "--wheel", "--no-isolation"],
stderr=subprocess.PIPE
+ [sys.executable, "-m", "build", "--wheel", "--no-isolation"],
+ stderr=subprocess.PIPE,
+ check=False,
)
- assert result.stderr.strip().endswith(
- b"ValueError: Unrecognized abi version for limited API: invalid"
- )
+ assert b"ValueError: Unrecognized abi version for limited API: invalid" in
result.stderr
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/extension_helpers-1.4.0/extension_helpers/version.py
new/extension_helpers-1.5.0/extension_helpers/version.py
--- old/extension_helpers-1.4.0/extension_helpers/version.py 2025-06-09
14:25:44.000000000 +0200
+++ new/extension_helpers-1.5.0/extension_helpers/version.py 2026-09-15
13:59:56.751694000 +0200
@@ -1,21 +1,24 @@
-# file generated by setuptools-scm
+# file generated by vcs-versioning
# don't change, don't track in version control
+from __future__ import annotations
-__all__ = ["__version__", "__version_tuple__", "version", "version_tuple"]
-
-TYPE_CHECKING = False
-if TYPE_CHECKING:
- from typing import Tuple
- from typing import Union
-
- VERSION_TUPLE = Tuple[Union[int, str], ...]
-else:
- VERSION_TUPLE = object
+__all__ = [
+ "__version__",
+ "__version_tuple__",
+ "version",
+ "version_tuple",
+ "__commit_id__",
+ "commit_id",
+]
version: str
__version__: str
-__version_tuple__: VERSION_TUPLE
-version_tuple: VERSION_TUPLE
+__version_tuple__: tuple[int | str, ...]
+version_tuple: tuple[int | str, ...]
+commit_id: str | None
+__commit_id__: str | None
+
+__version__ = version = '1.5.0'
+__version_tuple__ = version_tuple = (1, 5, 0)
-__version__ = version = '1.4.0'
-__version_tuple__ = version_tuple = (1, 4, 0)
+__commit_id__ = commit_id = 'g3c99edb4c'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/extension_helpers-1.4.0/extension_helpers.egg-info/PKG-INFO
new/extension_helpers-1.5.0/extension_helpers.egg-info/PKG-INFO
--- old/extension_helpers-1.4.0/extension_helpers.egg-info/PKG-INFO
2025-06-09 14:25:44.000000000 +0200
+++ new/extension_helpers-1.5.0/extension_helpers.egg-info/PKG-INFO
2026-09-15 13:59:56.787088600 +0200
@@ -1,14 +1,13 @@
Metadata-Version: 2.4
Name: extension-helpers
-Version: 1.4.0
+Version: 1.5.0
Summary: Utilities for building and installing packages with compiled
extensions
Author-email: The Astropy Developers <[email protected]>
-License: BSD 3-Clause License
+License-Expression: BSD-3-Clause
Project-URL: Homepage, https://github.com/astropy/extension-helpers
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: Framework :: Setuptools Plugin
-Classifier: License :: OSI Approved :: BSD License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 3
@@ -19,6 +18,7 @@
Requires-Python: >=3.10
Description-Content-Type: text/x-rst
License-File: LICENSE.rst
+License-File: licenses/LICENSE_ASTROSCRAPPY.rst
Requires-Dist: setuptools>=64
Requires-Dist: tomli>=1.0.0; python_version < "3.11"
Provides-Extra: test
@@ -53,4 +53,4 @@
the Astropy project but is intended to be general and usable by any Python
package.
-For more information, see the documentation at
http://extension-helpers.readthedocs.io
+For more information, see the documentation at
https://extension-helpers.readthedocs.io
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/extension_helpers-1.4.0/extension_helpers.egg-info/SOURCES.txt
new/extension_helpers-1.5.0/extension_helpers.egg-info/SOURCES.txt
--- old/extension_helpers-1.4.0/extension_helpers.egg-info/SOURCES.txt
2025-06-09 14:25:44.000000000 +0200
+++ new/extension_helpers-1.5.0/extension_helpers.egg-info/SOURCES.txt
2026-09-15 13:59:56.800526600 +0200
@@ -32,6 +32,8 @@
extension_helpers.egg-info/entry_points.txt
extension_helpers.egg-info/not-zip-safe
extension_helpers.egg-info/requires.txt
+extension_helpers.egg-info/scm_file_list.json
+extension_helpers.egg-info/scm_version.json
extension_helpers.egg-info/top_level.txt
extension_helpers/src/compiler.c
extension_helpers/tests/__init__.py
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/extension_helpers-1.4.0/extension_helpers.egg-info/scm_file_list.json
new/extension_helpers-1.5.0/extension_helpers.egg-info/scm_file_list.json
--- old/extension_helpers-1.4.0/extension_helpers.egg-info/scm_file_list.json
1970-01-01 01:00:00.000000000 +0100
+++ new/extension_helpers-1.5.0/extension_helpers.egg-info/scm_file_list.json
2026-09-15 13:59:56.785496500 +0200
@@ -0,0 +1,38 @@
+{
+ "files": [
+ ".github/dependabot.yml",
+ ".github/release.yml",
+ ".github/workflows/main.yml",
+ ".github/workflows/update-changelog.yml",
+ ".gitignore",
+ ".pre-commit-config.yaml",
+ ".readthedocs.yaml",
+ "CHANGES.md",
+ "CONTRIBUTING.md",
+ "LICENSE.rst",
+ "MANIFEST.in",
+ "README.rst",
+ "conftest.py",
+ "docs/Makefile",
+ "docs/api.rst",
+ "docs/conf.py",
+ "docs/index.rst",
+ "docs/make.bat",
+ "docs/openmp.rst",
+ "docs/using.rst",
+ "extension_helpers/__init__.py",
+ "extension_helpers/_openmp_helpers.py",
+ "extension_helpers/_setup_helpers.py",
+ "extension_helpers/_utils.py",
+ "extension_helpers/conftest.py",
+ "extension_helpers/src/compiler.c",
+ "extension_helpers/tests/__init__.py",
+ "extension_helpers/tests/py311_backports.py",
+ "extension_helpers/tests/test_openmp_helpers.py",
+ "extension_helpers/tests/test_setup_helpers.py",
+ "extension_helpers/tests/test_utils.py",
+ "licenses/LICENSE_ASTROSCRAPPY.rst",
+ "pyproject.toml",
+ "tox.ini"
+ ]
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/extension_helpers-1.4.0/extension_helpers.egg-info/scm_version.json
new/extension_helpers-1.5.0/extension_helpers.egg-info/scm_version.json
--- old/extension_helpers-1.4.0/extension_helpers.egg-info/scm_version.json
1970-01-01 01:00:00.000000000 +0100
+++ new/extension_helpers-1.5.0/extension_helpers.egg-info/scm_version.json
2026-09-15 13:59:56.778716600 +0200
@@ -0,0 +1,8 @@
+{
+ "tag": "1.5.0",
+ "distance": 0,
+ "node": "g3c99edb4cc6ee8af141015ccbe7fbcff1474344e",
+ "dirty": false,
+ "branch": "HEAD",
+ "node_date": "2026-09-15"
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/extension_helpers-1.4.0/pyproject.toml
new/extension_helpers-1.5.0/pyproject.toml
--- old/extension_helpers-1.4.0/pyproject.toml 2025-06-09 14:25:36.000000000
+0200
+++ new/extension_helpers-1.5.0/pyproject.toml 2026-09-15 13:59:44.286991000
+0200
@@ -1,14 +1,14 @@
[project]
name = "extension-helpers"
authors = [{name = "The Astropy Developers", email = "[email protected]"}]
-license = {text = "BSD 3-Clause License"}
+license = "BSD-3-Clause"
+license-files = ["LICENSE.rst", "licenses/LICENSE_ASTROSCRAPPY.rst"]
description = "Utilities for building and installing packages with compiled
extensions"
readme = "README.rst"
classifiers = [
"Development Status :: 5 - Production/Stable",
"Intended Audience :: Developers",
"Framework :: Setuptools Plugin",
- "License :: OSI Approved :: BSD License",
"Operating System :: OS Independent",
"Programming Language :: Python",
"Programming Language :: Python :: 3",
@@ -45,7 +45,6 @@
[tool.setuptools]
zip-safe = false
provides = ["extension_helpers"]
-license-files = ["LICENSE.rst"]
include-package-data = false
[tool.setuptools.packages]
@@ -92,7 +91,7 @@
]
[build-system]
-requires = ["setuptools>=43.0.0",
+requires = ["setuptools>=77.0.1",
"setuptools_scm>=6.2"]
build-backend = 'setuptools.build_meta'
@@ -136,6 +135,8 @@
"PC180", # ignore using `prettier` in pre-commit
"PC901", # ignore using custom update message (we have many of the default
ones in our history already)
"PC170", # ignore using pygrep
+ "PP006", # ignore defining dev dependency group
+ "PP304", # ignore setting log_level in pytest
"PY005", # ignore having a tests/ folder
]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/extension_helpers-1.4.0/tox.ini
new/extension_helpers-1.5.0/tox.ini
--- old/extension_helpers-1.4.0/tox.ini 2025-06-09 14:25:36.000000000 +0200
+++ new/extension_helpers-1.5.0/tox.ini 2026-09-15 13:59:44.286991000 +0200
@@ -13,6 +13,7 @@
setenv =
osxclang: CC=clang-20
linuxgcc: CC=gcc_linux-64
+ COVERAGE_FILE={toxinidir}/.coverage
changedir =
test: .tmp/{envname}
whitelist_externals =