зеркало из https://github.com/mozilla/gecko-dev.git
169 строки
5.7 KiB
Python
169 строки
5.7 KiB
Python
import json
|
|
import os
|
|
import sys
|
|
import zipfile
|
|
|
|
ABS_HERE = os.path.abspath(os.path.dirname(__file__))
|
|
NEW_IMPORT_SYSTEM = sys.version_info[0] == 3
|
|
|
|
|
|
class VersionPlatformSelect(object):
|
|
def __init__(self):
|
|
self.archive = ABS_HERE
|
|
self._zip_file = zipfile.ZipFile(ABS_HERE, "r")
|
|
self.modules = self._load("modules.json")
|
|
self.distributions = self._load("distributions.json")
|
|
self.__cache = {}
|
|
|
|
def _load(self, of_file):
|
|
version = ".".join(str(i) for i in sys.version_info[0:2])
|
|
per_version = json.loads(self.get_data(of_file).decode("utf-8"))
|
|
all_platforms = per_version[version] if version in per_version else per_version["3.9"]
|
|
content = all_platforms.get("==any", {}) # start will all platforms
|
|
not_us = "!={}".format(sys.platform)
|
|
for key, value in all_platforms.items(): # now override that with not platform
|
|
if key.startswith("!=") and key != not_us:
|
|
content.update(value)
|
|
content.update(all_platforms.get("=={}".format(sys.platform), {})) # and finish it off with our platform
|
|
return content
|
|
|
|
def __enter__(self):
|
|
return self
|
|
|
|
def __exit__(self, exc_type, exc_val, exc_tb):
|
|
self._zip_file.close()
|
|
|
|
def find_mod(self, fullname):
|
|
if fullname in self.modules:
|
|
result = self.modules[fullname]
|
|
return result
|
|
|
|
def get_filename(self, fullname):
|
|
zip_path = self.find_mod(fullname)
|
|
return None if zip_path is None else os.path.join(ABS_HERE, zip_path)
|
|
|
|
def get_data(self, filename):
|
|
if filename.startswith(ABS_HERE):
|
|
# keep paths relative from the zipfile
|
|
filename = filename[len(ABS_HERE) + 1 :]
|
|
filename = filename.lstrip(os.sep)
|
|
if sys.platform == "win32":
|
|
# paths within the zipfile is always /, fixup on Windows to transform \ to /
|
|
filename = "/".join(filename.split(os.sep))
|
|
with self._zip_file.open(filename) as file_handler:
|
|
return file_handler.read()
|
|
|
|
def find_distributions(self, context):
|
|
dist_class = versioned_distribution_class()
|
|
name = context.name
|
|
if name in self.distributions:
|
|
result = dist_class(file_loader=self.get_data, dist_path=self.distributions[name])
|
|
yield result
|
|
|
|
def __repr__(self):
|
|
return "{}(path={})".format(self.__class__.__name__, ABS_HERE)
|
|
|
|
def _register_distutils_finder(self):
|
|
if "distlib" not in self.modules:
|
|
return
|
|
|
|
class DistlibFinder(object):
|
|
def __init__(self, path, loader):
|
|
self.path = path
|
|
self.loader = loader
|
|
|
|
def find(self, name):
|
|
class Resource(object):
|
|
def __init__(self, content):
|
|
self.bytes = content
|
|
|
|
full_path = os.path.join(self.path, name)
|
|
return Resource(self.loader.get_data(full_path))
|
|
|
|
# noinspection PyPackageRequirements
|
|
from distlib.resources import register_finder
|
|
|
|
register_finder(self, lambda module: DistlibFinder(os.path.dirname(module.__file__), self))
|
|
|
|
|
|
_VER_DISTRIBUTION_CLASS = None
|
|
|
|
|
|
def versioned_distribution_class():
|
|
global _VER_DISTRIBUTION_CLASS
|
|
if _VER_DISTRIBUTION_CLASS is None:
|
|
if sys.version_info >= (3, 8):
|
|
# noinspection PyCompatibility
|
|
from importlib.metadata import Distribution
|
|
else:
|
|
# noinspection PyUnresolvedReferences
|
|
from importlib_metadata import Distribution
|
|
|
|
class VersionedDistribution(Distribution):
|
|
def __init__(self, file_loader, dist_path):
|
|
self.file_loader = file_loader
|
|
self.dist_path = dist_path
|
|
|
|
def read_text(self, filename):
|
|
return self.file_loader(self.locate_file(filename)).decode("utf-8")
|
|
|
|
def locate_file(self, path):
|
|
return os.path.join(self.dist_path, path)
|
|
|
|
_VER_DISTRIBUTION_CLASS = VersionedDistribution
|
|
return _VER_DISTRIBUTION_CLASS
|
|
|
|
|
|
if NEW_IMPORT_SYSTEM:
|
|
# noinspection PyCompatibility
|
|
# noinspection PyCompatibility
|
|
from importlib.abc import SourceLoader
|
|
from importlib.util import spec_from_file_location
|
|
|
|
class VersionedFindLoad(VersionPlatformSelect, SourceLoader):
|
|
def find_spec(self, fullname, path, target=None):
|
|
zip_path = self.find_mod(fullname)
|
|
if zip_path is not None:
|
|
spec = spec_from_file_location(name=fullname, loader=self)
|
|
return spec
|
|
|
|
def module_repr(self, module):
|
|
raise NotImplementedError
|
|
|
|
|
|
else:
|
|
# noinspection PyDeprecation
|
|
from imp import new_module
|
|
|
|
class VersionedFindLoad(VersionPlatformSelect):
|
|
def find_module(self, fullname, path=None):
|
|
return self if self.find_mod(fullname) else None
|
|
|
|
def load_module(self, fullname):
|
|
filename = self.get_filename(fullname)
|
|
code = self.get_data(filename)
|
|
mod = sys.modules.setdefault(fullname, new_module(fullname))
|
|
mod.__file__ = filename
|
|
mod.__loader__ = self
|
|
is_package = filename.endswith("__init__.py")
|
|
if is_package:
|
|
mod.__path__ = [os.path.dirname(filename)]
|
|
mod.__package__ = fullname
|
|
else:
|
|
mod.__package__ = fullname.rpartition(".")[0]
|
|
exec(code, mod.__dict__)
|
|
return mod
|
|
|
|
|
|
def run():
|
|
with VersionedFindLoad() as finder:
|
|
sys.meta_path.insert(0, finder)
|
|
finder._register_distutils_finder()
|
|
from virtualenv.__main__ import run as run_virtualenv
|
|
|
|
run_virtualenv()
|
|
|
|
|
|
if __name__ == "__main__":
|
|
run()
|