setuptools: python setup.py develop fails with `version = attr: pkg.__version__` in setup.cfg
See also https://github.com/pypa/pip/issues/6350
When a package has version = attr: pkg.__version__
in its setup.cfg
file, python setup.py develop
can fail with a ModuleNotFoundError
if not all runtime dependencies have been installed yet.
I’ve created a minimal repo to reproduce the error: https://github.com/kohr-h/minimal
Reproducing the error:
- Create a fresh environment with
python
inside, but withoutnumpy
(our example dependency) - Run
python setup.py develop
in the repo root
Workaround:
- Install
numpy
as well - Now
python setup.py develop
succeeds
Traceback
Traceback (most recent call last):
File "setup.py", line 3, in <module>
setup()
File "/home/hkohr/miniconda/envs/tmp/lib/python3.7/site-packages/setuptools/__init__.py", line 145, in setup
return distutils.core.setup(**attrs)
File "/home/hkohr/miniconda/envs/tmp/lib/python3.7/distutils/core.py", line 121, in setup
dist.parse_config_files()
File "/home/hkohr/miniconda/envs/tmp/lib/python3.7/site-packages/setuptools/dist.py", line 705, in parse_config_files
ignore_option_errors=ignore_option_errors)
File "/home/hkohr/miniconda/envs/tmp/lib/python3.7/site-packages/setuptools/config.py", line 120, in parse_configuration
meta.parse()
File "/home/hkohr/miniconda/envs/tmp/lib/python3.7/site-packages/setuptools/config.py", line 425, in parse
section_parser_method(section_options)
File "/home/hkohr/miniconda/envs/tmp/lib/python3.7/site-packages/setuptools/config.py", line 398, in parse_section
self[name] = value
File "/home/hkohr/miniconda/envs/tmp/lib/python3.7/site-packages/setuptools/config.py", line 183, in __setitem__
value = parser(value)
File "/home/hkohr/miniconda/envs/tmp/lib/python3.7/site-packages/setuptools/config.py", line 513, in _parse_version
version = self._parse_attr(value, self.package_dir)
File "/home/hkohr/miniconda/envs/tmp/lib/python3.7/site-packages/setuptools/config.py", line 348, in _parse_attr
module = import_module(module_name)
File "/home/hkohr/miniconda/envs/tmp/lib/python3.7/importlib/__init__.py", line 127, in import_module
return _bootstrap._gcd_import(name[level:], package, level)
File "<frozen importlib._bootstrap>", line 1006, in _gcd_import
File "<frozen importlib._bootstrap>", line 983, in _find_and_load
File "<frozen importlib._bootstrap>", line 967, in _find_and_load_unlocked
File "<frozen importlib._bootstrap>", line 677, in _load_unlocked
File "<frozen importlib._bootstrap_external>", line 728, in exec_module
File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
File "/home/hkohr/git/minimal/minimal/__init__.py", line 2, in <module>
from . import mod
File "/home/hkohr/git/minimal/minimal/mod.py", line 1, in <module>
import numpy
ModuleNotFoundError: No module named 'numpy'
I wonder whether this can be fixed elegantly and does not sit too deep.
About this issue
- Original URL
- State: closed
- Created 5 years ago
- Reactions: 2
- Comments: 16 (2 by maintainers)
Links to this issue
Commits related to this issue
- Don't rely on attr: hydep.__version__ in setup.cfg Very nice feature, but causes problems with fresh installs. Essentially causes the package to be imported, which trickles down to a numpy and/or sci... — committed to CORE-GATECH-GROUP/hydep by deleted user 4 years ago
- Remove version See https://github.com/pypa/setuptools/issues/1724 — committed to voanhduy1512/eks-rolling-update by deleted user 3 years ago
- Fix poor setuptools behavior for parsing module version setuptools >= 46.4.0 has rudimentary AST analysis for attr: balsam.__version to work without importing balsam (and hence possibly failing due t... — committed to felker/balsam by felker 3 years ago
- Add CI using GitHub workflows. Fix for __version__: see https://github.com/pypa/setuptools/issues/1724#issuecomment-700736641 — committed to jaemolihm/wannier-berri by jaemolihm 3 years ago
- Add CI using GitHub workflows. Fix for __version__: see https://github.com/pypa/setuptools/issues/1724#issuecomment-700736641 — committed to jaemolihm/wannier-berri by jaemolihm 3 years ago
- Fixing ordering dependency importing version number Addressing problem caused by https://github.com/pypa/setuptools/issues/1724 Accessing the version attribute could cause odd dependencies on import ... — committed to GardenTools/CrcEngine by GardenTools 3 years ago
- Add version info (reference: https://github.com/pypa/setuptools/issues/1724#issuecomment-627241822 and https://stackoverflow.com/a/16084844/13115170) — committed to jakob-bagterp/timer-for-python by jakob-bagterp 3 years ago
- Trying to get the version in setup.cfg causes a failure with pip install -e . This is because setuptools tries to import the msticpy package before dependencies are fully installed. See https://githu... — committed to microsoft/msticpy by ianhelle 2 years ago
- Setup.cfg and Pyproject.toml (#287) * Moving most setup config to setup.cfg Extras couldn't be moved there since we have multiple overlapping extra groups. Updated import_analyzer.py to avoid cre... — committed to microsoft/msticpy by ianhelle 2 years ago
- Setup.cfg and Pyproject.toml (#287) * Moving most setup config to setup.cfg Extras couldn't be moved there since we have multiple overlapping extra groups. Updated import_analyzer.py to avoid cre... — committed to juju4/msticpy by ianhelle 2 years ago
- Try changing attr path https://github.com/pypa/setuptools/issues/1724 — committed to open2c/cooler by nvictus a year ago
- Migrate setup.py completely to pyproject.toml (#306) * Migrate setup.py completely to pyproject.toml * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre... — committed to open2c/cooler by nvictus a year ago
- Add CI using GitHub workflows. Fix for __version__: see https://github.com/pypa/setuptools/issues/1724#issuecomment-700736641 — committed to wannier-berri/wannier-berri by jaemolihm 3 years ago
Yes, though one small correction - those two conditions need a boolean-AND, not or 😃. I’m going to venture that 90% of packages that declare a simple one-liner in a module outside of
__init__.py
turn around and try to import that into__init__.py
so that they can bring it directly under the package namespace.Example:
Then:
Breaks with:
whereas removing the
flask
import in__init__.py
(and optionally dropping frominstall_requires
) succeeds, verifiable withpython3 -c 'import package_a; print(package_a.__version__)'
.For future reference, I managed to work around this error by using
attr: pkg.__init__.__version__
instead ofattr: pkg.__version__
.Right - I am probably glossing over some details from https://github.com/pypa/setuptools/pull/1753, but that changelog entries reads as if this was the exact situation that is avoided by the ast-based finder.
The problem here appears to be that
setuptools
tries to load the “parent module” before AST - analyzing_version.py
. Not sure why it needs to do that.Moving it to
__init__.py
seems to work, however:As far as I know, the
attr
also allows specification of a specific module rather than using the package name (implicitly__init__.py
)Working example from @pganssle 's own:
https://github.com/pganssle/zoneinfo/blob/ceea631bea8d68662c6661f9027b98eede209790/setup.cfg#L3
But perhaps that’s because
zoneinfo
has no third-party deps.Confused here, since setuptools docs read:
Does that not apply to
pip install [-e] .
? Perhaps that should be a disclaimer, since @greschd 's band-aid works; if you have:Where
_version.py
defines__version__ == '1.0.0'
and that is imported into__init.py__
after any third-party imports, then setup will fail, but placing the import before any third-party deps makes it work. Isn’t the point of the AST approach to avoid things like this?@pganssle Thanks a lot for your detailed reply. I understand that the issue sits too deep and would require too far-reaching changes to be resolved. I would have loved to use
setuptools_scm
, but since our release branches are stale, that tool infers the wrong version. Instead, I’ll probably go for a hand-writtenVERSION
text file that is included asin
setup.cfg
(withsetuptools >=39.2
), and read as string in the package__init__.py
.I’ll close the issue.