setuptools icon indicating copy to clipboard operation
setuptools copied to clipboard

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

Open da1910 opened this issue 4 years ago • 3 comments

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

  • [X] I agree to follow the PSF Code of Conduct

da1910 avatar Dec 06 '21 11:12 da1910

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.

jaraco avatar Dec 30 '21 16:12 jaraco

@da1910 Did you solve it?

livneros-greeneye avatar Jan 11 '24 10:01 livneros-greeneye

I did not. To my knowledge this issue persists.

da1910 avatar Jan 11 '24 10:01 da1910

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

jaraco avatar Aug 16 '24 19:08 jaraco

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

da1910 avatar Aug 16 '24 19:08 da1910

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 avatar Aug 16 '24 20:08 jaraco

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.

jaraco avatar Aug 16 '24 20:08 jaraco