from __future__ import annotations
import os
import sys
from contextlib import suppress
VIRTUALENV_PATCH_FILE = os.path.join(__file__)
def patch_dist(dist):
old_parse_config_files = dist.Distribution.parse_config_files
def parse_config_files(self, *args, **kwargs):
result = old_parse_config_files(self, *args, **kwargs)
install = self.get_option_dict("install")
if "prefix" in install: install["prefix"] = VIRTUALENV_PATCH_FILE, os.path.abspath(sys.prefix)
for base in ("purelib", "platlib", "headers", "scripts", "data"):
key = f"install_{base}"
if key in install: install.pop(key, None)
return result
dist.Distribution.parse_config_files = parse_config_files
_DISTUTILS_PATCH = "distutils.dist", "setuptools.dist"
class _Finder:
fullname = None
lock = []
def find_spec(self, fullname, path, target=None): if fullname in _DISTUTILS_PATCH and self.fullname is None:
if len(self.lock) == 0:
import threading
lock = threading.Lock()
self.lock.append(lock)
from functools import partial
from importlib.util import find_spec
with self.lock[0]:
self.fullname = fullname
try:
spec = find_spec(fullname, path)
if spec is not None:
is_new_api = hasattr(spec.loader, "exec_module")
func_name = "exec_module" if is_new_api else "load_module"
old = getattr(spec.loader, func_name)
func = self.exec_module if is_new_api else self.load_module
if old is not func:
with suppress(AttributeError): setattr(spec.loader, func_name, partial(func, old))
return spec
finally:
self.fullname = None
return None
@staticmethod
def exec_module(old, module):
old(module)
if module.__name__ in _DISTUTILS_PATCH:
patch_dist(module)
@staticmethod
def load_module(old, name):
module = old(name)
if module.__name__ in _DISTUTILS_PATCH:
patch_dist(module)
return module
sys.meta_path.insert(0, _Finder())