Add updated version of requirementslib

Signed-off-by: Dan Ryan <dan@danryan.co>
This commit is contained in:
Dan Ryan
2018-11-22 00:57:48 -05:00
parent 1277c09c37
commit b3098d24f8
3 changed files with 118 additions and 23 deletions
+1 -1
View File
@@ -1,5 +1,5 @@
# -*- coding=utf-8 -*-
__version__ = '1.3.1'
__version__ = '1.3.2'
import logging
import warnings
+17
View File
@@ -0,0 +1,17 @@
# -*- coding=utf-8 -*-
from __future__ import print_function, absolute_import
import os
from appdirs import user_cache_dir
def is_type_checking():
try:
from typing import TYPE_CHECKING
except ImportError:
return False
return TYPE_CHECKING
REQUIREMENTSLIB_CACHE_DIR = os.getenv("REQUIREMENTSLIB_CACHE_DIR", user_cache_dir("pipenv"))
MYPY_RUNNING = os.environ.get("MYPY_RUNNING", is_type_checking())
+100 -22
View File
@@ -1,22 +1,79 @@
# -*- coding: utf-8 -*-
from __future__ import absolute_import, unicode_literals, print_function
from __future__ import absolute_import, print_function, unicode_literals
import attr
import copy
import os
import sys
import attr
import tomlkit
from vistir.compat import Path, FileNotFoundError
from .requirements import Requirement
from .project import ProjectFile
from .utils import optional_instance_of
from ..exceptions import RequirementError
from ..utils import is_vcs, is_editable, merge_items
import plette.models.base
import plette.pipfiles
from vistir.compat import FileNotFoundError, Path
from ..exceptions import RequirementError
from ..utils import is_editable, is_vcs, merge_items
from .project import ProjectFile
from .requirements import Requirement
from .utils import optional_instance_of
from ..environment import MYPY_RUNNING
if MYPY_RUNNING:
from typing import Union, Any, Dict, Iterable, Sequence, Mapping, List, NoReturn
package_type = Dict[str, Dict[str, Union[List[str], str]]]
source_type = Dict[str, Union[str, bool]]
sources_type = Iterable[source_type]
meta_type = Dict[str, Union[int, Dict[str, str], sources_type]]
lockfile_type = Dict[str, Union[package_type, meta_type]]
# Let's start by patching plette to make sure we can validate data without being broken
try:
import cerberus
except ImportError:
cerberus = None
VALIDATORS = plette.models.base.VALIDATORS
def patch_plette():
# type: () -> NoReturn
names = ["plette.models.base", plette.models.base.__name__]
names = [name for name in names if name in sys.modules]
for name in names:
if name in sys.modules:
module = sys.modules[name]
else:
module = plette.models.base
original_fn = getattr(module, "validate")
for key in ["__qualname__", "__name__", "__module__"]:
original_val = getattr(original_fn, key, None)
if original_val is not None:
setattr(validate, key, original_val)
setattr(module, "validate", validate)
sys.modules[name] = module
def patch_plette():
# type: () -> NoReturn
names = ["plette.models.base", plette.models.base.__name__]
names = [name for name in names if name in sys.modules]
for name in names:
if name in sys.modules:
module = sys.modules[name]
else:
module = plette.models.base
original_fn = getattr(module, "validate")
for key in ["__qualname__", "__name__", "__module__"]:
setattr(validate, key, getattr(original_fn, key))
setattr(module, "validate", validate)
sys.modules[name] = module
patch_plette()
is_pipfile = optional_instance_of(plette.pipfiles.Pipfile)
is_path = optional_instance_of(Path)
@@ -24,8 +81,10 @@ is_projectfile = optional_instance_of(ProjectFile)
def reorder_source_keys(data):
for i, entry in enumerate(data["source"]):
table = tomlkit.table()
# type: ignore
sources = data["source"] # type: sources_type
for i, entry in enumerate(sources):
table = tomlkit.table() # type: Mapping
table["name"] = entry["name"]
table["url"] = entry["url"]
table["verify_ssl"] = entry["verify_ssl"]
@@ -36,6 +95,7 @@ def reorder_source_keys(data):
class PipfileLoader(plette.pipfiles.Pipfile):
@classmethod
def validate(cls, data):
# type: (Dict[str, Any]) -> None
for key, klass in plette.pipfiles.PIPFILE_SECTIONS.items():
if key not in data or key == "source":
continue
@@ -46,6 +106,7 @@ class PipfileLoader(plette.pipfiles.Pipfile):
@classmethod
def load(cls, f, encoding=None):
# type: (Any, str) -> PipfileLoader
content = f.read()
if encoding is not None:
content = content.decode(encoding)
@@ -69,6 +130,7 @@ class PipfileLoader(plette.pipfiles.Pipfile):
return instance
def __getattribute__(self, key):
# type: (str) -> Any
if key == "source":
return self._data[key]
return super(PipfileLoader, self).__getattribute__(key)
@@ -78,7 +140,7 @@ class PipfileLoader(plette.pipfiles.Pipfile):
class Pipfile(object):
path = attr.ib(validator=is_path, type=Path)
projectfile = attr.ib(validator=is_projectfile, type=ProjectFile)
_pipfile = attr.ib(type=plette.pipfiles.Pipfile)
_pipfile = attr.ib(type=PipfileLoader)
_pyproject = attr.ib(default=attr.Factory(tomlkit.document), type=tomlkit.toml_document.TOMLDocument)
build_system = attr.ib(default=attr.Factory(dict), type=dict)
requirements = attr.ib(default=attr.Factory(list), type=list)
@@ -86,22 +148,27 @@ class Pipfile(object):
@path.default
def _get_path(self):
# type: () -> Path
return Path(os.curdir).absolute()
@projectfile.default
def _get_projectfile(self):
# type: () -> ProjectFile
return self.load_projectfile(os.curdir, create=False)
@_pipfile.default
def _get_pipfile(self):
# type: () -> Union[plette.pipfiles.Pipfile, PipfileLoader]
return self.projectfile.model
@property
def pipfile(self):
# type: () -> Union[PipfileLoader, plette.pipfiles.Pipfile]
return self._pipfile
def get_deps(self, dev=False, only=True):
deps = {}
# type: (bool, bool) -> Dict[str, Dict[str, Union[List[str], str]]]
deps = {} # type: Dict[str, Dict[str, Union[List[str], str]]]
if dev:
deps.update(self.pipfile._data["dev-packages"])
if only:
@@ -109,15 +176,18 @@ class Pipfile(object):
return merge_items([deps, self.pipfile._data["packages"]])
def get(self, k):
# type: (str) -> Any
return self.__getitem__(k)
def __contains__(self, k):
# type: (str) -> bool
check_pipfile = k in self.extended_keys or self.pipfile.__contains__(k)
if check_pipfile:
return True
return super(Pipfile, self).__contains__(k)
return False
def __getitem__(self, k, *args, **kwargs):
# type: ignore
retval = None
pipfile = self._pipfile
section = None
@@ -139,6 +209,7 @@ class Pipfile(object):
return retval
def __getattr__(self, k, *args, **kwargs):
# type: ignore
retval = None
pipfile = super(Pipfile, self).__getattribute__("_pipfile")
try:
@@ -151,14 +222,17 @@ class Pipfile(object):
@property
def requires_python(self):
# type: () -> bool
return self._pipfile.requires.requires_python
@property
def allow_prereleases(self):
# type: () -> bool
return self._pipfile.get("pipenv", {}).get("allow_prereleases", False)
@classmethod
def read_projectfile(cls, path):
# type: (str) -> ProjectFile
"""Read the specified project file and provide an interface for writing/updating.
:param str path: Path to the target file.
@@ -174,6 +248,7 @@ class Pipfile(object):
@classmethod
def load_projectfile(cls, path, create=False):
# type: (str, bool) -> ProjectFile
"""Given a path, load or create the necessary pipfile.
:param str path: Path to the project root or pipfile
@@ -198,6 +273,7 @@ class Pipfile(object):
@classmethod
def load(cls, path, create=False):
# type: (str, bool) -> Pipfile
"""Given a path, load or create the necessary pipfile.
:param str path: Path to the project root or pipfile
@@ -226,22 +302,22 @@ class Pipfile(object):
return cls(**creation_args)
def write(self):
# type: () -> None
self.projectfile.model = copy.deepcopy(self._pipfile)
self.projectfile.write()
@property
def dev_packages(self, as_requirements=True):
if as_requirements:
return self.dev_requirements
return self._pipfile.get('dev-packages', {})
def dev_packages(self):
# type: () -> List[Requirement]
return self.dev_requirements
@property
def packages(self, as_requirements=True):
if as_requirements:
return self.requirements
return self._pipfile.get('packages', {})
def packages(self):
# type: () -> List[Requirement]
return self.requirements
def _read_pyproject(self):
# type: () -> None
pyproject = self.path.parent.joinpath("pyproject.toml")
if pyproject.exists():
self._pyproject = tomlkit.load(pyproject)
@@ -256,8 +332,10 @@ class Pipfile(object):
@property
def build_requires(self):
# type: () -> List[str]
return self.build_system.get("requires", [])
@property
def build_backend(self):
# type: () -> str
return self.build_system.get("build-backend", None)