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] TypeError: canonicalize_version() got an unexpected keyword argument 'strip_trailing_zero' #4483

Closed
tim-s-ccs opened this issue Jul 18, 2024 · 36 comments

Comments

@tim-s-ccs
Copy link

setuptools version

setuptools>=71.0.0

Python version

Python 3.12

OS

Ubuntu

Additional environment information

I found this bug when running the test for the project in GitHub actions

Description

When I install the requirements in my Python package project (pip-sync requirements-dev.txt) I get an error within setuptools which says:

Preparing metadata (setup.py) ... error
error: subprocess-exited-with-error

× python setup.py egg_info did not run successfully.
...
TypeError: canonicalize_version() got an unexpected keyword argument 'strip_trailing_zero'

This error was caused by using setuptools >= 71.0.0

Not to speculate but it looks like the issue was introduced by this commit in setuptools: 00384a5

And this commit is including new changes from the packaging project and its this commit here where we can see the issue:
pypa/packaging@cc938f9
https://github.com/pypa/packaging/blame/4493dfcd95a893f676a7aa4bd17c547bea676371/src/packaging/utils.py#L58

Expected behavior

I would expect pip-sync requirements-dev.txt to run successfully

How to Reproduce

Clone https://github.com/tim-s-ccs/example-python-package.git
Make sure you are using Python 3.12 and you have pip-tools installed (pip install --upgrade pip wheel pip-tools)
Make sure you are using the correct version of setuptools pip install --upgrade setuptools==71.0.0
Run pip-compile requirements-dev.in

Output

    error: subprocess-exited-with-error
    
    × python setup.py egg_info did not run successfully.
    │ exit code: 1
    ╰─> [42 lines of output]
        running egg_info
        creating /private/var/folders/kt/n16_msf56_z3kfyb65l37wxhb_m4s_/T/pip-pip-egg-info-3sca_19y/example_python_package.egg-info
        writing /private/var/folders/kt/n16_msf56_z3kfyb65l37wxhb_m4s_/T/pip-pip-egg-info-3sca_19y/example_python_package.egg-info/PKG-INFO
        writing dependency_links to /private/var/folders/kt/n16_msf56_z3kfyb65l37wxhb_m4s_/T/pip-pip-egg-info-3sca_19y/example_python_package.egg-info/dependency_links.txt
        writing top-level names to /private/var/folders/kt/n16_msf56_z3kfyb65l37wxhb_m4s_/T/pip-pip-egg-info-3sca_19y/example_python_package.egg-info/top_level.txt
        writing manifest file '/private/var/folders/kt/n16_msf56_z3kfyb65l37wxhb_m4s_/T/pip-pip-egg-info-3sca_19y/example_python_package.egg-info/SOURCES.txt'
        reading manifest file '/private/var/folders/kt/n16_msf56_z3kfyb65l37wxhb_m4s_/T/pip-pip-egg-info-3sca_19y/example_python_package.egg-info/SOURCES.txt'
        Traceback (most recent call last):
          File "<string>", line 2, in <module>
          File "<pip-setuptools-caller>", line 34, in <module>
          File "/Users/my.name/Code/test/example-python-package/setup.py", line 16, in <module>
            setup(
          File "/Users/my.name/.pyenv/versions/3.12.2/lib/python3.12/site-packages/setuptools/__init__.py", line 106, in setup
            return distutils.core.setup(**attrs)
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
          File "/Users/my.name/.pyenv/versions/3.12.2/lib/python3.12/site-packages/setuptools/_distutils/core.py", line 184, in setup
            return run_commands(dist)
                   ^^^^^^^^^^^^^^^^^^
          File "/Users/my.name/.pyenv/versions/3.12.2/lib/python3.12/site-packages/setuptools/_distutils/core.py", line 200, in run_commands
            dist.run_commands()
          File "/Users/my.name/.pyenv/versions/3.12.2/lib/python3.12/site-packages/setuptools/_distutils/dist.py", line 970, in run_commands
            self.run_command(cmd)
          File "/Users/my.name/.pyenv/versions/3.12.2/lib/python3.12/site-packages/setuptools/dist.py", line 974, in run_command
            super().run_command(command)
          File "/Users/my.name/.pyenv/versions/3.12.2/lib/python3.12/site-packages/setuptools/_distutils/dist.py", line 989, in run_command
            cmd_obj.run()
          File "/Users/my.name/.pyenv/versions/3.12.2/lib/python3.12/site-packages/setuptools/command/egg_info.py", line 321, in run
            self.find_sources()
          File "/Users/my.name/.pyenv/versions/3.12.2/lib/python3.12/site-packages/setuptools/command/egg_info.py", line 329, in find_sources
            mm.run()
          File "/Users/my.name/.pyenv/versions/3.12.2/lib/python3.12/site-packages/setuptools/command/egg_info.py", line 555, in run
            self.prune_file_list()
          File "/Users/my.name/.pyenv/versions/3.12.2/lib/python3.12/site-packages/setuptools/command/egg_info.py", line 621, in prune_file_list
            base_dir = self.distribution.get_fullname()
                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
          File "/Users/my.name/.pyenv/versions/3.12.2/lib/python3.12/site-packages/setuptools/_core_metadata.py", line 266, in get_fullname
            return _distribution_fullname(self.get_name(), self.get_version())
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
          File "/Users/my.name/.pyenv/versions/3.12.2/lib/python3.12/site-packages/setuptools/_core_metadata.py", line 284, in _distribution_fullname
            canonicalize_version(version, strip_trailing_zero=False),
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        TypeError: canonicalize_version() got an unexpected keyword argument 'strip_trailing_zero'
        [end of output]
    
    note: This error originates from a subprocess, and is likely not a problem with pip.
Traceback (most recent call last):
  File "/Users/my.name/.pyenv/versions/3.12.2/lib/python3.12/site-packages/pip/_internal/operations/build/metadata_legacy.py", line 64, in generate_metadata
    call_subprocess(
  File "/Users/my.name/.pyenv/versions/3.12.2/lib/python3.12/site-packages/pip/_internal/utils/subprocess.py", line 209, in call_subprocess
    raise error
pip._internal.exceptions.InstallationSubprocessError: python setup.py egg_info exited with 1

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/Users/my.name/.pyenv/versions/3.12.2/bin/pip-compile", line 8, in <module>
    sys.exit(cli())
             ^^^^^
  File "/Users/my.name/.pyenv/versions/3.12.2/lib/python3.12/site-packages/click/core.py", line 1157, in __call__
    return self.main(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/my.name/.pyenv/versions/3.12.2/lib/python3.12/site-packages/click/core.py", line 1078, in main
    rv = self.invoke(ctx)
         ^^^^^^^^^^^^^^^^
  File "/Users/my.name/.pyenv/versions/3.12.2/lib/python3.12/site-packages/click/core.py", line 1434, in invoke
    return ctx.invoke(self.callback, **ctx.params)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/my.name/.pyenv/versions/3.12.2/lib/python3.12/site-packages/click/core.py", line 783, in invoke
    return __callback(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/my.name/.pyenv/versions/3.12.2/lib/python3.12/site-packages/click/decorators.py", line 33, in new_func
    return f(get_current_context(), *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/my.name/.pyenv/versions/3.12.2/lib/python3.12/site-packages/piptools/scripts/compile.py", line 470, in cli
    results = resolver.resolve(max_rounds=max_rounds)
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/my.name/.pyenv/versions/3.12.2/lib/python3.12/site-packages/piptools/resolver.py", line 604, in resolve
    is_resolved = self._do_resolve(
                  ^^^^^^^^^^^^^^^^^
  File "/Users/my.name/.pyenv/versions/3.12.2/lib/python3.12/site-packages/piptools/resolver.py", line 636, in _do_resolve
    resolver.resolve(
  File "/Users/my.name/.pyenv/versions/3.12.2/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/resolver.py", line 76, in resolve
    collected = self.factory.collect_root_requirements(root_reqs)
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/my.name/.pyenv/versions/3.12.2/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/factory.py", line 538, in collect_root_requirements
    reqs = list(
           ^^^^^
  File "/Users/my.name/.pyenv/versions/3.12.2/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/factory.py", line 494, in _make_requirements_from_install_req
    cand = self._make_base_candidate_from_link(
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/my.name/.pyenv/versions/3.12.2/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/factory.py", line 210, in _make_base_candidate_from_link
    self._editable_candidate_cache[link] = EditableCandidate(
                                           ^^^^^^^^^^^^^^^^^^
  File "/Users/my.name/.pyenv/versions/3.12.2/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/candidates.py", line 328, in __init__
    super().__init__(
  File "/Users/my.name/.pyenv/versions/3.12.2/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/candidates.py", line 158, in __init__
    self.dist = self._prepare()
                ^^^^^^^^^^^^^^^
  File "/Users/my.name/.pyenv/versions/3.12.2/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/candidates.py", line 235, in _prepare
    dist = self._prepare_distribution()
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/my.name/.pyenv/versions/3.12.2/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/candidates.py", line 338, in _prepare_distribution
    return self._factory.preparer.prepare_editable_requirement(self._ireq)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/my.name/.pyenv/versions/3.12.2/lib/python3.12/site-packages/pip/_internal/operations/prepare.py", line 698, in prepare_editable_requirement
    dist = _get_prepared_distribution(
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/my.name/.pyenv/versions/3.12.2/lib/python3.12/site-packages/pip/_internal/operations/prepare.py", line 72, in _get_prepared_distribution
    abstract_dist.prepare_distribution_metadata(
  File "/Users/my.name/.pyenv/versions/3.12.2/lib/python3.12/site-packages/pip/_internal/distributions/sdist.py", line 69, in prepare_distribution_metadata
    self.req.prepare_metadata()
  File "/Users/my.name/.pyenv/versions/3.12.2/lib/python3.12/site-packages/pip/_internal/req/req_install.py", line 580, in prepare_metadata
    self.metadata_directory = generate_metadata_legacy(
                              ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/my.name/.pyenv/versions/3.12.2/lib/python3.12/site-packages/pip/_internal/operations/build/metadata_legacy.py", line 71, in generate_metadata
    raise MetadataGenerationFailed(package_details=details) from error
pip._internal.exceptions.MetadataGenerationFailed: metadata generation failed
@tim-s-ccs tim-s-ccs added bug Needs Triage Issues that need to be evaluated for severity and status. labels Jul 18, 2024
@Kaflak
Copy link

Kaflak commented Jul 18, 2024

Issue is visible when you use packaging<22.0

@tonythomas01
Copy link

Could reproduce the same issue. Fixed by downgrading to 70.x

@Kaflak
Copy link

Kaflak commented Jul 18, 2024

Also it can be fixed by update packaging to 22.0 or higher

@jaraco
Copy link
Member

jaraco commented Jul 18, 2024

This behavior is by design. Similar to the issue reported in #4478, the new Setuptools 71 will prefer installed dependencies over the vendored ones. You'll want to either uninstall the older (incompatible) dependencies from the environment or install these dependencies. You may be tempted to install setuptools[core], but please avoid doing that as core is an internal implementation detail.

@mikealfare
Copy link

This behavior is by design. Similar to the issue reported in #4478, the new Setuptools 71 will prefer installed dependencies over the vendored ones. You'll want to either uninstall the older (incompatible) dependencies from the environment or install these dependencies. You may be tempted to install setuptools[core], but please avoid doing that as core is an internal implementation detail.

Just to confirm, we're seeing this happen in this environment:

python -m pip install --upgrade pip
python -m pip install --upgrade setuptools wheel twine check-wheel-contents

Is that correct? It sounds like you're saying the issue is old dependencies existing in the environment, but we should have the most current packages here.

@tim-s-ccs
Copy link
Author

Thanks @jaraco this was helpful. In my project where I was having the issue because on older version of packaging was a dependancy (not compatible with setuptools v71.0.0 or maybe earlier). Updating that dependancy did indeed fix the issue.

It's a bit annoying that the behaviour of setuptools changed which messed up my tests (which gets the latest version of setuptools when setting up) but that is very much my fault and not your teams.

Again, thanks for your comment as it helped my to understand the issue better and what the cause was.


For anyone who has a situation like me where my tests just started failing I'd check to make sure your dependancies and the dependancies of setuptools are compatible.

@mikealfare
Copy link

Thanks @jaraco this was helpful. In my project where I was having the issue because on older version of packaging was a dependancy (not compatible with setuptools v71.0.0 or maybe earlier). Updating that dependancy did indeed fix the issue.

It's a bit annoying that the behaviour of setuptools changed which messed up my tests (which gets the latest version of setuptools when setting up) but that is very much my fault and not your teams.

Again, thanks for your comment as it helped my to understand the issue better and what the cause was.

For anyone who has a situation like me where my tests just started failing I'd check to make sure your dependancies and the dependancies of setuptools are compatible.

Thanks for posting your solution. I'm trying to reason through how we're running into the same issue. We're not specifying packaging anywhere, so I would assume we would get the most current version. And when I install locally, I get the same version of packaging you specify in your PR. Perhaps the CI image I'm using already has packaging installed, but with an older version? I'll investigate and post back if I find something. But it would definitely be a sharp corner if pip install --upgrade setuptools no longer works on ubuntu-latest.

webknjaz added a commit to webknjaz/ansible that referenced this issue Jul 18, 2024
This is now necessary since `setuptools >= 71` started preferring
externally present stdlib deps over the vendored ones.

Refs:
* pypa/setuptools#4457
* pypa/setuptools#4483
* pypa/setuptools#2825
@jaraco
Copy link
Member

jaraco commented Jul 18, 2024

Perhaps the CI image I'm using already has packaging installed, but with an older version?

Yes, probably.

Thanks for posting your solution. I'm trying to reason through how we're running into the same issue. We're not specifying packaging anywhere, so I would assume we would get the most current version. And when I install locally, I get the same version of packaging you specify in your PR. Perhaps the CI image I'm using already has packaging installed, but with an older version? I'll investigate and post back if I find something. But it would definitely be a sharp corner if pip install --upgrade setuptools no longer works on ubuntu-latest.

Agreed, it is a bit of a sharp corner, and we made the major release as a signal of this shift in expectations. The issue is that while you're holding it correctly and pip install -U setuptools should theoretically upgrade all the required dependencies, it cannot currently due to the bootstrapping problem. I'm actively working on solving that issue, but in the meantime, one needs to pip install -U setuptools[core] to prepare an environment safely.

You may be tempted to install setuptools[core], but please avoid doing that as core is an internal implementation detail.

I think I may have been too cautious about this advice. We specifically want to avoid packages themselves making this declaration in build-requires. I believe it's safe to use in systems integration tooling.

@mikealfare
Copy link

@jaraco Thanks for taking the time to respond. This advice is super useful:

You may be tempted to install setuptools[core], but please avoid doing that as core is an internal implementation detail.

I think I may have been too cautious about this advice. We specifically want to avoid packages themselves making this declaration in build-requires. I believe it's safe to use in systems integration tooling.

The issue that we wound up running into is that older versions of our package actually take a runtime dependency on packaging. Upon verifying the package (by installing it), the version of packaging was getting clobbered. This was only causing an issue for the sdist, and not the wheel.

dtm2451 added a commit to mountetna/monoetna that referenced this issue Oct 9, 2024
openstack-mirroring pushed a commit to openstack/placement that referenced this issue Oct 19, 2024
py39 jobs (on ubuntu-focal) started to fail due to recent virtualenv
release (20.26.4) on Yoga (which bundles setuptools), because we have
'packaging==21.3' in this branch that is not compatible with newer
setuptools [1].

setuptools is bundled in virtualenv, so it has to be capped via the
virtualenv package. tox also needed to be capped (<4) as gate uses
tox 3.28.0, but with capping virtualenv we pull in latest tox as well,
which would cause other errors.

[1] pypa/setuptools#4483

Change-Id: Icd7a5e7bb0941513e7ab5a778ee3811740f38028
openstack-mirroring pushed a commit to openstack/trove that referenced this issue Oct 21, 2024
py38 jobs (on ubuntu-focal) started to fail due to recent virtualenv
release (20.26.4) on Yoga (which bundles setuptools), because we have
'packaging==21.3' in this branch that is not compatible with newer
setuptools [1].

setuptools is bundled in virtualenv, so it has to be capped via the
virtualenv package. Note, that we also have to cap it explicitly,
otherwise tox somehow pulls in latest setuptools.

[1] pypa/setuptools#4483

Change-Id: Id9e02f8b26bad5e2ef74908012de0b81898c04d0
openstack-mirroring pushed a commit to openstack/placement that referenced this issue Oct 21, 2024
py39 jobs (on ubuntu-focal) started to fail due to recent virtualenv
release (20.26.4) on Yoga (which bundles setuptools), because we have
'packaging==21.3' in this branch that is not compatible with newer
setuptools [1].

setuptools is bundled in virtualenv, so it has to be capped via the
virtualenv package. tox also needed to be capped (<4) as gate uses
tox 3.28.0, but with capping virtualenv we pull in latest tox as well,
which would cause other errors.

[1] pypa/setuptools#4483

Change-Id: Icd7a5e7bb0941513e7ab5a778ee3811740f38028
(cherry picked from commit 9bc2b3c)
openstack-mirroring pushed a commit to openstack/horizon that referenced this issue Oct 21, 2024
py39 jobs (on ubuntu-focal) started to fail due to recent virtualenv
release (20.26.4) on Yoga (which bundles setuptools), because we have
'packaging==21.3' in this branch that is not compatible with newer
setuptools [1].

setuptools is bundled in virtualenv, so it has to be capped via the
virtualenv package. tox also needed to be capped (<4) as gate uses
tox 3.28.0, but with capping virtualenv we pull in latest tox as well,
which would cause other errors.

[1] pypa/setuptools#4483

Change-Id: I294f6715c41fd1651e92f41c6601880c19f442a7
@ArslanKAS
Copy link

Quote reply

Could reproduce the same issue. Fixed by downgrading to 70.x

You save me!!! all you need to do is upgrade to setuptools==70.0.0. Don't try > 74 or less than 70. None of them can work!!! Packaging I use is 24.1.

For me: pip3.10 install --upgrade setuptools==70.0.0

You can use: pip install --upgrade setuptools==70.0.0

Thanks it worked

@NorseGaud
Copy link

Why do I need to downgrade to 70.0.0? This is nuts...

@jvaehsen-deloitte
Copy link

Why do I need to downgrade to 70.0.0? This is nuts...

did you try this?
#4483 (comment)

@mauvilsa
Copy link

Downgrading setuptools or adding packaging with a specific version as a dependency are both weird. The docs just say that people need to add setuptools as a build dependency, nothing about packaging. If setuptools depends on packaging, and it is incompatible with older versions of packaging, then "packaging>=MIN_VERSION" should be a required dependency of setuptools, not in a core optional dependency recommended to not be used.

@jaraco how is this behavior "by design"? What I see in the docs does not help.

leust pushed a commit to sapcc/requirements that referenced this issue Oct 30, 2024
A recent release of setuptools breaks when packaging is <22.0 [0].
Because we can't reliably pin setuptools in the real world (we expect
people to simple create a venv and pip install from there (with our
without tools like tox) we update our stable constraint to 23.1 to match
stable/2023.2 in order to get things working again.

[0] pypa/setuptools#4483

Change-Id: If75a86941b636580b5220f9ea5fa80a12d1bf2e6
dupondje added a commit to teamdotblue/vdsm that referenced this issue Nov 7, 2024
There is an incompatibility between packaging version from CentOS and
setuptools from pip. Which causes a failure running the tests:
TypeError: canonicalize_version() got an unexpected keyword argument 'strip_trailing_zero'

See also pypa/setuptools#4483

Fix this by using a the current packaging version instead of the CentOS
packaged one.

Signed-off-by: Jean-Louis Dupond <[email protected]>
dupondje added a commit to teamdotblue/vdsm that referenced this issue Nov 7, 2024
There is an incompatibility between packaging version from CentOS and
setuptools from pip. Which causes a failure running the tests:
TypeError: canonicalize_version() got an unexpected keyword argument 'strip_trailing_zero'

See also pypa/setuptools#4483

Fix this by using a the current packaging version instead of the CentOS
packaged one.

Signed-off-by: Jean-Louis Dupond <[email protected]>
bahill added a commit to DataBiosphere/hca-ingest that referenced this issue Nov 8, 2024
sandrobonazzola pushed a commit to oVirt/vdsm that referenced this issue Nov 19, 2024
There is an incompatibility between packaging version from CentOS and
setuptools from pip. Which causes a failure running the tests:
TypeError: canonicalize_version() got an unexpected keyword argument 'strip_trailing_zero'

See also pypa/setuptools#4483

Fix this by using a the current packaging version instead of the CentOS
packaged one.

Signed-off-by: Jean-Louis Dupond <[email protected]>
@leikoilja
Copy link

I was constantly getting the same error on a previously working Jupiter Notebook with python 3.10 no matter what dependencies I was trying to change.
Turns out my conda environment was enforcing broken versions of setuptools and packaging.
Changed the entire conda env to run python 3.12 and the issue went away ✅

@jaraco
Copy link
Member

jaraco commented Nov 23, 2024

@jaraco how is this behavior "by design"?

  • Setuptools wishes to use a standards-based canonicalization of the version number.
  • The best available standards-based implementation of canonicalize_version is in the packaging module.
  • Setuptools therefore is declaring its dependency on a compatible version of packaging.
  • Due to bootstrapping problems in the ecosystem, setuptools cannot declare dependencies on anything that's built by Setuptools or which has dependencies that are built by setuptools.

(aside) Now that I write (4), I realize that packaging uses flit-core, so maybe it's viable to move that dependency (and others that aren't affected by the bootstrapping problem) to required dependencies and not optional.

When I say it's by design, I mean I'm unaware of any other design that meets Setuptools stated goal to be able to follow standard dependency practices and declare dependencies on any packages it requires. This goal is something I've been working on for years.

I recognize and sympathize with the downstream effects of this transition, but I have to say, I'm really appreciating the progress this project has made toward having a simpler and more manageable vendoring strategy and possibly eventually removing the need for vendoring altogether.

I'm open to suggestions, but "just bundle everything all the time" is a regression in the design and a non-starter. What is your suggestion?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests