1
1
# mypy: allow-untyped-defs
2
2
3
+ import logging
3
4
import os
4
5
import shutil
6
+ import site
5
7
import sys
6
- import logging
8
+ import sysconfig
9
+ from pathlib import Path
7
10
from shutil import which
8
11
9
12
# The `pkg_resources` module is provided by `setuptools`, which is itself a
@@ -27,9 +30,7 @@ def __init__(self, path, skip_virtualenv_setup):
27
30
self .path = path
28
31
self .skip_virtualenv_setup = skip_virtualenv_setup
29
32
if not skip_virtualenv_setup :
30
- self .virtualenv = which ("virtualenv" )
31
- if not self .virtualenv :
32
- raise ValueError ("virtualenv must be installed and on the PATH" )
33
+ self .virtualenv = [sys .executable , "-m" , "venv" ]
33
34
self ._working_set = None
34
35
35
36
@property
@@ -47,7 +48,7 @@ def create(self):
47
48
if os .path .exists (self .path ):
48
49
shutil .rmtree (self .path )
49
50
self ._working_set = None
50
- call (self .virtualenv , self .path , "-p" , sys . executable )
51
+ call (* self .virtualenv , self .path )
51
52
52
53
@property
53
54
def bin_path (self ):
@@ -100,9 +101,37 @@ def activate(self):
100
101
# https://github.com/web-platform-tests/wpt/issues/27377
101
102
# https://github.com/python/cpython/pull/9516
102
103
os .environ .pop ('__PYVENV_LAUNCHER__' , None )
103
- path = os .path .join (self .bin_path , "activate_this.py" )
104
- with open (path ) as f :
105
- exec (f .read (), {"__file__" : path })
104
+
105
+ # Setup the path and site packages as if we'd launched with the virtualenv active
106
+ bin_dir = os .path .join (self .path , "bin" )
107
+ os .environ ["PATH" ] = os .pathsep .join ([bin_dir ] + os .environ .get ("PATH" , "" ).split (os .pathsep ))
108
+ os .environ ["VIRTUAL_ENV" ] = self .path
109
+
110
+ prev_length = len (sys .path )
111
+
112
+ schemes = sysconfig .get_scheme_names ()
113
+ if "venv" in schemes :
114
+ scheme = "venv"
115
+ else :
116
+ scheme = "nt_user" if os .name == "nt" else "posix_user"
117
+ sys_paths = sysconfig .get_paths (scheme )
118
+ data_path = sys_paths ["data" ]
119
+ added = set ()
120
+ # Add the venv library paths as sitedirs.
121
+ # This converts system paths like /usr/local/lib/python3.10/site-packages
122
+ # to venv-relative paths like {self.path}/lib/python3.10/site-packages and adds
123
+ # those paths as site dirs to be used for module import.
124
+ for key in ["purelib" , "platlib" ]:
125
+ host_path = Path (sys_paths [key ])
126
+ relative_path = host_path .relative_to (data_path )
127
+ site_dir = os .path .normpath (os .path .normcase (Path (self .path ) / relative_path ))
128
+ if site_dir not in added :
129
+ site .addsitedir (site_dir )
130
+ added .add (site_dir )
131
+ sys .path [:] = sys .path [prev_length :] + sys .path [0 :prev_length ]
132
+
133
+ sys .real_prefix = sys .prefix
134
+ sys .prefix = self .path
106
135
107
136
def start (self ):
108
137
if not self .exists or self .broken_link :
0 commit comments