Skip to content

pip-25.0.1 runs setup.py with broken import behaviour #13289

Open
@julian-smith-artifex-com

Description

Description

pip-25.0.1 appears to run setup.py in such a way that import platform picks up a local platform/ directory if it exists, instead of the built-in module.

This happens if platform/ is empty, or if it contains other files and directories without a __init__.py file.

I include a Python script that shows the broken behaviour.

  • Run with no args: ./pipbug.py.
  • If not run in a venv it reruns itself inside a new venv.
  • Then it creates a new project directory with a pyproject.toml file, a (non-working) setup.py and an empty platform/ directory.
  • Then it attempts to build a wheel with pip-24.3.1 and pip-25.0.1.

Expected behavior

import platform should get the built-in module regardless of whether there is a local platform directory.

pip version

25.0.1

Python version

3.11 and 3.12.

OS

Linux, OpenBSD.

How to Reproduce

Run this Python script as file pipbug.py:

#!/usr/bin/env python3

'''
pip-25.0.1 runs setup.py in such a way that `import platform` picks up local
`platform/` directory, not the built-in module.
'''

import os
import shlex
import shutil
import subprocess
import sys
import textwrap


filep = os.path.normpath(__file__)

def run(command, check=1):
    print(f'Running: {command}', flush=1)
    return subprocess.run(command, shell=1, check=check)

def main():
    # Create project directory {filep}_testdir
    testdir = f'{filep}_testdir'
    shutil.rmtree(testdir, ignore_errors=1)
    os.mkdir(testdir)
    # Create empty `platform/` directory.
    os.mkdir(f'{testdir}/platform')
    
    # Create (non-working) setup.py.
    with open(f'{testdir}/setup.py', 'w') as f:
        f.write(
                textwrap.dedent('''
                    import os
                    import platform
                    import sys
                    print(f'setup.py: {sys.path=}')
                    print(f'setup.py: {os.getcwd()=}')
                    print(f'setup.py: {dir(platform)=}')
                    print(f'setup.py: {platform.__file__=}')
                    print(f'setup.py: {getattr(platform, "__path__", None)=}')
                    print(f'setup.py: {platform.system()=}')
                    ''')
                )

    # Create pyproject.toml.
    with open(f'{testdir}/pyproject.toml', 'w') as f:
        f.write(
                textwrap.dedent('''
                    [build-system]
                    requires = []

                    # See pep-517.
                    #
                    build-backend = "setup"
                    backend-path = ["."]
                    ''')
                )

    # Attempt to create wheel with pip-24.3.1. This gives expected error:
    #   AttributeError: module 'setup' has no attribute 'build_wheel'
    print('=' * 80)
    print(f'Testing with pip-24.3.1')
    run(f'pip install pip==24.3.1')
    run(f'pip wheel -v {os.path.abspath(testdir)}', check=0)
    
    # Attempt to create wheel with pip-25.0.1. This gives different error:
    #   AttributeError: module 'platform' has no attribute 'system'
    print('=' * 80)
    print(f'Testing with pip-25.0.1')
    run(f'pip install pip==25.0.1')
    run(f'pip wheel -v {os.path.abspath(testdir)}', check=0)


if __name__ == '__main__':
    if sys.prefix == sys.base_prefix:
        # Not running in a venv. Rerun ourselves in a venv.
        command = f'{sys.executable} -m venv {filep}_venv'
        command += f' && . {filep}_venv/bin/activate'
        command += f' && python'
        for arg in sys.argv:
            command += f' {shlex.quote(arg)}'
        run(command)
    else:
        main()

Output

Example output on Linux is below.

  • With pip-24.3.1 we get expected error `AttributeError: module 'setup' has no attribute 'build_wheel'.
  • With pip-25.0.1 we get earlier error AttributeError: module 'platform' has no attribute 'system', because import platform has picked up the local empty platform directory instead of the built-in module platform.
> ./pipbug.py
Running: /usr/bin/python3 -m venv [...]/pipbug.py_venv && . [...]/pipbug.py_venv/bin/activate && python ./pipbug.py
================================================================================
Testing with pip-24.3.1
Running: pip install pip==24.3.1
Collecting pip==24.3.1
  Using cached pip-24.3.1-py3-none-any.whl.metadata (3.7 kB)
Using cached pip-24.3.1-py3-none-any.whl (1.8 MB)
Installing collected packages: pip
  Attempting uninstall: pip
    Found existing installation: pip 25.0.1
    Uninstalling pip-25.0.1:
      Successfully uninstalled pip-25.0.1
Successfully installed pip-24.3.1

[notice] A new release of pip is available: 24.3.1 -> 25.0.1
[notice] To update, run: pip install --upgrade pip
Running: pip wheel -v [...]/pipbug.py_testdir
Processing ./pipbug.py_testdir
  Getting requirements to build wheel: started
  Running command Getting requirements to build wheel
  setup.py: sys.path=['[...]/pipbug.py_testdir', '[...]/pipbug.py_venv/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/_in_process', '/tmp/pip-build-env-4awji4kl/site', '/usr/lib/python312.zip', '/usr/lib/python3.12', '/usr/lib/python3.12/lib-dynload', '/tmp/pip-build-env-4awji4kl/overlay/lib/python3.12/site-packages', '/tmp/pip-build-env-4awji4kl/normal/lib/python3.12/site-packages']
  setup.py: os.getcwd()='[...]/pipbug.py_testdir'
  setup.py: dir(platform)=['_Processor', '_WIN32_CLIENT_RELEASES', '_WIN32_SERVER_RELEASES', '__builtins__', '__cached__', '__copyright__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', '__version__', '_comparable_version', '_default_architecture', '_follow_symlinks', '_get_machine_win32', '_java_getprop', '_mac_ver_xml', '_node', '_norm_version', '_os_release_cache', '_os_release_candidates', '_parse_os_release', '_platform', '_platform_cache', '_sys_version', '_sys_version_cache', '_syscmd_file', '_syscmd_ver', '_uname_cache', '_unknown_as_blank', '_ver_stages', '_win32_ver', '_wmi_query', 'architecture', 'collections', 'freedesktop_os_release', 'functools', 'itertools', 'java_ver', 'libc_ver', 'mac_ver', 'machine', 'node', 'os', 'platform', 'processor', 'python_branch', 'python_build', 'python_compiler', 'python_implementation', 'python_revision', 'python_version', 'python_version_tuple', 're', 'release', 'sys', 'system', 'system_alias', 'uname', 'uname_result', 'version', 'win32_edition', 'win32_is_iot', 'win32_ver']
  Getting requirements to build wheel: finished with status 'done'
  Preparing metadata (pyproject.toml): started
  setup.py: platform.__file__='/usr/lib/python3.12/platform.py'
  setup.py: getattr(platform, "__path__", None)=None
  setup.py: platform.system()='Linux'
  Running command Preparing metadata (pyproject.toml)
  setup.py: sys.path=['[...]/pipbug.py_testdir', '[...]/pipbug.py_venv/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/_in_process', '/tmp/pip-build-env-4awji4kl/site', '/usr/lib/python312.zip', '/usr/lib/python3.12', '/usr/lib/python3.12/lib-dynload', '/tmp/pip-build-env-4awji4kl/overlay/lib/python3.12/site-packages', '/tmp/pip-build-env-4awji4kl/normal/lib/python3.12/site-packages']
  setup.py: os.getcwd()='[...]/pipbug.py_testdir'
  setup.py: dir(platform)=['_Processor', '_WIN32_CLIENT_RELEASES', '_WIN32_SERVER_RELEASES', '__builtins__', '__cached__', '__copyright__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', '__version__', '_comparable_version', '_default_architecture', '_follow_symlinks', '_get_machine_win32', '_java_getprop', '_mac_ver_xml', '_node', '_norm_version', '_os_release_cache', '_os_release_candidates', '_parse_os_release', '_platform', '_platform_cache', '_sys_version', '_sys_version_cache', '_syscmd_file', '_syscmd_ver', '_uname_cache', '_unknown_as_blank', '_ver_stages', '_win32_ver', '_wmi_query', 'architecture', 'collections', 'freedesktop_os_release', 'functools', 'itertools', 'java_ver', 'libc_ver', 'mac_ver', 'machine', 'node', 'os', 'platform', 'processor', 'python_branch', 'python_build', 'python_compiler', 'python_implementation', 'python_revision', 'python_version', 'python_version_tuple', 're', 'release', 'sys', 'system', 'system_alias', 'uname', 'uname_result', 'version', 'win32_edition', 'win32_is_iot', 'win32_ver']
  setup.py: platform.__file__='/usr/lib/python3.12/platform.py'
  setup.py: getattr(platform, "__path__", None)=None
  setup.py: platform.system()='Linux'
  Traceback (most recent call last):
    File "[...]/pipbug.py_venv/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/_in_process/_in_process.py", line 353, in <module>
      main()
    File "[...]/pipbug.py_venv/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/_in_process/_in_process.py", line 335, in main
      json_out['return_val'] = hook(**hook_input['kwargs'])
                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    File "[...]/pipbug.py_venv/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/_in_process/_in_process.py", line 152, in prepare_metadata_for_build_wheel
      whl_basename = backend.build_wheel(metadata_directory, config_settings)
                     ^^^^^^^^^^^^^^^^^^^
  AttributeError: module 'setup' has no attribute 'build_wheel'
  Preparing metadata (pyproject.toml): finished with status 'error'
  error: subprocess-exited-with-error
  
  � Preparing metadata (pyproject.toml) did not run successfully.
  � exit code: 1
  ��> See above for output.
  
  note: This error originates from a subprocess, and is likely not a problem with pip.
  full command: [...]/pipbug.py_venv/bin/python3 [...]/pipbug.py_venv/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/_in_process/_in_process.py prepare_metadata_for_build_wheel /tmp/tmpoiz5wz0s
  cwd: [...]/pipbug.py_testdir

[notice] A new release of pip is available: 24.3.1 -> 25.0.1
[notice] To update, run: pip install --upgrade pip
error: metadata-generation-failed

� Encountered error while generating package metadata.
��> See above for output.

note: This is an issue with the package mentioned above, not pip.
hint: See above for details.
================================================================================
Testing with pip-25.0.1
Running: pip install pip==25.0.1
Collecting pip==25.0.1
  Using cached pip-25.0.1-py3-none-any.whl.metadata (3.7 kB)
Using cached pip-25.0.1-py3-none-any.whl (1.8 MB)
Installing collected packages: pip
  Attempting uninstall: pip
    Found existing installation: pip 24.3.1
    Uninstalling pip-24.3.1:
      Successfully uninstalled pip-24.3.1
Successfully installed pip-25.0.1
Running: pip wheel -v [...]/pipbug.py_testdir
Processing ./pipbug.py_testdir
  Getting requirements to build wheel: started
  Running command Getting requirements to build wheel
  setup.py: sys.path=['/tmp/pip-build-env-9swhkfon/site', '/usr/lib/python312.zip', '/usr/lib/python3.12', '/usr/lib/python3.12/lib-dynload', '/tmp/pip-build-env-9swhkfon/overlay/lib/python3.12/site-packages', '/tmp/pip-build-env-9swhkfon/normal/lib/python3.12/site-packages']
  setup.py: os.getcwd()='[...]/pipbug.py_testdir'
  setup.py: dir(platform)=['__doc__', '__file__', '__loader__', '__name__', '__package__', '__path__', '__spec__']
  setup.py: platform.__file__=None
  setup.py: getattr(platform, "__path__", None)=_NamespacePath(['[...]/pipbug.py_testdir/platform'])
  Traceback (most recent call last):
    File "[...]/pipbug.py_venv/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/_in_process/_in_process.py", line 389, in <module>
      main()
    File "[...]/pipbug.py_venv/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/_in_process/_in_process.py", line 373, in main
      json_out["return_val"] = hook(**hook_input["kwargs"])
                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    File "[...]/pipbug.py_venv/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/_in_process/_in_process.py", line 137, in get_requires_for_build_wheel
      backend = _build_backend()
                ^^^^^^^^^^^^^^^^
    File "[...]/pipbug.py_venv/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/_in_process/_in_process.py", line 70, in _build_backend
      obj = import_module(mod_path)
            ^^^^^^^^^^^^^^^^^^^^^^^
    File "/usr/lib/python3.12/importlib/__init__.py", line 90, in import_module
      return _bootstrap._gcd_import(name[level:], package, level)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    File "<frozen importlib._bootstrap>", line 1387, in _gcd_import
    File "<frozen importlib._bootstrap>", line 1360, in _find_and_load
    File "<frozen importlib._bootstrap>", line 1331, in _find_and_load_unlocked
    File "<frozen importlib._bootstrap>", line 935, in _load_unlocked
    File "<frozen importlib._bootstrap_external>", line 999, in exec_module
    File "<frozen importlib._bootstrap>", line 488, in _call_with_frames_removed
    File "[...]/pipbug.py_testdir/setup.py", line 10, in <module>
      print(f'setup.py: {platform.system()=}')
                         ^^^^^^^^^^^^^^^
  AttributeError: module 'platform' has no attribute 'system'
  error: subprocess-exited-with-error
  
  � Getting requirements to build wheel did not run successfully.
  � exit code: 1
  ��> See above for output.
  
  note: This error originates from a subprocess, and is likely not a problem with pip.
  full command: [...]/pipbug.py_venv/bin/python3 [...]/pipbug.py_venv/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/_in_process/_in_process.py get_requires_for_build_wheel /tmp/tmp1lbpiwek
  cwd: [...]/pipbug.py_testdir
  Getting requirements to build wheel: finished with status 'error'
error: subprocess-exited-with-error

� Getting requirements to build wheel did not run successfully.
� exit code: 1
��> See above for output.

note: This error originates from a subprocess, and is likely not a problem with pip.

Code of Conduct

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions