@@ -76,6 +76,9 @@ def canonicalize_license_expression(s: str) -> str:
76
76
MesonArgs = Mapping [MesonArgsKeys , List [str ]]
77
77
78
78
79
+ _PYPROJECT_METADATA_VERSION = tuple (map (int , pyproject_metadata .__version__ .split ('.' )[:2 ]))
80
+ _SUPPORTED_DYNAMIC_FIELDS = {'version' , } if _PYPROJECT_METADATA_VERSION < (0 , 9 ) else {'version' , 'license' , 'license-files' }
81
+
79
82
_NINJA_REQUIRED_VERSION = '1.8.2'
80
83
_MESON_REQUIRED_VERSION = '0.63.3' # keep in sync with the version requirement in pyproject.toml
81
84
@@ -257,7 +260,7 @@ def from_pyproject( # type: ignore[override]
257
260
metadata = super ().from_pyproject (data , project_dir , metadata_version )
258
261
259
262
# Check for unsupported dynamic fields.
260
- unsupported_dynamic = set (metadata .dynamic ) - { 'version' , }
263
+ unsupported_dynamic = set (metadata .dynamic ) - _SUPPORTED_DYNAMIC_FIELDS # type: ignore[operator]
261
264
if unsupported_dynamic :
262
265
fields = ', ' .join (f'"{ x } "' for x in unsupported_dynamic )
263
266
raise pyproject_metadata .ConfigurationError (f'Unsupported dynamic fields: { fields } ' )
@@ -728,13 +731,30 @@ def __init__(
728
731
raise pyproject_metadata .ConfigurationError (
729
732
'Field "version" declared as dynamic but version is not defined in meson.build' )
730
733
self ._metadata .version = packaging .version .Version (version )
734
+ if 'license' in self ._metadata .dynamic :
735
+ license = self ._meson_license
736
+ if license is None :
737
+ raise pyproject_metadata .ConfigurationError (
738
+ 'Field "license" declared as dynamic but license is not specified in meson.build' )
739
+ # mypy is not happy when analyzing typing based on
740
+ # pyproject-metadata < 0.9 where license needs to be of
741
+ # License type. However, this code is not executed if
742
+ # pyproject-metadata is older than 0.9 because then dynamic
743
+ # license is not allowed.
744
+ self ._metadata .license = license # type: ignore[assignment, unused-ignore]
745
+ if 'license-files' in self ._metadata .dynamic :
746
+ self ._metadata .license_files = self ._meson_license_files
731
747
else :
732
748
# if project section is missing, use minimal metdata from meson.build
733
749
name , version = self ._meson_name , self ._meson_version
734
750
if version is None :
735
751
raise pyproject_metadata .ConfigurationError (
736
752
'Section "project" missing in pyproject.toml and version is not defined in meson.build' )
737
- self ._metadata = Metadata (name = name , version = packaging .version .Version (version ))
753
+ kwargs = {
754
+ 'license' : self ._meson_license ,
755
+ 'license_files' : self ._meson_license_files
756
+ } if _PYPROJECT_METADATA_VERSION >= (0 , 9 ) else {}
757
+ self ._metadata = Metadata (name = name , version = packaging .version .Version (version ), ** kwargs )
738
758
739
759
# verify that we are running on a supported interpreter
740
760
if self ._metadata .requires_python :
@@ -859,6 +879,31 @@ def _meson_version(self) -> Optional[str]:
859
879
return None
860
880
return value
861
881
882
+ @property
883
+ def _meson_license (self ) -> Optional [str ]:
884
+ """The license specified with the ``license`` argument to ``project()`` in meson.build."""
885
+ value = self ._info ('intro-projectinfo' ).get ('license' , None )
886
+ if value is None :
887
+ return None
888
+ assert isinstance (value , list )
889
+ if len (value ) > 1 :
890
+ raise pyproject_metadata .ConfigurationError (
891
+ 'using a list of strings for the license declared in meson.build is ambiguous: use a SPDX license expression' )
892
+ value = value [0 ]
893
+ assert isinstance (value , str )
894
+ if value == 'unknown' :
895
+ return None
896
+ return str (canonicalize_license_expression (value )) # str() is to make mypy happy
897
+
898
+ @property
899
+ def _meson_license_files (self ) -> Optional [List [pathlib .Path ]]:
900
+ """The license files specified with the ``license_files`` argument to ``project()`` in meson.build."""
901
+ value = self ._info ('intro-projectinfo' ).get ('license_files' , None )
902
+ if not value :
903
+ return None
904
+ assert isinstance (value , list )
905
+ return [pathlib .Path (x ) for x in value ]
906
+
862
907
def sdist (self , directory : Path ) -> pathlib .Path :
863
908
"""Generates a sdist (source distribution) in the specified directory."""
864
909
# Generate meson dist file.
0 commit comments