未验证 提交 809cc9d1 编写于 作者: F Frost Ming

fix packages loading

上级 ea55cddf
......@@ -143,8 +143,7 @@ the outside, the PDM's installer has already injected the package path to the `s
### 3. What site-packages will be loaded when using PDM?
Only packages in the local `__pypackages__` directory will be loaded. `site-packages` of Python interpreter isn't loaded.
It is fully isolated.
Packages in the local `__pypackages__` directory will be loaded before the system-level `site-packages` for islation.
### 4. Can I relocate or move the `__pypackages__` folder for deployment?
......
......@@ -131,7 +131,7 @@ PEP 582 尚处于草案阶段,还需要补充很多细节,比如提案中并
### 3. 使用 PDM 时会载入哪些三方库路径?
只有本项目的 `__pypackages__` 中的包会被载入,也就是说,Python 的 `site-packages` 目录不会被载入,完全项目隔离
本项目的 `__pypackages__` 中的包会在系统的`site-packages`之前被载入,这样能更好地隔离包的环境
### 4. 我能把 `__pypackages__` 保存下来用来部署到别的机器上吗?
......
......@@ -277,13 +277,6 @@ test_shell shell echo $FOO shell command
You can add an `help` option with the description of the script, and it will be displayed in the `Description` column in the above output.
### Include system site-packages in the isolated environment
By default, system-level site-packages will be excluded from the `sys.path` when PEP 582 is enabled, unless:
- Run `pdm run` with `-s/--site-packages` flag.
- With environment variable `PDM_WITH_SITE_PACKAGES=1`.
## How we make PEP 582 packages available to the Python interpreter
Thanks to the [site packages loading](https://docs.python.org/3/library/site.html) on Python startup. It is possible to patch the `sys.path`
......
......@@ -27,12 +27,6 @@ class Command(BaseCommand):
action="store_true",
help="Show all available scripts defined in pyproject.toml",
)
parser.add_argument(
"-s",
"--site-packages",
action="store_true",
help="Load site-packages from system interpreter",
)
parser.add_argument("command", nargs="?", help="The command to run")
parser.add_argument(
"args",
......@@ -163,8 +157,6 @@ class Command(BaseCommand):
if options.list:
return self._show_list(project)
global_env_options = project.scripts.get("_", {}) if project.scripts else {}
if options.site_packages:
os.environ.update({"PDM_WITH_SITE_PACKAGES": "1"})
if project.scripts and options.command in project.scripts:
self._run_script(project, options.command, options.args, global_env_options)
else:
......
import os
import site
import sys
import warnings
def get_pypackages_path(maxdepth=5):
......@@ -37,49 +36,27 @@ def main():
self_path = os.path.normcase(os.path.dirname(os.path.abspath(__file__)))
sys.path[:] = [path for path in sys.path if os.path.normcase(path) != self_path]
with_site_packages = os.getenv("PDM_WITH_SITE_PACKAGES")
needs_user_site = False
needs_site_packages = False
script_path = None
if getattr(sys, "argv", None) is None:
warnings.warn(
"PEP 582 can't be loaded based on the script path. "
"As Python 2.7 reached the end of life on 2020/01/01, "
"please upgrade to Python 3.",
)
else:
script_path = os.path.normcase(os.path.realpath(sys.argv[0]))
needs_user_site = script_path.startswith(os.path.normcase(site.USER_BASE))
needs_site_packages = any(
script_path.startswith(os.path.normcase(p)) for p in site.PREFIXES
)
libpath = get_pypackages_path()
if not libpath:
return
pypackages = os.path.dirname(os.path.dirname(libpath))
# First, drop site related paths.
original_sys_path = sys.path[:]
paths_to_remove = set()
if not (with_site_packages or needs_user_site):
site.addusersitepackages(paths_to_remove)
if not (
with_site_packages
or needs_site_packages
or script_path
and not script_path.startswith(os.path.normcase(os.path.dirname(pypackages)))
):
site.addsitepackages(paths_to_remove)
paths_to_remove = set(os.path.normcase(path) for path in paths_to_remove)
known_paths = set()
site.addusersitepackages(known_paths)
site.addsitepackages(known_paths)
known_paths = set(os.path.normcase(path) for path in known_paths)
original_sys_path = [
path
for path in original_sys_path
if os.path.normcase(path) not in paths_to_remove
path for path in original_sys_path if os.path.normcase(path) not in known_paths
]
sys.path[:] = original_sys_path
# Second, add lib directories, ensuring .pth file are processed.
site.addsitedir(libpath)
# Then add the removed path to the tail of the paths
known_paths.clear()
site.addusersitepackages(known_paths)
site.addsitepackages(known_paths)
main()
......
import json
import os
import subprocess
import textwrap
......@@ -9,18 +8,6 @@ from pdm.cli.actions import PEP582_PATH
from pdm.utils import cd, temp_environ
def test_pep582_not_loading_site_packages(project, invoke, capfd):
with cd(project.root):
invoke(["install"], obj=project)
invoke(
["run", "python", "-c", "import sys,json;print(json.dumps(sys.path))"],
obj=project,
)
sys_path = json.loads(capfd.readouterr()[0])
assert not any("site-packages" in p for p in sys_path)
assert str(project.environment.packages_path / "lib") in sys_path
@pytest.mark.pypi
def test_pep582_launcher_for_python_interpreter(project, invoke):
project.meta["requires-python"] = ">=3.6"
......@@ -38,16 +25,6 @@ def test_pep582_launcher_for_python_interpreter(project, invoke):
assert output.decode().strip() == "2.24.0"
def test_pep582_launcher_with_system_site_packages(project, invoke):
with cd(project.root):
invoke(["install"], obj=project)
result = invoke(["run", "python", "-c", "import resolvelib"], obj=project)
assert result.exit_code != 0
result = invoke(["run", "-s", "python", "-c", "import resolvelib"], obj=project)
assert result.exit_code == 0
def test_run_command_not_found(invoke):
result = invoke(["run", "foobar"])
assert "Command 'foobar' is not found on your PATH." in result.stderr
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册