@@ -379,6 +379,28 @@ def test_target_overrides_global(self, isolation):
379
379
assert builder .config .strict_naming is True
380
380
381
381
382
+ class TestMacOSMaxCompat :
383
+ def test_default (self , isolation ):
384
+ builder = WheelBuilder (str (isolation ))
385
+
386
+ assert builder .config .macos_max_compat is builder .config .macos_max_compat is True
387
+
388
+ def test_correct (self , isolation ):
389
+ config = {'tool' : {'hatch' : {'build' : {'targets' : {'wheel' : {'macos-max-compat' : False }}}}}}
390
+ builder = WheelBuilder (str (isolation ), config = config )
391
+
392
+ assert builder .config .macos_max_compat is False
393
+
394
+ def test_not_boolean (self , isolation ):
395
+ config = {'tool' : {'hatch' : {'build' : {'targets' : {'wheel' : {'macos-max-compat' : 9000 }}}}}}
396
+ builder = WheelBuilder (str (isolation ), config = config )
397
+
398
+ with pytest .raises (
399
+ TypeError , match = 'Field `tool.hatch.build.targets.wheel.macos-max-compat` must be a boolean'
400
+ ):
401
+ _ = builder .config .macos_max_compat
402
+
403
+
382
404
class TestConstructEntryPointsFile :
383
405
def test_default (self , isolation ):
384
406
config = {'project' : {}}
@@ -1070,7 +1092,7 @@ def initialize(self, version, build_data):
1070
1092
'hatch' : {
1071
1093
'version' : {'path' : 'my_app/__about__.py' },
1072
1094
'build' : {
1073
- 'targets' : {'wheel' : {'versions' : ['standard' ]}},
1095
+ 'targets' : {'wheel' : {'versions' : ['standard' ], 'macos-max-compat' : False }},
1074
1096
'artifacts' : ['my_app/lib.so' ],
1075
1097
'hooks' : {'custom' : {'path' : DEFAULT_BUILD_SCRIPT }},
1076
1098
},
@@ -1152,7 +1174,7 @@ def initialize(self, version, build_data):
1152
1174
'hatch' : {
1153
1175
'version' : {'path' : 'my_app/__about__.py' },
1154
1176
'build' : {
1155
- 'targets' : {'wheel' : {'versions' : ['standard' ]}},
1177
+ 'targets' : {'wheel' : {'versions' : ['standard' ], 'macos-max-compat' : False }},
1156
1178
'artifacts' : ['my_app/lib.so' ],
1157
1179
'hooks' : {'custom' : {'path' : DEFAULT_BUILD_SCRIPT }},
1158
1180
},
@@ -1235,7 +1257,7 @@ def initialize(self, version, build_data):
1235
1257
'hatch' : {
1236
1258
'version' : {'path' : 'my_app/__about__.py' },
1237
1259
'build' : {
1238
- 'targets' : {'wheel' : {'versions' : ['standard' ]}},
1260
+ 'targets' : {'wheel' : {'versions' : ['standard' ], 'macos-max-compat' : False }},
1239
1261
'artifacts' : ['my_app/lib.so' ],
1240
1262
'hooks' : {'custom' : {'path' : DEFAULT_BUILD_SCRIPT }},
1241
1263
},
@@ -1318,7 +1340,7 @@ def initialize(self, version, build_data):
1318
1340
'hatch' : {
1319
1341
'version' : {'path' : 'my_app/__about__.py' },
1320
1342
'build' : {
1321
- 'targets' : {'wheel' : {'versions' : ['standard' ]}},
1343
+ 'targets' : {'wheel' : {'versions' : ['standard' ], 'macos-max-compat' : False }},
1322
1344
'hooks' : {'custom' : {'path' : DEFAULT_BUILD_SCRIPT }},
1323
1345
},
1324
1346
},
@@ -1403,7 +1425,7 @@ def initialize(self, version, build_data):
1403
1425
'hatch' : {
1404
1426
'version' : {'path' : 'my_app/__about__.py' },
1405
1427
'build' : {
1406
- 'targets' : {'wheel' : {'versions' : ['standard' ]}},
1428
+ 'targets' : {'wheel' : {'versions' : ['standard' ], 'macos-max-compat' : False }},
1407
1429
'hooks' : {'custom' : {'path' : DEFAULT_BUILD_SCRIPT }},
1408
1430
},
1409
1431
},
@@ -1484,7 +1506,7 @@ def initialize(self, version, build_data):
1484
1506
'hatch' : {
1485
1507
'version' : {'path' : 'src/my_app/__about__.py' },
1486
1508
'build' : {
1487
- 'targets' : {'wheel' : {'versions' : ['standard' ]}},
1509
+ 'targets' : {'wheel' : {'versions' : ['standard' ], 'macos-max-compat' : False }},
1488
1510
'hooks' : {'custom' : {'path' : DEFAULT_BUILD_SCRIPT }},
1489
1511
},
1490
1512
},
@@ -1760,7 +1782,7 @@ def initialize(self, version, build_data):
1760
1782
'hatch' : {
1761
1783
'version' : {'path' : 'my_app/__about__.py' },
1762
1784
'build' : {
1763
- 'targets' : {'wheel' : {'versions' : ['standard' ]}},
1785
+ 'targets' : {'wheel' : {'versions' : ['standard' ], 'macos-max-compat' : False }},
1764
1786
'artifacts' : ['my_app/lib.so' ],
1765
1787
'hooks' : {'custom' : {'path' : DEFAULT_BUILD_SCRIPT }},
1766
1788
},
@@ -2846,7 +2868,7 @@ def initialize(self, version, build_data):
2846
2868
'hatch' : {
2847
2869
'version' : {'path' : 'my_app/__about__.py' },
2848
2870
'build' : {
2849
- 'targets' : {'wheel' : {'versions' : ['standard' ]}},
2871
+ 'targets' : {'wheel' : {'versions' : ['standard' ], 'macos-max-compat' : False }},
2850
2872
'artifacts' : ['my_app/lib.so' ],
2851
2873
'hooks' : {'custom' : {'path' : DEFAULT_BUILD_SCRIPT }},
2852
2874
},
@@ -2888,3 +2910,91 @@ def initialize(self, version, build_data):
2888
2910
tag = expected_tag ,
2889
2911
)
2890
2912
helpers .assert_files (extraction_directory , expected_files )
2913
+
2914
+ @pytest .mark .requires_macos
2915
+ def test_macos_max_compat (self , hatch , helpers , temp_dir , config_file ):
2916
+ config_file .model .template .plugins ['default' ]['src-layout' ] = False
2917
+ config_file .save ()
2918
+
2919
+ project_name = 'My.App'
2920
+
2921
+ with temp_dir .as_cwd ():
2922
+ result = hatch ('new' , project_name )
2923
+
2924
+ assert result .exit_code == 0 , result .output
2925
+
2926
+ project_path = temp_dir / 'my-app'
2927
+
2928
+ vcs_ignore_file = project_path / '.gitignore'
2929
+ vcs_ignore_file .write_text ('*.pyc\n *.so\n *.h' )
2930
+
2931
+ build_script = project_path / DEFAULT_BUILD_SCRIPT
2932
+ build_script .write_text (
2933
+ helpers .dedent (
2934
+ """
2935
+ import pathlib
2936
+
2937
+ from hatchling.builders.hooks.plugin.interface import BuildHookInterface
2938
+
2939
+ class CustomHook(BuildHookInterface):
2940
+ def initialize(self, version, build_data):
2941
+ build_data['pure_python'] = False
2942
+ build_data['infer_tag'] = True
2943
+
2944
+ pathlib.Path('my_app', 'lib.so').touch()
2945
+ pathlib.Path('my_app', 'lib.h').touch()
2946
+ """
2947
+ )
2948
+ )
2949
+
2950
+ config = {
2951
+ 'project' : {'name' : project_name , 'requires-python' : '>3' , 'dynamic' : ['version' ]},
2952
+ 'tool' : {
2953
+ 'hatch' : {
2954
+ 'version' : {'path' : 'my_app/__about__.py' },
2955
+ 'build' : {
2956
+ 'targets' : {'wheel' : {'versions' : ['standard' ]}},
2957
+ 'artifacts' : ['my_app/lib.so' ],
2958
+ 'hooks' : {'custom' : {'path' : DEFAULT_BUILD_SCRIPT }},
2959
+ },
2960
+ },
2961
+ },
2962
+ }
2963
+ builder = WheelBuilder (str (project_path ), config = config )
2964
+
2965
+ build_path = project_path / 'dist'
2966
+ build_path .mkdir ()
2967
+
2968
+ with project_path .as_cwd ():
2969
+ artifacts = list (builder .build (str (build_path )))
2970
+
2971
+ assert len (artifacts ) == 1
2972
+ expected_artifact = artifacts [0 ]
2973
+
2974
+ build_artifacts = list (build_path .iterdir ())
2975
+ assert len (build_artifacts ) == 1
2976
+ assert expected_artifact == str (build_artifacts [0 ])
2977
+
2978
+ tag = next (sys_tags ())
2979
+ tag_parts = [tag .interpreter , tag .abi , tag .platform ]
2980
+ sdk_version_major , sdk_version_minor = tag_parts [2 ].split ('_' )[1 :3 ]
2981
+ if int (sdk_version_major ) >= 11 :
2982
+ tag_parts [2 ] = tag_parts [2 ].replace (f'{ sdk_version_major } _{ sdk_version_minor } ' , '10_16' , 1 )
2983
+
2984
+ expected_tag = '-' .join (tag_parts )
2985
+ assert expected_artifact == str (build_path / f'{ builder .project_id } -{ expected_tag } .whl' )
2986
+
2987
+ extraction_directory = temp_dir / '_archive'
2988
+ extraction_directory .mkdir ()
2989
+
2990
+ with zipfile .ZipFile (str (expected_artifact ), 'r' ) as zip_archive :
2991
+ zip_archive .extractall (str (extraction_directory ))
2992
+
2993
+ metadata_directory = f'{ builder .project_id } .dist-info'
2994
+ expected_files = helpers .get_template_files (
2995
+ 'wheel.standard_default_build_script_artifacts' ,
2996
+ project_name ,
2997
+ metadata_directory = metadata_directory ,
2998
+ tag = expected_tag ,
2999
+ )
3000
+ helpers .assert_files (extraction_directory , expected_files )
0 commit comments