1
1
from __future__ import annotations
2
2
3
+ import functools
3
4
import io
4
5
import itertools
5
6
import numbers
27
28
from ._reqs import _StrOrIter
28
29
from .config import pyprojecttoml , setupcfg
29
30
from .discovery import ConfigDiscovery
31
+ from .errors import InvalidConfigError
30
32
from .monkey import get_unpatched
31
33
from .warnings import InformationOnly , SetuptoolsDeprecationWarning
32
34
@@ -490,8 +492,8 @@ def _parse_config_files(self, filenames=None): # noqa: C901
490
492
continue
491
493
492
494
val = parser .get (section , opt )
493
- opt = self .warn_dash_deprecation (opt , section )
494
- opt = self .make_option_lowercase (opt , section )
495
+ opt = self ._enforce_underscore (opt , section )
496
+ opt = self ._enforce_option_lowercase (opt , section )
495
497
opt_dict [opt ] = (filename , val )
496
498
497
499
# Make the ConfigParser forget everything (so we retain
@@ -516,64 +518,42 @@ def _parse_config_files(self, filenames=None): # noqa: C901
516
518
except ValueError as e :
517
519
raise DistutilsOptionError (e ) from e
518
520
519
- def warn_dash_deprecation (self , opt : str , section : str ) -> str :
520
- if section in (
521
- 'options.extras_require' ,
522
- 'options.data_files' ,
523
- ):
521
+ def _enforce_underscore (self , opt : str , section : str ) -> str :
522
+ if "-" not in opt or not self ._config_requires_normalization (section ):
524
523
return opt
525
524
526
- underscore_opt = opt .replace ('-' , '_' )
527
- commands = list (
528
- itertools .chain (
529
- distutils .command .__all__ ,
530
- self ._setuptools_commands (),
531
- )
525
+ raise InvalidConfigError (
526
+ f"Invalid dash-separated key { opt !r} in { section !r} (setup.cfg), "
527
+ f"please use the underscore name { opt .replace ('-' , '_' )!r} instead."
528
+ # Warning initially introduced in 3 Mar 2021
532
529
)
533
- if (
534
- not section .startswith ('options' )
535
- and section != 'metadata'
536
- and section not in commands
537
- ):
538
- return underscore_opt
539
-
540
- if '-' in opt :
541
- SetuptoolsDeprecationWarning .emit (
542
- "Invalid dash-separated options" ,
543
- f"""
544
- Usage of dash-separated { opt !r} will not be supported in future
545
- versions. Please use the underscore name { underscore_opt !r} instead.
546
- """ ,
547
- see_docs = "userguide/declarative_config.html" ,
548
- due_date = (2025 , 3 , 3 ),
549
- # Warning initially introduced in 3 Mar 2021
550
- )
551
- return underscore_opt
552
530
553
- def _setuptools_commands (self ):
554
- try :
555
- entry_points = metadata .distribution ('setuptools' ).entry_points
556
- return {ep .name for ep in entry_points } # Avoid newer API for compatibility
557
- except metadata .PackageNotFoundError :
558
- # during bootstrapping, distribution doesn't exist
559
- return []
560
-
561
- def make_option_lowercase (self , opt : str , section : str ) -> str :
562
- if section != 'metadata' or opt .islower ():
531
+ def _enforce_option_lowercase (self , opt : str , section : str ) -> str :
532
+ if opt .islower () or not self ._config_requires_normalization (section ):
563
533
return opt
564
534
565
- lowercase_opt = opt .lower ()
566
- SetuptoolsDeprecationWarning .emit (
567
- "Invalid uppercase configuration" ,
568
- f"""
569
- Usage of uppercase key { opt !r} in { section !r} will not be supported in
570
- future versions. Please use lowercase { lowercase_opt !r} instead.
571
- """ ,
572
- see_docs = "userguide/declarative_config.html" ,
573
- due_date = (2025 , 3 , 3 ),
535
+ raise InvalidConfigError (
536
+ f"Invalid uppercase key { opt !r} in { section !r} (setup.cfg), "
537
+ f"please use lowercase { opt .lower ()!r} instead."
574
538
# Warning initially introduced in 6 Mar 2021
575
539
)
576
- return lowercase_opt
540
+
541
+ def _config_requires_normalization (self , section : str ) -> bool :
542
+ skip = (
543
+ 'options.extras_require' ,
544
+ 'options.data_files' ,
545
+ 'options.entry_points' ,
546
+ 'options.package_data' ,
547
+ 'options.exclude_package_data' ,
548
+ )
549
+ return section not in skip and self ._is_setuptools_section (section )
550
+
551
+ def _is_setuptools_section (self , section : str ) -> bool :
552
+ return (
553
+ section == "metadata"
554
+ or section .startswith ("option" )
555
+ or section in _setuptools_commands ()
556
+ )
577
557
578
558
# FIXME: 'Distribution._set_command_options' is too complex (14)
579
559
def _set_command_options (self , command_obj , option_dict = None ): # noqa: C901
@@ -999,6 +979,18 @@ def run_command(self, command) -> None:
999
979
super ().run_command (command )
1000
980
1001
981
982
+ @functools .cache
983
+ def _setuptools_commands () -> set [str ]:
984
+ try :
985
+ # Use older API for importlib.metadata compatibility
986
+ entry_points = metadata .distribution ('setuptools' ).entry_points
987
+ eps = (ep .name for ep in entry_points )
988
+ except metadata .PackageNotFoundError :
989
+ # during bootstrapping, distribution doesn't exist
990
+ return set (distutils .command .__all__ )
991
+ return {* distutils .command .__all__ , * eps }
992
+
993
+
1002
994
class DistDeprecationWarning (SetuptoolsDeprecationWarning ):
1003
995
"""Class for warning about deprecations in dist in
1004
996
setuptools. Not ignored by default, unlike DeprecationWarning."""
0 commit comments