Skip to content

Commit

Permalink
Merge pull request #91 from frostming/bugfix/89
Browse files Browse the repository at this point in the history
validate python_requires
  • Loading branch information
frostming authored Mar 29, 2020
2 parents 25a5d2d + 76f34f2 commit b5dfb6e
Show file tree
Hide file tree
Showing 16 changed files with 256 additions and 229 deletions.
1 change: 1 addition & 0 deletions news/89.bugfix
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Validate user input for `python_requires` when initializing project.
2 changes: 2 additions & 0 deletions news/89.dep
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Update dependencies `pythonfinder`, `python-cfonts`, `pip-shims` and many others.
Drop dependency `vistir`.
345 changes: 145 additions & 200 deletions pdm.lock

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions pdm/cli/actions.py
Original file line number Diff line number Diff line change
Expand Up @@ -354,6 +354,7 @@ def do_init(
"build-system": {"requires": ["pdm"], "build-backend": "pdm.builders.api"},
}
if python_requires and python_requires != "*":
get_specifier(python_requires)
data["tool"]["pdm"]["python_requires"] = python_requires
if not project.pyproject:
project._pyproject = data
Expand Down
2 changes: 1 addition & 1 deletion pdm/installers.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,13 @@
from pip._internal.utils import logging as pip_logging
from pip._vendor.pkg_resources import Distribution, EggInfoDistribution, safe_name
from pip_shims import shims
from vistir import cd

from pdm.exceptions import InstallationError
from pdm.iostream import stream
from pdm.models.candidates import Candidate
from pdm.models.environment import Environment
from pdm.models.requirements import parse_requirement, strip_extras
from pdm.utils import cd


def _is_dist_editable(dist: Distribution) -> bool:
Expand Down
2 changes: 1 addition & 1 deletion pdm/models/caches.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@

import pip_shims
from pip._vendor import requests
from vistir.contextmanagers import open_file

from pdm._types import CandidateInfo
from pdm.exceptions import CorruptedCacheError
from pdm.utils import open_file

if TYPE_CHECKING:
from pdm.models.candidates import Candidate
Expand Down
18 changes: 5 additions & 13 deletions pdm/models/environment.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,9 @@
from pip_shims import shims
from pythonfinder import Finder
from pythonfinder.environment import PYENV_INSTALLED, PYENV_ROOT
from vistir.contextmanagers import temp_environ
from vistir.path import normalize_path

from pdm.exceptions import NoPythonVersion
from pdm.iostream import stream
from pdm.models.specifiers import PySpecSet
from pdm.utils import (
allow_all_wheels,
cached_property,
Expand All @@ -31,6 +28,7 @@
get_python_version,
get_sys_config_paths,
get_venv_python,
temp_environ,
)

if TYPE_CHECKING:
Expand Down Expand Up @@ -181,8 +179,8 @@ def activate(self):

def is_local(self, path) -> bool:
"""PEP 582 version of ``is_local()`` function."""
return normalize_path(path).startswith(
normalize_path(self.packages_path.as_posix())
return misc.normalize_path(path).startswith(
misc.normalize_path(self.packages_path.as_posix())
)

def evaluate_marker(self, text: str, extra=None) -> bool:
Expand Down Expand Up @@ -343,21 +341,15 @@ class GlobalEnvironment(Environment):

is_global = True

def __init__(self, project: Project) -> None:
super().__init__(project)
self.python_requires = PySpecSet(
"==" + get_python_version(self.python_executable, True)
)

def get_paths(self) -> Dict[str, str]:
paths = get_sys_config_paths(self.python_executable)
paths["prefix"] = paths["data"]
paths["headers"] = paths["include"]
return paths

def is_local(self, path) -> bool:
return normalize_path(path).startswith(
normalize_path(self.get_paths()["prefix"])
return misc.normalize_path(path).startswith(
misc.normalize_path(self.get_paths()["prefix"])
)

@property
Expand Down
17 changes: 14 additions & 3 deletions pdm/project/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
import tomlkit
from pip._vendor.pkg_resources import safe_name
from pip_shims import shims
from vistir.contextmanagers import atomic_open_for_write

from pdm._types import Source
from pdm.exceptions import ProjectError
Expand All @@ -26,7 +25,13 @@
from pdm.project.meta import PackageMeta
from pdm.resolver import BaseProvider, EagerUpdateProvider, ReusePinProvider
from pdm.resolver.reporters import SpinnerReporter
from pdm.utils import cached_property, find_project_root, get_venv_python
from pdm.utils import (
atomic_open_for_write,
cached_property,
find_project_root,
get_python_version,
get_venv_python,
)

if TYPE_CHECKING:
from tomlkit.container import Container
Expand Down Expand Up @@ -137,7 +142,13 @@ def is_pdm(self) -> bool:
@cached_property
def environment(self) -> Environment:
if self.is_global:
return GlobalEnvironment(self)
env = GlobalEnvironment(self)
# Rewrite global project's python requires to be
# compatible with the exact version
env.python_requires = PySpecSet(
"==" + get_python_version(env.python_executable, True)
)
return env
if self.config["use_venv"] and "VIRTUAL_ENV" in os.environ:
self.project_config["python.path"] = get_venv_python()
return GlobalEnvironment(self)
Expand Down
4 changes: 2 additions & 2 deletions pdm/project/meta.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@
from typing import TYPE_CHECKING, Dict, List, Union

import setuptools
import vistir
from pkg_resources import safe_name

from pdm.exceptions import ProjectError
from pdm.models.markers import Marker
from pdm.utils import cd

if TYPE_CHECKING:
from pdm.project import Project
Expand Down Expand Up @@ -148,7 +148,7 @@ def convert_package_paths(self) -> Dict[str, Union[List, Dict]]:
package_data = {"": ["*"]}
exclude_package_data = {}

with vistir.cd(self.project.root.as_posix()):
with cd(self.project.root.as_posix()):
if not self.includes:
if os.path.isdir("src"):
package_dir[""] = "src"
Expand Down
68 changes: 66 additions & 2 deletions pdm/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@
import urllib.parse as parse
from contextlib import contextmanager
from pathlib import Path
from typing import TYPE_CHECKING, Any, Dict, List, Optional, Tuple
from typing import TYPE_CHECKING, Any, Dict, List, Optional, Tuple, Union

from distlib.wheel import Wheel
from pip_shims.shims import InstallCommand, PackageFinder, TargetPython
from pip_shims.shims import InstallCommand, PackageFinder, TargetPython, url_to_path

from pdm._types import Source

Expand Down Expand Up @@ -418,3 +418,67 @@ def get_venv_python() -> Optional[str]:
suffix = ""
scripts = "bin"
return os.path.join(venv, scripts, f"python{suffix}")


@contextmanager
def atomic_open_for_write(filename: Union[Path, str], *, encoding: str = "utf-8"):
fd, name = tempfile.mkstemp("-atomic-write", "pdm-")
filename = str(filename)
try:
f = open(fd, "w", encoding=encoding)
yield f
except Exception:
f.close()
os.unlink(name)
raise
else:
f.close()
try:
os.unlink(filename)
except OSError:
pass
os.rename(name, filename)


@contextmanager
def cd(path: str):
_old_cwd = os.getcwd()
os.chdir(path)
try:
yield
finally:
os.chdir(_old_cwd)


@contextmanager
def temp_environ():
environ = os.environ.copy()
try:
yield
finally:
os.environ.clear()
os.environ.update(environ)


@contextmanager
def open_file(url, session=None):
if url.startswith("file://"):
local_path = url_to_path(url)
if os.path.isdir(local_path):
raise ValueError("Cannot open directory for read: {}".format(url))
else:
with open(local_path, "rb") as local_file:
yield local_file
else:
headers = {"Accept-Encoding": "identity"}
with session.get(url, headers=headers, stream=True) as resp:
try:
raw = getattr(resp, "raw", None)
result = raw if raw else resp
yield result
finally:
if raw:
conn = getattr(raw, "_connection")
if conn is not None:
conn.close()
result.close()
1 change: 0 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ pytest = "*"
pytest-cov = "*"
pytest-mock = "*"
towncrier = "<20.0.0,>=19.2.0"
pytest-sugar = "<1.0.0,>=0.9.2"
pytest-xdist = "<2.0.0,>=1.31.0"

[tool.pdm.doc-dependencies]
Expand Down
1 change: 0 additions & 1 deletion setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ known_first_party = pdm
known_third_party =
click
halo
vistir
distlib
pythonfinder
pytest
Expand Down
11 changes: 10 additions & 1 deletion setup_dev.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,16 @@ def main():
subprocess.check_call([venv_python.as_posix(), "-m", "pip", "install", "pdm"])

subprocess.check_call(
[venv_python.as_posix(), "-m", "pip", "install", "pip", "pip_shims", "-U"]
[
venv_python.as_posix(),
"-m",
"pip",
"install",
"-U",
"pip",
"pip_shims",
"vistir",
]
)

print("Setup project for development...", flush=True)
Expand Down
7 changes: 6 additions & 1 deletion tests/cli/test_actions.py
Original file line number Diff line number Diff line change
Expand Up @@ -357,7 +357,7 @@ def test_list_dependency_graph(capsys):
project = Project()
actions.do_list(project, True)
content, _ = capsys.readouterr()
assert "halo 0.0.28 [ required: <1.0.0,>=0.0.28 ]" in content
assert "halo 0.0.29 [ required: <1.0.0,>=0.0.28 ]" in content
assert "six 1.14.0 [ required: >=1.12.0 ]" in content


Expand Down Expand Up @@ -390,3 +390,8 @@ def test_update_ignore_constraints(project, repository, working_set):
actions.do_update(project, unconstrained=True, packages=("pytz",))
assert project.tool_settings["dependencies"]["pytz"] == "<2021.0.0,>=2020.2"
assert project.get_locked_candidates()["pytz"].version == "2020.2"


def test_init_validate_python_requires(project_no_init):
with pytest.raises(ValueError):
actions.do_init(project_no_init, python_requires="3.7")
3 changes: 1 addition & 2 deletions tests/cli/test_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,10 @@
from pathlib import Path

import pytest
from vistir.contextmanagers import temp_environ

from pdm.cli import actions
from pdm.models.requirements import parse_requirement
from pdm.utils import get_python_version
from pdm.utils import get_python_version, temp_environ


def test_help_option(invoke):
Expand Down
2 changes: 1 addition & 1 deletion tests/test_project.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
from pathlib import Path

import pytest
from vistir import temp_environ

from pdm.project import Project
from pdm.utils import temp_environ


def test_project_python_with_pyenv_support(project, mocker):
Expand Down

0 comments on commit b5dfb6e

Please sign in to comment.