Add files using upload-large-folder tool
Browse filesThis view is limited to 50 files because it contains too many changes.
See raw diff
- .venv/lib/python3.11/site-packages/virtualenv/create/__init__.py +0 -0
- .venv/lib/python3.11/site-packages/virtualenv/create/__pycache__/__init__.cpython-311.pyc +0 -0
- .venv/lib/python3.11/site-packages/virtualenv/create/__pycache__/creator.cpython-311.pyc +0 -0
- .venv/lib/python3.11/site-packages/virtualenv/create/__pycache__/debug.cpython-311.pyc +0 -0
- .venv/lib/python3.11/site-packages/virtualenv/create/__pycache__/describe.cpython-311.pyc +0 -0
- .venv/lib/python3.11/site-packages/virtualenv/create/__pycache__/pyenv_cfg.cpython-311.pyc +0 -0
- .venv/lib/python3.11/site-packages/virtualenv/create/creator.py +241 -0
- .venv/lib/python3.11/site-packages/virtualenv/create/debug.py +102 -0
- .venv/lib/python3.11/site-packages/virtualenv/create/describe.py +110 -0
- .venv/lib/python3.11/site-packages/virtualenv/create/pyenv_cfg.py +68 -0
- .venv/lib/python3.11/site-packages/virtualenv/create/via_global_ref/__init__.py +0 -0
- .venv/lib/python3.11/site-packages/virtualenv/create/via_global_ref/__pycache__/__init__.cpython-311.pyc +0 -0
- .venv/lib/python3.11/site-packages/virtualenv/create/via_global_ref/__pycache__/_virtualenv.cpython-311.pyc +0 -0
- .venv/lib/python3.11/site-packages/virtualenv/create/via_global_ref/__pycache__/api.cpython-311.pyc +0 -0
- .venv/lib/python3.11/site-packages/virtualenv/create/via_global_ref/__pycache__/store.cpython-311.pyc +0 -0
- .venv/lib/python3.11/site-packages/virtualenv/create/via_global_ref/__pycache__/venv.cpython-311.pyc +0 -0
- .venv/lib/python3.11/site-packages/virtualenv/create/via_global_ref/_virtualenv.py +103 -0
- .venv/lib/python3.11/site-packages/virtualenv/create/via_global_ref/api.py +116 -0
- .venv/lib/python3.11/site-packages/virtualenv/create/via_global_ref/builtin/__init__.py +0 -0
- .venv/lib/python3.11/site-packages/virtualenv/create/via_global_ref/builtin/__pycache__/__init__.cpython-311.pyc +0 -0
- .venv/lib/python3.11/site-packages/virtualenv/create/via_global_ref/builtin/__pycache__/builtin_way.cpython-311.pyc +0 -0
- .venv/lib/python3.11/site-packages/virtualenv/create/via_global_ref/builtin/__pycache__/ref.cpython-311.pyc +0 -0
- .venv/lib/python3.11/site-packages/virtualenv/create/via_global_ref/builtin/__pycache__/via_global_self_do.cpython-311.pyc +0 -0
- .venv/lib/python3.11/site-packages/virtualenv/create/via_global_ref/builtin/builtin_way.py +19 -0
- .venv/lib/python3.11/site-packages/virtualenv/create/via_global_ref/builtin/cpython/__init__.py +0 -0
- .venv/lib/python3.11/site-packages/virtualenv/create/via_global_ref/builtin/cpython/__pycache__/__init__.cpython-311.pyc +0 -0
- .venv/lib/python3.11/site-packages/virtualenv/create/via_global_ref/builtin/cpython/__pycache__/common.cpython-311.pyc +0 -0
- .venv/lib/python3.11/site-packages/virtualenv/create/via_global_ref/builtin/cpython/__pycache__/cpython3.cpython-311.pyc +0 -0
- .venv/lib/python3.11/site-packages/virtualenv/create/via_global_ref/builtin/cpython/__pycache__/mac_os.cpython-311.pyc +0 -0
- .venv/lib/python3.11/site-packages/virtualenv/create/via_global_ref/builtin/cpython/common.py +73 -0
- .venv/lib/python3.11/site-packages/virtualenv/create/via_global_ref/builtin/cpython/cpython3.py +135 -0
- .venv/lib/python3.11/site-packages/virtualenv/create/via_global_ref/builtin/cpython/mac_os.py +281 -0
- .venv/lib/python3.11/site-packages/virtualenv/create/via_global_ref/builtin/pypy/__init__.py +0 -0
- .venv/lib/python3.11/site-packages/virtualenv/create/via_global_ref/builtin/pypy/__pycache__/__init__.cpython-311.pyc +0 -0
- .venv/lib/python3.11/site-packages/virtualenv/create/via_global_ref/builtin/pypy/__pycache__/common.cpython-311.pyc +0 -0
- .venv/lib/python3.11/site-packages/virtualenv/create/via_global_ref/builtin/pypy/__pycache__/pypy3.cpython-311.pyc +0 -0
- .venv/lib/python3.11/site-packages/virtualenv/create/via_global_ref/builtin/pypy/common.py +53 -0
- .venv/lib/python3.11/site-packages/virtualenv/create/via_global_ref/builtin/pypy/pypy3.py +76 -0
- .venv/lib/python3.11/site-packages/virtualenv/create/via_global_ref/builtin/ref.py +178 -0
- .venv/lib/python3.11/site-packages/virtualenv/create/via_global_ref/builtin/via_global_self_do.py +118 -0
- .venv/lib/python3.11/site-packages/virtualenv/create/via_global_ref/store.py +26 -0
- .venv/lib/python3.11/site-packages/virtualenv/create/via_global_ref/venv.py +104 -0
- .venv/lib/python3.11/site-packages/virtualenv/seed/__pycache__/__init__.cpython-311.pyc +0 -0
- .venv/lib/python3.11/site-packages/virtualenv/seed/__pycache__/seeder.cpython-311.pyc +0 -0
- .venv/lib/python3.11/site-packages/virtualenv/seed/embed/via_app_data/__pycache__/__init__.cpython-311.pyc +0 -0
- .venv/lib/python3.11/site-packages/virtualenv/seed/embed/via_app_data/__pycache__/via_app_data.cpython-311.pyc +0 -0
- .venv/lib/python3.11/site-packages/virtualenv/seed/embed/via_app_data/pip_install/__init__.py +0 -0
- .venv/lib/python3.11/site-packages/virtualenv/seed/embed/via_app_data/pip_install/__pycache__/__init__.cpython-311.pyc +0 -0
- .venv/lib/python3.11/site-packages/virtualenv/seed/embed/via_app_data/pip_install/__pycache__/base.cpython-311.pyc +0 -0
- .venv/lib/python3.11/site-packages/virtualenv/seed/embed/via_app_data/pip_install/__pycache__/copy.cpython-311.pyc +0 -0
.venv/lib/python3.11/site-packages/virtualenv/create/__init__.py
ADDED
|
File without changes
|
.venv/lib/python3.11/site-packages/virtualenv/create/__pycache__/__init__.cpython-311.pyc
ADDED
|
Binary file (190 Bytes). View file
|
|
|
.venv/lib/python3.11/site-packages/virtualenv/create/__pycache__/creator.cpython-311.pyc
ADDED
|
Binary file (13.8 kB). View file
|
|
|
.venv/lib/python3.11/site-packages/virtualenv/create/__pycache__/debug.cpython-311.pyc
ADDED
|
Binary file (4.77 kB). View file
|
|
|
.venv/lib/python3.11/site-packages/virtualenv/create/__pycache__/describe.cpython-311.pyc
ADDED
|
Binary file (7.27 kB). View file
|
|
|
.venv/lib/python3.11/site-packages/virtualenv/create/__pycache__/pyenv_cfg.cpython-311.pyc
ADDED
|
Binary file (4.44 kB). View file
|
|
|
.venv/lib/python3.11/site-packages/virtualenv/create/creator.py
ADDED
|
@@ -0,0 +1,241 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from __future__ import annotations
|
| 2 |
+
|
| 3 |
+
import json
|
| 4 |
+
import logging
|
| 5 |
+
import os
|
| 6 |
+
import sys
|
| 7 |
+
import textwrap
|
| 8 |
+
from abc import ABC, abstractmethod
|
| 9 |
+
from argparse import ArgumentTypeError
|
| 10 |
+
from ast import literal_eval
|
| 11 |
+
from collections import OrderedDict
|
| 12 |
+
from pathlib import Path
|
| 13 |
+
|
| 14 |
+
from virtualenv.discovery.cached_py_info import LogCmd
|
| 15 |
+
from virtualenv.util.path import safe_delete
|
| 16 |
+
from virtualenv.util.subprocess import run_cmd
|
| 17 |
+
from virtualenv.version import __version__
|
| 18 |
+
|
| 19 |
+
from .pyenv_cfg import PyEnvCfg
|
| 20 |
+
|
| 21 |
+
HERE = Path(os.path.abspath(__file__)).parent
|
| 22 |
+
DEBUG_SCRIPT = HERE / "debug.py"
|
| 23 |
+
LOGGER = logging.getLogger(__name__)
|
| 24 |
+
|
| 25 |
+
|
| 26 |
+
class CreatorMeta:
|
| 27 |
+
def __init__(self) -> None:
|
| 28 |
+
self.error = None
|
| 29 |
+
|
| 30 |
+
|
| 31 |
+
class Creator(ABC):
|
| 32 |
+
"""A class that given a python Interpreter creates a virtual environment."""
|
| 33 |
+
|
| 34 |
+
def __init__(self, options, interpreter) -> None:
|
| 35 |
+
"""
|
| 36 |
+
Construct a new virtual environment creator.
|
| 37 |
+
|
| 38 |
+
:param options: the CLI option as parsed from :meth:`add_parser_arguments`
|
| 39 |
+
:param interpreter: the interpreter to create virtual environment from
|
| 40 |
+
"""
|
| 41 |
+
self.interpreter = interpreter
|
| 42 |
+
self._debug = None
|
| 43 |
+
self.dest = Path(options.dest)
|
| 44 |
+
self.clear = options.clear
|
| 45 |
+
self.no_vcs_ignore = options.no_vcs_ignore
|
| 46 |
+
self.pyenv_cfg = PyEnvCfg.from_folder(self.dest)
|
| 47 |
+
self.app_data = options.app_data
|
| 48 |
+
self.env = options.env
|
| 49 |
+
|
| 50 |
+
def __repr__(self) -> str:
|
| 51 |
+
return f"{self.__class__.__name__}({', '.join(f'{k}={v}' for k, v in self._args())})"
|
| 52 |
+
|
| 53 |
+
def _args(self):
|
| 54 |
+
return [
|
| 55 |
+
("dest", str(self.dest)),
|
| 56 |
+
("clear", self.clear),
|
| 57 |
+
("no_vcs_ignore", self.no_vcs_ignore),
|
| 58 |
+
]
|
| 59 |
+
|
| 60 |
+
@classmethod
|
| 61 |
+
def can_create(cls, interpreter): # noqa: ARG003
|
| 62 |
+
"""
|
| 63 |
+
Determine if we can create a virtual environment.
|
| 64 |
+
|
| 65 |
+
:param interpreter: the interpreter in question
|
| 66 |
+
:return: ``None`` if we can't create, any other object otherwise that will be forwarded to \
|
| 67 |
+
:meth:`add_parser_arguments`
|
| 68 |
+
"""
|
| 69 |
+
return True
|
| 70 |
+
|
| 71 |
+
@classmethod
|
| 72 |
+
def add_parser_arguments(cls, parser, interpreter, meta, app_data): # noqa: ARG003
|
| 73 |
+
"""
|
| 74 |
+
Add CLI arguments for the creator.
|
| 75 |
+
|
| 76 |
+
:param parser: the CLI parser
|
| 77 |
+
:param app_data: the application data folder
|
| 78 |
+
:param interpreter: the interpreter we're asked to create virtual environment for
|
| 79 |
+
:param meta: value as returned by :meth:`can_create`
|
| 80 |
+
"""
|
| 81 |
+
parser.add_argument(
|
| 82 |
+
"dest",
|
| 83 |
+
help="directory to create virtualenv at",
|
| 84 |
+
type=cls.validate_dest,
|
| 85 |
+
)
|
| 86 |
+
parser.add_argument(
|
| 87 |
+
"--clear",
|
| 88 |
+
dest="clear",
|
| 89 |
+
action="store_true",
|
| 90 |
+
help="remove the destination directory if exist before starting (will overwrite files otherwise)",
|
| 91 |
+
default=False,
|
| 92 |
+
)
|
| 93 |
+
parser.add_argument(
|
| 94 |
+
"--no-vcs-ignore",
|
| 95 |
+
dest="no_vcs_ignore",
|
| 96 |
+
action="store_true",
|
| 97 |
+
help="don't create VCS ignore directive in the destination directory",
|
| 98 |
+
default=False,
|
| 99 |
+
)
|
| 100 |
+
|
| 101 |
+
@abstractmethod
|
| 102 |
+
def create(self):
|
| 103 |
+
"""Perform the virtual environment creation."""
|
| 104 |
+
raise NotImplementedError
|
| 105 |
+
|
| 106 |
+
@classmethod
|
| 107 |
+
def validate_dest(cls, raw_value): # noqa: C901
|
| 108 |
+
"""No path separator in the path, valid chars and must be write-able."""
|
| 109 |
+
|
| 110 |
+
def non_write_able(dest, value):
|
| 111 |
+
common = Path(*os.path.commonprefix([value.parts, dest.parts]))
|
| 112 |
+
msg = f"the destination {dest.relative_to(common)} is not write-able at {common}"
|
| 113 |
+
raise ArgumentTypeError(msg)
|
| 114 |
+
|
| 115 |
+
# the file system must be able to encode
|
| 116 |
+
# note in newer CPython this is always utf-8 https://www.python.org/dev/peps/pep-0529/
|
| 117 |
+
encoding = sys.getfilesystemencoding()
|
| 118 |
+
refused = OrderedDict()
|
| 119 |
+
kwargs = {"errors": "ignore"} if encoding != "mbcs" else {}
|
| 120 |
+
for char in str(raw_value):
|
| 121 |
+
try:
|
| 122 |
+
trip = char.encode(encoding, **kwargs).decode(encoding)
|
| 123 |
+
if trip == char:
|
| 124 |
+
continue
|
| 125 |
+
raise ValueError(trip) # noqa: TRY301
|
| 126 |
+
except ValueError:
|
| 127 |
+
refused[char] = None
|
| 128 |
+
if refused:
|
| 129 |
+
bad = "".join(refused.keys())
|
| 130 |
+
msg = f"the file system codec ({encoding}) cannot handle characters {bad!r} within {raw_value!r}"
|
| 131 |
+
raise ArgumentTypeError(msg)
|
| 132 |
+
if os.pathsep in raw_value:
|
| 133 |
+
msg = (
|
| 134 |
+
f"destination {raw_value!r} must not contain the path separator ({os.pathsep})"
|
| 135 |
+
f" as this would break the activation scripts"
|
| 136 |
+
)
|
| 137 |
+
raise ArgumentTypeError(msg)
|
| 138 |
+
|
| 139 |
+
value = Path(raw_value)
|
| 140 |
+
if value.exists() and value.is_file():
|
| 141 |
+
msg = f"the destination {value} already exists and is a file"
|
| 142 |
+
raise ArgumentTypeError(msg)
|
| 143 |
+
dest = Path(os.path.abspath(str(value))).resolve() # on Windows absolute does not imply resolve so use both
|
| 144 |
+
value = dest
|
| 145 |
+
while dest:
|
| 146 |
+
if dest.exists():
|
| 147 |
+
if os.access(str(dest), os.W_OK):
|
| 148 |
+
break
|
| 149 |
+
non_write_able(dest, value)
|
| 150 |
+
base, _ = dest.parent, dest.name
|
| 151 |
+
if base == dest:
|
| 152 |
+
non_write_able(dest, value) # pragma: no cover
|
| 153 |
+
dest = base
|
| 154 |
+
return str(value)
|
| 155 |
+
|
| 156 |
+
def run(self):
|
| 157 |
+
if self.dest.exists() and self.clear:
|
| 158 |
+
LOGGER.debug("delete %s", self.dest)
|
| 159 |
+
safe_delete(self.dest)
|
| 160 |
+
self.create()
|
| 161 |
+
self.add_cachedir_tag()
|
| 162 |
+
self.set_pyenv_cfg()
|
| 163 |
+
if not self.no_vcs_ignore:
|
| 164 |
+
self.setup_ignore_vcs()
|
| 165 |
+
|
| 166 |
+
def add_cachedir_tag(self):
|
| 167 |
+
"""Generate a file indicating that this is not meant to be backed up."""
|
| 168 |
+
cachedir_tag_file = self.dest / "CACHEDIR.TAG"
|
| 169 |
+
if not cachedir_tag_file.exists():
|
| 170 |
+
cachedir_tag_text = textwrap.dedent("""
|
| 171 |
+
Signature: 8a477f597d28d172789f06886806bc55
|
| 172 |
+
# This file is a cache directory tag created by Python virtualenv.
|
| 173 |
+
# For information about cache directory tags, see:
|
| 174 |
+
# https://bford.info/cachedir/
|
| 175 |
+
""").strip()
|
| 176 |
+
cachedir_tag_file.write_text(cachedir_tag_text, encoding="utf-8")
|
| 177 |
+
|
| 178 |
+
def set_pyenv_cfg(self):
|
| 179 |
+
self.pyenv_cfg.content = OrderedDict()
|
| 180 |
+
self.pyenv_cfg["home"] = os.path.dirname(os.path.abspath(self.interpreter.system_executable))
|
| 181 |
+
self.pyenv_cfg["implementation"] = self.interpreter.implementation
|
| 182 |
+
self.pyenv_cfg["version_info"] = ".".join(str(i) for i in self.interpreter.version_info)
|
| 183 |
+
self.pyenv_cfg["virtualenv"] = __version__
|
| 184 |
+
|
| 185 |
+
def setup_ignore_vcs(self):
|
| 186 |
+
"""Generate ignore instructions for version control systems."""
|
| 187 |
+
# mark this folder to be ignored by VCS, handle https://www.python.org/dev/peps/pep-0610/#registered-vcs
|
| 188 |
+
git_ignore = self.dest / ".gitignore"
|
| 189 |
+
if not git_ignore.exists():
|
| 190 |
+
git_ignore.write_text("# created by virtualenv automatically\n*\n", encoding="utf-8")
|
| 191 |
+
# Mercurial - does not support the .hgignore file inside a subdirectory directly, but only if included via the
|
| 192 |
+
# subinclude directive from root, at which point on might as well ignore the directory itself, see
|
| 193 |
+
# https://www.selenic.com/mercurial/hgignore.5.html for more details
|
| 194 |
+
# Bazaar - does not support ignore files in sub-directories, only at root level via .bzrignore
|
| 195 |
+
# Subversion - does not support ignore files, requires direct manipulation with the svn tool
|
| 196 |
+
|
| 197 |
+
@property
|
| 198 |
+
def debug(self):
|
| 199 |
+
""":return: debug information about the virtual environment (only valid after :meth:`create` has run)"""
|
| 200 |
+
if self._debug is None and self.exe is not None:
|
| 201 |
+
self._debug = get_env_debug_info(self.exe, self.debug_script(), self.app_data, self.env)
|
| 202 |
+
return self._debug
|
| 203 |
+
|
| 204 |
+
@staticmethod
|
| 205 |
+
def debug_script():
|
| 206 |
+
return DEBUG_SCRIPT
|
| 207 |
+
|
| 208 |
+
|
| 209 |
+
def get_env_debug_info(env_exe, debug_script, app_data, env):
|
| 210 |
+
env = env.copy()
|
| 211 |
+
env.pop("PYTHONPATH", None)
|
| 212 |
+
|
| 213 |
+
with app_data.ensure_extracted(debug_script) as debug_script_extracted:
|
| 214 |
+
cmd = [str(env_exe), str(debug_script_extracted)]
|
| 215 |
+
LOGGER.debug("debug via %r", LogCmd(cmd))
|
| 216 |
+
code, out, err = run_cmd(cmd)
|
| 217 |
+
|
| 218 |
+
try:
|
| 219 |
+
if code != 0:
|
| 220 |
+
if out:
|
| 221 |
+
result = literal_eval(out)
|
| 222 |
+
else:
|
| 223 |
+
if code == 2 and "file" in err: # noqa: PLR2004
|
| 224 |
+
# Re-raise FileNotFoundError from `run_cmd()`
|
| 225 |
+
raise OSError(err) # noqa: TRY301
|
| 226 |
+
raise Exception(err) # noqa: TRY002, TRY301
|
| 227 |
+
else:
|
| 228 |
+
result = json.loads(out)
|
| 229 |
+
if err:
|
| 230 |
+
result["err"] = err
|
| 231 |
+
except Exception as exception: # noqa: BLE001
|
| 232 |
+
return {"out": out, "err": err, "returncode": code, "exception": repr(exception)}
|
| 233 |
+
if "sys" in result and "path" in result["sys"]:
|
| 234 |
+
del result["sys"]["path"][0]
|
| 235 |
+
return result
|
| 236 |
+
|
| 237 |
+
|
| 238 |
+
__all__ = [
|
| 239 |
+
"Creator",
|
| 240 |
+
"CreatorMeta",
|
| 241 |
+
]
|
.venv/lib/python3.11/site-packages/virtualenv/create/debug.py
ADDED
|
@@ -0,0 +1,102 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Inspect a target Python interpreter virtual environment wise."""
|
| 2 |
+
|
| 3 |
+
from __future__ import annotations
|
| 4 |
+
|
| 5 |
+
import sys # built-in
|
| 6 |
+
|
| 7 |
+
|
| 8 |
+
def encode_path(value):
|
| 9 |
+
if value is None:
|
| 10 |
+
return None
|
| 11 |
+
if not isinstance(value, (str, bytes)):
|
| 12 |
+
value = repr(value) if isinstance(value, type) else repr(type(value))
|
| 13 |
+
if isinstance(value, bytes):
|
| 14 |
+
value = value.decode(sys.getfilesystemencoding())
|
| 15 |
+
return value
|
| 16 |
+
|
| 17 |
+
|
| 18 |
+
def encode_list_path(value):
|
| 19 |
+
return [encode_path(i) for i in value]
|
| 20 |
+
|
| 21 |
+
|
| 22 |
+
def run():
|
| 23 |
+
"""Print debug data about the virtual environment."""
|
| 24 |
+
try:
|
| 25 |
+
from collections import OrderedDict # noqa: PLC0415
|
| 26 |
+
except ImportError: # pragma: no cover
|
| 27 |
+
# this is possible if the standard library cannot be accessed
|
| 28 |
+
|
| 29 |
+
OrderedDict = dict # pragma: no cover # noqa: N806
|
| 30 |
+
result = OrderedDict([("sys", OrderedDict())])
|
| 31 |
+
path_keys = (
|
| 32 |
+
"executable",
|
| 33 |
+
"_base_executable",
|
| 34 |
+
"prefix",
|
| 35 |
+
"base_prefix",
|
| 36 |
+
"real_prefix",
|
| 37 |
+
"exec_prefix",
|
| 38 |
+
"base_exec_prefix",
|
| 39 |
+
"path",
|
| 40 |
+
"meta_path",
|
| 41 |
+
)
|
| 42 |
+
for key in path_keys:
|
| 43 |
+
value = getattr(sys, key, None)
|
| 44 |
+
value = encode_list_path(value) if isinstance(value, list) else encode_path(value)
|
| 45 |
+
result["sys"][key] = value
|
| 46 |
+
result["sys"]["fs_encoding"] = sys.getfilesystemencoding()
|
| 47 |
+
result["sys"]["io_encoding"] = getattr(sys.stdout, "encoding", None)
|
| 48 |
+
result["version"] = sys.version
|
| 49 |
+
|
| 50 |
+
try:
|
| 51 |
+
import sysconfig # noqa: PLC0415
|
| 52 |
+
|
| 53 |
+
# https://bugs.python.org/issue22199
|
| 54 |
+
makefile = getattr(sysconfig, "get_makefile_filename", getattr(sysconfig, "_get_makefile_filename", None))
|
| 55 |
+
result["makefile_filename"] = encode_path(makefile())
|
| 56 |
+
except ImportError:
|
| 57 |
+
pass
|
| 58 |
+
|
| 59 |
+
import os # landmark # noqa: PLC0415
|
| 60 |
+
|
| 61 |
+
result["os"] = repr(os)
|
| 62 |
+
|
| 63 |
+
try:
|
| 64 |
+
import site # site # noqa: PLC0415
|
| 65 |
+
|
| 66 |
+
result["site"] = repr(site)
|
| 67 |
+
except ImportError as exception: # pragma: no cover
|
| 68 |
+
result["site"] = repr(exception) # pragma: no cover
|
| 69 |
+
|
| 70 |
+
try:
|
| 71 |
+
import datetime # site # noqa: PLC0415
|
| 72 |
+
|
| 73 |
+
result["datetime"] = repr(datetime)
|
| 74 |
+
except ImportError as exception: # pragma: no cover
|
| 75 |
+
result["datetime"] = repr(exception) # pragma: no cover
|
| 76 |
+
|
| 77 |
+
try:
|
| 78 |
+
import math # site # noqa: PLC0415
|
| 79 |
+
|
| 80 |
+
result["math"] = repr(math)
|
| 81 |
+
except ImportError as exception: # pragma: no cover
|
| 82 |
+
result["math"] = repr(exception) # pragma: no cover
|
| 83 |
+
|
| 84 |
+
# try to print out, this will validate if other core modules are available (json in this case)
|
| 85 |
+
try:
|
| 86 |
+
import json # noqa: PLC0415
|
| 87 |
+
|
| 88 |
+
result["json"] = repr(json)
|
| 89 |
+
except ImportError as exception:
|
| 90 |
+
result["json"] = repr(exception)
|
| 91 |
+
else:
|
| 92 |
+
try:
|
| 93 |
+
content = json.dumps(result, indent=2)
|
| 94 |
+
sys.stdout.write(content)
|
| 95 |
+
except (ValueError, TypeError) as exception: # pragma: no cover
|
| 96 |
+
sys.stderr.write(repr(exception))
|
| 97 |
+
sys.stdout.write(repr(result)) # pragma: no cover
|
| 98 |
+
raise SystemExit(1) # noqa: B904 # pragma: no cover
|
| 99 |
+
|
| 100 |
+
|
| 101 |
+
if __name__ == "__main__":
|
| 102 |
+
run()
|
.venv/lib/python3.11/site-packages/virtualenv/create/describe.py
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from __future__ import annotations
|
| 2 |
+
|
| 3 |
+
from abc import ABC
|
| 4 |
+
from collections import OrderedDict
|
| 5 |
+
from pathlib import Path
|
| 6 |
+
|
| 7 |
+
from virtualenv.info import IS_WIN
|
| 8 |
+
|
| 9 |
+
|
| 10 |
+
class Describe:
|
| 11 |
+
"""Given a host interpreter tell us information about what the created interpreter might look like."""
|
| 12 |
+
|
| 13 |
+
suffix = ".exe" if IS_WIN else ""
|
| 14 |
+
|
| 15 |
+
def __init__(self, dest, interpreter) -> None:
|
| 16 |
+
self.interpreter = interpreter
|
| 17 |
+
self.dest = dest
|
| 18 |
+
self._stdlib = None
|
| 19 |
+
self._stdlib_platform = None
|
| 20 |
+
self._system_stdlib = None
|
| 21 |
+
self._conf_vars = None
|
| 22 |
+
|
| 23 |
+
@property
|
| 24 |
+
def bin_dir(self):
|
| 25 |
+
return self.script_dir
|
| 26 |
+
|
| 27 |
+
@property
|
| 28 |
+
def script_dir(self):
|
| 29 |
+
return self.dest / self.interpreter.install_path("scripts")
|
| 30 |
+
|
| 31 |
+
@property
|
| 32 |
+
def purelib(self):
|
| 33 |
+
return self.dest / self.interpreter.install_path("purelib")
|
| 34 |
+
|
| 35 |
+
@property
|
| 36 |
+
def platlib(self):
|
| 37 |
+
return self.dest / self.interpreter.install_path("platlib")
|
| 38 |
+
|
| 39 |
+
@property
|
| 40 |
+
def libs(self):
|
| 41 |
+
return list(OrderedDict(((self.platlib, None), (self.purelib, None))).keys())
|
| 42 |
+
|
| 43 |
+
@property
|
| 44 |
+
def stdlib(self):
|
| 45 |
+
if self._stdlib is None:
|
| 46 |
+
self._stdlib = Path(self.interpreter.sysconfig_path("stdlib", config_var=self._config_vars))
|
| 47 |
+
return self._stdlib
|
| 48 |
+
|
| 49 |
+
@property
|
| 50 |
+
def stdlib_platform(self):
|
| 51 |
+
if self._stdlib_platform is None:
|
| 52 |
+
self._stdlib_platform = Path(self.interpreter.sysconfig_path("platstdlib", config_var=self._config_vars))
|
| 53 |
+
return self._stdlib_platform
|
| 54 |
+
|
| 55 |
+
@property
|
| 56 |
+
def _config_vars(self):
|
| 57 |
+
if self._conf_vars is None:
|
| 58 |
+
self._conf_vars = self._calc_config_vars(self.dest)
|
| 59 |
+
return self._conf_vars
|
| 60 |
+
|
| 61 |
+
def _calc_config_vars(self, to):
|
| 62 |
+
sys_vars = self.interpreter.sysconfig_vars
|
| 63 |
+
return {k: (to if v is not None and v.startswith(self.interpreter.prefix) else v) for k, v in sys_vars.items()}
|
| 64 |
+
|
| 65 |
+
@classmethod
|
| 66 |
+
def can_describe(cls, interpreter): # noqa: ARG003
|
| 67 |
+
"""Knows means it knows how the output will look."""
|
| 68 |
+
return True
|
| 69 |
+
|
| 70 |
+
@property
|
| 71 |
+
def env_name(self):
|
| 72 |
+
return self.dest.parts[-1]
|
| 73 |
+
|
| 74 |
+
@property
|
| 75 |
+
def exe(self):
|
| 76 |
+
return self.bin_dir / f"{self.exe_stem()}{self.suffix}"
|
| 77 |
+
|
| 78 |
+
@classmethod
|
| 79 |
+
def exe_stem(cls):
|
| 80 |
+
"""Executable name without suffix - there seems to be no standard way to get this without creating it."""
|
| 81 |
+
raise NotImplementedError
|
| 82 |
+
|
| 83 |
+
def script(self, name):
|
| 84 |
+
return self.script_dir / f"{name}{self.suffix}"
|
| 85 |
+
|
| 86 |
+
|
| 87 |
+
class Python3Supports(Describe, ABC):
|
| 88 |
+
@classmethod
|
| 89 |
+
def can_describe(cls, interpreter):
|
| 90 |
+
return interpreter.version_info.major == 3 and super().can_describe(interpreter) # noqa: PLR2004
|
| 91 |
+
|
| 92 |
+
|
| 93 |
+
class PosixSupports(Describe, ABC):
|
| 94 |
+
@classmethod
|
| 95 |
+
def can_describe(cls, interpreter):
|
| 96 |
+
return interpreter.os == "posix" and super().can_describe(interpreter)
|
| 97 |
+
|
| 98 |
+
|
| 99 |
+
class WindowsSupports(Describe, ABC):
|
| 100 |
+
@classmethod
|
| 101 |
+
def can_describe(cls, interpreter):
|
| 102 |
+
return interpreter.os == "nt" and super().can_describe(interpreter)
|
| 103 |
+
|
| 104 |
+
|
| 105 |
+
__all__ = [
|
| 106 |
+
"Describe",
|
| 107 |
+
"PosixSupports",
|
| 108 |
+
"Python3Supports",
|
| 109 |
+
"WindowsSupports",
|
| 110 |
+
]
|
.venv/lib/python3.11/site-packages/virtualenv/create/pyenv_cfg.py
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from __future__ import annotations
|
| 2 |
+
|
| 3 |
+
import logging
|
| 4 |
+
import os
|
| 5 |
+
from collections import OrderedDict
|
| 6 |
+
|
| 7 |
+
LOGGER = logging.getLogger(__name__)
|
| 8 |
+
|
| 9 |
+
|
| 10 |
+
class PyEnvCfg:
|
| 11 |
+
def __init__(self, content, path) -> None:
|
| 12 |
+
self.content = content
|
| 13 |
+
self.path = path
|
| 14 |
+
|
| 15 |
+
@classmethod
|
| 16 |
+
def from_folder(cls, folder):
|
| 17 |
+
return cls.from_file(folder / "pyvenv.cfg")
|
| 18 |
+
|
| 19 |
+
@classmethod
|
| 20 |
+
def from_file(cls, path):
|
| 21 |
+
content = cls._read_values(path) if path.exists() else OrderedDict()
|
| 22 |
+
return PyEnvCfg(content, path)
|
| 23 |
+
|
| 24 |
+
@staticmethod
|
| 25 |
+
def _read_values(path):
|
| 26 |
+
content = OrderedDict()
|
| 27 |
+
for line in path.read_text(encoding="utf-8").splitlines():
|
| 28 |
+
equals_at = line.index("=")
|
| 29 |
+
key = line[:equals_at].strip()
|
| 30 |
+
value = line[equals_at + 1 :].strip()
|
| 31 |
+
content[key] = value
|
| 32 |
+
return content
|
| 33 |
+
|
| 34 |
+
def write(self):
|
| 35 |
+
LOGGER.debug("write %s", self.path)
|
| 36 |
+
text = ""
|
| 37 |
+
for key, value in self.content.items():
|
| 38 |
+
normalized_value = os.path.realpath(value) if value and os.path.exists(value) else value
|
| 39 |
+
line = f"{key} = {normalized_value}"
|
| 40 |
+
LOGGER.debug("\t%s", line)
|
| 41 |
+
text += line
|
| 42 |
+
text += "\n"
|
| 43 |
+
self.path.write_text(text, encoding="utf-8")
|
| 44 |
+
|
| 45 |
+
def refresh(self):
|
| 46 |
+
self.content = self._read_values(self.path)
|
| 47 |
+
return self.content
|
| 48 |
+
|
| 49 |
+
def __setitem__(self, key, value) -> None:
|
| 50 |
+
self.content[key] = value
|
| 51 |
+
|
| 52 |
+
def __getitem__(self, key):
|
| 53 |
+
return self.content[key]
|
| 54 |
+
|
| 55 |
+
def __contains__(self, item) -> bool:
|
| 56 |
+
return item in self.content
|
| 57 |
+
|
| 58 |
+
def update(self, other):
|
| 59 |
+
self.content.update(other)
|
| 60 |
+
return self
|
| 61 |
+
|
| 62 |
+
def __repr__(self) -> str:
|
| 63 |
+
return f"{self.__class__.__name__}(path={self.path})"
|
| 64 |
+
|
| 65 |
+
|
| 66 |
+
__all__ = [
|
| 67 |
+
"PyEnvCfg",
|
| 68 |
+
]
|
.venv/lib/python3.11/site-packages/virtualenv/create/via_global_ref/__init__.py
ADDED
|
File without changes
|
.venv/lib/python3.11/site-packages/virtualenv/create/via_global_ref/__pycache__/__init__.cpython-311.pyc
ADDED
|
Binary file (205 Bytes). View file
|
|
|
.venv/lib/python3.11/site-packages/virtualenv/create/via_global_ref/__pycache__/_virtualenv.cpython-311.pyc
ADDED
|
Binary file (4.61 kB). View file
|
|
|
.venv/lib/python3.11/site-packages/virtualenv/create/via_global_ref/__pycache__/api.cpython-311.pyc
ADDED
|
Binary file (7.46 kB). View file
|
|
|
.venv/lib/python3.11/site-packages/virtualenv/create/via_global_ref/__pycache__/store.cpython-311.pyc
ADDED
|
Binary file (1.29 kB). View file
|
|
|
.venv/lib/python3.11/site-packages/virtualenv/create/via_global_ref/__pycache__/venv.cpython-311.pyc
ADDED
|
Binary file (6.8 kB). View file
|
|
|
.venv/lib/python3.11/site-packages/virtualenv/create/via_global_ref/_virtualenv.py
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Patches that are applied at runtime to the virtual environment."""
|
| 2 |
+
|
| 3 |
+
from __future__ import annotations
|
| 4 |
+
|
| 5 |
+
import os
|
| 6 |
+
import sys
|
| 7 |
+
|
| 8 |
+
VIRTUALENV_PATCH_FILE = os.path.join(__file__)
|
| 9 |
+
|
| 10 |
+
|
| 11 |
+
def patch_dist(dist):
|
| 12 |
+
"""
|
| 13 |
+
Distutils allows user to configure some arguments via a configuration file:
|
| 14 |
+
https://docs.python.org/3/install/index.html#distutils-configuration-files.
|
| 15 |
+
|
| 16 |
+
Some of this arguments though don't make sense in context of the virtual environment files, let's fix them up.
|
| 17 |
+
""" # noqa: D205
|
| 18 |
+
# we cannot allow some install config as that would get packages installed outside of the virtual environment
|
| 19 |
+
old_parse_config_files = dist.Distribution.parse_config_files
|
| 20 |
+
|
| 21 |
+
def parse_config_files(self, *args, **kwargs):
|
| 22 |
+
result = old_parse_config_files(self, *args, **kwargs)
|
| 23 |
+
install = self.get_option_dict("install")
|
| 24 |
+
|
| 25 |
+
if "prefix" in install: # the prefix governs where to install the libraries
|
| 26 |
+
install["prefix"] = VIRTUALENV_PATCH_FILE, os.path.abspath(sys.prefix)
|
| 27 |
+
for base in ("purelib", "platlib", "headers", "scripts", "data"):
|
| 28 |
+
key = f"install_{base}"
|
| 29 |
+
if key in install: # do not allow global configs to hijack venv paths
|
| 30 |
+
install.pop(key, None)
|
| 31 |
+
return result
|
| 32 |
+
|
| 33 |
+
dist.Distribution.parse_config_files = parse_config_files
|
| 34 |
+
|
| 35 |
+
|
| 36 |
+
# Import hook that patches some modules to ignore configuration values that break package installation in case
|
| 37 |
+
# of virtual environments.
|
| 38 |
+
_DISTUTILS_PATCH = "distutils.dist", "setuptools.dist"
|
| 39 |
+
# https://docs.python.org/3/library/importlib.html#setting-up-an-importer
|
| 40 |
+
|
| 41 |
+
|
| 42 |
+
class _Finder:
|
| 43 |
+
"""A meta path finder that allows patching the imported distutils modules."""
|
| 44 |
+
|
| 45 |
+
fullname = None
|
| 46 |
+
|
| 47 |
+
# lock[0] is threading.Lock(), but initialized lazily to avoid importing threading very early at startup,
|
| 48 |
+
# because there are gevent-based applications that need to be first to import threading by themselves.
|
| 49 |
+
# See https://github.com/pypa/virtualenv/issues/1895 for details.
|
| 50 |
+
lock = [] # noqa: RUF012
|
| 51 |
+
|
| 52 |
+
def find_spec(self, fullname, path, target=None): # noqa: ARG002
|
| 53 |
+
if fullname in _DISTUTILS_PATCH and self.fullname is None: # noqa: PLR1702
|
| 54 |
+
# initialize lock[0] lazily
|
| 55 |
+
if len(self.lock) == 0:
|
| 56 |
+
import threading # noqa: PLC0415
|
| 57 |
+
|
| 58 |
+
lock = threading.Lock()
|
| 59 |
+
# there is possibility that two threads T1 and T2 are simultaneously running into find_spec,
|
| 60 |
+
# observing .lock as empty, and further going into hereby initialization. However due to the GIL,
|
| 61 |
+
# list.append() operation is atomic and this way only one of the threads will "win" to put the lock
|
| 62 |
+
# - that every thread will use - into .lock[0].
|
| 63 |
+
# https://docs.python.org/3/faq/library.html#what-kinds-of-global-value-mutation-are-thread-safe
|
| 64 |
+
self.lock.append(lock)
|
| 65 |
+
|
| 66 |
+
from functools import partial # noqa: PLC0415
|
| 67 |
+
from importlib.util import find_spec # noqa: PLC0415
|
| 68 |
+
|
| 69 |
+
with self.lock[0]:
|
| 70 |
+
self.fullname = fullname
|
| 71 |
+
try:
|
| 72 |
+
spec = find_spec(fullname, path)
|
| 73 |
+
if spec is not None:
|
| 74 |
+
# https://www.python.org/dev/peps/pep-0451/#how-loading-will-work
|
| 75 |
+
is_new_api = hasattr(spec.loader, "exec_module")
|
| 76 |
+
func_name = "exec_module" if is_new_api else "load_module"
|
| 77 |
+
old = getattr(spec.loader, func_name)
|
| 78 |
+
func = self.exec_module if is_new_api else self.load_module
|
| 79 |
+
if old is not func:
|
| 80 |
+
try: # noqa: SIM105
|
| 81 |
+
setattr(spec.loader, func_name, partial(func, old))
|
| 82 |
+
except AttributeError:
|
| 83 |
+
pass # C-Extension loaders are r/o such as zipimporter with <3.7
|
| 84 |
+
return spec
|
| 85 |
+
finally:
|
| 86 |
+
self.fullname = None
|
| 87 |
+
return None
|
| 88 |
+
|
| 89 |
+
@staticmethod
|
| 90 |
+
def exec_module(old, module):
|
| 91 |
+
old(module)
|
| 92 |
+
if module.__name__ in _DISTUTILS_PATCH:
|
| 93 |
+
patch_dist(module)
|
| 94 |
+
|
| 95 |
+
@staticmethod
|
| 96 |
+
def load_module(old, name):
|
| 97 |
+
module = old(name)
|
| 98 |
+
if module.__name__ in _DISTUTILS_PATCH:
|
| 99 |
+
patch_dist(module)
|
| 100 |
+
return module
|
| 101 |
+
|
| 102 |
+
|
| 103 |
+
sys.meta_path.insert(0, _Finder())
|
.venv/lib/python3.11/site-packages/virtualenv/create/via_global_ref/api.py
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from __future__ import annotations
|
| 2 |
+
|
| 3 |
+
import logging
|
| 4 |
+
import os
|
| 5 |
+
from abc import ABC
|
| 6 |
+
from pathlib import Path
|
| 7 |
+
|
| 8 |
+
from virtualenv.create.creator import Creator, CreatorMeta
|
| 9 |
+
from virtualenv.info import fs_supports_symlink
|
| 10 |
+
|
| 11 |
+
LOGGER = logging.getLogger(__name__)
|
| 12 |
+
|
| 13 |
+
|
| 14 |
+
class ViaGlobalRefMeta(CreatorMeta):
|
| 15 |
+
def __init__(self) -> None:
|
| 16 |
+
super().__init__()
|
| 17 |
+
self.copy_error = None
|
| 18 |
+
self.symlink_error = None
|
| 19 |
+
if not fs_supports_symlink():
|
| 20 |
+
self.symlink_error = "the filesystem does not supports symlink"
|
| 21 |
+
|
| 22 |
+
@property
|
| 23 |
+
def can_copy(self):
|
| 24 |
+
return not self.copy_error
|
| 25 |
+
|
| 26 |
+
@property
|
| 27 |
+
def can_symlink(self):
|
| 28 |
+
return not self.symlink_error
|
| 29 |
+
|
| 30 |
+
|
| 31 |
+
class ViaGlobalRefApi(Creator, ABC):
|
| 32 |
+
def __init__(self, options, interpreter) -> None:
|
| 33 |
+
super().__init__(options, interpreter)
|
| 34 |
+
self.symlinks = self._should_symlink(options)
|
| 35 |
+
self.enable_system_site_package = options.system_site
|
| 36 |
+
|
| 37 |
+
@staticmethod
|
| 38 |
+
def _should_symlink(options):
|
| 39 |
+
# Priority of where the option is set to follow the order: CLI, env var, file, hardcoded.
|
| 40 |
+
# If both set at same level prefers copy over symlink.
|
| 41 |
+
copies, symlinks = getattr(options, "copies", False), getattr(options, "symlinks", False)
|
| 42 |
+
copy_src, sym_src = options.get_source("copies"), options.get_source("symlinks")
|
| 43 |
+
for level in ["cli", "env var", "file", "default"]:
|
| 44 |
+
s_opt = symlinks if sym_src == level else None
|
| 45 |
+
c_opt = copies if copy_src == level else None
|
| 46 |
+
if s_opt is True and c_opt is True:
|
| 47 |
+
return False
|
| 48 |
+
if s_opt is True:
|
| 49 |
+
return True
|
| 50 |
+
if c_opt is True:
|
| 51 |
+
return False
|
| 52 |
+
return False # fallback to copy
|
| 53 |
+
|
| 54 |
+
@classmethod
|
| 55 |
+
def add_parser_arguments(cls, parser, interpreter, meta, app_data):
|
| 56 |
+
super().add_parser_arguments(parser, interpreter, meta, app_data)
|
| 57 |
+
parser.add_argument(
|
| 58 |
+
"--system-site-packages",
|
| 59 |
+
default=False,
|
| 60 |
+
action="store_true",
|
| 61 |
+
dest="system_site",
|
| 62 |
+
help="give the virtual environment access to the system site-packages dir",
|
| 63 |
+
)
|
| 64 |
+
if not meta.can_symlink and not meta.can_copy:
|
| 65 |
+
msg = "neither symlink or copy method supported"
|
| 66 |
+
raise RuntimeError(msg)
|
| 67 |
+
group = parser.add_mutually_exclusive_group()
|
| 68 |
+
if meta.can_symlink:
|
| 69 |
+
group.add_argument(
|
| 70 |
+
"--symlinks",
|
| 71 |
+
default=True,
|
| 72 |
+
action="store_true",
|
| 73 |
+
dest="symlinks",
|
| 74 |
+
help="try to use symlinks rather than copies, when symlinks are not the default for the platform",
|
| 75 |
+
)
|
| 76 |
+
if meta.can_copy:
|
| 77 |
+
group.add_argument(
|
| 78 |
+
"--copies",
|
| 79 |
+
"--always-copy",
|
| 80 |
+
default=not meta.can_symlink,
|
| 81 |
+
action="store_true",
|
| 82 |
+
dest="copies",
|
| 83 |
+
help="try to use copies rather than symlinks, even when symlinks are the default for the platform",
|
| 84 |
+
)
|
| 85 |
+
|
| 86 |
+
def create(self):
|
| 87 |
+
self.install_patch()
|
| 88 |
+
|
| 89 |
+
def install_patch(self):
|
| 90 |
+
text = self.env_patch_text()
|
| 91 |
+
if text:
|
| 92 |
+
pth = self.purelib / "_virtualenv.pth"
|
| 93 |
+
LOGGER.debug("create virtualenv import hook file %s", pth)
|
| 94 |
+
pth.write_text("import _virtualenv", encoding="utf-8")
|
| 95 |
+
dest_path = self.purelib / "_virtualenv.py"
|
| 96 |
+
LOGGER.debug("create %s", dest_path)
|
| 97 |
+
dest_path.write_text(text, encoding="utf-8")
|
| 98 |
+
|
| 99 |
+
def env_patch_text(self):
|
| 100 |
+
"""Patch the distutils package to not be derailed by its configuration files."""
|
| 101 |
+
with self.app_data.ensure_extracted(Path(__file__).parent / "_virtualenv.py") as resolved_path:
|
| 102 |
+
text = resolved_path.read_text(encoding="utf-8")
|
| 103 |
+
return text.replace('"__SCRIPT_DIR__"', repr(os.path.relpath(str(self.script_dir), str(self.purelib))))
|
| 104 |
+
|
| 105 |
+
def _args(self):
|
| 106 |
+
return [*super()._args(), ("global", self.enable_system_site_package)]
|
| 107 |
+
|
| 108 |
+
def set_pyenv_cfg(self):
|
| 109 |
+
super().set_pyenv_cfg()
|
| 110 |
+
self.pyenv_cfg["include-system-site-packages"] = "true" if self.enable_system_site_package else "false"
|
| 111 |
+
|
| 112 |
+
|
| 113 |
+
__all__ = [
|
| 114 |
+
"ViaGlobalRefApi",
|
| 115 |
+
"ViaGlobalRefMeta",
|
| 116 |
+
]
|
.venv/lib/python3.11/site-packages/virtualenv/create/via_global_ref/builtin/__init__.py
ADDED
|
File without changes
|
.venv/lib/python3.11/site-packages/virtualenv/create/via_global_ref/builtin/__pycache__/__init__.cpython-311.pyc
ADDED
|
Binary file (213 Bytes). View file
|
|
|
.venv/lib/python3.11/site-packages/virtualenv/create/via_global_ref/builtin/__pycache__/builtin_way.cpython-311.pyc
ADDED
|
Binary file (1.23 kB). View file
|
|
|
.venv/lib/python3.11/site-packages/virtualenv/create/via_global_ref/builtin/__pycache__/ref.cpython-311.pyc
ADDED
|
Binary file (10.5 kB). View file
|
|
|
.venv/lib/python3.11/site-packages/virtualenv/create/via_global_ref/builtin/__pycache__/via_global_self_do.cpython-311.pyc
ADDED
|
Binary file (7.98 kB). View file
|
|
|
.venv/lib/python3.11/site-packages/virtualenv/create/via_global_ref/builtin/builtin_way.py
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from __future__ import annotations
|
| 2 |
+
|
| 3 |
+
from abc import ABC
|
| 4 |
+
|
| 5 |
+
from virtualenv.create.creator import Creator
|
| 6 |
+
from virtualenv.create.describe import Describe
|
| 7 |
+
|
| 8 |
+
|
| 9 |
+
class VirtualenvBuiltin(Creator, Describe, ABC):
|
| 10 |
+
"""A creator that does operations itself without delegation, if we can create it we can also describe it."""
|
| 11 |
+
|
| 12 |
+
def __init__(self, options, interpreter) -> None:
|
| 13 |
+
Creator.__init__(self, options, interpreter)
|
| 14 |
+
Describe.__init__(self, self.dest, interpreter)
|
| 15 |
+
|
| 16 |
+
|
| 17 |
+
__all__ = [
|
| 18 |
+
"VirtualenvBuiltin",
|
| 19 |
+
]
|
.venv/lib/python3.11/site-packages/virtualenv/create/via_global_ref/builtin/cpython/__init__.py
ADDED
|
File without changes
|
.venv/lib/python3.11/site-packages/virtualenv/create/via_global_ref/builtin/cpython/__pycache__/__init__.cpython-311.pyc
ADDED
|
Binary file (221 Bytes). View file
|
|
|
.venv/lib/python3.11/site-packages/virtualenv/create/via_global_ref/builtin/cpython/__pycache__/common.cpython-311.pyc
ADDED
|
Binary file (5.11 kB). View file
|
|
|
.venv/lib/python3.11/site-packages/virtualenv/create/via_global_ref/builtin/cpython/__pycache__/cpython3.cpython-311.pyc
ADDED
|
Binary file (8.05 kB). View file
|
|
|
.venv/lib/python3.11/site-packages/virtualenv/create/via_global_ref/builtin/cpython/__pycache__/mac_os.cpython-311.pyc
ADDED
|
Binary file (18.6 kB). View file
|
|
|
.venv/lib/python3.11/site-packages/virtualenv/create/via_global_ref/builtin/cpython/common.py
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from __future__ import annotations
|
| 2 |
+
|
| 3 |
+
import re
|
| 4 |
+
from abc import ABC
|
| 5 |
+
from collections import OrderedDict
|
| 6 |
+
from pathlib import Path
|
| 7 |
+
|
| 8 |
+
from virtualenv.create.describe import PosixSupports, WindowsSupports
|
| 9 |
+
from virtualenv.create.via_global_ref.builtin.ref import RefMust, RefWhen
|
| 10 |
+
from virtualenv.create.via_global_ref.builtin.via_global_self_do import ViaGlobalRefVirtualenvBuiltin
|
| 11 |
+
|
| 12 |
+
|
| 13 |
+
class CPython(ViaGlobalRefVirtualenvBuiltin, ABC):
|
| 14 |
+
@classmethod
|
| 15 |
+
def can_describe(cls, interpreter):
|
| 16 |
+
return interpreter.implementation == "CPython" and super().can_describe(interpreter)
|
| 17 |
+
|
| 18 |
+
@classmethod
|
| 19 |
+
def exe_stem(cls):
|
| 20 |
+
return "python"
|
| 21 |
+
|
| 22 |
+
|
| 23 |
+
class CPythonPosix(CPython, PosixSupports, ABC):
|
| 24 |
+
"""Create a CPython virtual environment on POSIX platforms."""
|
| 25 |
+
|
| 26 |
+
@classmethod
|
| 27 |
+
def _executables(cls, interpreter):
|
| 28 |
+
host_exe = Path(interpreter.system_executable)
|
| 29 |
+
major, minor = interpreter.version_info.major, interpreter.version_info.minor
|
| 30 |
+
targets = OrderedDict((i, None) for i in ["python", f"python{major}", f"python{major}.{minor}", host_exe.name])
|
| 31 |
+
yield host_exe, list(targets.keys()), RefMust.NA, RefWhen.ANY
|
| 32 |
+
|
| 33 |
+
|
| 34 |
+
class CPythonWindows(CPython, WindowsSupports, ABC):
|
| 35 |
+
@classmethod
|
| 36 |
+
def _executables(cls, interpreter):
|
| 37 |
+
# symlink of the python executables does not work reliably, copy always instead
|
| 38 |
+
# - https://bugs.python.org/issue42013
|
| 39 |
+
# - venv
|
| 40 |
+
host = cls.host_python(interpreter)
|
| 41 |
+
for path in (host.parent / n for n in {"python.exe", host.name}):
|
| 42 |
+
yield host, [path.name], RefMust.COPY, RefWhen.ANY
|
| 43 |
+
# for more info on pythonw.exe see https://stackoverflow.com/a/30313091
|
| 44 |
+
python_w = host.parent / "pythonw.exe"
|
| 45 |
+
yield python_w, [python_w.name], RefMust.COPY, RefWhen.ANY
|
| 46 |
+
|
| 47 |
+
@classmethod
|
| 48 |
+
def host_python(cls, interpreter):
|
| 49 |
+
return Path(interpreter.system_executable)
|
| 50 |
+
|
| 51 |
+
|
| 52 |
+
def is_mac_os_framework(interpreter):
|
| 53 |
+
if interpreter.platform == "darwin":
|
| 54 |
+
return interpreter.sysconfig_vars.get("PYTHONFRAMEWORK") == "Python3"
|
| 55 |
+
return False
|
| 56 |
+
|
| 57 |
+
|
| 58 |
+
def is_macos_brew(interpreter):
|
| 59 |
+
return interpreter.platform == "darwin" and _BREW.fullmatch(interpreter.system_prefix) is not None
|
| 60 |
+
|
| 61 |
+
|
| 62 |
+
_BREW = re.compile(
|
| 63 |
+
r"/(usr/local|opt/homebrew)/(opt/python@3\.\d{1,2}|Cellar/python@3\.\d{1,2}/3\.\d{1,2}\.\d{1,2})/Frameworks/"
|
| 64 |
+
r"Python\.framework/Versions/3\.\d{1,2}",
|
| 65 |
+
)
|
| 66 |
+
|
| 67 |
+
__all__ = [
|
| 68 |
+
"CPython",
|
| 69 |
+
"CPythonPosix",
|
| 70 |
+
"CPythonWindows",
|
| 71 |
+
"is_mac_os_framework",
|
| 72 |
+
"is_macos_brew",
|
| 73 |
+
]
|
.venv/lib/python3.11/site-packages/virtualenv/create/via_global_ref/builtin/cpython/cpython3.py
ADDED
|
@@ -0,0 +1,135 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from __future__ import annotations
|
| 2 |
+
|
| 3 |
+
import abc
|
| 4 |
+
import fnmatch
|
| 5 |
+
from itertools import chain
|
| 6 |
+
from operator import methodcaller as method
|
| 7 |
+
from pathlib import Path
|
| 8 |
+
from textwrap import dedent
|
| 9 |
+
|
| 10 |
+
from virtualenv.create.describe import Python3Supports
|
| 11 |
+
from virtualenv.create.via_global_ref.builtin.ref import PathRefToDest
|
| 12 |
+
from virtualenv.create.via_global_ref.store import is_store_python
|
| 13 |
+
|
| 14 |
+
from .common import CPython, CPythonPosix, CPythonWindows, is_mac_os_framework, is_macos_brew
|
| 15 |
+
|
| 16 |
+
|
| 17 |
+
class CPython3(CPython, Python3Supports, abc.ABC):
|
| 18 |
+
"""CPython 3 or later."""
|
| 19 |
+
|
| 20 |
+
|
| 21 |
+
class CPython3Posix(CPythonPosix, CPython3):
|
| 22 |
+
@classmethod
|
| 23 |
+
def can_describe(cls, interpreter):
|
| 24 |
+
return (
|
| 25 |
+
is_mac_os_framework(interpreter) is False
|
| 26 |
+
and is_macos_brew(interpreter) is False
|
| 27 |
+
and super().can_describe(interpreter)
|
| 28 |
+
)
|
| 29 |
+
|
| 30 |
+
def env_patch_text(self):
|
| 31 |
+
text = super().env_patch_text()
|
| 32 |
+
if self.pyvenv_launch_patch_active(self.interpreter):
|
| 33 |
+
text += dedent(
|
| 34 |
+
"""
|
| 35 |
+
# for https://github.com/python/cpython/pull/9516, see https://github.com/pypa/virtualenv/issues/1704
|
| 36 |
+
import os
|
| 37 |
+
if "__PYVENV_LAUNCHER__" in os.environ:
|
| 38 |
+
del os.environ["__PYVENV_LAUNCHER__"]
|
| 39 |
+
""",
|
| 40 |
+
)
|
| 41 |
+
return text
|
| 42 |
+
|
| 43 |
+
@classmethod
|
| 44 |
+
def pyvenv_launch_patch_active(cls, interpreter):
|
| 45 |
+
ver = interpreter.version_info
|
| 46 |
+
return interpreter.platform == "darwin" and ((3, 7, 8) > ver >= (3, 7) or (3, 8, 3) > ver >= (3, 8))
|
| 47 |
+
|
| 48 |
+
|
| 49 |
+
class CPython3Windows(CPythonWindows, CPython3):
|
| 50 |
+
"""CPython 3 on Windows."""
|
| 51 |
+
|
| 52 |
+
@classmethod
|
| 53 |
+
def setup_meta(cls, interpreter):
|
| 54 |
+
if is_store_python(interpreter): # store python is not supported here
|
| 55 |
+
return None
|
| 56 |
+
return super().setup_meta(interpreter)
|
| 57 |
+
|
| 58 |
+
@classmethod
|
| 59 |
+
def sources(cls, interpreter):
|
| 60 |
+
if cls.has_shim(interpreter):
|
| 61 |
+
refs = cls.executables(interpreter)
|
| 62 |
+
else:
|
| 63 |
+
refs = chain(
|
| 64 |
+
cls.executables(interpreter),
|
| 65 |
+
cls.dll_and_pyd(interpreter),
|
| 66 |
+
cls.python_zip(interpreter),
|
| 67 |
+
)
|
| 68 |
+
yield from refs
|
| 69 |
+
|
| 70 |
+
@classmethod
|
| 71 |
+
def executables(cls, interpreter):
|
| 72 |
+
return super().sources(interpreter)
|
| 73 |
+
|
| 74 |
+
@classmethod
|
| 75 |
+
def has_shim(cls, interpreter):
|
| 76 |
+
return interpreter.version_info.minor >= 7 and cls.shim(interpreter) is not None # noqa: PLR2004
|
| 77 |
+
|
| 78 |
+
@classmethod
|
| 79 |
+
def shim(cls, interpreter):
|
| 80 |
+
shim = Path(interpreter.system_stdlib) / "venv" / "scripts" / "nt" / "python.exe"
|
| 81 |
+
if shim.exists():
|
| 82 |
+
return shim
|
| 83 |
+
return None
|
| 84 |
+
|
| 85 |
+
@classmethod
|
| 86 |
+
def host_python(cls, interpreter):
|
| 87 |
+
if cls.has_shim(interpreter):
|
| 88 |
+
# starting with CPython 3.7 Windows ships with a venvlauncher.exe that avoids the need for dll/pyd copies
|
| 89 |
+
# it also means the wrapper must be copied to avoid bugs such as https://bugs.python.org/issue42013
|
| 90 |
+
return cls.shim(interpreter)
|
| 91 |
+
return super().host_python(interpreter)
|
| 92 |
+
|
| 93 |
+
@classmethod
|
| 94 |
+
def dll_and_pyd(cls, interpreter):
|
| 95 |
+
folders = [Path(interpreter.system_executable).parent]
|
| 96 |
+
|
| 97 |
+
# May be missing on some Python hosts.
|
| 98 |
+
# See https://github.com/pypa/virtualenv/issues/2368
|
| 99 |
+
dll_folder = Path(interpreter.system_prefix) / "DLLs"
|
| 100 |
+
if dll_folder.is_dir():
|
| 101 |
+
folders.append(dll_folder)
|
| 102 |
+
|
| 103 |
+
for folder in folders:
|
| 104 |
+
for file in folder.iterdir():
|
| 105 |
+
if file.suffix in {".pyd", ".dll"}:
|
| 106 |
+
yield PathRefToDest(file, cls.to_bin)
|
| 107 |
+
|
| 108 |
+
@classmethod
|
| 109 |
+
def python_zip(cls, interpreter):
|
| 110 |
+
"""
|
| 111 |
+
"python{VERSION}.zip" contains compiled *.pyc std lib packages, where
|
| 112 |
+
"VERSION" is `py_version_nodot` var from the `sysconfig` module.
|
| 113 |
+
:see: https://docs.python.org/3/using/windows.html#the-embeddable-package
|
| 114 |
+
:see: `discovery.py_info.PythonInfo` class (interpreter).
|
| 115 |
+
:see: `python -m sysconfig` output.
|
| 116 |
+
|
| 117 |
+
:note: The embeddable Python distribution for Windows includes
|
| 118 |
+
"python{VERSION}.zip" and "python{VERSION}._pth" files. User can
|
| 119 |
+
move/rename *zip* file and edit `sys.path` by editing *_pth* file.
|
| 120 |
+
Here the `pattern` is used only for the default *zip* file name!
|
| 121 |
+
""" # noqa: D205
|
| 122 |
+
pattern = f"*python{interpreter.version_nodot}.zip"
|
| 123 |
+
matches = fnmatch.filter(interpreter.path, pattern)
|
| 124 |
+
matched_paths = map(Path, matches)
|
| 125 |
+
existing_paths = filter(method("exists"), matched_paths)
|
| 126 |
+
path = next(existing_paths, None)
|
| 127 |
+
if path is not None:
|
| 128 |
+
yield PathRefToDest(path, cls.to_bin)
|
| 129 |
+
|
| 130 |
+
|
| 131 |
+
__all__ = [
|
| 132 |
+
"CPython3",
|
| 133 |
+
"CPython3Posix",
|
| 134 |
+
"CPython3Windows",
|
| 135 |
+
]
|
.venv/lib/python3.11/site-packages/virtualenv/create/via_global_ref/builtin/cpython/mac_os.py
ADDED
|
@@ -0,0 +1,281 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""The Apple Framework builds require their own customization."""
|
| 2 |
+
|
| 3 |
+
from __future__ import annotations
|
| 4 |
+
|
| 5 |
+
import logging
|
| 6 |
+
import os
|
| 7 |
+
import struct
|
| 8 |
+
import subprocess
|
| 9 |
+
from abc import ABC, abstractmethod
|
| 10 |
+
from pathlib import Path
|
| 11 |
+
from textwrap import dedent
|
| 12 |
+
|
| 13 |
+
from virtualenv.create.via_global_ref.builtin.ref import (
|
| 14 |
+
ExePathRefToDest,
|
| 15 |
+
PathRefToDest,
|
| 16 |
+
RefMust,
|
| 17 |
+
)
|
| 18 |
+
from virtualenv.create.via_global_ref.builtin.via_global_self_do import BuiltinViaGlobalRefMeta
|
| 19 |
+
|
| 20 |
+
from .common import CPython, CPythonPosix, is_mac_os_framework, is_macos_brew
|
| 21 |
+
from .cpython3 import CPython3
|
| 22 |
+
|
| 23 |
+
LOGGER = logging.getLogger(__name__)
|
| 24 |
+
|
| 25 |
+
|
| 26 |
+
class CPythonmacOsFramework(CPython, ABC):
|
| 27 |
+
@classmethod
|
| 28 |
+
def can_describe(cls, interpreter):
|
| 29 |
+
return is_mac_os_framework(interpreter) and super().can_describe(interpreter)
|
| 30 |
+
|
| 31 |
+
def create(self):
|
| 32 |
+
super().create()
|
| 33 |
+
|
| 34 |
+
# change the install_name of the copied python executables
|
| 35 |
+
target = self.desired_mach_o_image_path()
|
| 36 |
+
current = self.current_mach_o_image_path()
|
| 37 |
+
for src in self._sources:
|
| 38 |
+
if isinstance(src, ExePathRefToDest) and (src.must == RefMust.COPY or not self.symlinks):
|
| 39 |
+
exes = [self.bin_dir / src.base]
|
| 40 |
+
if not self.symlinks:
|
| 41 |
+
exes.extend(self.bin_dir / a for a in src.aliases)
|
| 42 |
+
for exe in exes:
|
| 43 |
+
fix_mach_o(str(exe), current, target, self.interpreter.max_size)
|
| 44 |
+
|
| 45 |
+
@classmethod
|
| 46 |
+
def _executables(cls, interpreter):
|
| 47 |
+
for _, targets, must, when in super()._executables(interpreter):
|
| 48 |
+
# Make sure we use the embedded interpreter inside the framework, even if sys.executable points to the
|
| 49 |
+
# stub executable in ${sys.prefix}/bin.
|
| 50 |
+
# See http://groups.google.com/group/python-virtualenv/browse_thread/thread/17cab2f85da75951
|
| 51 |
+
fixed_host_exe = Path(interpreter.prefix) / "Resources" / "Python.app" / "Contents" / "MacOS" / "Python"
|
| 52 |
+
yield fixed_host_exe, targets, must, when
|
| 53 |
+
|
| 54 |
+
@abstractmethod
|
| 55 |
+
def current_mach_o_image_path(self):
|
| 56 |
+
raise NotImplementedError
|
| 57 |
+
|
| 58 |
+
@abstractmethod
|
| 59 |
+
def desired_mach_o_image_path(self):
|
| 60 |
+
raise NotImplementedError
|
| 61 |
+
|
| 62 |
+
|
| 63 |
+
class CPython3macOsFramework(CPythonmacOsFramework, CPython3, CPythonPosix):
|
| 64 |
+
def current_mach_o_image_path(self):
|
| 65 |
+
return "@executable_path/../../../../Python3"
|
| 66 |
+
|
| 67 |
+
def desired_mach_o_image_path(self):
|
| 68 |
+
return "@executable_path/../.Python"
|
| 69 |
+
|
| 70 |
+
@classmethod
|
| 71 |
+
def sources(cls, interpreter):
|
| 72 |
+
yield from super().sources(interpreter)
|
| 73 |
+
|
| 74 |
+
# add a symlink to the host python image
|
| 75 |
+
exe = Path(interpreter.prefix) / "Python3"
|
| 76 |
+
yield PathRefToDest(exe, dest=lambda self, _: self.dest / ".Python", must=RefMust.SYMLINK)
|
| 77 |
+
|
| 78 |
+
@property
|
| 79 |
+
def reload_code(self):
|
| 80 |
+
result = super().reload_code
|
| 81 |
+
return dedent(
|
| 82 |
+
f"""
|
| 83 |
+
# the bundled site.py always adds the global site package if we're on python framework build, escape this
|
| 84 |
+
import sys
|
| 85 |
+
before = sys._framework
|
| 86 |
+
try:
|
| 87 |
+
sys._framework = None
|
| 88 |
+
{result}
|
| 89 |
+
finally:
|
| 90 |
+
sys._framework = before
|
| 91 |
+
""",
|
| 92 |
+
)
|
| 93 |
+
|
| 94 |
+
|
| 95 |
+
def fix_mach_o(exe, current, new, max_size):
|
| 96 |
+
"""
|
| 97 |
+
https://en.wikipedia.org/wiki/Mach-O.
|
| 98 |
+
|
| 99 |
+
Mach-O, short for Mach object file format, is a file format for executables, object code, shared libraries,
|
| 100 |
+
dynamically-loaded code, and core dumps. A replacement for the a.out format, Mach-O offers more extensibility and
|
| 101 |
+
faster access to information in the symbol table.
|
| 102 |
+
|
| 103 |
+
Each Mach-O file is made up of one Mach-O header, followed by a series of load commands, followed by one or more
|
| 104 |
+
segments, each of which contains between 0 and 255 sections. Mach-O uses the REL relocation format to handle
|
| 105 |
+
references to symbols. When looking up symbols Mach-O uses a two-level namespace that encodes each symbol into an
|
| 106 |
+
'object/symbol name' pair that is then linearly searched for by first the object and then the symbol name.
|
| 107 |
+
|
| 108 |
+
The basic structure—a list of variable-length "load commands" that reference pages of data elsewhere in the file—was
|
| 109 |
+
also used in the executable file format for Accent. The Accent file format was in turn, based on an idea from Spice
|
| 110 |
+
Lisp.
|
| 111 |
+
|
| 112 |
+
With the introduction of Mac OS X 10.6 platform the Mach-O file underwent a significant modification that causes
|
| 113 |
+
binaries compiled on a computer running 10.6 or later to be (by default) executable only on computers running Mac
|
| 114 |
+
OS X 10.6 or later. The difference stems from load commands that the dynamic linker, in previous Mac OS X versions,
|
| 115 |
+
does not understand. Another significant change to the Mach-O format is the change in how the Link Edit tables
|
| 116 |
+
(found in the __LINKEDIT section) function. In 10.6 these new Link Edit tables are compressed by removing unused and
|
| 117 |
+
unneeded bits of information, however Mac OS X 10.5 and earlier cannot read this new Link Edit table format.
|
| 118 |
+
"""
|
| 119 |
+
try:
|
| 120 |
+
LOGGER.debug("change Mach-O for %s from %s to %s", exe, current, new)
|
| 121 |
+
_builtin_change_mach_o(max_size)(exe, current, new)
|
| 122 |
+
except Exception as e: # noqa: BLE001
|
| 123 |
+
LOGGER.warning("Could not call _builtin_change_mac_o: %s. Trying to call install_name_tool instead.", e)
|
| 124 |
+
try:
|
| 125 |
+
cmd = ["install_name_tool", "-change", current, new, exe]
|
| 126 |
+
subprocess.check_call(cmd)
|
| 127 |
+
except Exception:
|
| 128 |
+
logging.fatal("Could not call install_name_tool -- you must have Apple's development tools installed")
|
| 129 |
+
raise
|
| 130 |
+
|
| 131 |
+
|
| 132 |
+
def _builtin_change_mach_o(maxint): # noqa: C901
|
| 133 |
+
MH_MAGIC = 0xFEEDFACE # noqa: N806
|
| 134 |
+
MH_CIGAM = 0xCEFAEDFE # noqa: N806
|
| 135 |
+
MH_MAGIC_64 = 0xFEEDFACF # noqa: N806
|
| 136 |
+
MH_CIGAM_64 = 0xCFFAEDFE # noqa: N806
|
| 137 |
+
FAT_MAGIC = 0xCAFEBABE # noqa: N806
|
| 138 |
+
BIG_ENDIAN = ">" # noqa: N806
|
| 139 |
+
LITTLE_ENDIAN = "<" # noqa: N806
|
| 140 |
+
LC_LOAD_DYLIB = 0xC # noqa: N806
|
| 141 |
+
|
| 142 |
+
class FileView:
|
| 143 |
+
"""A proxy for file-like objects that exposes a given view of a file. Modified from macholib."""
|
| 144 |
+
|
| 145 |
+
def __init__(self, file_obj, start=0, size=maxint) -> None:
|
| 146 |
+
if isinstance(file_obj, FileView):
|
| 147 |
+
self._file_obj = file_obj._file_obj # noqa: SLF001
|
| 148 |
+
else:
|
| 149 |
+
self._file_obj = file_obj
|
| 150 |
+
self._start = start
|
| 151 |
+
self._end = start + size
|
| 152 |
+
self._pos = 0
|
| 153 |
+
|
| 154 |
+
def __repr__(self) -> str:
|
| 155 |
+
return f"<fileview [{self._start:d}, {self._end:d}] {self._file_obj!r}>"
|
| 156 |
+
|
| 157 |
+
def tell(self):
|
| 158 |
+
return self._pos
|
| 159 |
+
|
| 160 |
+
def _checkwindow(self, seek_to, op):
|
| 161 |
+
if not (self._start <= seek_to <= self._end):
|
| 162 |
+
msg = f"{op} to offset {seek_to:d} is outside window [{self._start:d}, {self._end:d}]"
|
| 163 |
+
raise OSError(msg)
|
| 164 |
+
|
| 165 |
+
def seek(self, offset, whence=0):
|
| 166 |
+
seek_to = offset
|
| 167 |
+
if whence == os.SEEK_SET:
|
| 168 |
+
seek_to += self._start
|
| 169 |
+
elif whence == os.SEEK_CUR:
|
| 170 |
+
seek_to += self._start + self._pos
|
| 171 |
+
elif whence == os.SEEK_END:
|
| 172 |
+
seek_to += self._end
|
| 173 |
+
else:
|
| 174 |
+
msg = f"Invalid whence argument to seek: {whence!r}"
|
| 175 |
+
raise OSError(msg)
|
| 176 |
+
self._checkwindow(seek_to, "seek")
|
| 177 |
+
self._file_obj.seek(seek_to)
|
| 178 |
+
self._pos = seek_to - self._start
|
| 179 |
+
|
| 180 |
+
def write(self, content):
|
| 181 |
+
here = self._start + self._pos
|
| 182 |
+
self._checkwindow(here, "write")
|
| 183 |
+
self._checkwindow(here + len(content), "write")
|
| 184 |
+
self._file_obj.seek(here, os.SEEK_SET)
|
| 185 |
+
self._file_obj.write(content)
|
| 186 |
+
self._pos += len(content)
|
| 187 |
+
|
| 188 |
+
def read(self, size=maxint):
|
| 189 |
+
assert size >= 0 # noqa: S101
|
| 190 |
+
here = self._start + self._pos
|
| 191 |
+
self._checkwindow(here, "read")
|
| 192 |
+
size = min(size, self._end - here)
|
| 193 |
+
self._file_obj.seek(here, os.SEEK_SET)
|
| 194 |
+
read_bytes = self._file_obj.read(size)
|
| 195 |
+
self._pos += len(read_bytes)
|
| 196 |
+
return read_bytes
|
| 197 |
+
|
| 198 |
+
def read_data(file, endian, num=1):
|
| 199 |
+
"""Read a given number of 32-bits unsigned integers from the given file with the given endianness."""
|
| 200 |
+
res = struct.unpack(endian + "L" * num, file.read(num * 4))
|
| 201 |
+
if len(res) == 1:
|
| 202 |
+
return res[0]
|
| 203 |
+
return res
|
| 204 |
+
|
| 205 |
+
def mach_o_change(at_path, what, value): # noqa: C901
|
| 206 |
+
"""
|
| 207 |
+
Replace a given name (what) in any LC_LOAD_DYLIB command found in the given binary with a new name (value),
|
| 208 |
+
provided it's shorter.
|
| 209 |
+
""" # noqa: D205
|
| 210 |
+
|
| 211 |
+
def do_macho(file, bits, endian):
|
| 212 |
+
# Read Mach-O header (the magic number is assumed read by the caller)
|
| 213 |
+
_cpu_type, _cpu_sub_type, _file_type, n_commands, _size_of_commands, _flags = read_data(file, endian, 6)
|
| 214 |
+
# 64-bits header has one more field.
|
| 215 |
+
if bits == 64: # noqa: PLR2004
|
| 216 |
+
read_data(file, endian)
|
| 217 |
+
# The header is followed by n commands
|
| 218 |
+
for _ in range(n_commands):
|
| 219 |
+
where = file.tell()
|
| 220 |
+
# Read command header
|
| 221 |
+
cmd, cmd_size = read_data(file, endian, 2)
|
| 222 |
+
if cmd == LC_LOAD_DYLIB:
|
| 223 |
+
# The first data field in LC_LOAD_DYLIB commands is the offset of the name, starting from the
|
| 224 |
+
# beginning of the command.
|
| 225 |
+
name_offset = read_data(file, endian)
|
| 226 |
+
file.seek(where + name_offset, os.SEEK_SET)
|
| 227 |
+
# Read the NUL terminated string
|
| 228 |
+
load = file.read(cmd_size - name_offset).decode()
|
| 229 |
+
load = load[: load.index("\0")]
|
| 230 |
+
# If the string is what is being replaced, overwrite it.
|
| 231 |
+
if load == what:
|
| 232 |
+
file.seek(where + name_offset, os.SEEK_SET)
|
| 233 |
+
file.write(value.encode() + b"\0")
|
| 234 |
+
# Seek to the next command
|
| 235 |
+
file.seek(where + cmd_size, os.SEEK_SET)
|
| 236 |
+
|
| 237 |
+
def do_file(file, offset=0, size=maxint):
|
| 238 |
+
file = FileView(file, offset, size)
|
| 239 |
+
# Read magic number
|
| 240 |
+
magic = read_data(file, BIG_ENDIAN)
|
| 241 |
+
if magic == FAT_MAGIC:
|
| 242 |
+
# Fat binaries contain nfat_arch Mach-O binaries
|
| 243 |
+
n_fat_arch = read_data(file, BIG_ENDIAN)
|
| 244 |
+
for _ in range(n_fat_arch):
|
| 245 |
+
# Read arch header
|
| 246 |
+
_cpu_type, _cpu_sub_type, offset, size, _align = read_data(file, BIG_ENDIAN, 5)
|
| 247 |
+
do_file(file, offset, size)
|
| 248 |
+
elif magic == MH_MAGIC:
|
| 249 |
+
do_macho(file, 32, BIG_ENDIAN)
|
| 250 |
+
elif magic == MH_CIGAM:
|
| 251 |
+
do_macho(file, 32, LITTLE_ENDIAN)
|
| 252 |
+
elif magic == MH_MAGIC_64:
|
| 253 |
+
do_macho(file, 64, BIG_ENDIAN)
|
| 254 |
+
elif magic == MH_CIGAM_64:
|
| 255 |
+
do_macho(file, 64, LITTLE_ENDIAN)
|
| 256 |
+
|
| 257 |
+
assert len(what) >= len(value) # noqa: S101
|
| 258 |
+
|
| 259 |
+
with open(at_path, "r+b") as f:
|
| 260 |
+
do_file(f)
|
| 261 |
+
|
| 262 |
+
return mach_o_change
|
| 263 |
+
|
| 264 |
+
|
| 265 |
+
class CPython3macOsBrew(CPython3, CPythonPosix):
|
| 266 |
+
@classmethod
|
| 267 |
+
def can_describe(cls, interpreter):
|
| 268 |
+
return is_macos_brew(interpreter) and super().can_describe(interpreter)
|
| 269 |
+
|
| 270 |
+
@classmethod
|
| 271 |
+
def setup_meta(cls, interpreter): # noqa: ARG003
|
| 272 |
+
meta = BuiltinViaGlobalRefMeta()
|
| 273 |
+
meta.copy_error = "Brew disables copy creation: https://github.com/Homebrew/homebrew-core/issues/138159"
|
| 274 |
+
return meta
|
| 275 |
+
|
| 276 |
+
|
| 277 |
+
__all__ = [
|
| 278 |
+
"CPython3macOsBrew",
|
| 279 |
+
"CPython3macOsFramework",
|
| 280 |
+
"CPythonmacOsFramework",
|
| 281 |
+
]
|
.venv/lib/python3.11/site-packages/virtualenv/create/via_global_ref/builtin/pypy/__init__.py
ADDED
|
File without changes
|
.venv/lib/python3.11/site-packages/virtualenv/create/via_global_ref/builtin/pypy/__pycache__/__init__.cpython-311.pyc
ADDED
|
Binary file (218 Bytes). View file
|
|
|
.venv/lib/python3.11/site-packages/virtualenv/create/via_global_ref/builtin/pypy/__pycache__/common.cpython-311.pyc
ADDED
|
Binary file (4.04 kB). View file
|
|
|
.venv/lib/python3.11/site-packages/virtualenv/create/via_global_ref/builtin/pypy/__pycache__/pypy3.cpython-311.pyc
ADDED
|
Binary file (4.01 kB). View file
|
|
|
.venv/lib/python3.11/site-packages/virtualenv/create/via_global_ref/builtin/pypy/common.py
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from __future__ import annotations
|
| 2 |
+
|
| 3 |
+
import abc
|
| 4 |
+
from pathlib import Path
|
| 5 |
+
|
| 6 |
+
from virtualenv.create.via_global_ref.builtin.ref import PathRefToDest, RefMust, RefWhen
|
| 7 |
+
from virtualenv.create.via_global_ref.builtin.via_global_self_do import ViaGlobalRefVirtualenvBuiltin
|
| 8 |
+
|
| 9 |
+
|
| 10 |
+
class PyPy(ViaGlobalRefVirtualenvBuiltin, abc.ABC):
|
| 11 |
+
@classmethod
|
| 12 |
+
def can_describe(cls, interpreter):
|
| 13 |
+
return interpreter.implementation == "PyPy" and super().can_describe(interpreter)
|
| 14 |
+
|
| 15 |
+
@classmethod
|
| 16 |
+
def _executables(cls, interpreter):
|
| 17 |
+
host = Path(interpreter.system_executable)
|
| 18 |
+
targets = sorted(f"{name}{PyPy.suffix}" for name in cls.exe_names(interpreter))
|
| 19 |
+
yield host, targets, RefMust.NA, RefWhen.ANY
|
| 20 |
+
|
| 21 |
+
@classmethod
|
| 22 |
+
def executables(cls, interpreter):
|
| 23 |
+
yield from super().sources(interpreter)
|
| 24 |
+
|
| 25 |
+
@classmethod
|
| 26 |
+
def exe_names(cls, interpreter):
|
| 27 |
+
return {
|
| 28 |
+
cls.exe_stem(),
|
| 29 |
+
"python",
|
| 30 |
+
f"python{interpreter.version_info.major}",
|
| 31 |
+
f"python{interpreter.version_info.major}.{interpreter.version_info.minor}",
|
| 32 |
+
}
|
| 33 |
+
|
| 34 |
+
@classmethod
|
| 35 |
+
def sources(cls, interpreter):
|
| 36 |
+
yield from cls.executables(interpreter)
|
| 37 |
+
for host in cls._add_shared_libs(interpreter):
|
| 38 |
+
yield PathRefToDest(host, dest=lambda self, s: self.bin_dir / s.name)
|
| 39 |
+
|
| 40 |
+
@classmethod
|
| 41 |
+
def _add_shared_libs(cls, interpreter):
|
| 42 |
+
# https://bitbucket.org/pypy/pypy/issue/1922/future-proofing-virtualenv
|
| 43 |
+
python_dir = Path(interpreter.system_executable).resolve().parent
|
| 44 |
+
yield from cls._shared_libs(python_dir)
|
| 45 |
+
|
| 46 |
+
@classmethod
|
| 47 |
+
def _shared_libs(cls, python_dir):
|
| 48 |
+
raise NotImplementedError
|
| 49 |
+
|
| 50 |
+
|
| 51 |
+
__all__ = [
|
| 52 |
+
"PyPy",
|
| 53 |
+
]
|
.venv/lib/python3.11/site-packages/virtualenv/create/via_global_ref/builtin/pypy/pypy3.py
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from __future__ import annotations
|
| 2 |
+
|
| 3 |
+
import abc
|
| 4 |
+
from pathlib import Path
|
| 5 |
+
|
| 6 |
+
from virtualenv.create.describe import PosixSupports, Python3Supports, WindowsSupports
|
| 7 |
+
from virtualenv.create.via_global_ref.builtin.ref import PathRefToDest
|
| 8 |
+
|
| 9 |
+
from .common import PyPy
|
| 10 |
+
|
| 11 |
+
|
| 12 |
+
class PyPy3(PyPy, Python3Supports, abc.ABC):
|
| 13 |
+
@classmethod
|
| 14 |
+
def exe_stem(cls):
|
| 15 |
+
return "pypy3"
|
| 16 |
+
|
| 17 |
+
@classmethod
|
| 18 |
+
def exe_names(cls, interpreter):
|
| 19 |
+
return super().exe_names(interpreter) | {"pypy"}
|
| 20 |
+
|
| 21 |
+
|
| 22 |
+
class PyPy3Posix(PyPy3, PosixSupports):
|
| 23 |
+
"""PyPy 3 on POSIX."""
|
| 24 |
+
|
| 25 |
+
@classmethod
|
| 26 |
+
def _shared_libs(cls, python_dir):
|
| 27 |
+
# glob for libpypy3-c.so, libpypy3-c.dylib, libpypy3.9-c.so ...
|
| 28 |
+
return python_dir.glob("libpypy3*.*")
|
| 29 |
+
|
| 30 |
+
def to_lib(self, src):
|
| 31 |
+
return self.dest / "lib" / src.name
|
| 32 |
+
|
| 33 |
+
@classmethod
|
| 34 |
+
def sources(cls, interpreter):
|
| 35 |
+
yield from super().sources(interpreter)
|
| 36 |
+
# PyPy >= 3.8 supports a standard prefix installation, where older
|
| 37 |
+
# versions always used a portable/development style installation.
|
| 38 |
+
# If this is a standard prefix installation, skip the below:
|
| 39 |
+
if interpreter.system_prefix == "/usr":
|
| 40 |
+
return
|
| 41 |
+
# Also copy/symlink anything under prefix/lib, which, for "portable"
|
| 42 |
+
# PyPy builds, includes the tk,tcl runtime and a number of shared
|
| 43 |
+
# objects. In distro-specific builds or on conda this should be empty
|
| 44 |
+
# (on PyPy3.8+ it will, like on CPython, hold the stdlib).
|
| 45 |
+
host_lib = Path(interpreter.system_prefix) / "lib"
|
| 46 |
+
stdlib = Path(interpreter.system_stdlib)
|
| 47 |
+
if host_lib.exists() and host_lib.is_dir():
|
| 48 |
+
for path in host_lib.iterdir():
|
| 49 |
+
if stdlib == path:
|
| 50 |
+
# For PyPy3.8+ the stdlib lives in lib/pypy3.8
|
| 51 |
+
# We need to avoid creating a symlink to it since that
|
| 52 |
+
# will defeat the purpose of a virtualenv
|
| 53 |
+
continue
|
| 54 |
+
yield PathRefToDest(path, dest=cls.to_lib)
|
| 55 |
+
|
| 56 |
+
|
| 57 |
+
class Pypy3Windows(PyPy3, WindowsSupports):
|
| 58 |
+
"""PyPy 3 on Windows."""
|
| 59 |
+
|
| 60 |
+
@property
|
| 61 |
+
def less_v37(self):
|
| 62 |
+
return self.interpreter.version_info.minor < 7 # noqa: PLR2004
|
| 63 |
+
|
| 64 |
+
@classmethod
|
| 65 |
+
def _shared_libs(cls, python_dir):
|
| 66 |
+
# glob for libpypy*.dll and libffi*.dll
|
| 67 |
+
for pattern in ["libpypy*.dll", "libffi*.dll"]:
|
| 68 |
+
srcs = python_dir.glob(pattern)
|
| 69 |
+
yield from srcs
|
| 70 |
+
|
| 71 |
+
|
| 72 |
+
__all__ = [
|
| 73 |
+
"PyPy3",
|
| 74 |
+
"PyPy3Posix",
|
| 75 |
+
"Pypy3Windows",
|
| 76 |
+
]
|
.venv/lib/python3.11/site-packages/virtualenv/create/via_global_ref/builtin/ref.py
ADDED
|
@@ -0,0 +1,178 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
Virtual environments in the traditional sense are built as reference to the host python. This file allows declarative
|
| 3 |
+
references to elements on the file system, allowing our system to automatically detect what modes it can support given
|
| 4 |
+
the constraints: e.g. can the file system symlink, can the files be read, executed, etc.
|
| 5 |
+
""" # noqa: D205
|
| 6 |
+
|
| 7 |
+
from __future__ import annotations
|
| 8 |
+
|
| 9 |
+
import os
|
| 10 |
+
from abc import ABC, abstractmethod
|
| 11 |
+
from collections import OrderedDict
|
| 12 |
+
from stat import S_IXGRP, S_IXOTH, S_IXUSR
|
| 13 |
+
|
| 14 |
+
from virtualenv.info import fs_is_case_sensitive, fs_supports_symlink
|
| 15 |
+
from virtualenv.util.path import copy, make_exe, symlink
|
| 16 |
+
|
| 17 |
+
|
| 18 |
+
class RefMust:
|
| 19 |
+
NA = "NA"
|
| 20 |
+
COPY = "copy"
|
| 21 |
+
SYMLINK = "symlink"
|
| 22 |
+
|
| 23 |
+
|
| 24 |
+
class RefWhen:
|
| 25 |
+
ANY = "ANY"
|
| 26 |
+
COPY = "copy"
|
| 27 |
+
SYMLINK = "symlink"
|
| 28 |
+
|
| 29 |
+
|
| 30 |
+
class PathRef(ABC):
|
| 31 |
+
"""Base class that checks if a file reference can be symlink/copied."""
|
| 32 |
+
|
| 33 |
+
FS_SUPPORTS_SYMLINK = fs_supports_symlink()
|
| 34 |
+
FS_CASE_SENSITIVE = fs_is_case_sensitive()
|
| 35 |
+
|
| 36 |
+
def __init__(self, src, must=RefMust.NA, when=RefWhen.ANY) -> None:
|
| 37 |
+
self.must = must
|
| 38 |
+
self.when = when
|
| 39 |
+
self.src = src
|
| 40 |
+
try:
|
| 41 |
+
self.exists = src.exists()
|
| 42 |
+
except OSError:
|
| 43 |
+
self.exists = False
|
| 44 |
+
self._can_read = None if self.exists else False
|
| 45 |
+
self._can_copy = None if self.exists else False
|
| 46 |
+
self._can_symlink = None if self.exists else False
|
| 47 |
+
|
| 48 |
+
def __repr__(self) -> str:
|
| 49 |
+
return f"{self.__class__.__name__}(src={self.src})"
|
| 50 |
+
|
| 51 |
+
@property
|
| 52 |
+
def can_read(self):
|
| 53 |
+
if self._can_read is None:
|
| 54 |
+
if self.src.is_file():
|
| 55 |
+
try:
|
| 56 |
+
with self.src.open("rb"):
|
| 57 |
+
self._can_read = True
|
| 58 |
+
except OSError:
|
| 59 |
+
self._can_read = False
|
| 60 |
+
else:
|
| 61 |
+
self._can_read = os.access(str(self.src), os.R_OK)
|
| 62 |
+
return self._can_read
|
| 63 |
+
|
| 64 |
+
@property
|
| 65 |
+
def can_copy(self):
|
| 66 |
+
if self._can_copy is None:
|
| 67 |
+
if self.must == RefMust.SYMLINK:
|
| 68 |
+
self._can_copy = self.can_symlink
|
| 69 |
+
else:
|
| 70 |
+
self._can_copy = self.can_read
|
| 71 |
+
return self._can_copy
|
| 72 |
+
|
| 73 |
+
@property
|
| 74 |
+
def can_symlink(self):
|
| 75 |
+
if self._can_symlink is None:
|
| 76 |
+
if self.must == RefMust.COPY:
|
| 77 |
+
self._can_symlink = self.can_copy
|
| 78 |
+
else:
|
| 79 |
+
self._can_symlink = self.FS_SUPPORTS_SYMLINK and self.can_read
|
| 80 |
+
return self._can_symlink
|
| 81 |
+
|
| 82 |
+
@abstractmethod
|
| 83 |
+
def run(self, creator, symlinks):
|
| 84 |
+
raise NotImplementedError
|
| 85 |
+
|
| 86 |
+
def method(self, symlinks):
|
| 87 |
+
if self.must == RefMust.SYMLINK:
|
| 88 |
+
return symlink
|
| 89 |
+
if self.must == RefMust.COPY:
|
| 90 |
+
return copy
|
| 91 |
+
return symlink if symlinks else copy
|
| 92 |
+
|
| 93 |
+
|
| 94 |
+
class ExePathRef(PathRef, ABC):
|
| 95 |
+
"""Base class that checks if a executable can be references via symlink/copy."""
|
| 96 |
+
|
| 97 |
+
def __init__(self, src, must=RefMust.NA, when=RefWhen.ANY) -> None:
|
| 98 |
+
super().__init__(src, must, when)
|
| 99 |
+
self._can_run = None
|
| 100 |
+
|
| 101 |
+
@property
|
| 102 |
+
def can_symlink(self):
|
| 103 |
+
if self.FS_SUPPORTS_SYMLINK:
|
| 104 |
+
return self.can_run
|
| 105 |
+
return False
|
| 106 |
+
|
| 107 |
+
@property
|
| 108 |
+
def can_run(self):
|
| 109 |
+
if self._can_run is None:
|
| 110 |
+
mode = self.src.stat().st_mode
|
| 111 |
+
for key in [S_IXUSR, S_IXGRP, S_IXOTH]:
|
| 112 |
+
if mode & key:
|
| 113 |
+
self._can_run = True
|
| 114 |
+
break
|
| 115 |
+
else:
|
| 116 |
+
self._can_run = False
|
| 117 |
+
return self._can_run
|
| 118 |
+
|
| 119 |
+
|
| 120 |
+
class PathRefToDest(PathRef):
|
| 121 |
+
"""Link a path on the file system."""
|
| 122 |
+
|
| 123 |
+
def __init__(self, src, dest, must=RefMust.NA, when=RefWhen.ANY) -> None:
|
| 124 |
+
super().__init__(src, must, when)
|
| 125 |
+
self.dest = dest
|
| 126 |
+
|
| 127 |
+
def run(self, creator, symlinks):
|
| 128 |
+
dest = self.dest(creator, self.src)
|
| 129 |
+
method = self.method(symlinks)
|
| 130 |
+
dest_iterable = dest if isinstance(dest, list) else (dest,)
|
| 131 |
+
if not dest.parent.exists():
|
| 132 |
+
dest.parent.mkdir(parents=True, exist_ok=True)
|
| 133 |
+
for dst in dest_iterable:
|
| 134 |
+
method(self.src, dst)
|
| 135 |
+
|
| 136 |
+
|
| 137 |
+
class ExePathRefToDest(PathRefToDest, ExePathRef):
|
| 138 |
+
"""Link a exe path on the file system."""
|
| 139 |
+
|
| 140 |
+
def __init__(self, src, targets, dest, must=RefMust.NA, when=RefWhen.ANY) -> None:
|
| 141 |
+
ExePathRef.__init__(self, src, must, when)
|
| 142 |
+
PathRefToDest.__init__(self, src, dest, must, when)
|
| 143 |
+
if not self.FS_CASE_SENSITIVE:
|
| 144 |
+
targets = list(OrderedDict((i.lower(), None) for i in targets).keys())
|
| 145 |
+
self.base = targets[0]
|
| 146 |
+
self.aliases = targets[1:]
|
| 147 |
+
self.dest = dest
|
| 148 |
+
|
| 149 |
+
def run(self, creator, symlinks):
|
| 150 |
+
bin_dir = self.dest(creator, self.src).parent
|
| 151 |
+
dest = bin_dir / self.base
|
| 152 |
+
method = self.method(symlinks)
|
| 153 |
+
method(self.src, dest)
|
| 154 |
+
if not symlinks:
|
| 155 |
+
make_exe(dest)
|
| 156 |
+
for extra in self.aliases:
|
| 157 |
+
link_file = bin_dir / extra
|
| 158 |
+
if link_file.exists():
|
| 159 |
+
link_file.unlink()
|
| 160 |
+
if symlinks:
|
| 161 |
+
link_file.symlink_to(self.base)
|
| 162 |
+
else:
|
| 163 |
+
copy(self.src, link_file)
|
| 164 |
+
if not symlinks:
|
| 165 |
+
make_exe(link_file)
|
| 166 |
+
|
| 167 |
+
def __repr__(self) -> str:
|
| 168 |
+
return f"{self.__class__.__name__}(src={self.src}, alias={self.aliases})"
|
| 169 |
+
|
| 170 |
+
|
| 171 |
+
__all__ = [
|
| 172 |
+
"ExePathRef",
|
| 173 |
+
"ExePathRefToDest",
|
| 174 |
+
"PathRef",
|
| 175 |
+
"PathRefToDest",
|
| 176 |
+
"RefMust",
|
| 177 |
+
"RefWhen",
|
| 178 |
+
]
|
.venv/lib/python3.11/site-packages/virtualenv/create/via_global_ref/builtin/via_global_self_do.py
ADDED
|
@@ -0,0 +1,118 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from __future__ import annotations
|
| 2 |
+
|
| 3 |
+
from abc import ABC
|
| 4 |
+
|
| 5 |
+
from virtualenv.create.via_global_ref.api import ViaGlobalRefApi, ViaGlobalRefMeta
|
| 6 |
+
from virtualenv.create.via_global_ref.builtin.ref import (
|
| 7 |
+
ExePathRefToDest,
|
| 8 |
+
RefMust,
|
| 9 |
+
RefWhen,
|
| 10 |
+
)
|
| 11 |
+
from virtualenv.util.path import ensure_dir
|
| 12 |
+
|
| 13 |
+
from .builtin_way import VirtualenvBuiltin
|
| 14 |
+
|
| 15 |
+
|
| 16 |
+
class BuiltinViaGlobalRefMeta(ViaGlobalRefMeta):
|
| 17 |
+
def __init__(self) -> None:
|
| 18 |
+
super().__init__()
|
| 19 |
+
self.sources = []
|
| 20 |
+
|
| 21 |
+
|
| 22 |
+
class ViaGlobalRefVirtualenvBuiltin(ViaGlobalRefApi, VirtualenvBuiltin, ABC):
|
| 23 |
+
def __init__(self, options, interpreter) -> None:
|
| 24 |
+
super().__init__(options, interpreter)
|
| 25 |
+
self._sources = getattr(options.meta, "sources", None) # if we're created as a describer this might be missing
|
| 26 |
+
|
| 27 |
+
@classmethod
|
| 28 |
+
def can_create(cls, interpreter):
|
| 29 |
+
"""By default, all built-in methods assume that if we can describe it we can create it."""
|
| 30 |
+
# first we must be able to describe it
|
| 31 |
+
if not cls.can_describe(interpreter):
|
| 32 |
+
return None
|
| 33 |
+
meta = cls.setup_meta(interpreter)
|
| 34 |
+
if meta is not None and meta:
|
| 35 |
+
cls._sources_can_be_applied(interpreter, meta)
|
| 36 |
+
return meta
|
| 37 |
+
|
| 38 |
+
@classmethod
|
| 39 |
+
def _sources_can_be_applied(cls, interpreter, meta):
|
| 40 |
+
for src in cls.sources(interpreter):
|
| 41 |
+
if src.exists:
|
| 42 |
+
if meta.can_copy and not src.can_copy:
|
| 43 |
+
meta.copy_error = f"cannot copy {src}"
|
| 44 |
+
if meta.can_symlink and not src.can_symlink:
|
| 45 |
+
meta.symlink_error = f"cannot symlink {src}"
|
| 46 |
+
else:
|
| 47 |
+
msg = f"missing required file {src}"
|
| 48 |
+
if src.when == RefMust.NA:
|
| 49 |
+
meta.error = msg
|
| 50 |
+
elif src.when == RefMust.COPY:
|
| 51 |
+
meta.copy_error = msg
|
| 52 |
+
elif src.when == RefMust.SYMLINK:
|
| 53 |
+
meta.symlink_error = msg
|
| 54 |
+
if not meta.can_copy and not meta.can_symlink:
|
| 55 |
+
meta.error = f"neither copy or symlink supported, copy: {meta.copy_error} symlink: {meta.symlink_error}"
|
| 56 |
+
if meta.error:
|
| 57 |
+
break
|
| 58 |
+
meta.sources.append(src)
|
| 59 |
+
|
| 60 |
+
@classmethod
|
| 61 |
+
def setup_meta(cls, interpreter): # noqa: ARG003
|
| 62 |
+
return BuiltinViaGlobalRefMeta()
|
| 63 |
+
|
| 64 |
+
@classmethod
|
| 65 |
+
def sources(cls, interpreter):
|
| 66 |
+
for host_exe, targets, must, when in cls._executables(interpreter):
|
| 67 |
+
yield ExePathRefToDest(host_exe, dest=cls.to_bin, targets=targets, must=must, when=when)
|
| 68 |
+
|
| 69 |
+
def to_bin(self, src):
|
| 70 |
+
return self.bin_dir / src.name
|
| 71 |
+
|
| 72 |
+
@classmethod
|
| 73 |
+
def _executables(cls, interpreter):
|
| 74 |
+
raise NotImplementedError
|
| 75 |
+
|
| 76 |
+
def create(self):
|
| 77 |
+
dirs = self.ensure_directories()
|
| 78 |
+
for directory in list(dirs):
|
| 79 |
+
if any(i for i in dirs if i is not directory and directory.parts == i.parts[: len(directory.parts)]):
|
| 80 |
+
dirs.remove(directory)
|
| 81 |
+
for directory in sorted(dirs):
|
| 82 |
+
ensure_dir(directory)
|
| 83 |
+
|
| 84 |
+
self.set_pyenv_cfg()
|
| 85 |
+
self.pyenv_cfg.write()
|
| 86 |
+
true_system_site = self.enable_system_site_package
|
| 87 |
+
try:
|
| 88 |
+
self.enable_system_site_package = False
|
| 89 |
+
for src in self._sources:
|
| 90 |
+
if (
|
| 91 |
+
src.when == RefWhen.ANY
|
| 92 |
+
or (src.when == RefWhen.SYMLINK and self.symlinks is True)
|
| 93 |
+
or (src.when == RefWhen.COPY and self.symlinks is False)
|
| 94 |
+
):
|
| 95 |
+
src.run(self, self.symlinks)
|
| 96 |
+
finally:
|
| 97 |
+
if true_system_site != self.enable_system_site_package:
|
| 98 |
+
self.enable_system_site_package = true_system_site
|
| 99 |
+
super().create()
|
| 100 |
+
|
| 101 |
+
def ensure_directories(self):
|
| 102 |
+
return {self.dest, self.bin_dir, self.script_dir, self.stdlib} | set(self.libs)
|
| 103 |
+
|
| 104 |
+
def set_pyenv_cfg(self):
|
| 105 |
+
"""
|
| 106 |
+
We directly inject the base prefix and base exec prefix to avoid site.py needing to discover these
|
| 107 |
+
from home (which usually is done within the interpreter itself).
|
| 108 |
+
""" # noqa: D205
|
| 109 |
+
super().set_pyenv_cfg()
|
| 110 |
+
self.pyenv_cfg["base-prefix"] = self.interpreter.system_prefix
|
| 111 |
+
self.pyenv_cfg["base-exec-prefix"] = self.interpreter.system_exec_prefix
|
| 112 |
+
self.pyenv_cfg["base-executable"] = self.interpreter.system_executable
|
| 113 |
+
|
| 114 |
+
|
| 115 |
+
__all__ = [
|
| 116 |
+
"BuiltinViaGlobalRefMeta",
|
| 117 |
+
"ViaGlobalRefVirtualenvBuiltin",
|
| 118 |
+
]
|
.venv/lib/python3.11/site-packages/virtualenv/create/via_global_ref/store.py
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from __future__ import annotations
|
| 2 |
+
|
| 3 |
+
from pathlib import Path
|
| 4 |
+
|
| 5 |
+
|
| 6 |
+
def handle_store_python(meta, interpreter):
|
| 7 |
+
if is_store_python(interpreter):
|
| 8 |
+
meta.symlink_error = "Windows Store Python does not support virtual environments via symlink"
|
| 9 |
+
return meta
|
| 10 |
+
|
| 11 |
+
|
| 12 |
+
def is_store_python(interpreter):
|
| 13 |
+
parts = Path(interpreter.system_executable).parts
|
| 14 |
+
return (
|
| 15 |
+
len(parts) > 4 # noqa: PLR2004
|
| 16 |
+
and parts[-4] == "Microsoft"
|
| 17 |
+
and parts[-3] == "WindowsApps"
|
| 18 |
+
and parts[-2].startswith("PythonSoftwareFoundation.Python.3.")
|
| 19 |
+
and parts[-1].startswith("python")
|
| 20 |
+
)
|
| 21 |
+
|
| 22 |
+
|
| 23 |
+
__all__ = [
|
| 24 |
+
"handle_store_python",
|
| 25 |
+
"is_store_python",
|
| 26 |
+
]
|
.venv/lib/python3.11/site-packages/virtualenv/create/via_global_ref/venv.py
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from __future__ import annotations # noqa: A005
|
| 2 |
+
|
| 3 |
+
import logging
|
| 4 |
+
from copy import copy
|
| 5 |
+
|
| 6 |
+
from virtualenv.create.via_global_ref.store import handle_store_python
|
| 7 |
+
from virtualenv.discovery.py_info import PythonInfo
|
| 8 |
+
from virtualenv.util.error import ProcessCallFailedError
|
| 9 |
+
from virtualenv.util.path import ensure_dir
|
| 10 |
+
from virtualenv.util.subprocess import run_cmd
|
| 11 |
+
|
| 12 |
+
from .api import ViaGlobalRefApi, ViaGlobalRefMeta
|
| 13 |
+
from .builtin.cpython.mac_os import CPython3macOsBrew
|
| 14 |
+
from .builtin.pypy.pypy3 import Pypy3Windows
|
| 15 |
+
|
| 16 |
+
LOGGER = logging.getLogger(__name__)
|
| 17 |
+
|
| 18 |
+
|
| 19 |
+
class Venv(ViaGlobalRefApi):
|
| 20 |
+
def __init__(self, options, interpreter) -> None:
|
| 21 |
+
self.describe = options.describe
|
| 22 |
+
super().__init__(options, interpreter)
|
| 23 |
+
current = PythonInfo.current()
|
| 24 |
+
self.can_be_inline = interpreter is current and interpreter.executable == interpreter.system_executable
|
| 25 |
+
self._context = None
|
| 26 |
+
|
| 27 |
+
def _args(self):
|
| 28 |
+
return super()._args() + ([("describe", self.describe.__class__.__name__)] if self.describe else [])
|
| 29 |
+
|
| 30 |
+
@classmethod
|
| 31 |
+
def can_create(cls, interpreter):
|
| 32 |
+
if interpreter.has_venv:
|
| 33 |
+
if CPython3macOsBrew.can_describe(interpreter):
|
| 34 |
+
return CPython3macOsBrew.setup_meta(interpreter)
|
| 35 |
+
meta = ViaGlobalRefMeta()
|
| 36 |
+
if interpreter.platform == "win32":
|
| 37 |
+
meta = handle_store_python(meta, interpreter)
|
| 38 |
+
return meta
|
| 39 |
+
return None
|
| 40 |
+
|
| 41 |
+
def create(self):
|
| 42 |
+
if self.can_be_inline:
|
| 43 |
+
self.create_inline()
|
| 44 |
+
else:
|
| 45 |
+
self.create_via_sub_process()
|
| 46 |
+
for lib in self.libs:
|
| 47 |
+
ensure_dir(lib)
|
| 48 |
+
super().create()
|
| 49 |
+
self.executables_for_win_pypy_less_v37()
|
| 50 |
+
|
| 51 |
+
def executables_for_win_pypy_less_v37(self):
|
| 52 |
+
"""
|
| 53 |
+
PyPy <= 3.6 (v7.3.3) for Windows contains only pypy3.exe and pypy3w.exe
|
| 54 |
+
Venv does not handle non-existing exe sources, e.g. python.exe, so this
|
| 55 |
+
patch does it.
|
| 56 |
+
""" # noqa: D205
|
| 57 |
+
creator = self.describe
|
| 58 |
+
if isinstance(creator, Pypy3Windows) and creator.less_v37:
|
| 59 |
+
for exe in creator.executables(self.interpreter):
|
| 60 |
+
exe.run(creator, self.symlinks)
|
| 61 |
+
|
| 62 |
+
def create_inline(self):
|
| 63 |
+
from venv import EnvBuilder # noqa: PLC0415
|
| 64 |
+
|
| 65 |
+
builder = EnvBuilder(
|
| 66 |
+
system_site_packages=self.enable_system_site_package,
|
| 67 |
+
clear=False,
|
| 68 |
+
symlinks=self.symlinks,
|
| 69 |
+
with_pip=False,
|
| 70 |
+
)
|
| 71 |
+
builder.create(str(self.dest))
|
| 72 |
+
|
| 73 |
+
def create_via_sub_process(self):
|
| 74 |
+
cmd = self.get_host_create_cmd()
|
| 75 |
+
LOGGER.info("using host built-in venv to create via %s", " ".join(cmd))
|
| 76 |
+
code, out, err = run_cmd(cmd)
|
| 77 |
+
if code != 0:
|
| 78 |
+
raise ProcessCallFailedError(code, out, err, cmd)
|
| 79 |
+
|
| 80 |
+
def get_host_create_cmd(self):
|
| 81 |
+
cmd = [self.interpreter.system_executable, "-m", "venv", "--without-pip"]
|
| 82 |
+
if self.enable_system_site_package:
|
| 83 |
+
cmd.append("--system-site-packages")
|
| 84 |
+
cmd.extend(("--symlinks" if self.symlinks else "--copies", str(self.dest)))
|
| 85 |
+
return cmd
|
| 86 |
+
|
| 87 |
+
def set_pyenv_cfg(self):
|
| 88 |
+
# prefer venv options over ours, but keep our extra
|
| 89 |
+
venv_content = copy(self.pyenv_cfg.refresh())
|
| 90 |
+
super().set_pyenv_cfg()
|
| 91 |
+
self.pyenv_cfg.update(venv_content)
|
| 92 |
+
|
| 93 |
+
def __getattribute__(self, item):
|
| 94 |
+
describe = object.__getattribute__(self, "describe")
|
| 95 |
+
if describe is not None and hasattr(describe, item):
|
| 96 |
+
element = getattr(describe, item)
|
| 97 |
+
if not callable(element) or item == "script":
|
| 98 |
+
return element
|
| 99 |
+
return object.__getattribute__(self, item)
|
| 100 |
+
|
| 101 |
+
|
| 102 |
+
__all__ = [
|
| 103 |
+
"Venv",
|
| 104 |
+
]
|
.venv/lib/python3.11/site-packages/virtualenv/seed/__pycache__/__init__.cpython-311.pyc
ADDED
|
Binary file (188 Bytes). View file
|
|
|
.venv/lib/python3.11/site-packages/virtualenv/seed/__pycache__/seeder.cpython-311.pyc
ADDED
|
Binary file (1.95 kB). View file
|
|
|
.venv/lib/python3.11/site-packages/virtualenv/seed/embed/via_app_data/__pycache__/__init__.cpython-311.pyc
ADDED
|
Binary file (207 Bytes). View file
|
|
|
.venv/lib/python3.11/site-packages/virtualenv/seed/embed/via_app_data/__pycache__/via_app_data.cpython-311.pyc
ADDED
|
Binary file (9.82 kB). View file
|
|
|
.venv/lib/python3.11/site-packages/virtualenv/seed/embed/via_app_data/pip_install/__init__.py
ADDED
|
File without changes
|
.venv/lib/python3.11/site-packages/virtualenv/seed/embed/via_app_data/pip_install/__pycache__/__init__.cpython-311.pyc
ADDED
|
Binary file (219 Bytes). View file
|
|
|
.venv/lib/python3.11/site-packages/virtualenv/seed/embed/via_app_data/pip_install/__pycache__/base.cpython-311.pyc
ADDED
|
Binary file (16.7 kB). View file
|
|
|
.venv/lib/python3.11/site-packages/virtualenv/seed/embed/via_app_data/pip_install/__pycache__/copy.cpython-311.pyc
ADDED
|
Binary file (3.11 kB). View file
|
|
|