-
Notifications
You must be signed in to change notification settings - Fork 3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Support PEP 405 include-system-site-packages configuration (#7155)
- Loading branch information
Showing
12 changed files
with
209 additions
and
24 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
Correctly handle system site-packages, in virtual environments created with venv (PEP 405). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
Correctly handle system site-packages, in virtual environments created with venv (PEP 405). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,34 +1,115 @@ | ||
import os.path | ||
from __future__ import absolute_import | ||
|
||
import logging | ||
import os | ||
import re | ||
import site | ||
import sys | ||
|
||
from pip._internal.utils.typing import MYPY_CHECK_RUNNING | ||
|
||
if MYPY_CHECK_RUNNING: | ||
from typing import List, Optional | ||
|
||
logger = logging.getLogger(__name__) | ||
_INCLUDE_SYSTEM_SITE_PACKAGES_REGEX = re.compile( | ||
r"include-system-site-packages\s*=\s*(?P<value>true|false)" | ||
) | ||
|
||
|
||
def _running_under_venv(): | ||
# type: () -> bool | ||
"""Checks if sys.base_prefix and sys.prefix match. | ||
This handles PEP 405 compliant virtual environments. | ||
""" | ||
return sys.prefix != getattr(sys, "base_prefix", sys.prefix) | ||
|
||
|
||
def _running_under_regular_virtualenv(): | ||
# type: () -> bool | ||
"""Checks if sys.real_prefix is set. | ||
This handles virtual environments created with pypa's virtualenv. | ||
""" | ||
# pypa/virtualenv case | ||
return hasattr(sys, 'real_prefix') | ||
|
||
|
||
def running_under_virtualenv(): | ||
# type: () -> bool | ||
"""Return True if we're running inside a virtualenv, False otherwise. | ||
""" | ||
Return True if we're running inside a virtualenv, False otherwise. | ||
return _running_under_venv() or _running_under_regular_virtualenv() | ||
|
||
|
||
def _get_pyvenv_cfg_lines(): | ||
# type: () -> Optional[List[str]] | ||
"""Reads {sys.prefix}/pyvenv.cfg and returns its contents as list of lines | ||
Returns None, if it could not read/access the file. | ||
""" | ||
if hasattr(sys, 'real_prefix'): | ||
# pypa/virtualenv case | ||
return True | ||
elif sys.prefix != getattr(sys, "base_prefix", sys.prefix): | ||
# PEP 405 venv | ||
pyvenv_cfg_file = os.path.join(sys.prefix, 'pyvenv.cfg') | ||
try: | ||
with open(pyvenv_cfg_file) as f: | ||
return f.read().splitlines() # avoids trailing newlines | ||
except IOError: | ||
return None | ||
|
||
|
||
def _no_global_under_venv(): | ||
# type: () -> bool | ||
"""Check `{sys.prefix}/pyvenv.cfg` for system site-packages inclusion | ||
PEP 405 specifies that when system site-packages are not supposed to be | ||
visible from a virtual environment, `pyvenv.cfg` must contain the following | ||
line: | ||
include-system-site-packages = false | ||
Additionally, log a warning if accessing the file fails. | ||
""" | ||
cfg_lines = _get_pyvenv_cfg_lines() | ||
if cfg_lines is None: | ||
# We're not in a "sane" venv, so assume there is no system | ||
# site-packages access (since that's PEP 405's default state). | ||
logger.warning( | ||
"Could not access 'pyvenv.cfg' despite a virtual environment " | ||
"being active. Assuming global site-packages is not accessible " | ||
"in this environment." | ||
) | ||
return True | ||
|
||
for line in cfg_lines: | ||
match = _INCLUDE_SYSTEM_SITE_PACKAGES_REGEX.match(line) | ||
if match is not None and match.group('value') == 'false': | ||
return True | ||
return False | ||
|
||
|
||
def virtualenv_no_global(): | ||
def _no_global_under_regular_virtualenv(): | ||
# type: () -> bool | ||
"""Check if "no-global-site-packages.txt" exists beside site.py | ||
This mirrors logic in pypa/virtualenv for determining whether system | ||
site-packages are visible in the virtual environment. | ||
""" | ||
Return True if in a venv and no system site packages. | ||
""" | ||
# this mirrors the logic in virtualenv.py for locating the | ||
# no-global-site-packages.txt file | ||
site_mod_dir = os.path.dirname(os.path.abspath(site.__file__)) | ||
no_global_file = os.path.join(site_mod_dir, 'no-global-site-packages.txt') | ||
if running_under_virtualenv() and os.path.isfile(no_global_file): | ||
return True | ||
else: | ||
return False | ||
no_global_site_packages_file = os.path.join( | ||
site_mod_dir, 'no-global-site-packages.txt', | ||
) | ||
return os.path.exists(no_global_site_packages_file) | ||
|
||
|
||
def virtualenv_no_global(): | ||
# type: () -> bool | ||
"""Returns a boolean, whether running in venv with no system site-packages. | ||
""" | ||
|
||
if _running_under_regular_virtualenv(): | ||
return _no_global_under_regular_virtualenv() | ||
|
||
if _running_under_venv(): | ||
return _no_global_under_venv() | ||
|
||
return False |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.