From d6948c636f5e657ac56911b71b7a459d326d8389 Mon Sep 17 00:00:00 2001 From: Benoit Pierre Date: Sun, 29 Apr 2018 19:47:42 +0200 Subject: dist: re-implement `fetch_build_egg` to use pip --- setuptools/installer.py | 129 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 129 insertions(+) create mode 100644 setuptools/installer.py (limited to 'setuptools/installer.py') diff --git a/setuptools/installer.py b/setuptools/installer.py new file mode 100644 index 00000000..35bc3cc5 --- /dev/null +++ b/setuptools/installer.py @@ -0,0 +1,129 @@ +import glob +import os +import subprocess +import sys +from distutils import log +from distutils.errors import DistutilsError + +import pkg_resources +from setuptools.command.easy_install import easy_install +from setuptools.wheel import Wheel + +from .py31compat import TemporaryDirectory + + +def _legacy_fetch_build_egg(dist, req): + """Fetch an egg needed for building. + + Legacy path using EasyInstall. + """ + tmp_dist = dist.__class__({'script_args': ['easy_install']}) + opts = tmp_dist.get_option_dict('easy_install') + opts.clear() + opts.update( + (k, v) + for k, v in dist.get_option_dict('easy_install').items() + if k in ( + # don't use any other settings + 'find_links', 'site_dirs', 'index_url', + 'optimize', 'site_dirs', 'allow_hosts', + )) + if dist.dependency_links: + links = dist.dependency_links[:] + if 'find_links' in opts: + links = opts['find_links'][1] + links + opts['find_links'] = ('setup', links) + install_dir = dist.get_egg_cache_dir() + cmd = easy_install( + tmp_dist, args=["x"], install_dir=install_dir, + exclude_scripts=True, + always_copy=False, build_directory=None, editable=False, + upgrade=False, multi_version=True, no_report=True, user=False + ) + cmd.ensure_finalized() + return cmd.easy_install(req) + + +def fetch_build_egg(dist, req): + """Fetch an egg needed for building. + + Use pip/wheel to fetch/build a wheel.""" + # Check pip is available. + try: + pkg_resources.get_distribution('pip') + except pkg_resources.DistributionNotFound: + dist.announce( + 'WARNING: The pip package is not available, falling back ' + 'to EasyInstall for handling setup_requires/test_requires; ' + 'this is deprecated and will be removed in a future version.' + , log.WARN + ) + return _legacy_fetch_build_egg(dist, req) + # Warn if wheel is not. + try: + pkg_resources.get_distribution('wheel') + except pkg_resources.DistributionNotFound: + dist.announce('WARNING: The wheel package is not available.', log.WARN) + if not isinstance(req, pkg_resources.Requirement): + req = pkg_resources.Requirement.parse(req) + # Take easy_install options into account, but do not override relevant + # pip environment variables (like PIP_INDEX_URL or PIP_QUIET); they'll + # take precedence. + opts = dist.get_option_dict('easy_install') + if 'allow_hosts' in opts: + raise DistutilsError('the `allow-hosts` option is not supported ' + 'when using pip to install requirements.') + if 'PIP_QUIET' in os.environ or 'PIP_VERBOSE' in os.environ: + quiet = False + else: + quiet = True + if 'PIP_INDEX_URL' in os.environ: + index_url = None + elif 'index_url' in opts: + index_url = opts['index_url'][1] + else: + index_url = None + if 'find_links' in opts: + find_links = opts['find_links'][1][:] + else: + find_links = [] + if dist.dependency_links: + find_links.extend(dist.dependency_links) + eggs_dir = os.path.realpath(dist.get_egg_cache_dir()) + environment = pkg_resources.Environment() + for egg_dist in pkg_resources.find_distributions(eggs_dir): + if egg_dist in req and environment.can_add(egg_dist): + return egg_dist + with TemporaryDirectory() as tmpdir: + cmd = [ + sys.executable, '-m', 'pip', + '--disable-pip-version-check', + 'wheel', '--no-deps', + '-w', tmpdir, + ] + if quiet: + cmd.append('--quiet') + if index_url is not None: + cmd.extend(('--index-url', index_url)) + if find_links is not None: + for link in find_links: + cmd.extend(('--find-links', link)) + # If requirement is a PEP 508 direct URL, directly pass + # the URL to pip, as `req @ url` does not work on the + # command line. + if req.url: + cmd.append(req.url) + else: + cmd.append(str(req)) + try: + subprocess.check_call(cmd) + except subprocess.CalledProcessError as e: + raise DistutilsError(str(e)) + wheel = Wheel(glob.glob(os.path.join(tmpdir, '*.whl'))[0]) + dist_location = os.path.join(eggs_dir, wheel.egg_name()) + wheel.install_as_egg(dist_location) + dist_metadata = pkg_resources.PathMetadata( + dist_location, os.path.join(dist_location, 'EGG-INFO')) + dist = pkg_resources.Distribution.from_filename( + dist_location, metadata=dist_metadata) + return dist -- cgit v1.2.1 From 6f46a4b703d4db225e96bb871e1bf6a7c3597329 Mon Sep 17 00:00:00 2001 From: Benoit Pierre Date: Tue, 26 Nov 2019 18:46:34 +0100 Subject: fix support for easy_install's find-links option in setup.cfg --- setuptools/installer.py | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'setuptools/installer.py') diff --git a/setuptools/installer.py b/setuptools/installer.py index 35bc3cc5..a5816608 100644 --- a/setuptools/installer.py +++ b/setuptools/installer.py @@ -7,11 +7,20 @@ from distutils.errors import DistutilsError import pkg_resources from setuptools.command.easy_install import easy_install +from setuptools.extern import six from setuptools.wheel import Wheel from .py31compat import TemporaryDirectory +def _fixup_find_links(find_links): + """Ensure find-links option end-up being a list of strings.""" + if isinstance(find_links, six.string_types): + return find_links.split() + assert isinstance(find_links, (tuple, list)) + return find_links + + def _legacy_fetch_build_egg(dist, req): """Fetch an egg needed for building. @@ -31,7 +40,7 @@ def _legacy_fetch_build_egg(dist, req): if dist.dependency_links: links = dist.dependency_links[:] if 'find_links' in opts: - links = opts['find_links'][1] + links + links = _fixup_find_links(opts['find_links'][1]) + links opts['find_links'] = ('setup', links) install_dir = dist.get_egg_cache_dir() cmd = easy_install( @@ -84,7 +93,7 @@ def fetch_build_egg(dist, req): else: index_url = None if 'find_links' in opts: - find_links = opts['find_links'][1][:] + find_links = _fixup_find_links(opts['find_links'][1])[:] else: find_links = [] if dist.dependency_links: -- cgit v1.2.1 From 7502dc9ca767927db9599f93cd48851ca59f7a62 Mon Sep 17 00:00:00 2001 From: Benoit Pierre Date: Tue, 26 Nov 2019 20:56:57 +0100 Subject: fix possible issue with transitive build dependencies Handle the case where a missing transitive build dependency is required by an extra for an already installed build dependency. --- setuptools/installer.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'setuptools/installer.py') diff --git a/setuptools/installer.py b/setuptools/installer.py index 35bc3cc5..ba9cfce9 100644 --- a/setuptools/installer.py +++ b/setuptools/installer.py @@ -64,8 +64,11 @@ def fetch_build_egg(dist, req): pkg_resources.get_distribution('wheel') except pkg_resources.DistributionNotFound: dist.announce('WARNING: The wheel package is not available.', log.WARN) - if not isinstance(req, pkg_resources.Requirement): - req = pkg_resources.Requirement.parse(req) + # Ignore environment markers: if we're here, it's needed. This ensure + # we don't try to ask pip for something like `babel; extra == "i18n"`, + # which would always be ignored. + req = pkg_resources.Requirement.parse(str(req)) + req.marker = None # Take easy_install options into account, but do not override relevant # pip environment variables (like PIP_INDEX_URL or PIP_QUIET); they'll # take precedence. -- cgit v1.2.1 From a2e883e1b838db529d992d4c6c8ab73c16f48591 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 1 Dec 2019 09:38:13 -0500 Subject: Extract function to strip the marker for concise code in the long function. --- setuptools/installer.py | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) (limited to 'setuptools/installer.py') diff --git a/setuptools/installer.py b/setuptools/installer.py index ba9cfce9..527b95de 100644 --- a/setuptools/installer.py +++ b/setuptools/installer.py @@ -64,11 +64,8 @@ def fetch_build_egg(dist, req): pkg_resources.get_distribution('wheel') except pkg_resources.DistributionNotFound: dist.announce('WARNING: The wheel package is not available.', log.WARN) - # Ignore environment markers: if we're here, it's needed. This ensure - # we don't try to ask pip for something like `babel; extra == "i18n"`, - # which would always be ignored. - req = pkg_resources.Requirement.parse(str(req)) - req.marker = None + # Ignore environment markers; if supplied, it is required. + req = strip_marker(req) # Take easy_install options into account, but do not override relevant # pip environment variables (like PIP_INDEX_URL or PIP_QUIET); they'll # take precedence. @@ -130,3 +127,15 @@ def fetch_build_egg(dist, req): dist = pkg_resources.Distribution.from_filename( dist_location, metadata=dist_metadata) return dist + + +def strip_marker(req): + """ + Return a new requirement without the environment marker to avoid + calling pip with something like `babel; extra == "i18n"`, which + would always be ignored. + """ + # create a copy to avoid mutating the input + req = pkg_resources.Requirement.parse(str(req)) + req.marker = None + return req -- cgit v1.2.1 From 3d4d8b9dde61b87271861b8c7ebeb168ac4fa72b Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 19 Jan 2020 12:46:30 -0500 Subject: =?UTF-8?q?=F0=9F=91=B9=20Feed=20the=20hobgoblins=20(delint).?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- setuptools/installer.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'setuptools/installer.py') diff --git a/setuptools/installer.py b/setuptools/installer.py index 9f8be2ef..1f183bd9 100644 --- a/setuptools/installer.py +++ b/setuptools/installer.py @@ -64,8 +64,8 @@ def fetch_build_egg(dist, req): dist.announce( 'WARNING: The pip package is not available, falling back ' 'to EasyInstall for handling setup_requires/test_requires; ' - 'this is deprecated and will be removed in a future version.' - , log.WARN + 'this is deprecated and will be removed in a future version.', + log.WARN ) return _legacy_fetch_build_egg(dist, req) # Warn if wheel is not. -- cgit v1.2.1 From a9eb9e73def8ca6c469e59f1b008746e368ad4c1 Mon Sep 17 00:00:00 2001 From: Ram Rachum Date: Tue, 16 Jun 2020 13:31:12 +0300 Subject: Fix exception causes all over the codebase --- setuptools/installer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'setuptools/installer.py') diff --git a/setuptools/installer.py b/setuptools/installer.py index 1f183bd9..e5acec27 100644 --- a/setuptools/installer.py +++ b/setuptools/installer.py @@ -127,7 +127,7 @@ def fetch_build_egg(dist, req): try: subprocess.check_call(cmd) except subprocess.CalledProcessError as e: - raise DistutilsError(str(e)) + raise DistutilsError(str(e)) from e wheel = Wheel(glob.glob(os.path.join(tmpdir, '*.whl'))[0]) dist_location = os.path.join(eggs_dir, wheel.egg_name()) wheel.install_as_egg(dist_location) -- cgit v1.2.1 From fb7ab81a3d080422687bad71f9ae9d36eeefbee2 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 16 Aug 2020 00:29:24 -0400 Subject: Remove Python 2 compatibility --- setuptools/installer.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'setuptools/installer.py') diff --git a/setuptools/installer.py b/setuptools/installer.py index e5acec27..e630b874 100644 --- a/setuptools/installer.py +++ b/setuptools/installer.py @@ -2,20 +2,18 @@ import glob import os import subprocess import sys +import tempfile from distutils import log from distutils.errors import DistutilsError import pkg_resources from setuptools.command.easy_install import easy_install -from setuptools.extern import six from setuptools.wheel import Wheel -from .py31compat import TemporaryDirectory - def _fixup_find_links(find_links): """Ensure find-links option end-up being a list of strings.""" - if isinstance(find_links, six.string_types): + if isinstance(find_links, str): return find_links.split() assert isinstance(find_links, (tuple, list)) return find_links @@ -103,7 +101,7 @@ def fetch_build_egg(dist, req): for egg_dist in pkg_resources.find_distributions(eggs_dir): if egg_dist in req and environment.can_add(egg_dist): return egg_dist - with TemporaryDirectory() as tmpdir: + with tempfile.TemporaryDirectory() as tmpdir: cmd = [ sys.executable, '-m', 'pip', '--disable-pip-version-check', -- cgit v1.2.1 From 9c88e35e0e54712f8ac361faffe5bc9cd370ad8d Mon Sep 17 00:00:00 2001 From: Sviatoslav Sydorenko Date: Thu, 31 Dec 2020 18:02:31 +0100 Subject: Simplify `setuptools.installer.fetch_build_egg` --- setuptools/installer.py | 23 ++++++++--------------- 1 file changed, 8 insertions(+), 15 deletions(-) (limited to 'setuptools/installer.py') diff --git a/setuptools/installer.py b/setuptools/installer.py index e630b874..ac2aba18 100644 --- a/setuptools/installer.py +++ b/setuptools/installer.py @@ -80,20 +80,17 @@ def fetch_build_egg(dist, req): if 'allow_hosts' in opts: raise DistutilsError('the `allow-hosts` option is not supported ' 'when using pip to install requirements.') - if 'PIP_QUIET' in os.environ or 'PIP_VERBOSE' in os.environ: - quiet = False - else: - quiet = True + quiet = 'PIP_QUIET' not in os.environ and 'PIP_VERBOSE' not in os.environ if 'PIP_INDEX_URL' in os.environ: index_url = None elif 'index_url' in opts: index_url = opts['index_url'][1] else: index_url = None - if 'find_links' in opts: - find_links = _fixup_find_links(opts['find_links'][1])[:] - else: - find_links = [] + find_links = ( + _fixup_find_links(opts['find_links'][1])[:] if 'find_links' in opts + else [] + ) if dist.dependency_links: find_links.extend(dist.dependency_links) eggs_dir = os.path.realpath(dist.get_egg_cache_dir()) @@ -112,16 +109,12 @@ def fetch_build_egg(dist, req): cmd.append('--quiet') if index_url is not None: cmd.extend(('--index-url', index_url)) - if find_links is not None: - for link in find_links: - cmd.extend(('--find-links', link)) + for link in find_links or []: + cmd.extend(('--find-links', link)) # If requirement is a PEP 508 direct URL, directly pass # the URL to pip, as `req @ url` does not work on the # command line. - if req.url: - cmd.append(req.url) - else: - cmd.append(str(req)) + cmd.append(req.url or str(req)) try: subprocess.check_call(cmd) except subprocess.CalledProcessError as e: -- cgit v1.2.1 From fc891f5cf6d93ad533e2afb5e15a2952408ab358 Mon Sep 17 00:00:00 2001 From: Sviatoslav Sydorenko Date: Thu, 31 Dec 2020 13:08:18 +0100 Subject: Apply noqa C901 comments to overly complex code --- setuptools/installer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'setuptools/installer.py') diff --git a/setuptools/installer.py b/setuptools/installer.py index ac2aba18..c5822a31 100644 --- a/setuptools/installer.py +++ b/setuptools/installer.py @@ -51,7 +51,7 @@ def _legacy_fetch_build_egg(dist, req): return cmd.easy_install(req) -def fetch_build_egg(dist, req): +def fetch_build_egg(dist, req): # noqa: C901 # is too complex (16) # FIXME """Fetch an egg needed for building. Use pip/wheel to fetch/build a wheel.""" -- cgit v1.2.1 From fbb705406dca3e8a41ac6be4a28e1611102cac5c Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 17 Jan 2021 01:36:19 -0500 Subject: Remove support for easy_install-based downloads for fetch_build_eggs (setup_requires). --- setuptools/installer.py | 46 +--------------------------------------------- 1 file changed, 1 insertion(+), 45 deletions(-) (limited to 'setuptools/installer.py') diff --git a/setuptools/installer.py b/setuptools/installer.py index c5822a31..57e2b587 100644 --- a/setuptools/installer.py +++ b/setuptools/installer.py @@ -7,7 +7,6 @@ from distutils import log from distutils.errors import DistutilsError import pkg_resources -from setuptools.command.easy_install import easy_install from setuptools.wheel import Wheel @@ -19,54 +18,11 @@ def _fixup_find_links(find_links): return find_links -def _legacy_fetch_build_egg(dist, req): - """Fetch an egg needed for building. - - Legacy path using EasyInstall. - """ - tmp_dist = dist.__class__({'script_args': ['easy_install']}) - opts = tmp_dist.get_option_dict('easy_install') - opts.clear() - opts.update( - (k, v) - for k, v in dist.get_option_dict('easy_install').items() - if k in ( - # don't use any other settings - 'find_links', 'site_dirs', 'index_url', - 'optimize', 'site_dirs', 'allow_hosts', - )) - if dist.dependency_links: - links = dist.dependency_links[:] - if 'find_links' in opts: - links = _fixup_find_links(opts['find_links'][1]) + links - opts['find_links'] = ('setup', links) - install_dir = dist.get_egg_cache_dir() - cmd = easy_install( - tmp_dist, args=["x"], install_dir=install_dir, - exclude_scripts=True, - always_copy=False, build_directory=None, editable=False, - upgrade=False, multi_version=True, no_report=True, user=False - ) - cmd.ensure_finalized() - return cmd.easy_install(req) - - def fetch_build_egg(dist, req): # noqa: C901 # is too complex (16) # FIXME """Fetch an egg needed for building. Use pip/wheel to fetch/build a wheel.""" - # Check pip is available. - try: - pkg_resources.get_distribution('pip') - except pkg_resources.DistributionNotFound: - dist.announce( - 'WARNING: The pip package is not available, falling back ' - 'to EasyInstall for handling setup_requires/test_requires; ' - 'this is deprecated and will be removed in a future version.', - log.WARN - ) - return _legacy_fetch_build_egg(dist, req) - # Warn if wheel is not. + # Warn if wheel is not available try: pkg_resources.get_distribution('wheel') except pkg_resources.DistributionNotFound: -- cgit v1.2.1