From 118edbb2b715c96620b51018c1d28e81f2318053 Mon Sep 17 00:00:00 2001 From: Benoit Pierre Date: Thu, 2 Nov 2017 21:19:39 +0100 Subject: easy_install: add support for installing from wheels Note: wheels are installed as eggs, so each install is self-contained and multiple versions of the same package can be installed at the same time. Limitations: - headers are not supported - resulting egg metadata requirements have their markers stripped --- setuptools/wheel.py | 125 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 125 insertions(+) create mode 100644 setuptools/wheel.py (limited to 'setuptools/wheel.py') diff --git a/setuptools/wheel.py b/setuptools/wheel.py new file mode 100644 index 00000000..6e3df77c --- /dev/null +++ b/setuptools/wheel.py @@ -0,0 +1,125 @@ +'''Wheels support.''' + +from distutils.util import get_platform +import email +import itertools +import os +import re +import zipfile + +from pkg_resources import Distribution, PathMetadata, parse_version +from setuptools import Distribution as SetuptoolsDistribution +from setuptools import pep425tags +from setuptools.command.egg_info import write_requirements + + +WHEEL_NAME = re.compile( + r"""^(?P.+?)-(?P\d.*?) + ((-(?P\d.*?))?-(?P.+?)-(?P.+?)-(?P.+?) + )\.whl$""", +re.VERBOSE).match + + +class Wheel(object): + + def __init__(self, filename): + match = WHEEL_NAME(os.path.basename(filename)) + if match is None: + raise ValueError('invalid wheel name: %r' % filename) + self.filename = filename + for k, v in match.groupdict().items(): + setattr(self, k, v) + + def tags(self): + '''List tags (py_version, abi, platform) supported by this wheel.''' + return itertools.product(self.py_version.split('.'), + self.abi.split('.'), + self.platform.split('.')) + + def is_compatible(self): + '''Is the wheel is compatible with the current platform?''' + supported_tags = pep425tags.get_supported() + return next((True for t in self.tags() if t in supported_tags), False) + + def egg_name(self): + return Distribution( + project_name=self.project_name, version=self.version, + platform=(None if self.platform == 'any' else get_platform()), + ).egg_name() + '.egg' + + def install_as_egg(self, destination_eggdir): + '''Install wheel as an egg directory.''' + with zipfile.ZipFile(self.filename) as zf: + dist_basename = '%s-%s' % (self.project_name, self.version) + dist_info = '%s.dist-info' % dist_basename + dist_data = '%s.data' % dist_basename + def get_metadata(name): + with zf.open('%s/%s' % (dist_info, name)) as fp: + value = fp.read().decode('utf-8') + return email.parser.Parser().parsestr(value) + wheel_metadata = get_metadata('WHEEL') + dist_metadata = get_metadata('METADATA') + # Check wheel format version is supported. + wheel_version = parse_version(wheel_metadata.get('Wheel-Version')) + if not parse_version('1.0') <= wheel_version < parse_version('2.0dev0'): + raise ValueError('unsupported wheel format version: %s' % wheel_version) + # Extract to target directory. + os.mkdir(destination_eggdir) + zf.extractall(destination_eggdir) + # Convert metadata. + dist_info = os.path.join(destination_eggdir, dist_info) + dist = Distribution.from_location( + destination_eggdir, dist_info, + metadata=PathMetadata(destination_eggdir, dist_info) + ) + # Note: we need to evaluate and strip markers now, + # as we can't easily convert back from the syntax: + # foobar; "linux" in sys_platform and extra == 'test' + def raw_req(req): + req.marker = None + return str(req) + install_requires = list(sorted(map(raw_req, dist.requires()))) + extras_require = { + extra: list(sorted( + req + for req in map(raw_req, dist.requires((extra,))) + if req not in install_requires + )) + for extra in dist.extras + } + egg_info = os.path.join(destination_eggdir, 'EGG-INFO') + os.rename(dist_info, egg_info) + os.rename(os.path.join(egg_info, 'METADATA'), + os.path.join(egg_info, 'PKG-INFO')) + setup_dist = SetuptoolsDistribution(attrs=dict( + install_requires=install_requires, + extras_require=extras_require, + )) + write_requirements(setup_dist.get_command_obj('egg_info'), + None, os.path.join(egg_info, 'requires.txt')) + # Move data entries to their correct location. + dist_data = os.path.join(destination_eggdir, dist_data) + dist_data_scripts = os.path.join(dist_data, 'scripts') + if os.path.exists(dist_data_scripts): + egg_info_scripts = os.path.join(destination_eggdir, + 'EGG-INFO', 'scripts') + os.mkdir(egg_info_scripts) + for entry in os.listdir(dist_data_scripts): + # Remove bytecode, as it's not properly handled + # during easy_install scripts install phase. + if entry.endswith('.pyc'): + os.unlink(os.path.join(dist_data_scripts, entry)) + else: + os.rename(os.path.join(dist_data_scripts, entry), + os.path.join(egg_info_scripts, entry)) + os.rmdir(dist_data_scripts) + for subdir in filter(os.path.exists, ( + os.path.join(dist_data, d) + for d in ('data', 'headers', 'purelib', 'platlib') + )): + for entry in os.listdir(subdir): + os.rename(os.path.join(subdir, entry), + os.path.join(destination_eggdir, entry)) + os.rmdir(subdir) + if os.path.exists(dist_data): + os.rmdir(dist_data) -- cgit v1.2.1 From e72afd6243713cd0d3f8a5bc5b50fb59934d7ff8 Mon Sep 17 00:00:00 2001 From: Benoit Pierre Date: Sun, 26 Nov 2017 23:11:14 +0100 Subject: fix encoding handling of wheels metadata --- setuptools/wheel.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'setuptools/wheel.py') diff --git a/setuptools/wheel.py b/setuptools/wheel.py index 6e3df77c..f711f38b 100644 --- a/setuptools/wheel.py +++ b/setuptools/wheel.py @@ -8,6 +8,7 @@ import re import zipfile from pkg_resources import Distribution, PathMetadata, parse_version +from pkg_resources.extern.six import PY3 from setuptools import Distribution as SetuptoolsDistribution from setuptools import pep425tags from setuptools.command.egg_info import write_requirements @@ -55,7 +56,7 @@ class Wheel(object): dist_data = '%s.data' % dist_basename def get_metadata(name): with zf.open('%s/%s' % (dist_info, name)) as fp: - value = fp.read().decode('utf-8') + value = fp.read().decode('utf-8') if PY3 else fp.read() return email.parser.Parser().parsestr(value) wheel_metadata = get_metadata('WHEEL') dist_metadata = get_metadata('METADATA') -- cgit v1.2.1 From da1c78f354fac3ce177e2869828a34b3e6df1820 Mon Sep 17 00:00:00 2001 From: Benoit Pierre Date: Mon, 27 Nov 2017 13:25:04 +0100 Subject: fix namespace packages handling of wheels --- setuptools/wheel.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'setuptools/wheel.py') diff --git a/setuptools/wheel.py b/setuptools/wheel.py index f711f38b..c2327213 100644 --- a/setuptools/wheel.py +++ b/setuptools/wheel.py @@ -20,6 +20,13 @@ WHEEL_NAME = re.compile( )\.whl$""", re.VERBOSE).match +NAMESPACE_PACKAGE_INIT = '''\ +try: + __import__('pkg_resources').declare_namespace(__name__) +except ImportError: + __path__ = __import__('pkgutil').extend_path(__path__, __name__) +''' + class Wheel(object): @@ -124,3 +131,14 @@ class Wheel(object): os.rmdir(subdir) if os.path.exists(dist_data): os.rmdir(dist_data) + # Fix namespace packages. + namespace_packages = os.path.join(egg_info, 'namespace_packages.txt') + if os.path.exists(namespace_packages): + with open(namespace_packages) as fp: + namespace_packages = fp.read().split() + for mod in namespace_packages: + mod_dir = os.path.join(destination_eggdir, *mod.split('.')) + mod_init = os.path.join(mod_dir, '__init__.py') + if os.path.exists(mod_dir) and not os.path.exists(mod_init): + with open(mod_init, 'w') as fp: + fp.write(NAMESPACE_PACKAGE_INIT) -- cgit v1.2.1 From 35c0e9c2d67cbda4033ba0e0b1c20e4df8c24ce7 Mon Sep 17 00:00:00 2001 From: Benoit Pierre Date: Thu, 30 Nov 2017 19:46:16 +0100 Subject: fix `data_files` handling when installing from wheel --- setuptools/wheel.py | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) (limited to 'setuptools/wheel.py') diff --git a/setuptools/wheel.py b/setuptools/wheel.py index c2327213..9ffe434a 100644 --- a/setuptools/wheel.py +++ b/setuptools/wheel.py @@ -28,6 +28,28 @@ except ImportError: ''' +def unpack(src_dir, dst_dir): + '''Move everything under `src_dir` to `dst_dir`, and delete the former.''' + for dirpath, dirnames, filenames in os.walk(src_dir): + subdir = os.path.relpath(dirpath, src_dir) + for f in filenames: + src = os.path.join(dirpath, f) + dst = os.path.join(dst_dir, subdir, f) + os.renames(src, dst) + for n, d in reversed(list(enumerate(dirnames))): + src = os.path.join(dirpath, d) + dst = os.path.join(dst_dir, subdir, d) + if not os.path.exists(dst): + # Directory does not exist in destination, + # rename it and prune it from os.walk list. + os.renames(src, dst) + del dirnames[n] + # Cleanup. + for dirpath, dirnames, filenames in os.walk(src_dir, topdown=True): + assert not filenames + os.rmdir(dirpath) + + class Wheel(object): def __init__(self, filename): @@ -125,10 +147,7 @@ class Wheel(object): os.path.join(dist_data, d) for d in ('data', 'headers', 'purelib', 'platlib') )): - for entry in os.listdir(subdir): - os.rename(os.path.join(subdir, entry), - os.path.join(destination_eggdir, entry)) - os.rmdir(subdir) + unpack(subdir, destination_eggdir) if os.path.exists(dist_data): os.rmdir(dist_data) # Fix namespace packages. -- cgit v1.2.1 From 929acc4e551448a68411968fb50336ad51ed4d3c Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sat, 17 Mar 2018 14:10:32 -0400 Subject: Setuptools now vendors its own direct dependencies (packaging, six, pyparsing). Ref #1296. --- setuptools/wheel.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'setuptools/wheel.py') diff --git a/setuptools/wheel.py b/setuptools/wheel.py index 9ffe434a..37dfa531 100644 --- a/setuptools/wheel.py +++ b/setuptools/wheel.py @@ -8,7 +8,7 @@ import re import zipfile from pkg_resources import Distribution, PathMetadata, parse_version -from pkg_resources.extern.six import PY3 +from setuptools.extern.six import PY3 from setuptools import Distribution as SetuptoolsDistribution from setuptools import pep425tags from setuptools.command.egg_info import write_requirements -- cgit v1.2.1 From 593b409fb66efcabe046e240a868b7dbcf1fc01b Mon Sep 17 00:00:00 2001 From: Arnon Yaari Date: Mon, 14 May 2018 17:10:29 +0300 Subject: Use canonicalize_name to look for .dist-info in wheel files Fixes issue #1350 --- setuptools/wheel.py | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) (limited to 'setuptools/wheel.py') diff --git a/setuptools/wheel.py b/setuptools/wheel.py index 37dfa531..4a33b203 100644 --- a/setuptools/wheel.py +++ b/setuptools/wheel.py @@ -4,10 +4,12 @@ from distutils.util import get_platform import email import itertools import os +import posixpath import re import zipfile from pkg_resources import Distribution, PathMetadata, parse_version +from setuptools.extern.packaging.utils import canonicalize_name from setuptools.extern.six import PY3 from setuptools import Distribution as SetuptoolsDistribution from setuptools import pep425tags @@ -77,14 +79,24 @@ class Wheel(object): platform=(None if self.platform == 'any' else get_platform()), ).egg_name() + '.egg' + def get_dist_info(self, zf): + # find the correct name of the .dist-info dir in the wheel file + for member in zf.namelist(): + dirname = posixpath.dirname(member) + if (dirname.endswith('.dist-info') and + canonicalize_name(dirname).startswith( + canonicalize_name(self.project_name))): + return dirname + raise ValueError("unsupported wheel format. .dist-info not found") + def install_as_egg(self, destination_eggdir): '''Install wheel as an egg directory.''' with zipfile.ZipFile(self.filename) as zf: dist_basename = '%s-%s' % (self.project_name, self.version) - dist_info = '%s.dist-info' % dist_basename + dist_info = self.get_dist_info(zf) dist_data = '%s.data' % dist_basename def get_metadata(name): - with zf.open('%s/%s' % (dist_info, name)) as fp: + with zf.open(posixpath.join(dist_info, name)) as fp: value = fp.read().decode('utf-8') if PY3 else fp.read() return email.parser.Parser().parsestr(value) wheel_metadata = get_metadata('WHEEL') -- cgit v1.2.1 From 885f0b174621be1c040848d141bae732ed06e030 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 3 Jun 2018 08:54:07 -0400 Subject: Feed the hobgoblins (delint). --- setuptools/wheel.py | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) (limited to 'setuptools/wheel.py') diff --git a/setuptools/wheel.py b/setuptools/wheel.py index 4a33b203..e171a979 100644 --- a/setuptools/wheel.py +++ b/setuptools/wheel.py @@ -20,7 +20,7 @@ WHEEL_NAME = re.compile( r"""^(?P.+?)-(?P\d.*?) ((-(?P\d.*?))?-(?P.+?)-(?P.+?)-(?P.+?) )\.whl$""", -re.VERBOSE).match + re.VERBOSE).match NAMESPACE_PACKAGE_INIT = '''\ try: @@ -95,16 +95,21 @@ class Wheel(object): dist_basename = '%s-%s' % (self.project_name, self.version) dist_info = self.get_dist_info(zf) dist_data = '%s.data' % dist_basename + def get_metadata(name): with zf.open(posixpath.join(dist_info, name)) as fp: value = fp.read().decode('utf-8') if PY3 else fp.read() return email.parser.Parser().parsestr(value) wheel_metadata = get_metadata('WHEEL') - dist_metadata = get_metadata('METADATA') # Check wheel format version is supported. wheel_version = parse_version(wheel_metadata.get('Wheel-Version')) - if not parse_version('1.0') <= wheel_version < parse_version('2.0dev0'): - raise ValueError('unsupported wheel format version: %s' % wheel_version) + wheel_v1 = ( + parse_version('1.0') <= wheel_version + < parse_version('2.0dev0') + ) + if not wheel_v1: + raise ValueError( + 'unsupported wheel format version: %s' % wheel_version) # Extract to target directory. os.mkdir(destination_eggdir) zf.extractall(destination_eggdir) @@ -114,8 +119,9 @@ class Wheel(object): destination_eggdir, dist_info, metadata=PathMetadata(destination_eggdir, dist_info) ) - # Note: we need to evaluate and strip markers now, - # as we can't easily convert back from the syntax: + + # Note: Evaluate and strip markers now, + # as it's difficult to convert back from the syntax: # foobar; "linux" in sys_platform and extra == 'test' def raw_req(req): req.marker = None @@ -163,13 +169,16 @@ class Wheel(object): if os.path.exists(dist_data): os.rmdir(dist_data) # Fix namespace packages. - namespace_packages = os.path.join(egg_info, 'namespace_packages.txt') + namespace_packages = os.path.join( + egg_info, 'namespace_packages.txt') if os.path.exists(namespace_packages): with open(namespace_packages) as fp: namespace_packages = fp.read().split() for mod in namespace_packages: mod_dir = os.path.join(destination_eggdir, *mod.split('.')) mod_init = os.path.join(mod_dir, '__init__.py') - if os.path.exists(mod_dir) and not os.path.exists(mod_init): + if ( + os.path.exists(mod_dir) + and not os.path.exists(mod_init)): with open(mod_init, 'w') as fp: fp.write(NAMESPACE_PACKAGE_INIT) -- cgit v1.2.1 From c2460c75c3e0aac25387c04d7601959d2b6a3449 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 3 Jun 2018 09:09:38 -0400 Subject: Extract method to save indentation --- setuptools/wheel.py | 181 ++++++++++++++++++++++++++-------------------------- 1 file changed, 92 insertions(+), 89 deletions(-) (limited to 'setuptools/wheel.py') diff --git a/setuptools/wheel.py b/setuptools/wheel.py index e171a979..3065f2a1 100644 --- a/setuptools/wheel.py +++ b/setuptools/wheel.py @@ -92,93 +92,96 @@ class Wheel(object): def install_as_egg(self, destination_eggdir): '''Install wheel as an egg directory.''' with zipfile.ZipFile(self.filename) as zf: - dist_basename = '%s-%s' % (self.project_name, self.version) - dist_info = self.get_dist_info(zf) - dist_data = '%s.data' % dist_basename - - def get_metadata(name): - with zf.open(posixpath.join(dist_info, name)) as fp: - value = fp.read().decode('utf-8') if PY3 else fp.read() - return email.parser.Parser().parsestr(value) - wheel_metadata = get_metadata('WHEEL') - # Check wheel format version is supported. - wheel_version = parse_version(wheel_metadata.get('Wheel-Version')) - wheel_v1 = ( - parse_version('1.0') <= wheel_version - < parse_version('2.0dev0') - ) - if not wheel_v1: - raise ValueError( - 'unsupported wheel format version: %s' % wheel_version) - # Extract to target directory. - os.mkdir(destination_eggdir) - zf.extractall(destination_eggdir) - # Convert metadata. - dist_info = os.path.join(destination_eggdir, dist_info) - dist = Distribution.from_location( - destination_eggdir, dist_info, - metadata=PathMetadata(destination_eggdir, dist_info) - ) - - # Note: Evaluate and strip markers now, - # as it's difficult to convert back from the syntax: - # foobar; "linux" in sys_platform and extra == 'test' - def raw_req(req): - req.marker = None - return str(req) - install_requires = list(sorted(map(raw_req, dist.requires()))) - extras_require = { - extra: list(sorted( - req - for req in map(raw_req, dist.requires((extra,))) - if req not in install_requires - )) - for extra in dist.extras - } - egg_info = os.path.join(destination_eggdir, 'EGG-INFO') - os.rename(dist_info, egg_info) - os.rename(os.path.join(egg_info, 'METADATA'), - os.path.join(egg_info, 'PKG-INFO')) - setup_dist = SetuptoolsDistribution(attrs=dict( - install_requires=install_requires, - extras_require=extras_require, + self._install_as_egg(destination_eggdir, zf) + + def _install_as_egg(self, destination_eggdir, zf): + dist_basename = '%s-%s' % (self.project_name, self.version) + dist_info = self.get_dist_info(zf) + dist_data = '%s.data' % dist_basename + + def get_metadata(name): + with zf.open(posixpath.join(dist_info, name)) as fp: + value = fp.read().decode('utf-8') if PY3 else fp.read() + return email.parser.Parser().parsestr(value) + wheel_metadata = get_metadata('WHEEL') + # Check wheel format version is supported. + wheel_version = parse_version(wheel_metadata.get('Wheel-Version')) + wheel_v1 = ( + parse_version('1.0') <= wheel_version + < parse_version('2.0dev0') + ) + if not wheel_v1: + raise ValueError( + 'unsupported wheel format version: %s' % wheel_version) + # Extract to target directory. + os.mkdir(destination_eggdir) + zf.extractall(destination_eggdir) + # Convert metadata. + dist_info = os.path.join(destination_eggdir, dist_info) + dist = Distribution.from_location( + destination_eggdir, dist_info, + metadata=PathMetadata(destination_eggdir, dist_info) + ) + + # Note: Evaluate and strip markers now, + # as it's difficult to convert back from the syntax: + # foobar; "linux" in sys_platform and extra == 'test' + def raw_req(req): + req.marker = None + return str(req) + install_requires = list(sorted(map(raw_req, dist.requires()))) + extras_require = { + extra: list(sorted( + req + for req in map(raw_req, dist.requires((extra,))) + if req not in install_requires )) - write_requirements(setup_dist.get_command_obj('egg_info'), - None, os.path.join(egg_info, 'requires.txt')) - # Move data entries to their correct location. - dist_data = os.path.join(destination_eggdir, dist_data) - dist_data_scripts = os.path.join(dist_data, 'scripts') - if os.path.exists(dist_data_scripts): - egg_info_scripts = os.path.join(destination_eggdir, - 'EGG-INFO', 'scripts') - os.mkdir(egg_info_scripts) - for entry in os.listdir(dist_data_scripts): - # Remove bytecode, as it's not properly handled - # during easy_install scripts install phase. - if entry.endswith('.pyc'): - os.unlink(os.path.join(dist_data_scripts, entry)) - else: - os.rename(os.path.join(dist_data_scripts, entry), - os.path.join(egg_info_scripts, entry)) - os.rmdir(dist_data_scripts) - for subdir in filter(os.path.exists, ( - os.path.join(dist_data, d) - for d in ('data', 'headers', 'purelib', 'platlib') - )): - unpack(subdir, destination_eggdir) - if os.path.exists(dist_data): - os.rmdir(dist_data) - # Fix namespace packages. - namespace_packages = os.path.join( - egg_info, 'namespace_packages.txt') - if os.path.exists(namespace_packages): - with open(namespace_packages) as fp: - namespace_packages = fp.read().split() - for mod in namespace_packages: - mod_dir = os.path.join(destination_eggdir, *mod.split('.')) - mod_init = os.path.join(mod_dir, '__init__.py') - if ( - os.path.exists(mod_dir) - and not os.path.exists(mod_init)): - with open(mod_init, 'w') as fp: - fp.write(NAMESPACE_PACKAGE_INIT) + for extra in dist.extras + } + egg_info = os.path.join(destination_eggdir, 'EGG-INFO') + os.rename(dist_info, egg_info) + os.rename(os.path.join(egg_info, 'METADATA'), + os.path.join(egg_info, 'PKG-INFO')) + setup_dist = SetuptoolsDistribution(attrs=dict( + install_requires=install_requires, + extras_require=extras_require, + )) + write_requirements(setup_dist.get_command_obj('egg_info'), + None, os.path.join(egg_info, 'requires.txt')) + # Move data entries to their correct location. + dist_data = os.path.join(destination_eggdir, dist_data) + dist_data_scripts = os.path.join(dist_data, 'scripts') + if os.path.exists(dist_data_scripts): + egg_info_scripts = os.path.join(destination_eggdir, + 'EGG-INFO', 'scripts') + os.mkdir(egg_info_scripts) + for entry in os.listdir(dist_data_scripts): + # Remove bytecode, as it's not properly handled + # during easy_install scripts install phase. + if entry.endswith('.pyc'): + os.unlink(os.path.join(dist_data_scripts, entry)) + else: + os.rename(os.path.join(dist_data_scripts, entry), + os.path.join(egg_info_scripts, entry)) + os.rmdir(dist_data_scripts) + for subdir in filter(os.path.exists, ( + os.path.join(dist_data, d) + for d in ('data', 'headers', 'purelib', 'platlib') + )): + unpack(subdir, destination_eggdir) + if os.path.exists(dist_data): + os.rmdir(dist_data) + # Fix namespace packages. + namespace_packages = os.path.join( + egg_info, 'namespace_packages.txt') + if os.path.exists(namespace_packages): + with open(namespace_packages) as fp: + namespace_packages = fp.read().split() + for mod in namespace_packages: + mod_dir = os.path.join(destination_eggdir, *mod.split('.')) + mod_init = os.path.join(mod_dir, '__init__.py') + if ( + os.path.exists(mod_dir) + and not os.path.exists(mod_init)): + with open(mod_init, 'w') as fp: + fp.write(NAMESPACE_PACKAGE_INIT) -- cgit v1.2.1 From ac3e41e61a72f34a46799f63531465495e3465a9 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 3 Jun 2018 09:11:14 -0400 Subject: Use the new breathing room to consolidate lines --- setuptools/wheel.py | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'setuptools/wheel.py') diff --git a/setuptools/wheel.py b/setuptools/wheel.py index 3065f2a1..d7ce56bf 100644 --- a/setuptools/wheel.py +++ b/setuptools/wheel.py @@ -107,8 +107,7 @@ class Wheel(object): # Check wheel format version is supported. wheel_version = parse_version(wheel_metadata.get('Wheel-Version')) wheel_v1 = ( - parse_version('1.0') <= wheel_version - < parse_version('2.0dev0') + parse_version('1.0') <= wheel_version < parse_version('2.0dev0') ) if not wheel_v1: raise ValueError( @@ -120,7 +119,7 @@ class Wheel(object): dist_info = os.path.join(destination_eggdir, dist_info) dist = Distribution.from_location( destination_eggdir, dist_info, - metadata=PathMetadata(destination_eggdir, dist_info) + metadata=PathMetadata(destination_eggdir, dist_info), ) # Note: Evaluate and strip markers now, @@ -180,8 +179,6 @@ class Wheel(object): for mod in namespace_packages: mod_dir = os.path.join(destination_eggdir, *mod.split('.')) mod_init = os.path.join(mod_dir, '__init__.py') - if ( - os.path.exists(mod_dir) - and not os.path.exists(mod_init)): + if os.path.exists(mod_dir) and not os.path.exists(mod_init): with open(mod_init, 'w') as fp: fp.write(NAMESPACE_PACKAGE_INIT) -- cgit v1.2.1 From 169639bd253b55bbc4ef021a666c57b6029d3c5f Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 3 Jun 2018 09:12:06 -0400 Subject: Remove redundant 'list' --- setuptools/wheel.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'setuptools/wheel.py') diff --git a/setuptools/wheel.py b/setuptools/wheel.py index d7ce56bf..193edafd 100644 --- a/setuptools/wheel.py +++ b/setuptools/wheel.py @@ -130,11 +130,11 @@ class Wheel(object): return str(req) install_requires = list(sorted(map(raw_req, dist.requires()))) extras_require = { - extra: list(sorted( + extra: sorted( req for req in map(raw_req, dist.requires((extra,))) if req not in install_requires - )) + ) for extra in dist.extras } egg_info = os.path.join(destination_eggdir, 'EGG-INFO') -- cgit v1.2.1 From f8d08c3929e7645ba134598793076d2a7d55344c Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 3 Jun 2018 09:15:11 -0400 Subject: Avoid hanging indents --- setuptools/wheel.py | 41 ++++++++++++++++++++++++++--------------- 1 file changed, 26 insertions(+), 15 deletions(-) (limited to 'setuptools/wheel.py') diff --git a/setuptools/wheel.py b/setuptools/wheel.py index 193edafd..920bb6f0 100644 --- a/setuptools/wheel.py +++ b/setuptools/wheel.py @@ -64,9 +64,11 @@ class Wheel(object): def tags(self): '''List tags (py_version, abi, platform) supported by this wheel.''' - return itertools.product(self.py_version.split('.'), - self.abi.split('.'), - self.platform.split('.')) + return itertools.product( + self.py_version.split('.'), + self.abi.split('.'), + self.platform.split('.'), + ) def is_compatible(self): '''Is the wheel is compatible with the current platform?''' @@ -139,20 +141,27 @@ class Wheel(object): } egg_info = os.path.join(destination_eggdir, 'EGG-INFO') os.rename(dist_info, egg_info) - os.rename(os.path.join(egg_info, 'METADATA'), - os.path.join(egg_info, 'PKG-INFO')) - setup_dist = SetuptoolsDistribution(attrs=dict( - install_requires=install_requires, - extras_require=extras_require, - )) - write_requirements(setup_dist.get_command_obj('egg_info'), - None, os.path.join(egg_info, 'requires.txt')) + os.rename( + os.path.join(egg_info, 'METADATA'), + os.path.join(egg_info, 'PKG-INFO'), + ) + setup_dist = SetuptoolsDistribution( + attrs=dict( + install_requires=install_requires, + extras_require=extras_require, + ), + ) + write_requirements( + setup_dist.get_command_obj('egg_info'), + None, + os.path.join(egg_info, 'requires.txt'), + ) # Move data entries to their correct location. dist_data = os.path.join(destination_eggdir, dist_data) dist_data_scripts = os.path.join(dist_data, 'scripts') if os.path.exists(dist_data_scripts): - egg_info_scripts = os.path.join(destination_eggdir, - 'EGG-INFO', 'scripts') + egg_info_scripts = os.path.join( + destination_eggdir, 'EGG-INFO', 'scripts') os.mkdir(egg_info_scripts) for entry in os.listdir(dist_data_scripts): # Remove bytecode, as it's not properly handled @@ -160,8 +169,10 @@ class Wheel(object): if entry.endswith('.pyc'): os.unlink(os.path.join(dist_data_scripts, entry)) else: - os.rename(os.path.join(dist_data_scripts, entry), - os.path.join(egg_info_scripts, entry)) + os.rename( + os.path.join(dist_data_scripts, entry), + os.path.join(egg_info_scripts, entry), + ) os.rmdir(dist_data_scripts) for subdir in filter(os.path.exists, ( os.path.join(dist_data, d) -- cgit v1.2.1 From 19d79d2f9fef6b9e024a1352ed51f9b7d829b768 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 3 Jun 2018 09:16:44 -0400 Subject: Extract method for fixing namespace packages --- setuptools/wheel.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'setuptools/wheel.py') diff --git a/setuptools/wheel.py b/setuptools/wheel.py index 920bb6f0..a64aa5bf 100644 --- a/setuptools/wheel.py +++ b/setuptools/wheel.py @@ -1,4 +1,4 @@ -'''Wheels support.''' +"""Wheels support.""" from distutils.util import get_platform import email @@ -181,7 +181,10 @@ class Wheel(object): unpack(subdir, destination_eggdir) if os.path.exists(dist_data): os.rmdir(dist_data) - # Fix namespace packages. + self._fix_namespace_packages(egg_info, destination_eggdir) + + @staticmethod + def _fix_namespace_packages(egg_info, destination_eggdir): namespace_packages = os.path.join( egg_info, 'namespace_packages.txt') if os.path.exists(namespace_packages): -- cgit v1.2.1 From ad676fe418b22c894385f8d1316f2a60d8d1a291 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 3 Jun 2018 09:18:48 -0400 Subject: Extract method for _move_data_entries --- setuptools/wheel.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'setuptools/wheel.py') diff --git a/setuptools/wheel.py b/setuptools/wheel.py index a64aa5bf..e3d807c1 100644 --- a/setuptools/wheel.py +++ b/setuptools/wheel.py @@ -156,7 +156,12 @@ class Wheel(object): None, os.path.join(egg_info, 'requires.txt'), ) - # Move data entries to their correct location. + self._move_data_entries(destination_eggdir, dist_data) + self._fix_namespace_packages(egg_info, destination_eggdir) + + @staticmethod + def _move_data_entries(destination_eggdir, dist_data): + """Move data entries to their correct location.""" dist_data = os.path.join(destination_eggdir, dist_data) dist_data_scripts = os.path.join(dist_data, 'scripts') if os.path.exists(dist_data_scripts): @@ -181,7 +186,6 @@ class Wheel(object): unpack(subdir, destination_eggdir) if os.path.exists(dist_data): os.rmdir(dist_data) - self._fix_namespace_packages(egg_info, destination_eggdir) @staticmethod def _fix_namespace_packages(egg_info, destination_eggdir): -- cgit v1.2.1 From 68f2ffd0bec368c31201a19b326d41dba5b81495 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 3 Jun 2018 09:28:50 -0400 Subject: Extract _convert_metadata. install_as_egg is almost comprehensible now. --- setuptools/wheel.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'setuptools/wheel.py') diff --git a/setuptools/wheel.py b/setuptools/wheel.py index e3d807c1..dc03bbc8 100644 --- a/setuptools/wheel.py +++ b/setuptools/wheel.py @@ -100,11 +100,19 @@ class Wheel(object): dist_basename = '%s-%s' % (self.project_name, self.version) dist_info = self.get_dist_info(zf) dist_data = '%s.data' % dist_basename + egg_info = os.path.join(destination_eggdir, 'EGG-INFO') + self._convert_metadata(zf, destination_eggdir, dist_info, egg_info) + self._move_data_entries(destination_eggdir, dist_data) + self._fix_namespace_packages(egg_info, destination_eggdir) + + @staticmethod + def _convert_metadata(zf, destination_eggdir, dist_info, egg_info): def get_metadata(name): with zf.open(posixpath.join(dist_info, name)) as fp: value = fp.read().decode('utf-8') if PY3 else fp.read() return email.parser.Parser().parsestr(value) + wheel_metadata = get_metadata('WHEEL') # Check wheel format version is supported. wheel_version = parse_version(wheel_metadata.get('Wheel-Version')) @@ -139,7 +147,6 @@ class Wheel(object): ) for extra in dist.extras } - egg_info = os.path.join(destination_eggdir, 'EGG-INFO') os.rename(dist_info, egg_info) os.rename( os.path.join(egg_info, 'METADATA'), @@ -156,8 +163,6 @@ class Wheel(object): None, os.path.join(egg_info, 'requires.txt'), ) - self._move_data_entries(destination_eggdir, dist_data) - self._fix_namespace_packages(egg_info, destination_eggdir) @staticmethod def _move_data_entries(destination_eggdir, dist_data): -- cgit v1.2.1 From cca86c7f1d4040834c3265ccecdd9e21b4036df5 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 3 Jun 2018 09:50:25 -0400 Subject: Use Python 3 syntax for new-style clasess --- setuptools/wheel.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'setuptools/wheel.py') diff --git a/setuptools/wheel.py b/setuptools/wheel.py index dc03bbc8..95a794a8 100644 --- a/setuptools/wheel.py +++ b/setuptools/wheel.py @@ -16,6 +16,9 @@ from setuptools import pep425tags from setuptools.command.egg_info import write_requirements +__metaclass__ = type + + WHEEL_NAME = re.compile( r"""^(?P.+?)-(?P\d.*?) ((-(?P\d.*?))?-(?P.+?)-(?P.+?)-(?P.+?) @@ -52,7 +55,7 @@ def unpack(src_dir, dst_dir): os.rmdir(dirpath) -class Wheel(object): +class Wheel: def __init__(self, filename): match = WHEEL_NAME(os.path.basename(filename)) -- cgit v1.2.1 From 3b8307541e6d24c5eeb4e4998cf9ee46b6e6506f Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Mon, 24 Dec 2018 12:01:01 -0500 Subject: Rely on package names to namespace the package contents. --- setuptools/wheel.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'setuptools/wheel.py') diff --git a/setuptools/wheel.py b/setuptools/wheel.py index 95a794a8..e11f0a1d 100644 --- a/setuptools/wheel.py +++ b/setuptools/wheel.py @@ -8,10 +8,11 @@ import posixpath import re import zipfile -from pkg_resources import Distribution, PathMetadata, parse_version +import pkg_resources +import setuptools +from pkg_resources import parse_version from setuptools.extern.packaging.utils import canonicalize_name from setuptools.extern.six import PY3 -from setuptools import Distribution as SetuptoolsDistribution from setuptools import pep425tags from setuptools.command.egg_info import write_requirements @@ -79,7 +80,7 @@ class Wheel: return next((True for t in self.tags() if t in supported_tags), False) def egg_name(self): - return Distribution( + return pkg_resources.Distribution( project_name=self.project_name, version=self.version, platform=(None if self.platform == 'any' else get_platform()), ).egg_name() + '.egg' @@ -130,9 +131,9 @@ class Wheel: zf.extractall(destination_eggdir) # Convert metadata. dist_info = os.path.join(destination_eggdir, dist_info) - dist = Distribution.from_location( + dist = pkg_resources.Distribution.from_location( destination_eggdir, dist_info, - metadata=PathMetadata(destination_eggdir, dist_info), + metadata=pkg_resources.PathMetadata(destination_eggdir, dist_info), ) # Note: Evaluate and strip markers now, @@ -155,7 +156,7 @@ class Wheel: os.path.join(egg_info, 'METADATA'), os.path.join(egg_info, 'PKG-INFO'), ) - setup_dist = SetuptoolsDistribution( + setup_dist = setuptools.Distribution( attrs=dict( install_requires=install_requires, extras_require=extras_require, -- cgit v1.2.1 From d7810a901382b827146874704f33bce896e1fb21 Mon Sep 17 00:00:00 2001 From: Benoit Pierre Date: Sat, 10 Aug 2019 02:18:34 +0200 Subject: wheel: silence info trace when writing `requires.txt` --- setuptools/wheel.py | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) (limited to 'setuptools/wheel.py') diff --git a/setuptools/wheel.py b/setuptools/wheel.py index e11f0a1d..2982926a 100644 --- a/setuptools/wheel.py +++ b/setuptools/wheel.py @@ -1,6 +1,7 @@ """Wheels support.""" from distutils.util import get_platform +from distutils import log import email import itertools import os @@ -162,11 +163,17 @@ class Wheel: extras_require=extras_require, ), ) - write_requirements( - setup_dist.get_command_obj('egg_info'), - None, - os.path.join(egg_info, 'requires.txt'), - ) + # Temporarily disable info traces. + log_threshold = log._global_log.threshold + log.set_threshold(log.WARN) + try: + write_requirements( + setup_dist.get_command_obj('egg_info'), + None, + os.path.join(egg_info, 'requires.txt'), + ) + finally: + log.set_threshold(log_threshold) @staticmethod def _move_data_entries(destination_eggdir, dist_data): -- cgit v1.2.1 From 16a3ef93fc66373f6c5f4da12303dd111403fcb1 Mon Sep 17 00:00:00 2001 From: Benoit Pierre Date: Mon, 17 Sep 2018 23:40:12 +0200 Subject: wheel: fix installation of empty namespace package --- setuptools/wheel.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'setuptools/wheel.py') diff --git a/setuptools/wheel.py b/setuptools/wheel.py index 2982926a..22eec05e 100644 --- a/setuptools/wheel.py +++ b/setuptools/wheel.py @@ -213,6 +213,8 @@ class Wheel: for mod in namespace_packages: mod_dir = os.path.join(destination_eggdir, *mod.split('.')) mod_init = os.path.join(mod_dir, '__init__.py') - if os.path.exists(mod_dir) and not os.path.exists(mod_init): + if not os.path.exists(mod_dir): + os.mkdir(mod_dir) + if not os.path.exists(mod_init): with open(mod_init, 'w') as fp: fp.write(NAMESPACE_PACKAGE_INIT) -- cgit v1.2.1 From 3d811b93a83d5931b821916c6ca172a69c403a97 Mon Sep 17 00:00:00 2001 From: Benoit Pierre Date: Fri, 23 Aug 2019 23:18:02 +0200 Subject: wheel: switch to `packaging.tags` for checking PEP 425 tags --- setuptools/wheel.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'setuptools/wheel.py') diff --git a/setuptools/wheel.py b/setuptools/wheel.py index e11f0a1d..502f8410 100644 --- a/setuptools/wheel.py +++ b/setuptools/wheel.py @@ -11,9 +11,9 @@ import zipfile import pkg_resources import setuptools from pkg_resources import parse_version +from setuptools.extern.packaging.tags import sys_tags from setuptools.extern.packaging.utils import canonicalize_name from setuptools.extern.six import PY3 -from setuptools import pep425tags from setuptools.command.egg_info import write_requirements @@ -76,7 +76,7 @@ class Wheel: def is_compatible(self): '''Is the wheel is compatible with the current platform?''' - supported_tags = pep425tags.get_supported() + supported_tags = set(map(str, sys_tags())) return next((True for t in self.tags() if t in supported_tags), False) def egg_name(self): -- cgit v1.2.1 From 926c80f5e84823f48103f3695f55f23949cc5d37 Mon Sep 17 00:00:00 2001 From: Benoit Pierre Date: Mon, 25 Nov 2019 11:24:10 +0100 Subject: wheel: fix `is_compatible` implementation --- setuptools/wheel.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'setuptools/wheel.py') diff --git a/setuptools/wheel.py b/setuptools/wheel.py index 3effd79b..025aaa82 100644 --- a/setuptools/wheel.py +++ b/setuptools/wheel.py @@ -77,7 +77,7 @@ class Wheel: def is_compatible(self): '''Is the wheel is compatible with the current platform?''' - supported_tags = set(map(str, sys_tags())) + supported_tags = set((t.interpreter, t.abi, t.platform) for t in sys_tags()) return next((True for t in self.tags() if t in supported_tags), False) def egg_name(self): -- 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/wheel.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'setuptools/wheel.py') diff --git a/setuptools/wheel.py b/setuptools/wheel.py index 025aaa82..ec1106a7 100644 --- a/setuptools/wheel.py +++ b/setuptools/wheel.py @@ -77,7 +77,8 @@ class Wheel: def is_compatible(self): '''Is the wheel is compatible with the current platform?''' - supported_tags = set((t.interpreter, t.abi, t.platform) for t in sys_tags()) + supported_tags = set( + (t.interpreter, t.abi, t.platform) for t in sys_tags()) return next((True for t in self.tags() if t in supported_tags), False) def egg_name(self): -- cgit v1.2.1 From 3b32ab28d78eb38f681d36ecef505a65d1cbad38 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Thu, 28 May 2020 07:54:35 -0400 Subject: In wheel-to-egg conversion, use simple pkg_resources-style namespace declaration for packages that declare namespace_packages. Fixes #2070. --- setuptools/wheel.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'setuptools/wheel.py') diff --git a/setuptools/wheel.py b/setuptools/wheel.py index ec1106a7..ca09bd19 100644 --- a/setuptools/wheel.py +++ b/setuptools/wheel.py @@ -27,12 +27,8 @@ WHEEL_NAME = re.compile( )\.whl$""", re.VERBOSE).match -NAMESPACE_PACKAGE_INIT = '''\ -try: - __import__('pkg_resources').declare_namespace(__name__) -except ImportError: - __path__ = __import__('pkgutil').extend_path(__path__, __name__) -''' +NAMESPACE_PACKAGE_INIT = \ + "__import__('pkg_resources').declare_namespace(__name__)\n" def unpack(src_dir, dst_dir): -- 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/wheel.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'setuptools/wheel.py') diff --git a/setuptools/wheel.py b/setuptools/wheel.py index ca09bd19..0be811af 100644 --- a/setuptools/wheel.py +++ b/setuptools/wheel.py @@ -14,13 +14,9 @@ import setuptools from pkg_resources import parse_version from setuptools.extern.packaging.tags import sys_tags from setuptools.extern.packaging.utils import canonicalize_name -from setuptools.extern.six import PY3 from setuptools.command.egg_info import write_requirements -__metaclass__ = type - - WHEEL_NAME = re.compile( r"""^(?P.+?)-(?P\d.*?) ((-(?P\d.*?))?-(?P.+?)-(?P.+?)-(?P.+?) @@ -112,7 +108,7 @@ class Wheel: def _convert_metadata(zf, destination_eggdir, dist_info, egg_info): def get_metadata(name): with zf.open(posixpath.join(dist_info, name)) as fp: - value = fp.read().decode('utf-8') if PY3 else fp.read() + value = fp.read().decode('utf-8') return email.parser.Parser().parsestr(value) wheel_metadata = get_metadata('WHEEL') -- cgit v1.2.1