@@ -29,13 +29,16 @@ class PyprojectFix:
2929
3030 - add missing pyproject.toml
3131 - add or update `[build-system] requires`
32+ - add fields to `[project] dynamic` (PEP 621)
3233
3334 Requirements in `update_build_requires` are added to
3435 `[build-system] requires`. If a requirement name matches an existing
3536 name, then the requirement is replaced.
3637
3738 Requirements in `remove_build_requires` are removed from
3839 `[build-system] requires`.
40+
41+ Entries in `add_dynamic_field` are merged into `[project] dynamic`.
3942 """
4043
4144 def __init__ (
@@ -45,18 +48,21 @@ def __init__(
4548 build_dir : pathlib .Path ,
4649 update_build_requires : list [str ],
4750 remove_build_requires : list [NormalizedName ],
51+ add_dynamic_field : list [str ] | None = None ,
4852 ) -> None :
4953 self .req = req
5054 self .build_dir = build_dir
5155 self .update_requirements = update_build_requires
5256 self .remove_requirements = remove_build_requires
57+ self .add_dynamic = add_dynamic_field or []
5358 self .pyproject_toml = self .build_dir / "pyproject.toml"
5459 self .setup_py = self .build_dir / "setup.py"
5560
5661 def run (self ) -> None :
5762 doc = self ._load ()
5863 build_system = self ._default_build_system (doc )
5964 self ._update_build_requires (build_system )
65+ self ._update_dynamic_fields (doc )
6066 logger .debug (
6167 "pyproject.toml %s: %s=%r, %s=%r" ,
6268 BUILD_SYSTEM ,
@@ -132,6 +138,25 @@ def _update_build_requires(self, build_system: TomlDict) -> None:
132138 new_requires ,
133139 )
134140
141+ def _update_dynamic_fields (self , doc : tomlkit .TOMLDocument ) -> None :
142+ """Merge new entries into ``[project] dynamic``."""
143+ if not self .add_dynamic :
144+ return
145+ project : TomlDict = doc .setdefault ("project" , {})
146+ old_dynamic : list [str ] = project .get ("dynamic" , [])
147+ merged = list (old_dynamic )
148+ for field in self .add_dynamic :
149+ if field not in merged :
150+ merged .append (field )
151+ merged .sort ()
152+ if set (merged ) != set (old_dynamic ):
153+ project ["dynamic" ] = merged
154+ logger .info (
155+ "changed project dynamic from %r to %r" ,
156+ old_dynamic ,
157+ merged ,
158+ )
159+
135160
136161def apply_project_override (
137162 ctx : context .WorkContext , req : Requirement , sdist_root_dir : pathlib .Path
@@ -140,17 +165,20 @@ def apply_project_override(
140165 pbi = ctx .package_build_info (req )
141166 update_build_requires = pbi .project_override .update_build_requires
142167 remove_build_requires = pbi .project_override .remove_build_requires
143- if update_build_requires or remove_build_requires :
168+ add_dynamic_field = pbi .project_override .add_dynamic_field
169+ if update_build_requires or remove_build_requires or add_dynamic_field :
144170 logger .debug (
145171 f"applying project_override: "
146- f"{ update_build_requires = } , { remove_build_requires = } "
172+ f"{ update_build_requires = } , { remove_build_requires = } , "
173+ f"{ add_dynamic_field = } "
147174 )
148175 build_dir = pbi .build_dir (sdist_root_dir )
149176 PyprojectFix (
150177 req ,
151178 build_dir = build_dir ,
152179 update_build_requires = update_build_requires ,
153180 remove_build_requires = remove_build_requires ,
181+ add_dynamic_field = add_dynamic_field ,
154182 ).run ()
155183 else :
156184 logger .debug ("no project_override" )
0 commit comments