Skip to content

Commit

Permalink
introduce a test which checks that we can build, install an import an…
Browse files Browse the repository at this point in the history
… universal ABI module. Also, introduce a @monkeypatch decorator which is a much nicer way to monkey-patch bdist_egg.write_stub
  • Loading branch information
antocuni committed Aug 2, 2022
1 parent 933617d commit 7110dd1
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 12 deletions.
41 changes: 29 additions & 12 deletions hpy/devel/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
from distutils.errors import DistutilsError
import setuptools.command as cmd
import setuptools.command.build_ext
from setuptools.command import bdist_egg as bdist_egg_mod
import setuptools.command.bdist_egg


DEFAULT_HPY_ABI = 'universal'
Expand Down Expand Up @@ -69,7 +69,6 @@ def fix_distribution(self, dist):
dist.hpydevel = self
base_build = dist.cmdclass.get("build", build)
build_ext = dist.cmdclass.get("build_ext", cmd.build_ext.build_ext)
orig_bdist_egg_write_stub = bdist_egg_mod.write_stub

# check that the supplied build_ext inherits from setuptools
if isinstance(build_ext, type):
Expand All @@ -93,22 +92,28 @@ def dist_has_ext_modules(self):
def build_has_ext_modules(self):
return self.distribution.has_ext_modules()

def bdist_egg_write_stub(resource, pyfile):
if resource.endswith(".hpy.so"):
log.info("stub file already created for %s", resource)
return
orig_bdist_egg_write_stub(resource, pyfile)

# replace build_ext subcommand
dist.cmdclass['build_ext'] = build_ext_hpy

dist.__class__.has_ext_modules = dist_has_ext_modules
base_build.has_ext_modules = build_has_ext_modules
# setuptools / distutils store subcommands in .subcommands which
# is a list of tuples of (extension_name, extension_needs_to_run_func).
# The two lines below replace .subcommand entry for build_ext.
idx = [sub[0] for sub in base_build.sub_commands].index("build_ext")
base_build.sub_commands[idx] = ("build_ext", build_has_ext_modules)
bdist_egg_mod.write_stub = bdist_egg_write_stub

@monkeypatch(setuptools.command.bdist_egg)
def write_stub(resource, pyfile):
"""
This is needed because the default bdist_egg unconditionally writes a .py
stub, thus overwriting the one which was created by
build_ext_hpy_mixin.write_stub.
"""
if resource.endswith(".hpy.so"):
log.info("stub file already created for %s", resource)
return
write_stub.super(resource, pyfile)


def handle_hpy_ext_modules(dist, attr, hpy_ext_modules):
Expand Down Expand Up @@ -206,9 +211,9 @@ def wrapper(self, ext_name):
return wrapper


# ====================================
# Augmented setuptools commands
# ====================================
# ==================================================
# Augmented setuptools commands and monkeypatching
# ==================================================

def make_mixin(base, mixin):
"""
Expand All @@ -220,6 +225,18 @@ class NewClass(mixin, base, object):
NewClass.__name__ = base.__name__ + '_hpy'
return NewClass

def monkeypatch(target):
"""
Decorator to monkey patch a function in a module. The original function
will be available as new_function.super()
"""
def decorator(fn):
name = fn.__name__
fn.super = getattr(target, name)
setattr(target, name, fn)
return fn
return decorator


class build_ext_hpy_mixin:
""" A mixin class to override setuptools.commands.build_ext """
Expand Down
21 changes: 21 additions & 0 deletions test/test_distutils.py
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,27 @@ def test_hpy_ext_modules_setup_install(self):
capture=True)
assert out == 'hpymod CPython ABI'

def test_hpy_ext_modules_universal_setup_install(self):
# first basic HPy test
self.gen_setup_py("""
setup(name = "hpy_test_project",
hpy_ext_modules = [hpymod],
)
""")
self.run('python', 'setup.py', '--hpy-abi=universal', 'install')
#
# check that we generated the .py shim
build = self.hpy_test_project.join('build')
lib = build.listdir('lib*')[0]
hpymod_py = lib.join('hpymod.py')
assert hpymod_py.check(exists=True)
assert 'This file is automatically generated by hpy' in hpymod_py.read()
#
# check that we can actually import the module
out = self.run('python', '-c', 'import hpymod; print(hpymod.__doc__)',
capture=True)
assert out == 'hpymod Universal ABI'

def test_hpy_ext_modules_build_platlib(self):
# check that if we have only hpy_ext_modules, the distribution is
# detected as "platform-specific" and not "platform-neutral". In
Expand Down

0 comments on commit 7110dd1

Please sign in to comment.