@@ -31,6 +31,7 @@ class PyProjectData:
3131 is_required : bool
3232 section_present : bool
3333 project_present : bool
34+ build_requires : list [str ]
3435
3536 @classmethod
3637 def for_testing (
@@ -41,6 +42,8 @@ def for_testing(
4142 project_present : bool = False ,
4243 project_name : str | None = None ,
4344 has_dynamic_version : bool = True ,
45+ build_requires : list [str ] | None = None ,
46+ local_scheme : str | None = None ,
4447 ) -> PyProjectData :
4548 """Create a PyProjectData instance for testing purposes."""
4649 project : TOML_RESULT
@@ -54,14 +57,22 @@ def for_testing(
5457 if project_present and has_dynamic_version :
5558 project ["dynamic" ] = ["version" ]
5659
60+ if build_requires is None :
61+ build_requires = []
62+ if local_scheme is not None :
63+ assert section_present
64+ section = {"local_scheme" : local_scheme }
65+ else :
66+ section = {}
5767 return cls (
5868 path = DEFAULT_PYPROJECT_PATH ,
5969 tool_name = DEFAULT_TOOL_NAME ,
6070 project = project ,
61- section = {} ,
71+ section = section ,
6272 is_required = is_required ,
6373 section_present = section_present ,
6474 project_present = project_present ,
75+ build_requires = build_requires ,
6576 )
6677
6778 @classmethod
@@ -76,6 +87,7 @@ def empty(
7687 is_required = False ,
7788 section_present = False ,
7889 project_present = False ,
90+ build_requires = [],
7991 )
8092
8193 @property
@@ -95,14 +107,28 @@ def should_infer(self) -> bool:
95107 """
96108 Determine if setuptools_scm should infer version based on configuration.
97109
98- Only infer when an explicit [tool.setuptools_scm] section is present.
99- The presence of setuptools-scm in build-system.requires or
100- project.dynamic does NOT auto-enable inference.
110+ Infer when:
111+ 1. An explicit [tool.setuptools_scm] section is present, OR
112+ 2. setuptools-scm[simple] is in build-system.requires AND
113+ version is in project.dynamic
101114
102115 Returns:
103116 True if [tool.setuptools_scm] is present, otherwise False
104117 """
105- return self .section_present
118+ # Original behavior: explicit tool section
119+ if self .section_present :
120+ return True
121+
122+ # New behavior: simple extra + dynamic version
123+ if self .project_present :
124+ dynamic_fields = self .project .get ("dynamic" , [])
125+ if "version" in dynamic_fields :
126+ if has_build_package_with_extra (
127+ self .build_requires , "setuptools-scm" , "simple"
128+ ):
129+ return True
130+
131+ return False
106132
107133
108134def has_build_package (
@@ -115,6 +141,34 @@ def has_build_package(
115141 return False
116142
117143
144+ def has_build_package_with_extra (
145+ requires : Sequence [str ], canonical_build_package_name : str , extra_name : str
146+ ) -> bool :
147+ """Check if a build dependency has a specific extra.
148+
149+ Args:
150+ requires: List of requirement strings from build-system.requires
151+ canonical_build_package_name: The canonical package name to look for
152+ extra_name: The extra name to check for (e.g., "simple")
153+
154+ Returns:
155+ True if the package is found with the specified extra
156+ """
157+ from .._requirement_cls import Requirement
158+
159+ for requirement_string in requires :
160+ try :
161+ requirement = Requirement (requirement_string )
162+ package_name = extract_package_name (requirement_string )
163+ if package_name == canonical_build_package_name :
164+ if extra_name in requirement .extras :
165+ return True
166+ except Exception :
167+ # If parsing fails, continue to next requirement
168+ continue
169+ return False
170+
171+
118172def read_pyproject (
119173 path : Path = DEFAULT_PYPROJECT_PATH ,
120174 tool_name : str = DEFAULT_TOOL_NAME ,
@@ -160,7 +214,14 @@ def read_pyproject(
160214 project = defn .get ("project" , {})
161215 project_present = "project" in defn
162216 pyproject_data = PyProjectData (
163- path , tool_name , project , section , is_required , section_present , project_present
217+ path ,
218+ tool_name ,
219+ project ,
220+ section ,
221+ is_required ,
222+ section_present ,
223+ project_present ,
224+ requires ,
164225 )
165226
166227 return pyproject_data
0 commit comments