@@ -658,6 +658,36 @@ def build_editable(self, directory: Path, verbose: bool = False) -> pathlib.Path
658
658
return wheel_file
659
659
660
660
661
+ def _validate_pyproject_config (pyproject : Dict [str , Any ]) -> Dict [str , Any ]:
662
+
663
+ def _table (scheme : Dict [str , Callable [[Any , str ], Any ]]) -> Callable [[Any , str ], Dict [str , Any ]]:
664
+ def func (value : Any , name : str ) -> Dict [str , Any ]:
665
+ if not isinstance (value , dict ):
666
+ raise ConfigError (f'configuration entry "{ name } " must be a table' )
667
+ table = {}
668
+ for key , val in value .items ():
669
+ check = scheme .get (key )
670
+ if check is None :
671
+ raise ConfigError (f'unknown configuration entry "{ name } .{ key } "' )
672
+ table [key ] = check (val , f'{ name } .{ key } ' )
673
+ return table
674
+ return func
675
+
676
+ def _strings (value : Any , name : str ) -> List [str ]:
677
+ if not isinstance (value , list ) or not all (isinstance (x , str ) for x in value ):
678
+ raise ConfigError (f'configuration entry "{ name } " must be a list of strings' )
679
+ return value
680
+
681
+ scheme = _table ({
682
+ 'args' : _table ({
683
+ name : _strings for name in _MESON_ARGS_KEYS
684
+ })
685
+ })
686
+
687
+ table = pyproject .get ('tool' , {}).get ('meson-python' , {})
688
+ return scheme (table , 'tool.meson-python' )
689
+
690
+
661
691
class Project ():
662
692
"""Meson project wrapper to generate Python artifacts."""
663
693
@@ -715,11 +745,13 @@ def __init__( # noqa: C901
715
745
self ._meson_cross_file .write_text (cross_file_data )
716
746
self ._meson_args ['setup' ].extend (('--cross-file' , os .fspath (self ._meson_cross_file )))
717
747
718
- # load config -- PEP 621 support is optional
719
- self ._config = tomllib .loads (self ._source_dir .joinpath ('pyproject.toml' ).read_text ())
720
- self ._pep621 = 'project' in self ._config
748
+ # load pyproject.toml
749
+ pyproject = tomllib .loads (self ._source_dir .joinpath ('pyproject.toml' ).read_text ())
750
+
751
+ # package metadata
752
+ self ._pep621 = 'project' in pyproject :
721
753
if self .pep621 :
722
- self ._metadata = pyproject_metadata .StandardMetadata .from_pyproject (self . _config , self ._source_dir )
754
+ self ._metadata = pyproject_metadata .StandardMetadata .from_pyproject (pyproject , self ._source_dir )
723
755
else :
724
756
print (
725
757
'{yellow}{bold}! Using Meson to generate the project metadata '
@@ -730,14 +762,10 @@ def __init__( # noqa: C901
730
762
if self ._metadata :
731
763
self ._validate_metadata ()
732
764
733
- # load meson args
734
- for key in self ._get_config_key ('args' ):
735
- self ._meson_args [key ].extend (self ._get_config_key (f'args.{ key } ' ))
736
- # XXX: We should validate the user args to make sure they don't conflict with ours.
737
-
738
- self ._check_for_unknown_config_keys ({
739
- 'args' : _MESON_ARGS_KEYS ,
740
- })
765
+ # load meson args from pyproject.toml
766
+ pyproject_config = _validate_pyproject_config (pyproject )
767
+ for key , value in pyproject_config .get ('args' , {}).items ():
768
+ self ._meson_args [key ].extend (value )
741
769
742
770
# meson arguments from the command line take precedence over
743
771
# arguments from the configuration file thus are added later
@@ -778,14 +806,6 @@ def __init__( # noqa: C901
778
806
if self ._metadata and 'version' in self ._metadata .dynamic :
779
807
self ._metadata .version = self .version
780
808
781
- def _get_config_key (self , key : str ) -> Any :
782
- value : Any = self ._config
783
- for part in f'tool.meson-python.{ key } ' .split ('.' ):
784
- if not isinstance (value , Mapping ):
785
- raise ConfigError (f'Configuration entry "tool.meson-python.{ key } " should be a TOML table not { type (value )} ' )
786
- value = value .get (part , {})
787
- return value
788
-
789
809
def _proc (self , * args : str ) -> None :
790
810
"""Invoke a subprocess."""
791
811
print ('{cyan}{bold}+ {}{reset}' .format (' ' .join (args ), ** _STYLES ))
@@ -858,17 +878,6 @@ def _validate_metadata(self) -> None:
858
878
f'expected { self ._metadata .requires_python } '
859
879
)
860
880
861
- def _check_for_unknown_config_keys (self , valid_args : Mapping [str , Collection [str ]]) -> None :
862
- config = self ._config .get ('tool' , {}).get ('meson-python' , {})
863
-
864
- for key , valid_subkeys in config .items ():
865
- if key not in valid_args :
866
- raise ConfigError (f'Unknown configuration key "tool.meson-python.{ key } "' )
867
-
868
- for subkey in valid_args [key ]:
869
- if subkey not in valid_subkeys :
870
- raise ConfigError (f'Unknown configuration key "tool.meson-python.{ key } .{ subkey } "' )
871
-
872
881
@cached_property
873
882
def _wheel_builder (self ) -> _WheelBuilder :
874
883
return _WheelBuilder (
0 commit comments