Repository: pypa/setuptools

Issue:
[BUG] PEP 631 TOMLs can conflict with deprecated configuration files
### setuptools version

setuptools==62.1.0

### Python version

Python 3.10.4

### OS

Arch Linux

### Additional environment information

_No response_

### Description

A package with PEP 621/631 compliant `pyproject.toml` and the `build_meta` backend may have its metadata and other configuration information overlaid with other information from `setup.py` or `setup.cfg` (which may be retained for fallback with `--no-use-pep517` while setuptools transitions to a stable PEP 517 implementation by default).

One cause is this [helper function](https://github.com/pypa/setuptools/blob/ddb8844eac49e0bf3b4f20067b425ffeac1531a2/setuptools/build_meta.py#L115) which guarantees that the "fallback" `setup.py` would be called even if `pyproject.toml` is fully defined.

### Expected behavior

I expected setuptools to identify that `pyproject.toml` has the `project` and `dependencies` table, and would further ignore other configuration files (though I may be disregarding the value/use of dynamic fields with this expectation).

### How to Reproduce

1. `pip install setuptools wheel build`
2. `git clone https://gist.github.com/nullableVoidPtr/d3f528136eff5c0e827ee98fd75da9dd`
3. `python -m build`
4. `cat project.egg-info/requires.txt`

### Output

```console
click
wheel
click
```
There is a duplication of the dependency `click` and the inclusion of `wheel` which was only included in `setup.cfg`.
(Side note: the discrepancy in dependencies between `pyproject.toml` and `setup.py` is highly unlikely in actual packages, but is used to illustrate the issue here).
There was no warnings relating to the conflict observed in the output of `python -m build`.

Note that this also works with `setup.cfg` (replacing `setup.py`) with the following:
```ini
[options]
install_requires =
    click
    wheel
```




Discussion:
CC @abravalheri, thank you for your hard work!
Hi @nullableVoidPtr, thank you for reporting this.


Is the silent overwrite the best action for this scenario?
Or should we first introduce a warning?
The main concern here is PEP 517 builds silently using something which should have been a _non-default fallback_ (at least in my case), so a warning would be good. There is a similar issue remediated at #3195, but the fix doesn't appear to apply to this case; not sure what's going on there but I'll need to debug.

One fix I've thought about was something in `setup.py` which allows it to be effectively disabled or behave differently under non-PEP517 builds (e.g. specifically invoked by `pip --no-use-pep517`). This could either be another `setup` keyword like `legacy_use_only=True` or `trust_toml=True`.
Not sure if there's a case for something like `from setuptools import is_pep517` for more involved `setup.py` scripts (personally, I think it could cause discrepancies in legacy-system builds and 'modern' builds).


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
@@ -195,8 +195,10 @@ def _python_requires(dist: "Distribution", val: dict, _root_dir):
 
 
 def _dependencies(dist: "Distribution", val: list, _root_dir):
-    existing = getattr(dist, "install_requires", [])
-    _set_config(dist, "install_requires", existing + val)
+    if getattr(dist, "install_requires", []):
+        msg = "`install_requires` overwritten in `pyproject.toml` (dependencies)"
+        warnings.warn(msg)
+    _set_config(dist, "install_requires", val)
 
 
 def _optional_dependencies(dist: "Distribution", val: dict, _root_dir):


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
@@ -257,6 +257,15 @@ def test_listed_in_dynamic(self, tmp_path, attr, field, value):
         dist_value = _some_attrgetter(f"metadata.{attr}", attr)(dist)
         assert dist_value == value
 
+    def test_warning_overwritten_dependencies(self, tmp_path):
+        src = "[project]\nname='pkg'\nversion='0.1'\ndependencies=['click']\n"
+        pyproject = tmp_path / "pyproject.toml"
+        pyproject.write_text(src, encoding="utf-8")
+        dist = makedist(tmp_path, install_requires=["wheel"])
+        with pytest.warns(match="`install_requires` overwritten"):
+            dist = pyprojecttoml.apply_configuration(dist, pyproject)
+        assert "wheel" not in dist.install_requires
+
     def test_optional_dependencies_dont_remove_env_markers(self, tmp_path):
         """
         Internally setuptools converts dependencies with markers to "extras".