1414from setuptools .dist import Distribution
1515from setuptools .config import setupcfg , pyprojecttoml
1616from setuptools .config import expand
17- from setuptools .config ._apply_pyprojecttoml import _WouldIgnoreField
17+ from setuptools .config ._apply_pyprojecttoml import _WouldIgnoreField , _some_attrgetter
18+ from setuptools .command .egg_info import write_requirements
1819
1920
2021EXAMPLES = (Path (__file__ ).parent / "setupcfg_examples.txt" ).read_text ()
@@ -207,12 +208,12 @@ def test_license_and_license_files(tmp_path):
207208
208209
209210class TestPresetField :
210- def pyproject (self , tmp_path , dynamic ):
211+ def pyproject (self , tmp_path , dynamic , extra_content = "" ):
211212 content = f"[project]\n name = 'proj'\n dynamic = { dynamic !r} \n "
212213 if "version" not in dynamic :
213214 content += "version = '42'\n "
214215 file = tmp_path / "pyproject.toml"
215- file .write_text (content , encoding = "utf-8" )
216+ file .write_text (content + extra_content , encoding = "utf-8" )
216217 return file
217218
218219 @pytest .mark .parametrize (
@@ -233,12 +234,14 @@ def test_not_listed_in_dynamic(self, tmp_path, attr, field, value):
233234 dist = pyprojecttoml .apply_configuration (dist , pyproject )
234235
235236 # TODO: Once support for pyproject.toml config stabilizes attr should be None
236- dist_value = getattr ( dist , attr , None ) or getattr (dist . metadata , attr , object () )
237+ dist_value = _some_attrgetter ( f"metadata. { attr } " , attr ) (dist )
237238 assert dist_value == value
238239
239240 @pytest .mark .parametrize (
240241 "attr, field, value" ,
241242 [
243+ ("install_requires" , "dependencies" , []),
244+ ("extras_require" , "optional-dependencies" , {}),
242245 ("install_requires" , "dependencies" , ["six" ]),
243246 ("classifiers" , "classifiers" , ["Private :: Classifier" ]),
244247 ]
@@ -247,9 +250,31 @@ def test_listed_in_dynamic(self, tmp_path, attr, field, value):
247250 pyproject = self .pyproject (tmp_path , [field ])
248251 dist = makedist (tmp_path , ** {attr : value })
249252 dist = pyprojecttoml .apply_configuration (dist , pyproject )
250- dist_value = getattr ( dist , attr , None ) or getattr (dist . metadata , attr , object () )
253+ dist_value = _some_attrgetter ( f"metadata. { attr } " , attr ) (dist )
251254 assert dist_value == value
252255
256+ def test_optional_dependencies_dont_remove_env_markers (self , tmp_path ):
257+ """
258+ Internally setuptools converts dependencies with markers to "extras".
259+ If ``install_requires`` is given by ``setup.py``, we have to ensure that
260+ applying ``optional-dependencies`` does not overwrite the mandatory
261+ dependencies with markers (see #3204).
262+ """
263+ # If setuptools replace its internal mechanism that uses `requires.txt`
264+ # this test has to be rewritten to adapt accordingly
265+ extra = "\n [project.optional-dependencies]\n foo = ['bar>1']\n "
266+ pyproject = self .pyproject (tmp_path , ["dependencies" ], extra )
267+ install_req = ['importlib-resources (>=3.0.0) ; python_version < "3.7"' ]
268+ dist = makedist (tmp_path , install_requires = install_req )
269+ dist = pyprojecttoml .apply_configuration (dist , pyproject )
270+ assert "foo" in dist .extras_require
271+ assert ':python_version < "3.7"' in dist .extras_require
272+ egg_info = dist .get_command_obj ("egg_info" )
273+ write_requirements (egg_info , tmp_path , tmp_path / "requires.txt" )
274+ reqs = (tmp_path / "requires.txt" ).read_text (encoding = "utf-8" )
275+ assert "importlib-resources" in reqs
276+ assert "bar" in reqs
277+
253278
254279# --- Auxiliary Functions ---
255280
0 commit comments