@@ -35,7 +35,13 @@ def test_get_compiler():
3535 assert get_compiler () in POSSIBLE_COMPILERS
3636
3737
38- def _extension_test_package (tmp_path , request , extension_type = "c" , include_numpy = False ):
38+ def _extension_test_package (
39+ tmp_path ,
40+ request = None ,
41+ extension_type = "c" ,
42+ include_numpy = False ,
43+ include_setup_py = True ,
44+ ):
3945 """Creates a simple test package with an extension module."""
4046
4147 test_pkg = tmp_path / "test_pkg"
@@ -106,24 +112,25 @@ def get_extensions():
106112 )
107113 )
108114
109- (test_pkg / "setup.py" ).write_text (
110- dedent (
111- f"""\
112- import sys
113- from os.path import join
114- from setuptools import setup, find_packages
115- sys.path.insert(0, r'{ extension_helpers_PATH } ')
116- from extension_helpers import get_extensions
117-
118- setup(
119- name='helpers_test_package',
120- version='0.1',
121- packages=find_packages(),
122- ext_modules=get_extensions()
123- )
124- """
115+ if include_setup_py :
116+ (test_pkg / "setup.py" ).write_text (
117+ dedent (
118+ f"""\
119+ import sys
120+ from os.path import join
121+ from setuptools import setup, find_packages
122+ sys.path.insert(0, r'{ extension_helpers_PATH } ')
123+ from extension_helpers import get_extensions
124+
125+ setup(
126+ name='helpers_test_package',
127+ version='0.1',
128+ packages=find_packages(),
129+ ext_modules=get_extensions()
130+ )
131+ """
132+ )
125133 )
126- )
127134
128135 if "" in sys .path :
129136 sys .path .remove ("" )
@@ -133,7 +140,8 @@ def get_extensions():
133140 def finalize ():
134141 cleanup_import ("helpers_test_package" )
135142
136- request .addfinalizer (finalize )
143+ if request :
144+ request .addfinalizer (finalize )
137145
138146 return test_pkg
139147
@@ -455,3 +463,133 @@ def test():
455463 pass
456464 else :
457465 raise AssertionError (package_name + ".compiler_version should not exist" )
466+
467+
468+ # Tests to make sure that limited API support works correctly
469+
470+
471+ @pytest .mark .parametrize ("config" , ("setup.cfg" , "pyproject.toml" ))
472+ @pytest .mark .parametrize ("limited_api" , (None , "cp310" ))
473+ @pytest .mark .parametrize ("extension_type" , ("c" , "pyx" , "both" ))
474+ def test_limited_api (tmp_path , config , limited_api , extension_type ):
475+
476+ package = _extension_test_package (
477+ tmp_path , extension_type = extension_type , include_numpy = True , include_setup_py = False
478+ )
479+
480+ if config == "setup.cfg" :
481+
482+ setup_cfg = dedent (
483+ """\
484+ [metadata]
485+ name = helpers_test_package
486+ version = 0.1
487+
488+ [options]
489+ packages = find:
490+
491+ [extension-helpers]
492+ use_extension_helpers = true
493+ """
494+ )
495+
496+ if limited_api :
497+ setup_cfg += f"\n [bdist_wheel]\n py_limited_api={ limited_api } "
498+
499+ (package / "setup.cfg" ).write_text (setup_cfg )
500+
501+ # Still require a minimal pyproject.toml file if no setup.py file
502+
503+ (package / "pyproject.toml" ).write_text (
504+ dedent (
505+ """
506+ [build-system]
507+ requires = ["setuptools>=43.0.0",
508+ "wheel"]
509+ build-backend = 'setuptools.build_meta'
510+
511+ [tool.extension-helpers]
512+ use_extension_helpers = true
513+ """
514+ )
515+ )
516+
517+ elif config == "pyproject.toml" :
518+
519+ pyproject_toml = dedent (
520+ """\
521+ [build-system]
522+ requires = ["setuptools>=43.0.0",
523+ "wheel"]
524+ build-backend = 'setuptools.build_meta'
525+
526+ [project]
527+ name = "hehlpers_test_package"
528+ version = "0.1"
529+
530+ [tool.setuptools.packages]
531+ find = {namespaces = false}
532+
533+ [tool.extension-helpers]
534+ use_extension_helpers = true
535+ """
536+ )
537+
538+ if limited_api :
539+ pyproject_toml += f'\n [tool.distutils.bdist_wheel]\n py-limited-api = "{ limited_api } "'
540+
541+ (package / "pyproject.toml" ).write_text (pyproject_toml )
542+
543+ with chdir (package ):
544+ subprocess .run ([sys .executable , "-m" , "build" , "--wheel" , "--no-isolation" ], check = True )
545+
546+ wheels = os .listdir (package / "dist" )
547+
548+ assert len (wheels ) == 1
549+ assert ("abi3" in wheels [0 ]) == (limited_api is not None )
550+
551+
552+ def test_limited_api_invalid_abi (tmp_path , capsys ):
553+
554+ package = _extension_test_package (
555+ tmp_path , extension_type = "c" , include_numpy = True , include_setup_py = False
556+ )
557+
558+ (package / "setup.cfg" ).write_text (
559+ dedent (
560+ """\
561+ [metadata]
562+ name = helpers_test_package
563+ version = 0.1
564+
565+ [options]
566+ packages = find:
567+
568+ [extension-helpers]
569+ use_extension_helpers = true
570+
571+ [bdist_wheel]
572+ py_limited_api=invalid
573+ """
574+ )
575+ )
576+
577+ (package / "pyproject.toml" ).write_text (
578+ dedent (
579+ """
580+ [build-system]
581+ requires = ["setuptools>=43.0.0",
582+ "wheel"]
583+ build-backend = 'setuptools.build_meta'
584+ """
585+ )
586+ )
587+
588+ with chdir (package ):
589+ result = subprocess .run (
590+ [sys .executable , "-m" , "build" , "--wheel" , "--no-isolation" ], stderr = subprocess .PIPE
591+ )
592+
593+ assert result .stderr .strip ().endswith (
594+ b"ValueError: Unrecognized abi version for limited API: invalid"
595+ )
0 commit comments