188 lines
5.8 KiB
Python
188 lines
5.8 KiB
Python
import re
|
|
import sys
|
|
import string
|
|
import subprocess
|
|
import venv
|
|
from tempfile import TemporaryDirectory
|
|
|
|
from path import Path
|
|
|
|
|
|
def remove_all(paths):
|
|
for path in paths:
|
|
path.rmtree() if path.isdir() else path.remove()
|
|
|
|
|
|
def update_vendored():
|
|
update_pkg_resources()
|
|
update_setuptools()
|
|
|
|
|
|
def rewrite_packaging(pkg_files, new_root):
|
|
"""
|
|
Rewrite imports in packaging to redirect to vendored copies.
|
|
"""
|
|
for file in pkg_files.glob('*.py'):
|
|
text = file.text()
|
|
text = re.sub(r' (pyparsing)', rf' {new_root}.\1', text)
|
|
text = text.replace(
|
|
'from six.moves.urllib import parse',
|
|
'from urllib import parse',
|
|
)
|
|
file.write_text(text)
|
|
|
|
|
|
def rewrite_jaraco_text(pkg_files, new_root):
|
|
"""
|
|
Rewrite imports in jaraco.text to redirect to vendored copies.
|
|
"""
|
|
for file in pkg_files.glob('*.py'):
|
|
text = file.read_text()
|
|
text = re.sub(r' (jaraco\.)', rf' {new_root}.\1', text)
|
|
text = re.sub(r' (importlib_resources)', rf' {new_root}.\1', text)
|
|
# suppress loading of lorem_ipsum; ref #3072
|
|
text = re.sub(r'^lorem_ipsum.*\n$', '', text, flags=re.M)
|
|
file.write_text(text)
|
|
|
|
|
|
def rewrite_jaraco(pkg_files, new_root):
|
|
"""
|
|
Rewrite imports in jaraco.functools to redirect to vendored copies.
|
|
"""
|
|
for file in pkg_files.glob('*.py'):
|
|
text = file.read_text()
|
|
text = re.sub(r' (more_itertools)', rf' {new_root}.\1', text)
|
|
file.write_text(text)
|
|
# required for zip-packaged setuptools #3084
|
|
pkg_files.joinpath('__init__.py').write_text('')
|
|
|
|
|
|
def rewrite_importlib_resources(pkg_files, new_root):
|
|
"""
|
|
Rewrite imports in importlib_resources to redirect to vendored copies.
|
|
"""
|
|
for file in pkg_files.glob('*.py'):
|
|
text = file.read_text().replace('importlib_resources.abc', '.abc')
|
|
text = text.replace('zipp', '..zipp')
|
|
file.write_text(text)
|
|
|
|
|
|
def rewrite_importlib_metadata(pkg_files, new_root):
|
|
"""
|
|
Rewrite imports in importlib_metadata to redirect to vendored copies.
|
|
"""
|
|
for file in pkg_files.glob('*.py'):
|
|
text = file.read_text().replace('typing_extensions', '..typing_extensions')
|
|
text = text.replace('import zipp', 'from .. import zipp')
|
|
file.write_text(text)
|
|
|
|
|
|
def rewrite_more_itertools(pkg_files: Path):
|
|
"""
|
|
Defer import of concurrent.futures. Workaround for #3090.
|
|
"""
|
|
more_file = pkg_files.joinpath('more.py')
|
|
text = more_file.read_text()
|
|
text = re.sub(r'^.*concurrent.futures.*?\n', '', text, flags=re.MULTILINE)
|
|
text = re.sub(
|
|
'ThreadPoolExecutor',
|
|
'__import__("concurrent.futures").futures.ThreadPoolExecutor',
|
|
text,
|
|
)
|
|
more_file.write_text(text)
|
|
|
|
|
|
def rewrite_nspektr(pkg_files: Path, new_root):
|
|
for file in pkg_files.glob('*.py'):
|
|
text = file.read_text()
|
|
text = re.sub(r' (more_itertools)', rf' {new_root}.\1', text)
|
|
text = re.sub(r' (jaraco\.\w+)', rf' {new_root}.\1', text)
|
|
text = re.sub(r' (packaging)', rf' {new_root}.\1', text)
|
|
text = re.sub(r' (importlib_metadata)', rf' {new_root}.\1', text)
|
|
file.write_text(text)
|
|
|
|
|
|
def clean(vendor):
|
|
"""
|
|
Remove all files out of the vendor directory except the meta
|
|
data (as pip uninstall doesn't support -t).
|
|
"""
|
|
remove_all(
|
|
path
|
|
for path in vendor.glob('*')
|
|
if path.basename() != 'vendored.txt'
|
|
)
|
|
|
|
|
|
def install(vendor):
|
|
clean(vendor)
|
|
install_args = [
|
|
sys.executable,
|
|
'-m', 'pip',
|
|
'install',
|
|
'-r', str(vendor / 'vendored.txt'),
|
|
'-t', str(vendor),
|
|
]
|
|
subprocess.check_call(install_args)
|
|
(vendor / '__init__.py').write_text('')
|
|
|
|
|
|
def update_pkg_resources():
|
|
vendor = Path('pkg_resources/_vendor')
|
|
install(vendor)
|
|
rewrite_packaging(vendor / 'packaging', 'pkg_resources.extern')
|
|
rewrite_jaraco_text(vendor / 'jaraco/text', 'pkg_resources.extern')
|
|
rewrite_jaraco(vendor / 'jaraco', 'pkg_resources.extern')
|
|
rewrite_importlib_resources(vendor / 'importlib_resources', 'pkg_resources.extern')
|
|
rewrite_more_itertools(vendor / "more_itertools")
|
|
|
|
|
|
def update_setuptools():
|
|
vendor = Path('setuptools/_vendor')
|
|
install(vendor)
|
|
install_validate_pyproject(vendor)
|
|
rewrite_packaging(vendor / 'packaging', 'setuptools.extern')
|
|
rewrite_jaraco_text(vendor / 'jaraco/text', 'setuptools.extern')
|
|
rewrite_jaraco(vendor / 'jaraco', 'setuptools.extern')
|
|
rewrite_importlib_resources(vendor / 'importlib_resources', 'setuptools.extern')
|
|
rewrite_importlib_metadata(vendor / 'importlib_metadata', 'setuptools.extern')
|
|
rewrite_more_itertools(vendor / "more_itertools")
|
|
rewrite_nspektr(vendor / "nspektr", 'setuptools.extern')
|
|
|
|
|
|
def install_validate_pyproject(vendor):
|
|
"""``validate-pyproject`` can be vendorized to remove all dependencies"""
|
|
req = next(
|
|
(x for x in (vendor / "vendored.txt").lines() if 'validate-pyproject' in x),
|
|
"validate-pyproject[all]"
|
|
)
|
|
|
|
pkg, _, _ = req.strip(string.whitespace + "#").partition("#")
|
|
pkg = pkg.strip()
|
|
|
|
opts = {}
|
|
if sys.version_info[:2] >= (3, 10):
|
|
opts["ignore_cleanup_errors"] = True
|
|
|
|
with TemporaryDirectory(**opts) as tmp:
|
|
env_builder = venv.EnvBuilder(with_pip=True)
|
|
env_builder.create(tmp)
|
|
context = env_builder.ensure_directories(tmp)
|
|
venv_python = getattr(context, 'env_exec_cmd', context.env_exe)
|
|
|
|
subprocess.check_call([venv_python, "-m", "pip", "install", pkg])
|
|
cmd = [
|
|
venv_python,
|
|
"-m",
|
|
"validate_pyproject.vendoring",
|
|
f"--output-dir={vendor / '_validate_pyproject' !s}",
|
|
"--enable-plugins",
|
|
"setuptools",
|
|
"distutils",
|
|
"--very-verbose"
|
|
]
|
|
subprocess.check_call(cmd)
|
|
|
|
|
|
__name__ == '__main__' and update_vendored()
|