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] Generated console scripts which depend on pkgs with dots in name fail if the dep was specified in setup.py with dashes instead #3157

Closed
AndydeCleyre opened this issue Mar 7, 2022 · 3 comments
Labels
bug Needs Triage Issues that need to be evaluated for severity and status.

Comments

@AndydeCleyre
Copy link

AndydeCleyre commented Mar 7, 2022

setuptools version

60.9.3

Python version

3.9.7

OS

Pop OS Linux

Additional environment information

No response

Description

I think the issue is really that dist.key's normalization should converge dots and dashes, as they are interchangeable.

When:

  • a setup.py file specifies a "normally" dotted requirement (with a . in its name), but uses a dash instead
  • the package is installed with pip

Then:

  • the launcher exits early with an error because the deps don't match

I see in docs/pkg_resources.rst:

dist.key is short for dist.project_name.lower(). It's used for case-insensitive comparison and indexing of distributions by project name.

I think the following are relevant:

In [1]: from pip._vendor.packaging.utils import canonicalize_name, _canonicalize_regex

In [2]: canonicalize_name??
Signature: canonicalize_name(name)
Docstring: <no docstring>
Source:
def canonicalize_name(name):
    # type: (str) -> NormalizedName
    # This is taken from PEP 503.
    value = _canonicalize_regex.sub("-", name).lower()
    return cast(NormalizedName, value)
File:      /usr/share/python-wheels/packaging-20.9-py2.py3-none-any.whl/packaging/utils.py
Type:      function

In [3]: _canonicalize_regex??
Type:        Pattern
String form: re.compile('[-_.]+')
File:        /usr/lib/python3.9/re.py
Docstring:   Compiled regular expression object.

Expected behavior

I would expect the launch script to succeed, as installing ruamel.yaml (for example) is happily interchangeable with ruamel-yaml as far as pip is concerned. If one of these is installed, the requirement is truly met.

How to Reproduce

$ git clone https://github.com/laurence-kobold/1576
$ cd 1576
$ python3 -m venv venv
$ . ./venv/bin/activate
$ pip install .
$ test-with-editable-dots

Output

$ git clone https://github.com/laurence-kobold/1576
Cloning into '1576'...
remote: Enumerating objects: 19, done.
remote: Counting objects: 100% (19/19), done.
remote: Compressing objects: 100% (15/15), done.
remote: Total 19 (delta 2), reused 19 (delta 2), pack-reused 0
Receiving objects: 100% (19/19), done.
Resolving deltas: 100% (2/2), done.

$ cd 1576
$ cat setup.py
from distutils.core import setup

setup(
  name='testing_editable_dots',
  install_requires=["ruamel-yaml"],
  entry_points={
          "console_scripts": [
              "test-with-editable-dots=testing_editable_dots.main:main",
          ],
      },
)

$ python3 -m venv venv

$ . ./venv/bin/activate

$ pip install .
Processing /home/andy/ANOTHER1576/1576
Collecting ruamel-yaml
  Using cached ruamel.yaml-0.17.21-py3-none-any.whl (109 kB)
Collecting ruamel.yaml.clib>=0.2.6
  Using cached ruamel.yaml.clib-0.2.6-cp39-cp39-manylinux1_x86_64.whl (539 kB)
Using legacy 'setup.py install' for testing-editable-dots, since package 'wheel' is not installed.
Installing collected packages: ruamel.yaml.clib, ruamel-yaml, testing-editable-dots
    Running setup.py install for testing-editable-dots ... done
Successfully installed ruamel-yaml ruamel.yaml.clib-0.2.6 testing-editable-dots-0.0.0

$ test-with-editable-dots
Traceback (most recent call last):
  File "/home/andy/ANOTHER1576/1576/venv/bin/test-with-editable-dots", line 6, in <module>
    from pkg_resources import load_entry_point
  File "/home/andy/ANOTHER1576/1576/venv/lib/python3.9/site-packages/pkg_resources/__init__.py", line 3252, in <module>
    def _initialize_master_working_set():
  File "/home/andy/ANOTHER1576/1576/venv/lib/python3.9/site-packages/pkg_resources/__init__.py", line 3235, in _call_aside
    f(*args, **kwargs)
  File "/home/andy/ANOTHER1576/1576/venv/lib/python3.9/site-packages/pkg_resources/__init__.py", line 3264, in _initialize_master_working_set
    working_set = WorkingSet._build_master()
  File "/home/andy/ANOTHER1576/1576/venv/lib/python3.9/site-packages/pkg_resources/__init__.py", line 583, in _build_master
    ws.require(__requires__)
  File "/home/andy/ANOTHER1576/1576/venv/lib/python3.9/site-packages/pkg_resources/__init__.py", line 900, in require
    needed = self.resolve(parse_requirements(requirements))
  File "/home/andy/ANOTHER1576/1576/venv/lib/python3.9/site-packages/pkg_resources/__init__.py", line 786, in resolve
    raise DistributionNotFound(req, requirers)
pkg_resources.DistributionNotFound: The 'ruamel-yaml' distribution was not found and is required by testing-editable-dots

EDIT: Output of the same, in an alpine linux container:

$ test-with-editable-dots
Traceback (most recent call last):
  File "/home/dev/1576/venv/bin/test-with-editable-dots", line 33, in <module>
    sys.exit(load_entry_point('testing-editable-dots==0.0.0', 'console_scripts', 'test-with-editable-dots')())
  File "/home/dev/1576/venv/bin/test-with-editable-dots", line 25, in importlib_load_entry_point
    return next(matches).load()
  File "/usr/lib/python3.9/importlib/metadata.py", line 77, in load
    module = import_module(match.group('module'))
  File "/usr/lib/python3.9/importlib/__init__.py", line 127, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "<frozen importlib._bootstrap>", line 1030, in _gcd_import
  File "<frozen importlib._bootstrap>", line 1007, in _find_and_load
  File "<frozen importlib._bootstrap>", line 972, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 228, in _call_with_frames_removed
  File "<frozen importlib._bootstrap>", line 1030, in _gcd_import
  File "<frozen importlib._bootstrap>", line 1007, in _find_and_load
  File "<frozen importlib._bootstrap>", line 984, in _find_and_load_unlocked
ModuleNotFoundError: No module named 'testing_editable_dots'
@AndydeCleyre
Copy link
Author

AndydeCleyre commented Mar 8, 2022

Also including here a quote from PEP 503:

This PEP references the concept of a "normalized" project name. As per PEP 426 the only valid characters in a name are the ASCII alphabet, ASCII numbers, ., -, and _. The name should be lowercased with all runs of the characters ., -, or _ replaced with a single - character.

@abravalheri
Copy link
Contributor

Hi @AndydeCleyre, thanks for reporting this.

Version 62 includes the fixes in #3153 provided by @ldaniluk.
Any chance that release fixes this problem?

@AndydeCleyre
Copy link
Author

@abravalheri Thanks!

Indeed it looks like the test case above ( https://github.com/laurence-kobold/1576 ) now succeeds when installed with the latest setuptools.

Thanks very much @ldaniluk !

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

2 participants