@@ -654,6 +654,36 @@ def build_editable(self, directory: Path, verbose: bool = False) -> pathlib.Path
654
654
return wheel_file
655
655
656
656
657
+ def _validate_pyproject_config (pyproject : Dict [str , Any ]) -> Dict [str , Any ]:
658
+
659
+ def _table (scheme : Dict [str , Callable [[Any , str ], Any ]]) -> Callable [[Any , str ], Dict [str , Any ]]:
660
+ def func (value : Any , name : str ) -> Dict [str , Any ]:
661
+ if not isinstance (value , dict ):
662
+ raise ConfigError (f'Configuration entry "{ name } " must be a table' )
663
+ table = {}
664
+ for key , val in value .items ():
665
+ check = scheme .get (key )
666
+ if check is None :
667
+ raise ConfigError (f'Unknown configuration entry "{ name } .{ key } "' )
668
+ table [key ] = check (val , f'{ name } .{ key } ' )
669
+ return table
670
+ return func
671
+
672
+ def _strings (value : Any , name : str ) -> List [str ]:
673
+ if not isinstance (value , list ) or not all (isinstance (x , str ) for x in value ):
674
+ raise ConfigError (f'Configuration entry "{ name } " must be a list of strings' )
675
+ return value
676
+
677
+ scheme = _table ({
678
+ 'args' : _table ({
679
+ name : _strings for name in _MESON_ARGS_KEYS
680
+ })
681
+ })
682
+
683
+ table = pyproject .get ('tool' , {}).get ('meson-python' , {})
684
+ return scheme (table , 'tool.meson-python' )
685
+
686
+
657
687
class Project ():
658
688
"""Meson project wrapper to generate Python artifacts."""
659
689
@@ -662,7 +692,7 @@ class Project():
662
692
]
663
693
_metadata : Optional [pyproject_metadata .StandardMetadata ]
664
694
665
- def __init__ ( # noqa: C901
695
+ def __init__ (
666
696
self ,
667
697
source_dir : Path ,
668
698
working_dir : Path ,
@@ -712,11 +742,13 @@ def __init__( # noqa: C901
712
742
self ._meson_cross_file .write_text (cross_file_data )
713
743
self ._meson_args ['setup' ].extend (('--cross-file' , os .fspath (self ._meson_cross_file )))
714
744
715
- # load config -- PEP 621 support is optional
716
- self ._config = tomllib .loads (self ._source_dir .joinpath ('pyproject.toml' ).read_text ())
717
- self ._pep621 = 'project' in self ._config
745
+ # load pyproject.toml
746
+ pyproject = tomllib .loads (self ._source_dir .joinpath ('pyproject.toml' ).read_text ())
747
+
748
+ # package metadata
749
+ self ._pep621 = 'project' in pyproject :
718
750
if self .pep621 :
719
- self ._metadata = pyproject_metadata .StandardMetadata .from_pyproject (self . _config , self ._source_dir )
751
+ self ._metadata = pyproject_metadata .StandardMetadata .from_pyproject (pyproject , self ._source_dir )
720
752
else :
721
753
print (
722
754
'{yellow}{bold}! Using Meson to generate the project metadata '
@@ -727,14 +759,10 @@ def __init__( # noqa: C901
727
759
if self ._metadata :
728
760
self ._validate_metadata ()
729
761
730
- # load meson args
731
- for key in self ._get_config_key ('args' ):
732
- self ._meson_args [key ].extend (self ._get_config_key (f'args.{ key } ' ))
733
- # XXX: We should validate the user args to make sure they don't conflict with ours.
734
-
735
- self ._check_for_unknown_config_keys ({
736
- 'args' : _MESON_ARGS_KEYS ,
737
- })
762
+ # load meson args from pyproject.toml
763
+ pyproject_config = _validate_pyproject_config (pyproject )
764
+ for key , value in pyproject_config .get ('args' , {}).items ():
765
+ self ._meson_args [key ].extend (value )
738
766
739
767
# meson arguments from the command line take precedence over
740
768
# arguments from the configuration file thus are added later
@@ -768,14 +796,6 @@ def __init__( # noqa: C901
768
796
if self ._metadata and 'version' in self ._metadata .dynamic :
769
797
self ._metadata .version = self .version
770
798
771
- def _get_config_key (self , key : str ) -> Any :
772
- value : Any = self ._config
773
- for part in f'tool.meson-python.{ key } ' .split ('.' ):
774
- if not isinstance (value , Mapping ):
775
- raise ConfigError (f'Configuration entry "tool.meson-python.{ key } " should be a TOML table not { type (value )} ' )
776
- value = value .get (part , {})
777
- return value
778
-
779
799
def _run (self , cmd : Sequence [str ]) -> None :
780
800
"""Invoke a subprocess."""
781
801
print ('{cyan}{bold}+ {}{reset}' .format (' ' .join (cmd ), ** _STYLES ))
@@ -834,17 +854,6 @@ def _validate_metadata(self) -> None:
834
854
f'expected { self ._metadata .requires_python } '
835
855
)
836
856
837
- def _check_for_unknown_config_keys (self , valid_args : Mapping [str , Collection [str ]]) -> None :
838
- config = self ._config .get ('tool' , {}).get ('meson-python' , {})
839
-
840
- for key , valid_subkeys in config .items ():
841
- if key not in valid_args :
842
- raise ConfigError (f'Unknown configuration key "tool.meson-python.{ key } "' )
843
-
844
- for subkey in valid_args [key ]:
845
- if subkey not in valid_subkeys :
846
- raise ConfigError (f'Unknown configuration key "tool.meson-python.{ key } .{ subkey } "' )
847
-
848
857
@cached_property
849
858
def _wheel_builder (self ) -> _WheelBuilder :
850
859
return _WheelBuilder (
0 commit comments