Repository: pypa/setuptools

Issue:
[BUG] dynamic = ["scripts"] in pyproject.toml doesn't work
### setuptools version

setuptools===67.6.0

### Python version

Python 3.11.2

### OS

Windows 11

### Additional environment information

_No response_

### Description

I'm trying to define a project whose metadata is specified in `pyproject.toml`, but whose console scripts are defined dynamically. In `pyproject.toml`, the console scripts are defined via the `project.scripts` table, so I would expect that to do it dynamically, I would have to set `dynamic = ["scripts"]`. However, this doesn't work; setuptools complains that I have to set `dynamic = ["entry-points"]`.


### Expected behavior

setuptools should emit a warning about `entry-points` not listed as dynamic if and only if `setup.py`/`setup.cfg` define any entry point groups that are not `console_scripts` or `gui_scripts`. For those, it should expect the `dynamic` field to contain `scripts` and `gui_scripts`, respectively.



### How to Reproduce

Create a project like this:

`pyproject.toml`:
```toml
[project]
name = "testproj"
version = "0"
dynamic = ["scripts"]

[build-system]
requires = ["setuptools"]
build-backend = "setuptools.build_meta"
```

`setup.py`:
```python
from setuptools import setup

setup(
    entry_points={
        "console_scripts": [
            "foobar=foobar:main",
        ],
    },
)
```

Now try to build a distribution.


### Output

```console
> python .\setup.py sdist
C:\Users\dpb\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.11_qbz5n2kfra8p0\LocalCache\local-packages\Python311\site-packages\setuptools\config\_apply_pyprojecttoml.py:103: _WouldIgnoreField: 'entry-points' defined outside of `pyproject.toml` would be ignored.
    !!


    ##########################################################################
    # configuration would be ignored/result in error due to `pyproject.toml` #
    ##########################################################################

    The following seems to be defined outside of `pyproject.toml`:

    `entry-points = {'console_scripts': ['foobar=foobar:main']}`

    According to the spec (see the link below), however, setuptools CANNOT
    consider this value unless 'entry-points' is listed as `dynamic`.

    https://packaging.python.org/en/latest/specifications/declaring-project-metadata/

    For the time being, `setuptools` will still consider the given value (as a
    **transitional** measure), but please note that future releases of setuptools will
    follow strictly the standard.

    To prevent this warning, you can list 'entry-points' under `dynamic` or alternatively
    remove the `[project]` table from your file and rely entirely on other means of
    configuration.


!!

[...]
```



Discussion:

Resolving patch:
diff --git a/setuptools/config/_apply_pyprojecttoml.py b/setuptools/config/_apply_pyprojecttoml.py
--- a/setuptools/config/_apply_pyprojecttoml.py
+++ b/setuptools/config/_apply_pyprojecttoml.py
@@ -279,6 +279,12 @@ def _normalise_cmd_options(desc: List[Tuple[str, Optional[str], str]]) -> Set[st
     return {_normalise_cmd_option_key(fancy_option[0]) for fancy_option in desc}
 
 
+def _get_previous_entrypoints(dist: "Distribution") -> Dict[str, list]:
+    ignore = ("console_scripts", "gui_scripts")
+    value = getattr(dist, "entry_points", None) or {}
+    return {k: v for k, v in value.items() if k not in ignore}
+
+
 def _attrgetter(attr):
     """
     Similar to ``operator.attrgetter`` but returns None if ``attr`` is not found
@@ -343,7 +349,7 @@ def _acessor(obj):
     "keywords": _attrgetter("metadata.keywords"),
     "classifiers": _attrgetter("metadata.classifiers"),
     "urls": _attrgetter("metadata.project_urls"),
-    "entry-points": _attrgetter("entry_points"),
+    "entry-points": _get_previous_entrypoints,
     "dependencies": _some_attrgetter("_orig_install_requires", "install_requires"),
     "optional-dependencies": _some_attrgetter("_orig_extras_require", "extras_require"),
 }


Test patch:
diff --git a/setuptools/tests/config/test_apply_pyprojecttoml.py b/setuptools/tests/config/test_apply_pyprojecttoml.py
--- a/setuptools/tests/config/test_apply_pyprojecttoml.py
+++ b/setuptools/tests/config/test_apply_pyprojecttoml.py
@@ -363,6 +363,18 @@ def test_optional_dependencies_dont_remove_env_markers(self, tmp_path):
         assert "importlib-resources" in reqs
         assert "bar" in reqs
 
+    @pytest.mark.parametrize(
+        "field,group",
+        [("scripts", "console_scripts"), ("gui-scripts", "gui_scripts")]
+    )
+    @pytest.mark.filterwarnings("error")
+    def test_scripts_dont_require_dynamic_entry_points(self, tmp_path, field, group):
+        # Issue 3862
+        pyproject = self.pyproject(tmp_path, [field])
+        dist = makedist(tmp_path, entry_points={group: ["foobar=foobar:main"]})
+        dist = pyprojecttoml.apply_configuration(dist, pyproject)
+        assert group in dist.entry_points
+
 
 class TestMeta:
     def test_example_file_in_sdist(self, setuptools_sdist):