Mercurial > repos > shellac > sam_consensus_v3
comparison env/lib/python3.9/site-packages/virtualenv/create/via_global_ref/_virtualenv.py @ 0:4f3585e2f14b draft default tip
"planemo upload commit 60cee0fc7c0cda8592644e1aad72851dec82c959"
author | shellac |
---|---|
date | Mon, 22 Mar 2021 18:12:50 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:4f3585e2f14b |
---|---|
1 """Patches that are applied at runtime to the virtual environment""" | |
2 # -*- coding: utf-8 -*- | |
3 | |
4 import os | |
5 import sys | |
6 | |
7 VIRTUALENV_PATCH_FILE = os.path.join(__file__) | |
8 | |
9 | |
10 def patch_dist(dist): | |
11 """ | |
12 Distutils allows user to configure some arguments via a configuration file: | |
13 https://docs.python.org/3/install/index.html#distutils-configuration-files | |
14 | |
15 Some of this arguments though don't make sense in context of the virtual environment files, let's fix them up. | |
16 """ | |
17 # we cannot allow some install config as that would get packages installed outside of the virtual environment | |
18 old_parse_config_files = dist.Distribution.parse_config_files | |
19 | |
20 def parse_config_files(self, *args, **kwargs): | |
21 result = old_parse_config_files(self, *args, **kwargs) | |
22 install = self.get_option_dict("install") | |
23 | |
24 if "prefix" in install: # the prefix governs where to install the libraries | |
25 install["prefix"] = VIRTUALENV_PATCH_FILE, os.path.abspath(sys.prefix) | |
26 for base in ("purelib", "platlib", "headers", "scripts", "data"): | |
27 key = "install_{}".format(base) | |
28 if key in install: # do not allow global configs to hijack venv paths | |
29 install.pop(key, None) | |
30 return result | |
31 | |
32 dist.Distribution.parse_config_files = parse_config_files | |
33 | |
34 | |
35 # Import hook that patches some modules to ignore configuration values that break package installation in case | |
36 # of virtual environments. | |
37 _DISTUTILS_PATCH = "distutils.dist", "setuptools.dist" | |
38 if sys.version_info > (3, 4): | |
39 # https://docs.python.org/3/library/importlib.html#setting-up-an-importer | |
40 from functools import partial | |
41 from importlib.abc import MetaPathFinder | |
42 from importlib.util import find_spec | |
43 | |
44 class _Finder(MetaPathFinder): | |
45 """A meta path finder that allows patching the imported distutils modules""" | |
46 | |
47 fullname = None | |
48 | |
49 # lock[0] is threading.Lock(), but initialized lazily to avoid importing threading very early at startup, | |
50 # because there are gevent-based applications that need to be first to import threading by themselves. | |
51 # See https://github.com/pypa/virtualenv/issues/1895 for details. | |
52 lock = [] | |
53 | |
54 def find_spec(self, fullname, path, target=None): | |
55 if fullname in _DISTUTILS_PATCH and self.fullname is None: | |
56 # initialize lock[0] lazily | |
57 if len(self.lock) == 0: | |
58 import threading | |
59 | |
60 lock = threading.Lock() | |
61 # there is possibility that two threads T1 and T2 are simultaneously running into find_spec, | |
62 # observing .lock as empty, and further going into hereby initialization. However due to the GIL, | |
63 # list.append() operation is atomic and this way only one of the threads will "win" to put the lock | |
64 # - that every thread will use - into .lock[0]. | |
65 # https://docs.python.org/3/faq/library.html#what-kinds-of-global-value-mutation-are-thread-safe | |
66 self.lock.append(lock) | |
67 | |
68 with self.lock[0]: | |
69 self.fullname = fullname | |
70 try: | |
71 spec = find_spec(fullname, path) | |
72 if spec is not None: | |
73 # https://www.python.org/dev/peps/pep-0451/#how-loading-will-work | |
74 is_new_api = hasattr(spec.loader, "exec_module") | |
75 func_name = "exec_module" if is_new_api else "load_module" | |
76 old = getattr(spec.loader, func_name) | |
77 func = self.exec_module if is_new_api else self.load_module | |
78 if old is not func: | |
79 try: | |
80 setattr(spec.loader, func_name, partial(func, old)) | |
81 except AttributeError: | |
82 pass # C-Extension loaders are r/o such as zipimporter with <python 3.7 | |
83 return spec | |
84 finally: | |
85 self.fullname = None | |
86 | |
87 @staticmethod | |
88 def exec_module(old, module): | |
89 old(module) | |
90 if module.__name__ in _DISTUTILS_PATCH: | |
91 patch_dist(module) | |
92 | |
93 @staticmethod | |
94 def load_module(old, name): | |
95 module = old(name) | |
96 if module.__name__ in _DISTUTILS_PATCH: | |
97 patch_dist(module) | |
98 return module | |
99 | |
100 sys.meta_path.insert(0, _Finder()) | |
101 else: | |
102 # https://www.python.org/dev/peps/pep-0302/ | |
103 from imp import find_module | |
104 from pkgutil import ImpImporter, ImpLoader | |
105 | |
106 class _VirtualenvImporter(object, ImpImporter): | |
107 def __init__(self, path=None): | |
108 object.__init__(self) | |
109 ImpImporter.__init__(self, path) | |
110 | |
111 def find_module(self, fullname, path=None): | |
112 if fullname in _DISTUTILS_PATCH: | |
113 try: | |
114 return _VirtualenvLoader(fullname, *find_module(fullname.split(".")[-1], path)) | |
115 except ImportError: | |
116 pass | |
117 return None | |
118 | |
119 class _VirtualenvLoader(object, ImpLoader): | |
120 def __init__(self, fullname, file, filename, etc): | |
121 object.__init__(self) | |
122 ImpLoader.__init__(self, fullname, file, filename, etc) | |
123 | |
124 def load_module(self, fullname): | |
125 module = super(_VirtualenvLoader, self).load_module(fullname) | |
126 patch_dist(module) | |
127 module.__loader__ = None # distlib fallback | |
128 return module | |
129 | |
130 sys.meta_path.append(_VirtualenvImporter()) |