Skip to content

Commit

Permalink
Use wheels instead for custom bdists
Browse files Browse the repository at this point in the history
  • Loading branch information
soltanmm-google committed Feb 11, 2016
1 parent 09b1950 commit 334e9e6
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 47 deletions.
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ futures>=2.2.0
cython>=0.23
coverage>=4.0
six>=1.10
wheel>=0.29
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ def cython_extensions(package_names, module_names, extra_sources, include_dirs,
'build_ext': commands.BuildExt,
'gather': commands.Gather,
'run_interop': commands.RunInterop,
'bdist_egg_grpc_custom': commands.BdistEggCustomName,
'bdist_wheel_grpc_custom': commands.BdistWheelCustomName,
}

# Ensure that package data is copied over before any commands have been run:
Expand Down
88 changes: 43 additions & 45 deletions src/python/grpcio/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,12 @@
import traceback

import setuptools
from setuptools.command import bdist_egg
from setuptools.command import build_ext
from setuptools.command import build_py
from setuptools.command import easy_install
from setuptools.command import install
from setuptools.command import test
from wheel import bdist_wheel

import support

Expand All @@ -59,6 +59,8 @@
USE_GRPC_CUSTOM_BDIST = bool(int(os.environ.get(
'GRPC_PYTHON_USE_CUSTOM_BDIST', '1')))

GRPC_CUSTOM_BDIST_EXT = '.whl'

CONF_PY_ADDENDUM = """
extensions.append('sphinx.ext.napoleon')
napoleon_google_docstring = True
Expand All @@ -74,54 +76,60 @@ class CommandError(Exception):

# TODO(atash): Remove this once PyPI has better Linux bdist support. See
# https://bitbucket.org/pypa/pypi/issues/120/binary-wheels-for-linux-are-not-supported
def _get_grpc_custom_bdist_egg(decorated_basename, target_egg_basename):
"""Returns a string path to a .egg file for Linux to install.
def _get_grpc_custom_bdist(decorated_basename, target_bdist_basename):
"""Returns a string path to a bdist file for Linux to install.
If we can retrieve a pre-compiled egg from online, uses it. Else, emits a
If we can retrieve a pre-compiled bdist from online, uses it. Else, emits a
warning and builds from source.
"""
# TODO(atash): somehow the name that's returned from `wheel` is different
# between different versions of 'wheel' (but from a compatibility standpoint,
# the names are compatible); we should have some way of determining name
# compatibility in the same way `wheel` does to avoid having to rename all of
# the custom wheels that we build/upload to GCS.

# Break import style to ensure that setup.py has had a chance to install the
# relevant package eggs.
# relevant package.
from six.moves.urllib import request
decorated_path = decorated_basename + '.egg'
decorated_path = decorated_basename + GRPC_CUSTOM_BDIST_EXT
try:
url = BINARIES_REPOSITORY + '/{target}'.format(target=decorated_path)
egg_data = request.urlopen(url).read()
bdist_data = request.urlopen(url).read()
except IOError as error:
raise CommandError(
'{}\n\nCould not find the bdist egg {}: {}'
'{}\n\nCould not find the bdist {}: {}'
.format(traceback.format_exc(), decorated_path, error.message))
# Our chosen local egg path.
egg_path = target_egg_basename + '.egg'
# Our chosen local bdist path.
bdist_path = target_bdist_basename + GRPC_CUSTOM_BDIST_EXT
try:
with open(egg_path, 'w') as egg_file:
egg_file.write(egg_data)
with open(bdist_path, 'w') as bdist_file:
bdist_file.write(bdist_data)
except IOError as error:
raise CommandError(
'{}\n\nCould not write grpcio egg: {}'
'{}\n\nCould not write grpcio bdist: {}'
.format(traceback.format_exc(), error.message))
return egg_path
return bdist_path


class EggNameMixin(object):
"""Mixin for setuptools.Command classes to enable acquiring the egg name."""
class WheelNameMixin(object):
"""Mixin for setuptools.Command classes to enable acquiring the bdist name."""

def egg_name(self, with_custom):
def wheel_name(self, with_custom):
"""
Args:
with_custom: Boolean describing whether or not to decorate the egg name
with_custom: Boolean describing whether or not to decorate the bdist name
with custom gRPC-specific target information.
"""
egg_command = self.get_finalized_command('bdist_egg')
base = os.path.splitext(os.path.basename(egg_command.egg_output))[0]
wheel_command = self.get_finalized_command('bdist_wheel')
base = wheel_command.get_archive_basename()
if with_custom:
flavor = 'ucs2' if sys.maxunicode == 65535 else 'ucs4'
return '{base}-{flavor}'.format(base=base, flavor=flavor)
else:
return base


class Install(install.install, EggNameMixin):
class Install(install.install, WheelNameMixin):
"""Custom Install command for gRPC Python.
This is for bdist shims and whatever else we might need a custom install
Expand All @@ -147,15 +155,15 @@ def run(self):
if self.use_grpc_custom_bdist:
try:
try:
egg_path = _get_grpc_custom_bdist_egg(self.egg_name(True),
self.egg_name(False))
bdist_path = _get_grpc_custom_bdist(self.wheel_name(True),
self.wheel_name(False))
except CommandError as error:
sys.stderr.write(
'\nWARNING: Failed to acquire grpcio prebuilt binary:\n'
'{}.\n\n'.format(error.message))
raise
try:
self._run_bdist_retrieval_install(egg_path)
self._run_bdist_retrieval_install(bdist_path)
except Exception as error:
# if anything else happens (and given how there's no way to really know
# what's happening in setuptools here, I mean *anything*), warn the user
Expand All @@ -171,29 +179,19 @@ def run(self):

# TODO(atash): Remove this once PyPI has better Linux bdist support. See
# https://bitbucket.org/pypa/pypi/issues/120/binary-wheels-for-linux-are-not-supported
def _run_bdist_retrieval_install(self, bdist_egg):
easy_install = self.distribution.get_command_class('easy_install')
easy_install_command = easy_install(
self.distribution, args='x', root=self.root, record=self.record,
)
easy_install_command.ensure_finalized()
easy_install_command.always_copy_from = '.'
easy_install_command.package_index.scan(glob.glob('*.egg'))
arguments = [bdist_egg]
if setuptools.bootstrap_install_from:
args.insert(0, setuptools.bootstrap_install_from)
easy_install_command.args = arguments
easy_install_command.run()
setuptools.bootstrap_install_from = None


class BdistEggCustomName(bdist_egg.bdist_egg, EggNameMixin):
"""Thin wrapper around the bdist_egg command to build with our custom name."""
def _run_bdist_retrieval_install(self, bdist_path):
import pip
pip.main(['install', bdist_path])


class BdistWheelCustomName(bdist_wheel.bdist_wheel, WheelNameMixin):
"""Thin wrapper around the bdist command to build with our custom name."""

def run(self):
bdist_egg.bdist_egg.run(self)
target = os.path.join(self.dist_dir, '{}.egg'.format(self.egg_name(True)))
shutil.move(self.get_outputs()[0], target)
bdist_wheel.bdist_wheel.run(self)
output = self.distribution.dist_files[-1][2]
target = os.path.join(self.dist_dir, '{}.whl'.format(self.wheel_name(True)))
shutil.move(output, target)


class SphinxDocumentation(setuptools.Command):
Expand Down
2 changes: 1 addition & 1 deletion tools/run_tests/build_artifact_python.sh
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ GRPC_PYTHON_BUILD_WITH_CYTHON=1 \
${SETARCH_CMD} python setup.py \
bdist_wheel \
sdist \
bdist_egg_grpc_custom
bdist_wheel_grpc_custom

mkdir -p artifacts

Expand Down

0 comments on commit 334e9e6

Please sign in to comment.