30
30
BuildFrontendConfig ,
31
31
BuildSelector ,
32
32
DependencyConstraints ,
33
+ EnableGroups ,
33
34
TestSelector ,
34
35
format_safe ,
36
+ read_python_configs ,
35
37
resources_dir ,
36
38
selector_matches ,
37
39
strtobool ,
@@ -512,6 +514,7 @@ def get(
512
514
env_plat : bool = True ,
513
515
option_format : OptionFormat | None = None ,
514
516
ignore_empty : bool = False ,
517
+ env_rule : InheritRule = InheritRule .NONE ,
515
518
) -> str :
516
519
"""
517
520
Get and return the value for the named option from environment,
@@ -543,8 +546,8 @@ def get(
543
546
(o .options .get (name ), o .inherit .get (name , InheritRule .NONE ))
544
547
for o in self .active_config_overrides
545
548
],
546
- (self .env .get (envvar ), InheritRule . NONE ),
547
- (self .env .get (plat_envvar ) if env_plat else None , InheritRule . NONE ),
549
+ (self .env .get (envvar ), env_rule ),
550
+ (self .env .get (plat_envvar ) if env_plat else None , env_rule ),
548
551
ignore_empty = ignore_empty ,
549
552
option_format = option_format ,
550
553
)
@@ -558,14 +561,15 @@ def __init__(
558
561
platform : PlatformName ,
559
562
command_line_arguments : CommandLineArguments ,
560
563
env : Mapping [str , str ],
561
- read_config_file : bool = True ,
564
+ defaults : bool = False ,
562
565
):
563
566
self .platform = platform
564
567
self .command_line_arguments = command_line_arguments
565
568
self .env = env
569
+ self ._defaults = defaults
566
570
567
571
self .reader = OptionsReader (
568
- self . config_file_path if read_config_file else None ,
572
+ None if defaults else self . config_file_path ,
569
573
platform = platform ,
570
574
env = env ,
571
575
disallow = DISALLOWED_OPTIONS ,
@@ -578,7 +582,7 @@ def __init__(
578
582
except FileNotFoundError :
579
583
self .pyproject_toml = None
580
584
581
- @property
585
+ @functools . cached_property
582
586
def config_file_path (self ) -> Path | None :
583
587
args = self .command_line_arguments
584
588
@@ -596,7 +600,7 @@ def config_file_path(self) -> Path | None:
596
600
def package_requires_python_str (self ) -> str | None :
597
601
return get_requires_python_str (self .package_dir , self .pyproject_toml )
598
602
599
- @property
603
+ @functools . cached_property
600
604
def globals (self ) -> GlobalOptions :
601
605
args = self .command_line_arguments
602
606
package_dir = args .package_dir
@@ -608,16 +612,34 @@ def globals(self) -> GlobalOptions:
608
612
skip_config = self .reader .get ("skip" , env_plat = False , option_format = ListFormat (sep = " " ))
609
613
test_skip = self .reader .get ("test-skip" , env_plat = False , option_format = ListFormat (sep = " " ))
610
614
615
+ allow_empty = args .allow_empty or strtobool (self .env .get ("CIBW_ALLOW_EMPTY" , "0" ))
616
+
617
+ enable_groups = self .reader .get (
618
+ "enable" , env_plat = False , option_format = ListFormat (sep = " " ), env_rule = InheritRule .APPEND
619
+ )
620
+ enable = {EnableGroups (group ) for group in enable_groups .split ()}
621
+
611
622
free_threaded_support = strtobool (
612
623
self .reader .get ("free-threaded-support" , env_plat = False , ignore_empty = True )
613
624
)
614
625
615
- allow_empty = args .allow_empty or strtobool (self .env .get ("CIBW_ALLOW_EMPTY" , "0" ))
616
-
617
626
prerelease_pythons = args .prerelease_pythons or strtobool (
618
627
self .env .get ("CIBW_PRERELEASE_PYTHONS" , "0" )
619
628
)
620
629
630
+ if free_threaded_support or prerelease_pythons :
631
+ msg = (
632
+ "free-threaded-support and prerelease-pythons should be specified by enable instead"
633
+ )
634
+ if enable :
635
+ raise OptionsReaderError (msg )
636
+ log .warning (msg )
637
+
638
+ if free_threaded_support :
639
+ enable .add (EnableGroups .CPythonFreeThreading )
640
+ if prerelease_pythons :
641
+ enable .add (EnableGroups .CPythonPrerelease )
642
+
621
643
# This is not supported in tool.cibuildwheel, as it comes from a standard location.
622
644
# Passing this in as an environment variable will override pyproject.toml, setup.cfg, or setup.py
623
645
requires_python_str : str | None = (
@@ -633,18 +655,30 @@ def globals(self) -> GlobalOptions:
633
655
build_config = args .only
634
656
skip_config = ""
635
657
architectures = Architecture .all_archs (self .platform )
636
- prerelease_pythons = True
637
- free_threaded_support = True
658
+ enable = set (EnableGroups )
638
659
639
660
build_selector = BuildSelector (
640
661
build_config = build_config ,
641
662
skip_config = skip_config ,
642
663
requires_python = requires_python ,
643
- prerelease_pythons = prerelease_pythons ,
644
- free_threaded_support = free_threaded_support ,
664
+ enable = frozenset (
665
+ enable | {EnableGroups .PyPy }
666
+ ), # For backwards compatibility, we are adding PyPy for now
645
667
)
646
668
test_selector = TestSelector (skip_config = test_skip )
647
669
670
+ all_configs = read_python_configs (self .platform )
671
+ all_pypy_ids = {
672
+ config ["identifier" ] for config in all_configs if config ["identifier" ].startswith ("pp" )
673
+ }
674
+ if (
675
+ not self ._defaults
676
+ and EnableGroups .PyPy not in enable
677
+ and any (build_selector (build_id ) for build_id in all_pypy_ids )
678
+ ):
679
+ msg = "PyPy builds will be disabled by default in version 3. Enabling PyPy builds should be specified by enable"
680
+ log .warning (msg )
681
+
648
682
return GlobalOptions (
649
683
package_dir = package_dir ,
650
684
output_dir = output_dir ,
@@ -831,7 +865,7 @@ def defaults(self) -> Options:
831
865
platform = self .platform ,
832
866
command_line_arguments = CommandLineArguments .defaults (),
833
867
env = {},
834
- read_config_file = False ,
868
+ defaults = True ,
835
869
)
836
870
837
871
def summary (self , identifiers : Iterable [str ]) -> str :
0 commit comments