From 334e9e6fa205eb3f8ebb798d47444856bf973a9d Mon Sep 17 00:00:00 2001 From: Masood Malekghassemi Date: Wed, 10 Feb 2016 20:12:59 -0800 Subject: Use wheels instead for custom bdists --- requirements.txt | 1 + setup.py | 2 +- src/python/grpcio/commands.py | 88 ++++++++++++++++---------------- tools/run_tests/build_artifact_python.sh | 2 +- 4 files changed, 46 insertions(+), 47 deletions(-) diff --git a/requirements.txt b/requirements.txt index a1cc88cfe7..e3208e6355 100644 --- a/requirements.txt +++ b/requirements.txt @@ -4,3 +4,4 @@ futures>=2.2.0 cython>=0.23 coverage>=4.0 six>=1.10 +wheel>=0.29 diff --git a/setup.py b/setup.py index f8450a7677..7da070ef0f 100644 --- a/setup.py +++ b/setup.py @@ -164,7 +164,7 @@ COMMAND_CLASS = { '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: diff --git a/src/python/grpcio/commands.py b/src/python/grpcio/commands.py index 774e7ad6a1..1561bbf05e 100644 --- a/src/python/grpcio/commands.py +++ b/src/python/grpcio/commands.py @@ -41,12 +41,12 @@ import sys 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 @@ -59,6 +59,8 @@ BINARIES_REPOSITORY = os.environ.get( 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 @@ -74,46 +76,52 @@ 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) @@ -121,7 +129,7 @@ class EggNameMixin(object): 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 @@ -147,15 +155,15 @@ class Install(install.install, EggNameMixin): 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 @@ -171,29 +179,19 @@ class Install(install.install, EggNameMixin): # 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): diff --git a/tools/run_tests/build_artifact_python.sh b/tools/run_tests/build_artifact_python.sh index 835fad83e1..f22ddd9185 100755 --- a/tools/run_tests/build_artifact_python.sh +++ b/tools/run_tests/build_artifact_python.sh @@ -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 -- cgit v1.2.3