setuptools icon indicating copy to clipboard operation
setuptools copied to clipboard

[BUG] optional dependency identifiers in a dynamic section cannot contain hyphens

Open leofang opened this issue 1 year ago • 0 comments

setuptools version

setuptools==67.6.1

Python version

Python 3.11

OS

Ubuntu

Additional environment information

No response

Description

We cannot name our dynamic, optional dependencies with a hyphen included. For example, for this particular example

# pyproject.toml

# ...

[tool.setuptools.dynamic.optional-dependencies]
torch-cu12 = { file = ["requirements/pip/torch-cu12.txt"] }

it fails

$ pip install -v .[torch-cu12]

Our current workaround is to change hyphen to underscore in both pyproject.toml and user-visible cmdline instruction:

$ pip install -v .[torch_cu12]

but it's not pretty and does not comply with the established community convention.

Expected behavior

Make pip install -v .[torch-cu12] work out of box.

How to Reproduce

Add the following two files to an empty folder and run pip install -v .[torch-cu12]:

  • pyproject.toml:
[build-system]
requires = ["setuptools"]
build-backend = "setuptools.build_meta"

[project]
name = "my_package"
version = "0.0.1"

[tool.setuptools.dynamic.optional-dependencies]
torch-cu12 = { file = ["requirements/pip/torch-cu12.txt"] }
  • requirements/pip/torch-cu12.txt:
torch >=2

Output

$ pip install -v .[torch-cu12]
Using pip 23.1 from /home/leof/miniforge3/envs/cuqnt_dev_py311_cu12/lib/python3.11/site-packages/pip (python 3.11)
Processing /home/leof/dev/nvmath-python/repro
  Running command pip subprocess to install build dependencies
  Collecting setuptools
    Using cached setuptools-69.5.1-py3-none-any.whl (894 kB)
  Installing collected packages: setuptools
  Successfully installed setuptools-69.5.1
  Installing build dependencies ... done
  Running command Getting requirements to build wheel
  configuration error: `tool.setuptools.dynamic.optional-dependencies` keys must be named by:

      {format: 'python-identifier'}

  GIVEN VALUE:
      {
          "torch-cu12": {
              "file": [
                  "requirements/pip/torch-cu12.txt"
              ]
          }
      }

  OFFENDING RULE: 'propertyNames'

  DEFINITION:
      {
          "type": "object",
          "propertyNames": {
              "format": "python-identifier"
          },
          "additionalProperties": false,
          "patternProperties": {
              ".+": {
                  "$id": "#/definitions/file-directive",
                  "title": "'file:' directive",
                  "description": "Value is read from a file (or list of files and then concatenated)",
                  "type": "object",
                  "additionalProperties": false,
                  "properties": {
                      "file": {
                          "oneOf": [
                              {
                                  "type": "string"
                              },
                              {
                                  "type": "array",
                                  "items": {
                                      "type": "string"
                                  }
                              }
                          ]
                      }
                  },
                  "required": [
                      "file"
                  ]
              }
          }
      }
  Traceback (most recent call last):
    File "/home/leof/miniforge3/envs/cuqnt_dev_py311_cu12/lib/python3.11/site-packages/pip/_vendor/pyproject_hooks/_in_process/_in_process.py", line 353, in <module>
      main()
    File "/home/leof/miniforge3/envs/cuqnt_dev_py311_cu12/lib/python3.11/site-packages/pip/_vendor/pyproject_hooks/_in_process/_in_process.py", line 335, in main
      json_out['return_val'] = hook(**hook_input['kwargs'])
                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    File "/home/leof/miniforge3/envs/cuqnt_dev_py311_cu12/lib/python3.11/site-packages/pip/_vendor/pyproject_hooks/_in_process/_in_process.py", line 118, in get_requires_for_build_wheel
      return hook(config_settings)
             ^^^^^^^^^^^^^^^^^^^^^
    File "/tmp/pip-build-env-741l9e1r/overlay/lib/python3.11/site-packages/setuptools/build_meta.py", line 325, in get_requires_for_build_wheel
      return self._get_build_requires(config_settings, requirements=['wheel'])
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    File "/tmp/pip-build-env-741l9e1r/overlay/lib/python3.11/site-packages/setuptools/build_meta.py", line 295, in _get_build_requires
      self.run_setup()
    File "/tmp/pip-build-env-741l9e1r/overlay/lib/python3.11/site-packages/setuptools/build_meta.py", line 311, in run_setup
      exec(code, locals())
    File "<string>", line 1, in <module>
    File "/tmp/pip-build-env-741l9e1r/overlay/lib/python3.11/site-packages/setuptools/__init__.py", line 104, in setup
      return distutils.core.setup(**attrs)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    File "/tmp/pip-build-env-741l9e1r/overlay/lib/python3.11/site-packages/setuptools/_distutils/core.py", line 158, in setup
      dist.parse_config_files()
    File "/tmp/pip-build-env-741l9e1r/overlay/lib/python3.11/site-packages/setuptools/dist.py", line 631, in parse_config_files
      pyprojecttoml.apply_configuration(self, filename, ignore_option_errors)
    File "/tmp/pip-build-env-741l9e1r/overlay/lib/python3.11/site-packages/setuptools/config/pyprojecttoml.py", line 68, in apply_configuration
      config = read_configuration(filepath, True, ignore_option_errors, dist)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    File "/tmp/pip-build-env-741l9e1r/overlay/lib/python3.11/site-packages/setuptools/config/pyprojecttoml.py", line 129, in read_configuration
      validate(subset, filepath)
    File "/tmp/pip-build-env-741l9e1r/overlay/lib/python3.11/site-packages/setuptools/config/pyprojecttoml.py", line 57, in validate
      raise ValueError(f"{error}\n{summary}") from None
  ValueError: invalid pyproject.toml config: `tool.setuptools.dynamic.optional-dependencies`.
  configuration error: `tool.setuptools.dynamic.optional-dependencies` keys must be named by:

      {format: 'python-identifier'}

  error: subprocess-exited-with-error
  
  × Getting requirements to build wheel did not run successfully.
  │ exit code: 1
  ╰─> See above for output.
  
  note: This error originates from a subprocess, and is likely not a problem with pip.
  full command: /home/leof/miniforge3/envs/cuqnt_dev_py311_cu12/bin/python3.11 /home/leof/miniforge3/envs/cuqnt_dev_py311_cu12/lib/python3.11/site-packages/pip/_vendor/pyproject_hooks/_in_process/_in_process.py get_requires_for_build_wheel /tmp/tmpct6k27m2
  cwd: /home/leof/dev/nvmath-python/repro
  Getting requirements to build wheel ... error
error: subprocess-exited-with-error

× Getting requirements to build wheel did not run successfully.
│ exit code: 1
╰─> See above for output.

note: This error originates from a subprocess, and is likely not a problem with pip.

leofang avatar May 04 '24 03:05 leofang