Open
Description
- a detailed description of the bug or problem you are having
Prior to 8.1.2 the following statement executed without raising an exception (8.0.2) in the setuptools CI, but now it started failing (8.1.2):
def test_get_output_mapping_with_stub(self, tmpdir_cwd, monkeypatch):
monkeypatch.setenv('SETUPTOOLS_EXT_SUFFIX', '.mp3') # make test OS-independent
> monkeypatch.setattr('setuptools.command.build_ext.use_stubs', True)
/home/runner/work/setuptools/setuptools/setuptools/tests/test_build_ext.py:141
The error message does not make much sense to me:
obj = <module 'setuptools.command' from '/home/runner/work/setuptools/setuptools/setuptools/command/__init__.py'>
name = 'build_ext', ann = 'setuptools.command.build_ext'
def annotated_getattr(obj: object, name: str, ann: str) -> object:
try:
> obj = getattr(obj, name)
E AttributeError: module 'setuptools.command' has no attribute 'build_ext'
/home/runner/work/setuptools/setuptools/.tox/py/lib/python3.11/site-packages/_pytest/monkeypatch.py:91: AttributeError
The above exception was the direct cause of the following exception:
self = <setuptools.tests.test_build_ext.TestBuildExt object at 0x7f41b3f86a50>
tmpdir_cwd = local('/home/runner/work/setuptools/setuptools')
monkeypatch = <_pytest.monkeypatch.MonkeyPatch object at 0x7f41b1dfe5d0>
def test_get_outputs(self, tmpdir_cwd, monkeypatch):
monkeypatch.setenv('SETUPTOOLS_EXT_SUFFIX', '.mp3') # make test OS-independent
> monkeypatch.setattr('setuptools.command.build_ext.use_stubs', False)
/home/runner/work/setuptools/setuptools/setuptools/tests/test_build_ext.py:109:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
/home/runner/work/setuptools/setuptools/.tox/py/lib/python3.11/site-packages/_pytest/monkeypatch.py:103: in derive_importpath
target = resolve(module)
/home/runner/work/setuptools/setuptools/.tox/py/lib/python3.11/site-packages/_pytest/monkeypatch.py:[85](https://github.com/pypa/setuptools/actions/runs/8853717171/job/24315188999#step:9:86): in resolve
found = annotated_getattr(found, part, used)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
obj = <module 'setuptools.command' from '/home/runner/work/setuptools/setuptools/setuptools/command/__init__.py'>
name = 'build_ext', ann = 'setuptools.command.build_ext'
def annotated_getattr(obj: object, name: str, ann: str) -> object:
try:
obj = getattr(obj, name)
except AttributeError as e:
> raise AttributeError(
f"{type(obj).__name__!r} object at {ann} has no attribute {name!r}"
) from e
E AttributeError: 'module' object at setuptools.command.build_ext has no attribute 'build_ext'
/home/runner/work/setuptools/setuptools/.tox/py/lib/python3.11/site-packages/_pytest/monkeypatch.py:[93](https://github.com/pypa/setuptools/actions/runs/8853717171/job/24315188999#step:9:94): AttributeError
Because:
setuptools.command.build_ext
is defined as a module, not an attribute ofsetuptools.command
setuptools.command.build_ext
module does define abuild_ext
class. But alsosetuptools.command.build_ext.build_ext
should have nothing to do with monkeypatchingsetuptools.command.build_ext.use_stubs
...
In the same workflow run, we also have other similar errors (e.g. AttributeError: module 'setuptools.command' has no attribute 'build_clib'
)
- [x] output of `pip list` from the virtual environment you are using
alabaster==0.7.16
attrs==23.2.0
autocommand==2.2.2
Babel==2.14.0
backports.tarfile==1.1.1
build==1.2.1
cachetools==5.3.3
certifi==2024.2.2
cffi==1.16.0
chardet==5.2.0
charset-normalizer==3.3.2
colorama==0.4.6
ConfigUpdater==3.2
coverage==7.5.0
cryptography==42.0.5
distlib==0.3.8
docutils==0.21.2
domdf-python-tools==3.8.0.post2
execnet==2.1.1
filelock==3.13.4
idna==3.7
imagesize==1.4.1
importlib_metadata==7.1.0
importlib_resources==6.4.0
inflect==7.2.1
ini2toml==0.14
iniconfig==2.0.0
jaraco.classes==3.4.0
jaraco.context==5.3.0
jaraco.develop==8.13.0
jaraco.env==1.0.0
jaraco.envs==2.6.0
jaraco.functools==4.0.1
jaraco.packaging==10.1.0
jaraco.path==3.7.0
jaraco.text==3.12.0
jaraco.ui==2.3.0
jaraco.vcs==2.2.0
jaraco.versioning==1.1.0
jeepney==0.8.0
Jinja2==3.1.3
keyring==25.2.0
MarkupSafe==2.1.5
more-itertools==10.2.0
mypy==1.9.0
mypy-extensions==1.0.0
natsort==8.4.0
packaging==24.0
path==16.14.0
pip==24.0
pip-run==12.6.1
platformdirs==4.2.1
pluggy==1.5.0
pycparser==2.22
Pygments==2.17.2
PyNaCl==1.5.0
pyproject-api==1.6.1
pyproject_hooks==1.0.0
pytest==8.1.2
pytest-checkdocs==2.12.0
pytest-cov==5.0.0
pytest-enabler==3.1.1
pytest-home==0.5.1
pytest-mypy==0.10.3
pytest-perf==0.14.0
pytest-ruff==0.3.1
pytest-timeout==2.3.1
pytest-xdist==3.5.0
python-dateutil==2.9.0.post0
pytz==2024.1
requests==2.31.0
requests-file==2.0.0
requests-toolbelt==1.0.0
ruff==0.4.2
SecretStorage==3.3.3
setuptools @ file:///home/runner/work/setuptools/setuptools/.tox/.tmp/package/1/setuptools-69.5.1.post20240426-0.editable-py3-none-any.whl#sha256=c45586b1cbdcef78ac5a07ff798e095fc4a634e8f28286d1144ed343e1f94bd2
six==1.16.0
snowballstemmer==2.2.0
Sphinx==7.3.7
sphinxcontrib-applehelp==1.0.8
sphinxcontrib-devhelp==1.0.6
sphinxcontrib-htmlhelp==2.0.5
sphinxcontrib-jsmath==1.0.1
sphinxcontrib-qthelp==1.0.7
sphinxcontrib-serializinghtml==1.1.10
subprocess-tee==0.4.1
tempora==5.5.1
toml==0.10.2
tomli==2.0.1
tomli_w==1.0.0
tomlkit==0.12.4
tox==4.15.0
typeguard==4.2.1
typing_extensions==4.11.0
urllib3==2.2.1
virtualenv==20.26.0
wheel==0.43.0
zipp==3.18.1
- pytest and operating system versions
ubuntu-latest (Github Actions) - Ubuntu 22.04 LTS
CPython 3.11.9
pytest==8.1.2
pytest-checkdocs==2.12.0
pytest-cov==5.0.0
pytest-enabler==3.1.1
pytest-home==0.5.1
pytest-mypy==0.10.3
pytest-perf==0.14.0
pytest-ruff==0.3.1
pytest-timeout==2.3.1
pytest-xdist==3.5.0
- minimal example if possible
Unfortunately I was not able to simplify the reproducer.
I tried to create a minimal example with monkeypatch
and nested modules but all works fine:
docker run --rm -it python:3.11-bookworm /bin/bash
cd /tmp
python3 -m venv .venv
.venv/bin/python -m pip install 'pytest==8.1.2'
mkdir -p pkg/a/b
cat <<EOF > pkg/a/b/__init__.py
def f():
from . import c
return c.y()
EOF
cat <<EOF > pkg/a/b/c.py
x = 37
def y(): return x
EOF
cat <<EOF > test_monkeypatch.py
from pkg.a import b
def test_monkeypatch(monkeypatch):
monkeypatch.setattr('pkg.a.b.c.x', 42)
assert b.f() == 42
EOF
.venv/bin/pytest test_monkeypatch.py # ==> this works fine...