Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 61 additions & 10 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
from distutils import log

from setuptools import setup, find_packages, Distribution
from setuptools.command.build_py import build_py as _build_py
from setuptools.command.build_ext import build_ext as _build_ext
from setuptools.command.sdist import sdist as _sdist

import os
import os.path
Expand Down Expand Up @@ -65,18 +68,39 @@ def run(self):

class PyrobufDistribution(Distribution):

def run_commands(self):
# By now the setup_requires deps have been fetched.
def __init__(self, attrs=None):
super().__init__(attrs)
self._pyrobuf_builtins_rendered = False
self._pyrobuf_builtins_added = False

def has_ext_modules(self):
return True

def ensure_pyrobuf_builtins(self):
if self._pyrobuf_builtins_added:
return

if not self.ext_modules:
self.ext_modules = list()
self.ext_modules.extend(self.pyrobufize_builtins())
Distribution.run_commands(self)
self.ext_modules = []

self.render_pyrobuf_builtins()
builtin_ext_modules = self.pyrobufize_builtins()
for ext in builtin_ext_modules:
if not hasattr(ext, '_needs_stub'):
ext._needs_stub = False

self.ext_modules.extend(builtin_ext_modules)
self._pyrobuf_builtins_added = True

def render_pyrobuf_builtins(self):
if self._pyrobuf_builtins_rendered:
return

def pyrobufize_builtins(self):
from jinja2 import Environment, PackageLoader
from Cython.Build import cythonize
env = Environment(loader=PackageLoader('pyrobuf.protobuf', 'templates'))

dry_run = getattr(self, 'dry_run', False)

templ_pyx = env.get_template('pyrobuf_list_pyx.tmpl')
templ_pxd = env.get_template('pyrobuf_list_pxd.tmpl')

Expand Down Expand Up @@ -106,7 +130,7 @@ def pyrobufize_builtins(self):
# Even if PYROBUF_LIST_PYX and PYROBUF_LIST_PXD already exist they should be re-built because
# we don't know whether they were built using *this* version of Python.
path = os.path.join(HERE, 'pyrobuf', 'src', PYROBUF_LIST_PYX)
if not self.dry_run:
if not dry_run:
with open(path, 'w') as fp:
fp.write(templ_pyx.render(
{'def': listdict, 'version_major': sys.version_info.major, 'format_map': format_map}
Expand All @@ -115,7 +139,7 @@ def pyrobufize_builtins(self):
log.info("rendering '%s' from '%s'" % (PYROBUF_LIST_PYX, templ_pyx.filename))

path = os.path.join(HERE, 'pyrobuf', 'src', PYROBUF_LIST_PXD)
if not self.dry_run:
if not dry_run:
with open(path, 'w') as fp:
fp.write(templ_pxd.render(
{'def': listdict, 'version_major': sys.version_info.major, 'format_map': format_map}
Expand All @@ -131,17 +155,44 @@ def pyrobufize_builtins(self):
defs.write('\n'.join('DEF PYROBUF_UNAME_%s = "%s"' % (k, v) for k, v in uname))
defs.write('\n')

self._pyrobuf_builtins_rendered = True

def pyrobufize_builtins(self):
from Cython.Build import cythonize

return cythonize(['pyrobuf/src/*.pyx'],
include_path=['pyrobuf/src'])


class build_py(_build_py):

def run(self):
self.distribution.render_pyrobuf_builtins()
_build_py.run(self)


class sdist(_sdist):

def run(self):
self.distribution.render_pyrobuf_builtins()
_sdist.run(self)


class build_ext(_build_ext):

def run(self):
self.distribution.ensure_pyrobuf_builtins()
self.extensions = self.distribution.ext_modules
_build_ext.run(self)


setup(
distclass=PyrobufDistribution,
name="pyrobuf",
version=VERSION,
packages=find_packages(),
include_package_data=True,
cmdclass={'clean': clean},
cmdclass={'build_py': build_py, 'build_ext': build_ext, 'clean': clean, 'sdist': sdist},
entry_points={
'console_scripts': ['pyrobuf = pyrobuf.__main__:main'],
'distutils.setup_keywords': [
Expand Down
47 changes: 47 additions & 0 deletions tests/test_setup_metadata.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import os
import subprocess
import sys
import zipfile


def test_setup_dist_info_succeeds(tmp_path):
root = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
cmd = [sys.executable, 'setup.py', 'egg_info', '--egg-base', str(tmp_path)]

proc = subprocess.run(
cmd,
cwd=root,
capture_output=True,
text=True,
)

output = proc.stdout + proc.stderr

assert proc.returncode == 0, output
assert "rendering 'pyrobuf_list.pyx'" not in output
assert 'Cythonizing pyrobuf/src' not in output


def test_wheel_contains_generated_builtin_headers(tmp_path):
root = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
cmd = [sys.executable, 'setup.py', 'bdist_wheel', '--dist-dir', str(tmp_path)]

proc = subprocess.run(
cmd,
cwd=root,
capture_output=True,
text=True,
)

output = proc.stdout + proc.stderr

assert proc.returncode == 0, output

wheels = sorted(tmp_path.glob('pyrobuf-*.whl'))
assert wheels, output

with zipfile.ZipFile(str(wheels[0])) as archive:
names = set(archive.namelist())

assert 'pyrobuf/src/pyrobuf_list.pxd' in names
assert 'pyrobuf/src/pyrobuf_list.pyx' in names