pypa / setuptools

Official project repository for the Setuptools build system
https://pypi.org/project/setuptools/
MIT License
2.47k stars 1.18k forks source link

[BUG] Package names with `/` cause unexpected behaviour and unhelpful exceptions #2917

Closed da1910 closed 1 month ago

da1910 commented 2 years ago

setuptools version

56.0.0

Python version

Python 3.8.10

OS

Windows 11

Additional environment information

Encountered via tox, which invokes build and eventually runs a sdist install via setuptools

Description

If you provide a package name in a setup.cfg file like "foo/bar" and you optionally pass the --sdist argument the build will fail with rather unhelpful error output.

It looks as though distutils treats the package name as a string and creates the tar filename from that string, whereas setuptools expects to find a tar file with the name {package_name}.tar.gz.

With more cleverly devised paths users can control where the tar.gz file ends up being created, putting it anywhere that the user has permission to write to.

Expected behavior

Wheel handles this case by normalizing the package name, this would be the most user-friendly solution, otherwise I would also be happy with an exception since the package name is probably invalid (or maybe should be?).

How to Reproduce

  1. Clone https://github.com/da1910/build-troubles
  2. cd build-troubles
  3. python -m build

Output

Traceback (most recent call last):
  File "C:\Users\me\AppData\Local\Temp\build-env-qewrwpt_\lib\site-packages\setuptools\build_meta.py", line 106, in _file_with_extension
    file, = matching
ValueError: not enough values to unpack (expected 1, got 0)

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "C:\git\build-troubles\venv\lib\site-packages\pep517\in_process\_in_process.py", line 363, in <module>
    main()
  File "C:\git\build-troubles\venv\lib\site-packages\pep517\in_process\_in_process.py", line 345, in main
    json_out['return_val'] = hook(**hook_input['kwargs'])
  File "C:\git\build-troubles\venv\lib\site-packages\pep517\in_process\_in_process.py", line 314, in build_sdist
    return backend.build_sdist(sdist_directory, config_settings)
  File "C:\Users\me\AppData\Local\Temp\build-env-qewrwpt_\lib\site-packages\setuptools\build_meta.py", line 234, in build_sdist
    return self._build_with_temp_dir(['sdist', '--formats', 'gztar'],
  File "C:\Users\me\AppData\Local\Temp\build-env-qewrwpt_\lib\site-packages\setuptools\build_meta.py", line 217, in _build_with_temp_dir
    result_basename = _file_with_extension(
  File "C:\Users\me\AppData\Local\Temp\build-env-qewrwpt_\lib\site-packages\setuptools\build_meta.py", line 108, in _file_with_extension
    raise ValueError(
ValueError: No distribution was found. Ensure that `setup.py` is not empty and that it calls `setup()`.

Code of Conduct

jaraco commented 2 years ago

I'm pretty sure the spec says that package names can contain only ., -, and _ characters (in addition to alphanumeric). Probably Setuptools should fail early on violation of the expectation.

livneros-greeneye commented 8 months ago

@da1910 Did you solve it?

da1910 commented 8 months ago

I did not. To my knowledge this issue persists.

jaraco commented 1 month ago

I'm pretty sure the spec says that package names can contain only ., -, and _ characters (in addition to alphanumeric). Probably Setuptools should fail early on violation of the expectation.

spec

da1910 commented 1 month ago

Seems like a nice and easy fix then, validate the package name up front against the spec

jaraco commented 1 month ago

There's something in setuptools now called 'validate pyproject'. It's possible that it's already doing the appropriate validation. I was going to test before I ran up against https://github.com/pypa/packaging/issues/678. Having worked around that issue, I'm now able to test and confirm the issue still exists when using 'setup.cfg', but when using pyproject.toml, the name is properly validated:

 draft [1] 🐚 cat pyproject.toml
[project]
name="foo/bar"
 draft 🐚 pyproject-build .
* Creating isolated environment: venv+pip...
* Installing packages in isolated environment:
  - setuptools >= 40.8.0
* Getting build dependencies for sdist...
configuration error: `project.name` must be pep508-identifier
DESCRIPTION:
    The name (primary identifier) of the project. MUST be statically defined.

GIVEN VALUE:
    "foo/bar"

OFFENDING RULE: 'format'

DEFINITION:
    {
        "type": "string",
        "format": "pep508-identifier"
    }

For more details about `format` see
https://validate-pyproject.readthedocs.io/en/latest/api/validate_pyproject.formats.html

Traceback (most recent call last):
  File "/Users/jaraco/Library/Application Support/pipx/venvs/build/lib/python3.13t/site-packages/pyproject_hooks/_in_process/_in_process.py", line 373, in <module>
    main()
    ~~~~^^
  File "/Users/jaraco/Library/Application Support/pipx/venvs/build/lib/python3.13t/site-packages/pyproject_hooks/_in_process/_in_process.py", line 357, in main
    json_out["return_val"] = hook(**hook_input["kwargs"])
                             ~~~~^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/jaraco/Library/Application Support/pipx/venvs/build/lib/python3.13t/site-packages/pyproject_hooks/_in_process/_in_process.py", line 308, in get_requires_for_build_sdist
    return hook(config_settings)
  File "/private/var/folders/f2/2plv6q2n7l932m2x004jlw340000gn/T/build-env-d0zgdok3/lib/python3.13t/site-packages/setuptools/build_meta.py", line 330, in get_requires_for_build_sdist
    return self._get_build_requires(config_settings, requirements=[])
           ~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/private/var/folders/f2/2plv6q2n7l932m2x004jlw340000gn/T/build-env-d0zgdok3/lib/python3.13t/site-packages/setuptools/build_meta.py", line 297, in _get_build_requires
    self.run_setup()
    ~~~~~~~~~~~~~~^^
  File "/private/var/folders/f2/2plv6q2n7l932m2x004jlw340000gn/T/build-env-d0zgdok3/lib/python3.13t/site-packages/setuptools/build_meta.py", line 497, in run_setup
    super().run_setup(setup_script=setup_script)
    ~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/private/var/folders/f2/2plv6q2n7l932m2x004jlw340000gn/T/build-env-d0zgdok3/lib/python3.13t/site-packages/setuptools/build_meta.py", line 313, in run_setup
    exec(code, locals())
    ~~~~^^^^^^^^^^^^^^^^
  File "<string>", line 1, in <module>
  File "/private/var/folders/f2/2plv6q2n7l932m2x004jlw340000gn/T/build-env-d0zgdok3/lib/python3.13t/site-packages/setuptools/__init__.py", line 108, in setup
    return distutils.core.setup(**attrs)
           ~~~~~~~~~~~~~~~~~~~~^^^^^^^^^
  File "/private/var/folders/f2/2plv6q2n7l932m2x004jlw340000gn/T/build-env-d0zgdok3/lib/python3.13t/site-packages/setuptools/_distutils/core.py", line 158, in setup
    dist.parse_config_files()
    ~~~~~~~~~~~~~~~~~~~~~~~^^
  File "/private/var/folders/f2/2plv6q2n7l932m2x004jlw340000gn/T/build-env-d0zgdok3/lib/python3.13t/site-packages/setuptools/dist.py", line 603, in parse_config_files
    pyprojecttoml.apply_configuration(self, filename, ignore_option_errors)
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/private/var/folders/f2/2plv6q2n7l932m2x004jlw340000gn/T/build-env-d0zgdok3/lib/python3.13t/site-packages/setuptools/config/pyprojecttoml.py", line 70, in apply_configuration
    config = read_configuration(filepath, True, ignore_option_errors, dist)
  File "/private/var/folders/f2/2plv6q2n7l932m2x004jlw340000gn/T/build-env-d0zgdok3/lib/python3.13t/site-packages/setuptools/config/pyprojecttoml.py", line 135, in read_configuration
    validate(subset, filepath)
    ~~~~~~~~^^^^^^^^^^^^^^^^^^
  File "/private/var/folders/f2/2plv6q2n7l932m2x004jlw340000gn/T/build-env-d0zgdok3/lib/python3.13t/site-packages/setuptools/config/pyprojecttoml.py", line 59, in validate
    raise ValueError(f"{error}\n{summary}") from None
ValueError: invalid pyproject.toml config: `project.name`.
configuration error: `project.name` must be pep508-identifier

ERROR Backend subprocess exited when trying to invoke get_requires_for_build_sdist

Therefore, my recommendation is:

If using setup.py or setup.cfg, provide a valid identifier or switch to using pyproject.toml.

jaraco commented 1 month ago

I'm flagging this as won't fix, but I'd also accept a PR to validate the name using setup.py or setup.cfg.