Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BUG] When running bdist_wheel on Windows, warning appears: "Config variable 'Py_DEBUG' is unset, Python ABI tag may be incorrect" #4637

Open
JoevDubach opened this issue Sep 6, 2024 · 0 comments
Labels
bug Needs Triage Issues that need to be evaluated for severity and status.

Comments

@JoevDubach
Copy link

JoevDubach commented Sep 6, 2024

setuptools version

setuptools==74.1.2

Python version

Python 3.9.13

OS

Windows

Additional environment information

No response

Description

Now that setuptools has incorporated bdist_wheel.py as setuptools/command/bdist_wheel.py, the issue pypa/wheel#461 that was previously fixable by changing wheel is now fixable by changing setuptools, so I'm reporting it in updated form here.

When building a wheel with "python -m build --wheel" on Windows, it ends up executing wheel/bdist_wheel.py, and outputs this warning to screen:

  if get_flag("Py_DEBUG", hasattr(sys, "gettotalrefcount"), warn=(impl == "cp")):

This is because setuptools/command/bdist_wheel.py has a local implementation of get_abi_tag() that's called by bdist_wheel.get_tag(), which is called by bdist_wheel.run(), bdist_wheel.write_wheelfile(), and editable_wheel._create_wheel_file(). This local implementation isn't able to detect the debug attribute properly on Windows, so it issues a warning.

But setuptools/_vendor/packaging/tags.py has another implementation of this functionality in _cpython_abis() that detects the debug attribute more correctly:

    py_version = tuple(py_version)  # To allow for version comparison.
    abis = []
    version = _version_nodot(py_version[:2])
    threading = debug = pymalloc = ucs4 = ""
    with_debug = _get_config_var("Py_DEBUG", warn)
    has_refcount = hasattr(sys, "gettotalrefcount")
    # Windows doesn't set Py_DEBUG, so checking for support of debug-compiled
    # extension modules is the best option.
    # https://github.com/pypa/pip/issues/3383#issuecomment-173267692
    has_ext = "_d.pyd" in EXTENSION_SUFFIXES
    if with_debug or (with_debug is None and (has_refcount or has_ext)):
        debug = "d"
    if py_version >= (3, 13) and _get_config_var("Py_GIL_DISABLED", warn):
        threading = "t"
    if py_version < (3, 8):
        with_pymalloc = _get_config_var("WITH_PYMALLOC", warn)
        if with_pymalloc or with_pymalloc is None:
            pymalloc = "m"
        if py_version < (3, 3):
            unicode_size = _get_config_var("Py_UNICODE_SIZE", warn)
            if unicode_size == 4 or (
                unicode_size is None and sys.maxunicode == 0x10FFFF
            ):
                ucs4 = "u"
    elif debug:
        # Debug builds can also load "normal" extension modules.
        # We can also assume no UCS-4 or pymalloc requirement.
        abis.append(f"cp{version}{threading}")
    abis.insert(0, f"cp{version}{threading}{debug}{pymalloc}{ucs4}")
    return abis

tags._cpython_abis() is called by tags.cpython_tags(), which is called by tags.sys_tags(). See pypa/packaging#194 and pypa/packaging#172 for work that improved this debug attribute detection on Windows.

setuptools/command/bdist_wheel.py already has:

from packaging import tags, version as _packaging_version

...and uses tags.interpreter_name(), tags.interpreter_version(), and tags.sys_tags(). So it seems like using the tags module a little more extensively should be safe, as long as it gives the same behavior on all Python versions still supported by setuptools (>=3.8).

It seems to me that the local implementation of get_abi_tag() could be replaced with an appropriate call to tags.sys_tags(), and get_abi_tag() could be removed. The current code does:

            impl_ver = tags.interpreter_version()
            impl = impl_name + impl_ver
            # We don't work on CPython 3.1, 3.0.
            if self.py_limited_api and (impl_name + impl_ver).startswith("cp3"):
                impl = self.py_limited_api
                abi_tag = "abi3"
            else:
                abi_tag = str(get_abi_tag()).lower()
            tag = (impl, abi_tag, plat_name)
            # issue gh-374: allow overriding plat_name
            supported_tags = [
                (t.interpreter, t.abi, plat_name) for t in tags.sys_tags()
            ]
            assert (
                tag in supported_tags
            ), f"would build wheel with unsupported tag {tag}"

...where I could imagine it instead doing:

            impl_ver = tags.interpreter_version()
            impl = impl_name + impl_ver
            # issue gh-374: allow overriding plat_name
            supported_tags = [
                (t.interpreter, t.abi, plat_name) for t in tags.sys_tags()
            ]
            # We don't work on CPython 3.1, 3.0.
            if self.py_limited_api and (impl_name + impl_ver).startswith("cp3"):
                impl = self.py_limited_api
                abi_tag = "abi3"
                tag = (impl, abi_tag, plat_name)
                assert (
                    tag in supported_tags
                ), f"would build wheel with unsupported tag {tag}"
            else:
                tag = supported_tags[0]

This change works for my use case and avoids the warning.

If this isn't feasible for some reason, another option would be to change the local implementation of get_abi_tag() to imitate the relevant packaging.tags._cpython_abis() code that detects the debug and with_pymalloc attributes, with a particular care not to warn on Windows in an expected situation that is immediately going to be rectified by an appropriate alternate detection mechanism. This is more complicated, so I won't attempt to suggest the exact patch for this option.

Expected behavior

Not getting this warning being output to screen:

  if get_flag("Py_DEBUG", hasattr(sys, "gettotalrefcount"), warn=(impl == "cp")):

How to Reproduce

  1. Run commands:
    mkdir setuptoolsbug
    mkdir setuptoolsbug\mymod
    cd setuptoolsbug\mymod

  2. Create setuptoolsbug\mymod\setup.py:


## forces the wheelname to include the binary component
class BinaryDistribution(setuptools.dist.Distribution):
    def has_ext_modules(self):
        return True

setuptools.setup(
    name = 'mymod',
    version = "1.0.0.0",
    description = 'MyMod',
    packages = setuptools.find_packages(),
    include_package_data=True,
    python_requires='>=3.9',
    distclass = BinaryDistribution
)
  1. Run commands:
..\myenv\Scripts\python -m pip install --disable-pip-version-check setuptools==74.1.2
..\myenv\Scripts\python -m pip install --disable-pip-version-check build==1.2.2
mkdir ..\wheelhouse
..\myenv\Scripts\python -m build --no-isolation --skip-dependency-check --wheel --outdir ..\wheelhouse

Output


D:\work\setuptoolsbug\mymod>..\myenv\Scripts\python -m pip install --disable-pip-version-check setuptools==74.1.2
Collecting setuptools==74.1.2
  Using cached setuptools-74.1.2-py3-none-any.whl (1.3 MB)
Installing collected packages: setuptools
  Attempting uninstall: setuptools
    Found existing installation: setuptools 58.1.0
    Uninstalling setuptools-58.1.0:
      Successfully uninstalled setuptools-58.1.0
Successfully installed setuptools-74.1.2

D:\work\setuptoolsbug\mymod>..\myenv\Scripts\python -m pip install --disable-pip-version-check build==1.2.2
Collecting build==1.2.2
  Using cached build-1.2.2-py3-none-any.whl (22 kB)
Collecting tomli>=1.1.0
  Using cached tomli-2.0.1-py3-none-any.whl (12 kB)
Collecting packaging>=19.1
  Using cached packaging-24.1-py3-none-any.whl (53 kB)
Collecting colorama
  Using cached colorama-0.4.6-py2.py3-none-any.whl (25 kB)
Collecting pyproject_hooks
  Using cached pyproject_hooks-1.1.0-py3-none-any.whl (9.2 kB)
Collecting importlib-metadata>=4.6
  Using cached importlib_metadata-8.4.0-py3-none-any.whl (26 kB)
Collecting zipp>=0.5
  Using cached zipp-3.20.1-py3-none-any.whl (9.0 kB)
Installing collected packages: zipp, tomli, pyproject_hooks, packaging, colorama, importlib-metadata, build
Successfully installed build-1.2.2 colorama-0.4.6 importlib-metadata-8.4.0 packaging-24.1 pyproject_hooks-1.1.0 tomli-2.0.1 zipp-3.20.1

D:\work\setuptoolsbug\mymod>mkdir ..\wheelhouse

D:\work\setuptoolsbug\mymod>..\myenv\Scripts\python -m build --no-isolation --skip-dependency-check --wheel --outdir ..\wheelhouse
* Building wheel...
running bdist_wheel
running build
running build_ext
installing to build\bdist.win-amd64\wheel
running install
running install_lib
warning: install_lib: 'build\lib.win-amd64-cpython-39' does not exist -- no Python modules to install

running install_egg_info
running egg_info
writing mymod.egg-info\PKG-INFO
writing dependency_links to mymod.egg-info\dependency_links.txt
writing top-level names to mymod.egg-info\top_level.txt
reading manifest file 'mymod.egg-info\SOURCES.txt'
writing manifest file 'mymod.egg-info\SOURCES.txt'
Copying mymod.egg-info to build\bdist.win-amd64\wheel\.\mymod-1.0.0.0-py3.9.egg-info
running install_scripts
D:\work\setuptoolsbug\myenv\lib\site-packages\setuptools\command\bdist_wheel.py:114: RuntimeWarning: Config variable 'Py_DEBUG' is unset, Python ABI tag may be incorrect
  if get_flag("Py_DEBUG", hasattr(sys, "gettotalrefcount"), warn=(impl == "cp")):
creating build\bdist.win-amd64\wheel\mymod-1.0.0.0.dist-info\WHEEL
creating 'D:\work\setuptoolsbug\wheelhouse\.tmp-o7l2a5kc\mymod-1.0.0.0-cp39-cp39-win_amd64.whl' and adding 'build\bdist.win-amd64\wheel' to it
adding 'mymod-1.0.0.0.dist-info/METADATA'
adding 'mymod-1.0.0.0.dist-info/WHEEL'
adding 'mymod-1.0.0.0.dist-info/top_level.txt'
adding 'mymod-1.0.0.0.dist-info/RECORD'
removing build\bdist.win-amd64\wheel
Successfully built mymod-1.0.0.0-cp39-cp39-win_amd64.whl
@JoevDubach JoevDubach added bug Needs Triage Issues that need to be evaluated for severity and status. labels Sep 6, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Needs Triage Issues that need to be evaluated for severity and status.
Projects
None yet
Development

No branches or pull requests

1 participant