]> crepu.dev Git - config.git/blame_incremental - djavu-asus/emacs/elpy/rpc-venv/lib/python3.11/site-packages/setuptools/wheel.py
Reorganización de directorios
[config.git] / djavu-asus / emacs / elpy / rpc-venv / lib / python3.11 / site-packages / setuptools / wheel.py
... / ...
CommitLineData
1"""Wheels support."""
2
3import email
4import itertools
5import os
6import posixpath
7import re
8import zipfile
9import contextlib
10
11from distutils.util import get_platform
12
13import pkg_resources
14import setuptools
15from pkg_resources import parse_version
16from setuptools.extern.packaging.tags import sys_tags
17from setuptools.extern.packaging.utils import canonicalize_name
18from setuptools.command.egg_info import write_requirements
19from setuptools.archive_util import _unpack_zipfile_obj
20
21
22WHEEL_NAME = re.compile(
23 r"""^(?P<project_name>.+?)-(?P<version>\d.*?)
24 ((-(?P<build>\d.*?))?-(?P<py_version>.+?)-(?P<abi>.+?)-(?P<platform>.+?)
25 )\.whl$""",
26 re.VERBOSE).match
27
28NAMESPACE_PACKAGE_INIT = \
29 "__import__('pkg_resources').declare_namespace(__name__)\n"
30
31
32def unpack(src_dir, dst_dir):
33 '''Move everything under `src_dir` to `dst_dir`, and delete the former.'''
34 for dirpath, dirnames, filenames in os.walk(src_dir):
35 subdir = os.path.relpath(dirpath, src_dir)
36 for f in filenames:
37 src = os.path.join(dirpath, f)
38 dst = os.path.join(dst_dir, subdir, f)
39 os.renames(src, dst)
40 for n, d in reversed(list(enumerate(dirnames))):
41 src = os.path.join(dirpath, d)
42 dst = os.path.join(dst_dir, subdir, d)
43 if not os.path.exists(dst):
44 # Directory does not exist in destination,
45 # rename it and prune it from os.walk list.
46 os.renames(src, dst)
47 del dirnames[n]
48 # Cleanup.
49 for dirpath, dirnames, filenames in os.walk(src_dir, topdown=True):
50 assert not filenames
51 os.rmdir(dirpath)
52
53
54@contextlib.contextmanager
55def disable_info_traces():
56 """
57 Temporarily disable info traces.
58 """
59 from distutils import log
60 saved = log.set_threshold(log.WARN)
61 try:
62 yield
63 finally:
64 log.set_threshold(saved)
65
66
67class Wheel:
68
69 def __init__(self, filename):
70 match = WHEEL_NAME(os.path.basename(filename))
71 if match is None:
72 raise ValueError('invalid wheel name: %r' % filename)
73 self.filename = filename
74 for k, v in match.groupdict().items():
75 setattr(self, k, v)
76
77 def tags(self):
78 '''List tags (py_version, abi, platform) supported by this wheel.'''
79 return itertools.product(
80 self.py_version.split('.'),
81 self.abi.split('.'),
82 self.platform.split('.'),
83 )
84
85 def is_compatible(self):
86 '''Is the wheel is compatible with the current platform?'''
87 supported_tags = set(
88 (t.interpreter, t.abi, t.platform) for t in sys_tags())
89 return next((True for t in self.tags() if t in supported_tags), False)
90
91 def egg_name(self):
92 return pkg_resources.Distribution(
93 project_name=self.project_name, version=self.version,
94 platform=(None if self.platform == 'any' else get_platform()),
95 ).egg_name() + '.egg'
96
97 def get_dist_info(self, zf):
98 # find the correct name of the .dist-info dir in the wheel file
99 for member in zf.namelist():
100 dirname = posixpath.dirname(member)
101 if (dirname.endswith('.dist-info') and
102 canonicalize_name(dirname).startswith(
103 canonicalize_name(self.project_name))):
104 return dirname
105 raise ValueError("unsupported wheel format. .dist-info not found")
106
107 def install_as_egg(self, destination_eggdir):
108 '''Install wheel as an egg directory.'''
109 with zipfile.ZipFile(self.filename) as zf:
110 self._install_as_egg(destination_eggdir, zf)
111
112 def _install_as_egg(self, destination_eggdir, zf):
113 dist_basename = '%s-%s' % (self.project_name, self.version)
114 dist_info = self.get_dist_info(zf)
115 dist_data = '%s.data' % dist_basename
116 egg_info = os.path.join(destination_eggdir, 'EGG-INFO')
117
118 self._convert_metadata(zf, destination_eggdir, dist_info, egg_info)
119 self._move_data_entries(destination_eggdir, dist_data)
120 self._fix_namespace_packages(egg_info, destination_eggdir)
121
122 @staticmethod
123 def _convert_metadata(zf, destination_eggdir, dist_info, egg_info):
124 def get_metadata(name):
125 with zf.open(posixpath.join(dist_info, name)) as fp:
126 value = fp.read().decode('utf-8')
127 return email.parser.Parser().parsestr(value)
128
129 wheel_metadata = get_metadata('WHEEL')
130 # Check wheel format version is supported.
131 wheel_version = parse_version(wheel_metadata.get('Wheel-Version'))
132 wheel_v1 = (
133 parse_version('1.0') <= wheel_version < parse_version('2.0dev0')
134 )
135 if not wheel_v1:
136 raise ValueError(
137 'unsupported wheel format version: %s' % wheel_version)
138 # Extract to target directory.
139 _unpack_zipfile_obj(zf, destination_eggdir)
140 # Convert metadata.
141 dist_info = os.path.join(destination_eggdir, dist_info)
142 dist = pkg_resources.Distribution.from_location(
143 destination_eggdir, dist_info,
144 metadata=pkg_resources.PathMetadata(destination_eggdir, dist_info),
145 )
146
147 # Note: Evaluate and strip markers now,
148 # as it's difficult to convert back from the syntax:
149 # foobar; "linux" in sys_platform and extra == 'test'
150 def raw_req(req):
151 req.marker = None
152 return str(req)
153 install_requires = list(map(raw_req, dist.requires()))
154 extras_require = {
155 extra: [
156 req
157 for req in map(raw_req, dist.requires((extra,)))
158 if req not in install_requires
159 ]
160 for extra in dist.extras
161 }
162 os.rename(dist_info, egg_info)
163 os.rename(
164 os.path.join(egg_info, 'METADATA'),
165 os.path.join(egg_info, 'PKG-INFO'),
166 )
167 setup_dist = setuptools.Distribution(
168 attrs=dict(
169 install_requires=install_requires,
170 extras_require=extras_require,
171 ),
172 )
173 with disable_info_traces():
174 write_requirements(
175 setup_dist.get_command_obj('egg_info'),
176 None,
177 os.path.join(egg_info, 'requires.txt'),
178 )
179
180 @staticmethod
181 def _move_data_entries(destination_eggdir, dist_data):
182 """Move data entries to their correct location."""
183 dist_data = os.path.join(destination_eggdir, dist_data)
184 dist_data_scripts = os.path.join(dist_data, 'scripts')
185 if os.path.exists(dist_data_scripts):
186 egg_info_scripts = os.path.join(
187 destination_eggdir, 'EGG-INFO', 'scripts')
188 os.mkdir(egg_info_scripts)
189 for entry in os.listdir(dist_data_scripts):
190 # Remove bytecode, as it's not properly handled
191 # during easy_install scripts install phase.
192 if entry.endswith('.pyc'):
193 os.unlink(os.path.join(dist_data_scripts, entry))
194 else:
195 os.rename(
196 os.path.join(dist_data_scripts, entry),
197 os.path.join(egg_info_scripts, entry),
198 )
199 os.rmdir(dist_data_scripts)
200 for subdir in filter(os.path.exists, (
201 os.path.join(dist_data, d)
202 for d in ('data', 'headers', 'purelib', 'platlib')
203 )):
204 unpack(subdir, destination_eggdir)
205 if os.path.exists(dist_data):
206 os.rmdir(dist_data)
207
208 @staticmethod
209 def _fix_namespace_packages(egg_info, destination_eggdir):
210 namespace_packages = os.path.join(
211 egg_info, 'namespace_packages.txt')
212 if os.path.exists(namespace_packages):
213 with open(namespace_packages) as fp:
214 namespace_packages = fp.read().split()
215 for mod in namespace_packages:
216 mod_dir = os.path.join(destination_eggdir, *mod.split('.'))
217 mod_init = os.path.join(mod_dir, '__init__.py')
218 if not os.path.exists(mod_dir):
219 os.mkdir(mod_dir)
220 if not os.path.exists(mod_init):
221 with open(mod_init, 'w') as fp:
222 fp.write(NAMESPACE_PACKAGE_INIT)