Merge branch 'purge-rfc3339-timestamp' of github.com:pypa/pipenv into purge-rfc3339-timestamp

Signed-off-by: Dan Ryan <dan@danryan.co>
This commit is contained in:
Dan Ryan
2018-04-16 19:38:12 -04:00
20 changed files with 518 additions and 7343 deletions
+1
View File
@@ -13,6 +13,7 @@ pytest-tap = "*"
flaky = "*"
stdeb = {version="*", markers="sys_platform == 'linux'"}
white = {version="*", markers="python_version >= '3.6'"}
pytz = "*"
[packages]
Generated
+2 -2
View File
@@ -1,7 +1,7 @@
{
"_meta": {
"hash": {
"sha256": "5941b36256503b9729e927f3249a366748da5c353b59c1e32ca7fd919b31a4d6"
"sha256": "bc81bb0e64d7ed1eed2627819b4a806d8cba554c1e0398191ba1ba32a216ed2a"
},
"pipfile-spec": 6,
"requires": {},
@@ -459,7 +459,7 @@
"sha256:fe3d218d5b61993d415aa2a9db6dd64c0e4cefb90164ebb197ef3b1d99f531dc"
],
"version": "==4.23.0"
}
},
"twine": {
"hashes": [
"sha256:08eb132bbaec40c6d25b358f546ec1dc96ebd2638a86eea68769d9e67fe2b129",
+19 -18
View File
@@ -15,10 +15,10 @@ import click_completion
import crayons
import dotenv
import delegator
import pexpect
from .vendor import pexpect
import pipfile
import pipdeptree
from pipreqs import pipreqs
from .vendor.pipreqs import pipreqs
from blindspin import spinner
from requests.packages import urllib3
@@ -117,7 +117,7 @@ if PIPENV_NOSPIN:
def which(command, location=None, allow_global=False):
if location is None:
location = project.virtualenv_location
location = project.virtualenv_location or os.environ.get('VIRTUAL_ENV')
if not allow_global:
if os.name == 'nt':
p = find_windows_executable(
@@ -183,7 +183,7 @@ def cleanup_virtualenv(bare=True):
def import_requirements(r=None, dev=False):
import pip9
from pip9.req.req_file import parse_requirements
from .vendor.pip9.req.req_file import parse_requirements
# Parse requirements.txt file with Pip's parser.
# Pip requires a `PipSession` which is a subclass of requests.Session.
@@ -1060,7 +1060,7 @@ def do_lock(
# TODO: be smarter about this.
vcs_deps = convert_deps_to_pip(project.vcs_dev_packages, project, r=False)
pip_freeze = delegator.run(
'{0} freeze'.format(escape_grouped_arguments(which_pip()))
'{0} -m pipenv.vendor.pip9 freeze'.format(escape_grouped_arguments(which('python', allow_global=system)))
).out
if vcs_deps:
for line in pip_freeze.strip().split('\n'):
@@ -1125,7 +1125,7 @@ def do_lock(
# Add refs for VCS installs.
# TODO: be smarter about this.
vcs_deps = convert_deps_to_pip(project.vcs_packages, project, r=False)
pip_freeze = delegator.run('{0} freeze'.format(which_pip())).out
pip_freeze = delegator.run('{0} -m pipenv.vendor.pip9 freeze'.format(which('python', allow_global=system))).out
for dep in vcs_deps:
for line in pip_freeze.strip().split('\n'):
try:
@@ -1228,8 +1228,8 @@ def do_purge(bare=False, downloads=False, allow_global=False, verbose=False):
return
freeze = delegator.run(
'{0} freeze'.format(
escape_grouped_arguments(which_pip(allow_global=allow_global))
'{0} -m pipenv.vendor.pip9 freeze'.format(
escape_grouped_arguments(which('python', allow_global=allow_global))
)
).out
# Remove comments from the output, if any.
@@ -1260,8 +1260,8 @@ def do_purge(bare=False, downloads=False, allow_global=False, verbose=False):
len(actually_installed)
)
)
command = '{0} uninstall {1} -y'.format(
escape_grouped_arguments(which_pip(allow_global=allow_global)),
command = '{0} -m pipenv.vendor.pip9 uninstall {1} -y'.format(
escape_grouped_arguments(which('python', allow_global=allow_global)),
' '.join(actually_installed),
)
if verbose:
@@ -1441,11 +1441,11 @@ def pip_install(
install_reqs += ' --require-hashes'
no_deps = '--no-deps' if no_deps else ''
pre = '--pre' if pre else ''
quoted_pip = which_pip(allow_global=allow_global)
quoted_pip = escape_grouped_arguments(quoted_pip)
quoted_python = which('python', allow_global=allow_global)
quoted_python = escape_grouped_arguments(quoted_python)
upgrade_strategy = '--upgrade --upgrade-strategy=only-if-needed' if selective_upgrade else ''
pip_command = '{0} install {4} {5} {6} {7} {3} {1} {2} --exists-action w'.format(
quoted_pip,
pip_command = '{0} -m pipenv.vendor.pip9 install {4} {5} {6} {7} {3} {1} {2} --exists-action w'.format(
quoted_python,
install_reqs,
' '.join(prepare_pip_source_args([source])),
no_deps,
@@ -1464,10 +1464,11 @@ def pip_install(
return c
def pip_download(package_name):
for source in project.sources:
cmd = '{0} download "{1}" -i {2} -d {3}'.format(
delegator.run(which_pip()),
escape_grouped_arguments(which_pip()),
package_name,
source['url'],
project.download_location,
@@ -2046,8 +2047,8 @@ def do_uninstall(
sys.exit(1)
for package_name in package_names:
click.echo(u'Un-installing {0}'.format(crayons.green(package_name)))
cmd = '"{0}" uninstall {1} -y'.format(
which_pip(allow_global=system), package_name
cmd = '"{0}" -m pipenv.vendor.pip9 uninstall {1} -y'.format(
which('python', allow_global=system), package_name
)
if verbose:
click.echo('$ {0}'.format(cmd))
@@ -2079,7 +2080,7 @@ def do_uninstall(
def do_shell(three=None, python=False, fancy=False, shell_args=None):
from pipenv.patched.pew import pew
from .patched.pew import pew
# Ensure that virtualenv is available.
ensure_project(three=three, python=python, validate=False)
Binary file not shown.
+3 -3
View File
@@ -19,7 +19,7 @@ try:
except ImportError:
import pathlib2 as pathlib
from pip9 import ConfigOptionParser
from .vendor.pip9 import ConfigOptionParser
from .cmdparse import Script
from .utils import (
mkdir_p,
@@ -218,7 +218,7 @@ class Project(object):
@classmethod
def _get_virtualenv_location(cls, name):
from pipenv.patched.pew.pew import get_workon_home
from .patched.pew.pew import get_workon_home
venv = get_workon_home() / name
if not venv.exists():
return ''
@@ -262,7 +262,7 @@ class Project(object):
return clean_name, encoded_hash
# Check for different capitalization of the same project.
from pipenv.patched.pew.pew import lsenvs
from .patched.pew.pew import lsenvs
for env in lsenvs():
try:
env_name, hash_ = env.rsplit('-', 1)
+17 -17
View File
@@ -20,7 +20,7 @@ try:
from weakref import finalize
except ImportError:
try:
from backports.weakref import finalize
from .vendor.backports.weakref import finalize
except ImportError:
class finalize(object):
def __init__(self, *args, **kwargs):
@@ -40,20 +40,20 @@ try:
from pathlib import Path
except ImportError:
try:
from pathlib2 import Path
from .vendor.pathlib2 import Path
except ImportError:
pass
from distutils.spawn import find_executable
from contextlib import contextmanager
from pipenv.patched.piptools.resolver import Resolver
from pipenv.patched.piptools.repositories.pypi import PyPIRepository
from pipenv.patched.piptools.scripts.compile import get_pip_command
from pipenv.patched.piptools import logging as piptools_logging
from pipenv.patched.piptools.exceptions import NoCandidateFound
from pip9.download import is_archive_file
from pip9.exceptions import DistributionNotFound
from pip9.index import Link
from pip9._vendor.requests.exceptions import HTTPError, ConnectionError
from .patched.piptools.resolver import Resolver
from .patched.piptools.repositories.pypi import PyPIRepository
from .patched.piptools.scripts.compile import get_pip_command
from .patched.piptools import logging as piptools_logging
from .patched.piptools.exceptions import NoCandidateFound
from .vendor.pip9.download import is_archive_file
from .vendor.pip9.exceptions import DistributionNotFound
from .vendor.pip9.index import Link
from .vendor.pip9._vendor.requests.exceptions import HTTPError, ConnectionError
from .pep508checker import lookup
from .environments import PIPENV_MAX_ROUNDS, PIPENV_CACHE_DIR
@@ -72,8 +72,8 @@ requests = requests.Session()
def get_requirement(dep):
from pip9.req.req_install import _strip_extras, Wheel
import requirements
from .vendor.pip9.req.req_install import _strip_extras, Wheel
from .vendor import requirements
"""Pre-clean requirement strings passed to the requirements parser.
Ensures that we can accept both local and relative paths, file and VCS URIs,
@@ -789,7 +789,7 @@ def is_editable(pipfile_entry):
def is_vcs(pipfile_entry):
from pipenv.vendor import requirements
from .vendor import requirements
"""Determine if dictionary entry from Pipfile is for a vcs dependency."""
if hasattr(pipfile_entry, 'keys'):
@@ -807,8 +807,8 @@ def is_vcs(pipfile_entry):
def is_installable_file(path):
"""Determine if a path can potentially be installed"""
from pip9.utils import is_installable_dir
from pip9.utils.packaging import specifiers
from .vendor.pip9.utils import is_installable_dir
from .vendor.pip9.utils.packaging import specifiers
if hasattr(path, 'keys') and any(
key for key in path.keys() if key in ['file', 'path']
@@ -859,7 +859,7 @@ def is_file(package):
def pep440_version(version):
"""Normalize version to PEP 440 standards"""
from pip9.index import parse_version
from .vendor.pip9.index import parse_version
# Use pip built-in version parser.
return str(parse_version(version))
-69
View File
@@ -1,69 +0,0 @@
from Levenshtein import *
from warnings import warn
class StringMatcher:
"""A SequenceMatcher-like class built on the top of Levenshtein"""
def _reset_cache(self):
self._ratio = self._distance = None
self._opcodes = self._editops = self._matching_blocks = None
def __init__(self, isjunk=None, seq1='', seq2=''):
if isjunk:
warn("isjunk not NOT implemented, it will be ignored")
self._str1, self._str2 = seq1, seq2
self._reset_cache()
def set_seqs(self, seq1, seq2):
self._str1, self._str2 = seq1, seq2
self._reset_cache()
def set_seq1(self, seq1):
self._str1 = seq1
self._reset_cache()
def set_seq2(self, seq2):
self._str2 = seq2
self._reset_cache()
def get_opcodes(self):
if not self._opcodes:
if self._editops:
self._opcodes = opcodes(self._editops, self._str1, self._str2)
else:
self._opcodes = opcodes(self._str1, self._str2)
return self._opcodes
def get_editops(self):
if not self._editops:
if self._opcodes:
self._editops = editops(self._opcodes, self._str1, self._str2)
else:
self._editops = editops(self._str1, self._str2)
return self._editops
def get_matching_blocks(self):
if not self._matching_blocks:
self._matching_blocks = matching_blocks(self.get_opcodes(),
self._str1, self._str2)
return self._matching_blocks
def ratio(self):
if not self._ratio:
self._ratio = ratio(self._str1, self._str2)
return self._ratio
def quick_ratio(self):
# This is usually quick enough :o)
if not self._ratio:
self._ratio = ratio(self._str1, self._str2)
return self._ratio
def real_quick_ratio(self):
len1, len2 = len(self._str1), len(self._str2)
return 2.0 * min(len1, len2) / (len1 + len2)
def distance(self):
if not self._distance:
self._distance = distance(self._str1, self._str2)
return self._distance
-4
View File
@@ -1,4 +0,0 @@
from Levenshtein import _levenshtein
from Levenshtein._levenshtein import *
__doc__ = _levenshtein.__doc__
File diff suppressed because it is too large Load Diff
-394
View File
@@ -1,394 +0,0 @@
/* @(#) $Id: Levenshtein.h,v 1.22 2005/01/13 20:02:56 yeti Exp $ */
#ifndef LEVENSHTEIN_H
#define LEVENSHTEIN_H
#ifndef size_t
# include <stdlib.h>
#endif
/* A bit dirty. */
#ifndef _LEV_STATIC_PY
# define _LEV_STATIC_PY /* */
#endif
/* In C, this is just wchar_t and unsigned char, in Python, lev_wchar can
* be anything. If you really want to cheat, define wchar_t to any integer
* type you like before including Levenshtein.h and recompile it. */
#ifndef lev_wchar
# ifndef wchar_t
# include <wchar.h>
# endif
# define lev_wchar wchar_t
#endif
typedef unsigned char lev_byte;
/* Edit opration type
* DON'T CHANGE! used ad arrays indices and the bits are occasionally used
* as flags */
typedef enum {
LEV_EDIT_KEEP = 0,
LEV_EDIT_REPLACE = 1,
LEV_EDIT_INSERT = 2,
LEV_EDIT_DELETE = 3,
LEV_EDIT_LAST /* sometimes returned when an error occurs */
} LevEditType;
/* Error codes returned by editop check functions */
typedef enum {
LEV_EDIT_ERR_OK = 0,
LEV_EDIT_ERR_TYPE, /* nonexistent edit type */
LEV_EDIT_ERR_OUT, /* edit out of string bounds */
LEV_EDIT_ERR_ORDER, /* ops are not ordered */
LEV_EDIT_ERR_BLOCK, /* incosistent block boundaries (block ops) */
LEV_EDIT_ERR_SPAN, /* sequence is not a full transformation (block ops) */
LEV_EDIT_ERR_LAST
} LevEditOpError;
/* string averaging method (UNUSED yet) */
typedef enum {
LEV_AVG_HEAD = 0, /* take operations from the head */
LEV_AVG_TAIL, /* take operations from the tail */
LEV_AVG_SPREAD, /* take a equidistantly distributed subset */
LEV_AVG_BLOCK, /* take a random continuous block */
LEV_AVG_RANDOM, /* take a random subset */
LEV_AVG_LAST
} LevAveragingType;
/* Edit operation (atomic).
* This is the `native' atomic edit operation. It differs from the difflib
* one's because it represents a change of one character, not a block. And
* we usually don't care about LEV_EDIT_KEEP, though the functions can handle
* them. The positions are interpreted as at the left edge of a character.
*/
typedef struct {
LevEditType type; /* editing operation type */
size_t spos; /* source block position */
size_t dpos; /* destination position */
} LevEditOp;
/* Edit operation (difflib-compatible).
* This is not `native', but conversion functions exist. These fields exactly
* correspond to the codeops() tuples fields (and this method is also the
* source of the silly OpCode name). Sequences must span over complete
* strings, subsequences are simply edit sequences with more (or larger)
* LEV_EDIT_KEEP blocks.
*/
typedef struct {
LevEditType type; /* editing operation type */
size_t sbeg, send; /* source block begin, end */
size_t dbeg, dend; /* destination block begin, end */
} LevOpCode;
/* Matching block (difflib-compatible). */
typedef struct {
size_t spos;
size_t dpos;
size_t len;
} LevMatchingBlock;
_LEV_STATIC_PY
size_t
lev_edit_distance(size_t len1,
const lev_byte *string1,
size_t len2,
const lev_byte *string2,
int xcost);
_LEV_STATIC_PY
size_t
lev_u_edit_distance(size_t len1,
const lev_wchar *string1,
size_t len2,
const lev_wchar *string2,
int xcost);
_LEV_STATIC_PY
size_t
lev_hamming_distance(size_t len,
const lev_byte *string1,
const lev_byte *string2);
_LEV_STATIC_PY
size_t
lev_u_hamming_distance(size_t len,
const lev_wchar *string1,
const lev_wchar *string2);
_LEV_STATIC_PY
double
lev_jaro_ratio(size_t len1,
const lev_byte *string1,
size_t len2,
const lev_byte *string2);
_LEV_STATIC_PY
double
lev_u_jaro_ratio(size_t len1,
const lev_wchar *string1,
size_t len2,
const lev_wchar *string2);
_LEV_STATIC_PY
double
lev_jaro_winkler_ratio(size_t len1, const lev_byte *string1,
size_t len2, const lev_byte *string2,
double pfweight);
_LEV_STATIC_PY
double
lev_u_jaro_winkler_ratio(size_t len1, const lev_wchar *string1,
size_t len2, const lev_wchar *string2,
double pfweight);
_LEV_STATIC_PY
lev_byte*
lev_greedy_median(size_t n,
const size_t *lengths,
const lev_byte *strings[],
const double *weights,
size_t *medlength);
_LEV_STATIC_PY
lev_wchar*
lev_u_greedy_median(size_t n,
const size_t *lengths,
const lev_wchar *strings[],
const double *weights,
size_t *medlength);
_LEV_STATIC_PY
lev_byte*
lev_median_improve(size_t len, const lev_byte *s,
size_t n, const size_t *lengths,
const lev_byte *strings[],
const double *weights,
size_t *medlength);
_LEV_STATIC_PY
lev_wchar*
lev_u_median_improve(size_t len, const lev_wchar *s,
size_t n, const size_t *lengths,
const lev_wchar *strings[],
const double *weights,
size_t *medlength);
_LEV_STATIC_PY
lev_byte*
lev_quick_median(size_t n,
const size_t *lengths,
const lev_byte *strings[],
const double *weights,
size_t *medlength);
_LEV_STATIC_PY
lev_wchar*
lev_u_quick_median(size_t n,
const size_t *lengths,
const lev_wchar *strings[],
const double *weights,
size_t *medlength);
_LEV_STATIC_PY
lev_byte*
lev_set_median(size_t n,
const size_t *lengths,
const lev_byte *strings[],
const double *weights,
size_t *medlength);
_LEV_STATIC_PY
size_t
lev_set_median_index(size_t n, const size_t *lengths,
const lev_byte *strings[],
const double *weights);
_LEV_STATIC_PY
lev_wchar*
lev_u_set_median(size_t n,
const size_t *lengths,
const lev_wchar *strings[],
const double *weights,
size_t *medlength);
_LEV_STATIC_PY
size_t
lev_u_set_median_index(size_t n, const size_t *lengths,
const lev_wchar *strings[],
const double *weights);
_LEV_STATIC_PY
double
lev_edit_seq_distance(size_t n1,
const size_t *lengths1,
const lev_byte *strings1[],
size_t n2,
const size_t *lengths2,
const lev_byte *strings2[]);
_LEV_STATIC_PY
double
lev_u_edit_seq_distance(size_t n1,
const size_t *lengths1,
const lev_wchar *strings1[],
size_t n2,
const size_t *lengths2,
const lev_wchar *strings2[]);
_LEV_STATIC_PY
double
lev_set_distance(size_t n1,
const size_t *lengths1,
const lev_byte *strings1[],
size_t n2,
const size_t *lengths2,
const lev_byte *strings2[]);
_LEV_STATIC_PY
double
lev_u_set_distance(size_t n1,
const size_t *lengths1,
const lev_wchar *strings1[],
size_t n2,
const size_t *lengths2,
const lev_wchar *strings2[]);
_LEV_STATIC_PY
int
lev_editops_check_errors(size_t len1,
size_t len2,
size_t n,
const LevEditOp *ops);
_LEV_STATIC_PY
int
lev_opcodes_check_errors(size_t len1,
size_t len2,
size_t nb,
const LevOpCode *bops);
_LEV_STATIC_PY
void
lev_editops_invert(size_t n,
LevEditOp *ops);
_LEV_STATIC_PY
void
lev_opcodes_invert(size_t nb,
LevOpCode *bops);
_LEV_STATIC_PY
LevMatchingBlock*
lev_editops_matching_blocks(size_t len1,
size_t len2,
size_t n,
const LevEditOp *ops,
size_t *nmblocks);
_LEV_STATIC_PY
LevMatchingBlock*
lev_opcodes_matching_blocks(size_t len1,
size_t len2,
size_t nb,
const LevOpCode *bops,
size_t *nmblocks);
_LEV_STATIC_PY
lev_byte*
lev_editops_apply(size_t len1,
const lev_byte* string1,
size_t len2,
const lev_byte* string2,
size_t n,
const LevEditOp *ops,
size_t *len);
_LEV_STATIC_PY
lev_wchar*
lev_u_editops_apply(size_t len1,
const lev_wchar* string1,
size_t len2,
const lev_wchar* string2,
size_t n,
const LevEditOp *ops,
size_t *len);
_LEV_STATIC_PY
lev_byte*
lev_opcodes_apply(size_t len1,
const lev_byte* string1,
size_t len2,
const lev_byte* string2,
size_t nb,
const LevOpCode *bops,
size_t *len);
_LEV_STATIC_PY
lev_wchar*
lev_u_opcodes_apply(size_t len1,
const lev_wchar* string1,
size_t len2,
const lev_wchar* string2,
size_t nb,
const LevOpCode *bops,
size_t *len);
_LEV_STATIC_PY
LevEditOp*
lev_editops_find(size_t len1,
const lev_byte *string1,
size_t len2,
const lev_byte *string2,
size_t *n);
_LEV_STATIC_PY
LevEditOp*
lev_u_editops_find(size_t len1,
const lev_wchar *string1,
size_t len2,
const lev_wchar *string2,
size_t *n);
_LEV_STATIC_PY
LevEditOp*
lev_opcodes_to_editops(size_t nb,
const LevOpCode *bops,
size_t *n,
int keepkeep);
_LEV_STATIC_PY
LevOpCode*
lev_editops_to_opcodes(size_t n,
const LevEditOp *ops,
size_t *nb,
size_t len1,
size_t len2);
_LEV_STATIC_PY
size_t
lev_editops_total_cost(size_t n,
const LevEditOp *ops);
_LEV_STATIC_PY
size_t
lev_opcodes_total_cost(size_t nb,
const LevOpCode *bops);
_LEV_STATIC_PY
LevEditOp*
lev_editops_normalize(size_t n,
const LevEditOp *ops,
size_t *nnorm);
_LEV_STATIC_PY LevEditOp*
lev_editops_subtract(size_t n,
const LevEditOp *ops,
size_t ns,
const LevEditOp *sub,
size_t *nrem);
/* UNUSED yet */
_LEV_STATIC_PY
void
lev_init_rng(unsigned long int seed);
#endif /* not LEVENSHTEIN_H */
+14
View File
@@ -0,0 +1,14 @@
# Taken from pip: https://github.com/pypa/pip/blob/95bcf8c5f6394298035a7332c441868f3b0169f4/src/pip/_vendor/Makefile
all: clean vendor
clean:
@# Delete vendored items
find . -maxdepth 1 -mindepth 1 -type d -exec rm -rf {} \;
vendor:
@# Install vendored libraries
pip install -t . -r vendor.txt
@# Cleanup .egg-info directories
rm -rf *.egg-info
rm -rf *.dist-info
+30
View File
@@ -0,0 +1,30 @@
# appdirs==1.4.4
backports.shutil_get_terminal_size==1.0.0
backports.weakref==1.0.post1
blindspin==2.0.1
click==6.7
click-completion==0.2.1
click-didyoumean==0.0.3
colorama==0.3.9
delegator.py==0.1.0
docopt==0.6.2
python-dotenv==0.8.2
first==2.0.1
iso8601==0.1.12
jinja2==2.9.5
markupsafe==1.0
parse==1.8.0
pathlib2==2.1.0
pexpect==4.2.1
pip==9.0.3
pipdeptree==0.10.1
pipreqs==0.4.8
ptyprocess==0.5.1
pytoml==0.1.14
requests==2.11.1
requirements-parser==0.2.0
six==1.10.0
semver==2.7.8
shutilwhich==1.1.0
toml==0.9.2
yarg==0.1.9
+1
View File
@@ -7,6 +7,7 @@ set -eo pipefail
# Set the PYPI vendor URL for pytest-pypi.
PYPI_VENDOR_DIR="$(pwd)/tests/pypi/"
export PYPI_VENDOR_DIR
export PYTHONIOENCODING="utf-8"
prefix() {
sed "s/^/ $1: /"
+5
View File
@@ -8,14 +8,19 @@ from shutil import rmtree
from setuptools import find_packages, setup, Command
here = os.path.abspath(os.path.dirname(__file__))
with codecs.open(os.path.join(here, 'README.rst'), encoding='utf-8') as f:
long_description = '\n' + f.read()
about = {}
with open(os.path.join(here, "pipenv", "__version__.py")) as f:
exec (f.read(), about)
if sys.argv[-1] == "publish":
os.system("python setup.py sdist bdist_wheel upload")
sys.exit()
required = [
'pip>=9.0.1',
'certifi',
+8
View File
@@ -0,0 +1,8 @@
# -*- coding=utf-8 -*-
# Copyied from pip's vendoring process
# see https://github.com/pypa/pip/blob/95bcf8c5f6394298035a7332c441868f3b0169f4/tasks/__init__.py
import invoke
from . import vendoring
ns = invoke.Collection(vendoring)
+373
View File
@@ -0,0 +1,373 @@
# -*- coding=utf-8 -*-
""""Vendoring script, python 3.5 needed"""
# Taken from pip
# see https://github.com/pypa/pip/blob/95bcf8c5f6394298035a7332c441868f3b0169f4/tasks/vendoring/__init__.py
from pathlib import Path
from pipenv.utils import TemporaryDirectory, mkdir_p
import os
import re
import shutil
import sys
import invoke
TASK_NAME = 'update'
FILE_WHITE_LIST = (
'Makefile',
'vendor.txt',
'__init__.py',
'README.rst',
'LICENSE*',
'appdirs.py',
'*.LICENSE'
)
FLATTEN = (
'click-completion',
'delegator',
'docopt',
'first',
'parse',
'pathlib2',
'pipdeptree',
'semver',
'six',
'toml',
)
def drop_dir(path):
shutil.rmtree(str(path))
def remove_all(paths):
for path in paths:
if path.is_dir():
drop_dir(path)
else:
path.unlink()
def log(msg):
print('[vendoring.%s] %s' % (TASK_NAME, msg))
def _get_vendor_dir(ctx):
git_root = ctx.run('git rev-parse --show-toplevel', hide=True).stdout
return Path(git_root.strip()) / 'pipenv' / 'vendor'
def _get_patched_dir(ctx):
git_root = ctx.run('git rev-parse --show-toplevel', hide=True).stdout
return Path(git_root.strip()) / 'pipenv' / 'patched'
def clean_vendor(ctx, vendor_dir):
# Old _vendor cleanup
remove_all(vendor_dir.glob('*.pyc'))
log('Cleaning %s' % vendor_dir)
for item in vendor_dir.iterdir():
if item.is_dir():
shutil.rmtree(str(item))
elif item.name not in FILE_WHITE_LIST:
item.unlink()
else:
log('Skipping %s' % item)
def detect_vendored_libs(vendor_dir):
retval = []
for item in vendor_dir.iterdir():
if item.is_dir():
retval.append(item.name)
elif item.name.endswith(".pyi"):
continue
elif item.name not in FILE_WHITE_LIST:
retval.append(item.name[:-3])
return retval
def rewrite_imports(package_dir, vendored_libs):
for item in package_dir.iterdir():
if item.is_dir():
rewrite_imports(item, vendored_libs)
elif item.name.endswith('.py'):
rewrite_file_imports(item, vendored_libs)
def rewrite_file_imports(item, vendored_libs):
"""Rewrite 'import xxx' and 'from xxx import' for vendored_libs"""
text = item.read_text(encoding='utf-8')
for lib in vendored_libs:
text = re.sub(
r'(\n\s*)import %s(\n\s*)' % lib,
r'\1from .vendor import %s\2' % lib,
text,
)
text = re.sub(
r'(\n\s*)from %s' % lib,
r'\1from .vendor.%s' % lib,
text,
)
item.write_text(text, encoding='utf-8')
def apply_patch(ctx, patch_file_path):
log('Applying patch %s' % patch_file_path.name)
ctx.run('git apply --verbose %s' % patch_file_path)
@invoke.task
def update_safety(ctx):
ignore_subdeps = ['pip', 'pip-egg-info', 'bin']
ignore_files = ['pip-delete-this-directory.txt', 'PKG-INFO']
vendor_dir = _get_patched_dir(ctx)
log('Using vendor dir: %s' % vendor_dir)
log('Downloading safety package files...')
build_dir = vendor_dir / 'build'
download_dir = TemporaryDirectory(prefix='pipenv-', suffix='-safety')
if build_dir.exists() and build_dir.is_dir():
drop_dir(build_dir)
ctx.run(
'pip download -b {0} --no-binary=:all: --no-clean -d {1} safety pyyaml'.format(
str(build_dir), str(download_dir.name),
)
)
safety_dir = build_dir / 'safety'
yaml_build_dir = build_dir / 'pyyaml'
main_file = safety_dir / '__main__.py'
main_content = """
from safety.cli import cli
# Disable insecure warnings.
import requests
from requests.packages.urllib3.exceptions import InsecureRequestWarning
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
cli(prog_name="safety")
""".strip()
with open(str(main_file), 'w') as fh:
fh.write(main_content)
with ctx.cd(str(safety_dir)):
ctx.run('pip install --no-compile --no-binary=:all: -t . .')
safety_dir = safety_dir.absolute()
yaml_dir = safety_dir / 'yaml'
if yaml_dir.exists():
version_choices = ['2', '3']
version_choices.remove(str(sys.version_info[0]))
mkdir_p(str(yaml_dir / 'yaml{0}'.format(sys.version_info[0])))
for fn in yaml_dir.glob('*.py'):
fn.rename(str(fn.parent.joinpath('yaml{0}'.format(sys.version_info[0]), fn.name)))
if version_choices[0] == '2':
lib = yaml_build_dir / 'lib' / 'yaml'
else:
lib = yaml_build_dir / 'lib3' / 'yaml'
shutil.copytree(str(lib.absolute()), str(yaml_dir / 'yaml{0}'.format(version_choices[0])))
yaml_init = yaml_dir / '__init__.py'
yaml_init.write_text("""
import sys
if sys.version_info[0] == 3:
from .yaml3 import *
else:
from .yaml2 import *
""".strip())
requests_dir = safety_dir / 'requests'
cacert = vendor_dir / 'requests' / 'cacert.pem'
if not cacert.exists():
from pipenv.vendor import requests
cacert = Path(requests.certs.where())
target_cert = requests_dir / 'cacert.pem'
target_cert.write_bytes(cacert.read_bytes())
ctx.run("sed -i 's/r = requests.get(url=url, timeout=REQUEST_TIMEOUT, headers=headers)/r = requests.get(url=url, timeout=REQUEST_TIMEOUT, headers=headers, verify=False)/g' {0}".format(str(safety_dir / 'safety' / 'safety.py')))
for egg in safety_dir.glob('*.egg-info'):
drop_dir(egg.absolute())
for dep in ignore_subdeps:
dep_dir = safety_dir / dep
if dep_dir.exists():
drop_dir(dep_dir)
for dep in ignore_files:
fn = safety_dir / dep
if fn.exists():
fn.unlink()
zip_name = '{0}/safety'.format(str(vendor_dir))
shutil.make_archive(zip_name, format='zip', root_dir=str(safety_dir), base_dir='./')
drop_dir(build_dir)
download_dir.cleanup()
@invoke.task
def get_licenses(ctx):
vendor_dir = _get_vendor_dir(ctx)
log('Using vendor dir: %s' % vendor_dir)
log('Downloading LICENSE files...')
build_dir = vendor_dir / 'build'
download_dir = TemporaryDirectory(prefix='pipenv-', suffix='-licenses')
if build_dir.exists() and build_dir.is_dir():
drop_dir(build_dir)
ctx.run(
'pip download -b {0} --no-binary=:all: --no-clean --no-deps -r {1}/vendor.txt -d {2}'.format(
str(build_dir), str(vendor_dir), str(download_dir.name),
)
)
for p in build_dir.glob('*/*LICENSE*'):
parent = p.parent
matches = [flat for flat in FLATTEN if parent.joinpath(flat).exists() or parent.name == flat]
egg_info_dir = [e for e in parent.glob('*.egg-info')]
if any(matches):
from pipenv.utils import pep423_name
pkg = pep423_name(matches[0]).lower()
pkg_name = pkg if parent.joinpath(pkg).exists() else parent.name.lower()
target_file = '{0}.LICENSE'.format(pkg_name)
target_file = vendor_dir / target_file
elif egg_info_dir:
egg_info_dir = egg_info_dir[0]
pkg_name = egg_info_dir.stem.lower()
target_file = vendor_dir / pkg_name / p.name.lower()
if '.' in pkg_name:
target_file = vendor_dir.joinpath(*pkg_name.split('.')) / p.name
else:
target_dir = vendor_dir / parent.name
if '.' in parent.name:
target_dir = vendor_dir.joinpath(*parent.name.split('.'))
target_file = target_dir / p.name.lower()
mkdir_p(str(target_file.parent.absolute()))
shutil.copyfile(str(p.absolute()), str(target_file.absolute()))
drop_dir(build_dir)
download_dir.cleanup()
def get_patched(ctx):
log('Reinstalling patched libraries')
patched_dir = _get_patched_dir(ctx)
ctx.run(
'pip install -t {0} -r {0}/patched.txt --no-compile --no-deps'.format(
str(patched_dir),
)
)
remove_all(patched_dir.glob('*.dist_info'))
remove_all(patched_dir.glob('*.egg-info'))
# Cleanup setuptools unneeded parts
(patched_dir / 'easy_install.py').unlink()
drop_dir(patched_dir / 'setuptools')
drop_dir(patched_dir / 'pkg_resources' / '_vendor')
drop_dir(patched_dir / 'pkg_resources' / 'extern')
# Drop interpreter and OS specific msgpack libs.
# Pip will rely on the python-only fallback instead.
remove_all(patched_dir.glob('msgpack/*.so'))
drop_dir(patched_dir / 'bin')
drop_dir(patched_dir / 'tests')
# Detect the vendored packages/modules
vendored_libs = detect_vendored_libs(patched_dir)
log("Detected vendored libraries: %s" % ", ".join(vendored_libs))
# Global import rewrites
log("Rewriting all imports related to vendored libs")
for item in patched_dir.iterdir():
if item.is_dir():
rewrite_imports(item, vendored_libs)
elif item.name not in FILE_WHITE_LIST:
rewrite_file_imports(item, vendored_libs)
# Special cases: apply stored patches
log("Apply patches")
patch_dir = Path(__file__).parent / 'patches'
for patch in patch_dir.glob('*.patch'):
apply_patch(ctx, patch)
def vendor(ctx, vendor_dir):
log('Reinstalling vendored libraries')
# We use --no-deps because we want to ensure that all of our dependencies
# are added to vendor.txt, this includes all dependencies recursively up
# the chain.
ctx.run(
'pip install -t {0} -r {0}/vendor.txt --no-compile --no-deps'.format(
str(vendor_dir),
)
)
remove_all(vendor_dir.glob('*.dist-info'))
remove_all(vendor_dir.glob('*.egg-info'))
# Cleanup setuptools unneeded parts
(vendor_dir / 'easy_install.py').unlink()
drop_dir(vendor_dir / 'setuptools')
drop_dir(vendor_dir / 'pkg_resources' / '_vendor')
drop_dir(vendor_dir / 'pkg_resources' / 'extern')
# Drop interpreter and OS specific msgpack libs.
# Pip will rely on the python-only fallback instead.
remove_all(vendor_dir.glob('msgpack/*.so'))
drop_dir(vendor_dir / 'bin')
drop_dir(vendor_dir / 'tests')
# Detect the vendored packages/modules
vendored_libs = detect_vendored_libs(vendor_dir)
log("Detected vendored libraries: %s" % ", ".join(vendored_libs))
# Global import rewrites
log("Rewriting all imports related to vendored libs")
for item in vendor_dir.iterdir():
if item.is_dir():
rewrite_imports(item, vendored_libs)
elif item.name not in FILE_WHITE_LIST:
rewrite_file_imports(item, vendored_libs)
@invoke.task
def rewrite_all_imports(ctx):
vendor_dir = _get_vendor_dir(ctx)
log('Using vendor dir: %s' % vendor_dir)
vendored_libs = detect_vendored_libs(vendor_dir)
log("Detected vendored libraries: %s" % ", ".join(vendored_libs))
log("Rewriting all imports related to vendored libs")
for item in vendor_dir.iterdir():
if item.is_dir():
rewrite_imports(item, vendored_libs)
elif item.name not in FILE_WHITE_LIST:
rewrite_file_imports(item, vendored_libs)
@invoke.task
def update_stubs(ctx):
vendor_dir = _get_vendor_dir(ctx)
vendored_libs = detect_vendored_libs(vendor_dir)
print("[vendoring.update_stubs] Add mypy stubs")
extra_stubs_needed = {
# Some projects need stubs other than a simple <name>.pyi
"six": ["six.__init__", "six.moves"],
# Some projects should not have stubs coz they're single file modules
"appdirs": [],
}
for lib in vendored_libs:
if lib not in extra_stubs_needed:
(vendor_dir / (lib + ".pyi")).write_text("from %s import *" % lib)
continue
for selector in extra_stubs_needed[lib]:
fname = selector.replace(".", os.sep) + ".pyi"
if selector.endswith(".__init__"):
selector = selector[:-9]
f_path = vendor_dir / fname
if not f_path.parent.exists():
f_path.parent.mkdir()
f_path.write_text("from %s import *" % selector)
@invoke.task(name=TASK_NAME, post=[update_stubs])
def main(ctx):
vendor_dir = _get_vendor_dir(ctx)
log('Using vendor dir: %s' % vendor_dir)
clean_vendor(ctx, vendor_dir)
vendor(ctx, vendor_dir)
get_licenses(ctx)
update_safety(ctx)
log('Revendoring complete')
View File
View File
View File
+45 -3
View File
@@ -1,14 +1,21 @@
# Make sure we use the patched packages.
# We need to import the patched packages directly from sys.path, so the
# identity checks can pass.
import pipenv # noqa
import datetime
import os
from prettytoml import lexer
import pytest
import pytz
from pipfile.api import PipfileParser
from prettytoml import lexer, tokens
from prettytoml.elements.atomic import AtomicElement
from prettytoml.elements.metadata import (
WhitespaceElement, PunctuationElement, CommentElement
)
from prettytoml.elements.table import TableElement
from pipenv.patched.pipfile.api import PipfileParser
from prettytoml.tokens.py2toml import create_primitive_token
def test_table():
@@ -62,3 +69,38 @@ class TestPipfileParser:
assert parsed_dict["list"][1] == {}
assert parsed_dict["bool"] is True
assert parsed_dict["none"] is None
@pytest.mark.parametrize('dt, content', [
( # Date.
datetime.date(1992, 8, 19),
'1992-08-19',
),
( # Naive time.
datetime.time(15, 10),
'15:10:00',
),
( # Aware time in UTC.
datetime.time(15, 10, tzinfo=pytz.UTC),
'15:10:00Z',
),
( # Aware local time.
datetime.time(15, 10, tzinfo=pytz.FixedOffset(8 * 60)),
'15:10:00+08:00',
),
( # Naive datetime.
datetime.datetime(1992, 8, 19, 15, 10),
'1992-08-19T15:10:00',
),
( # Aware datetime in UTC.
datetime.datetime(1992, 8, 19, 15, 10, tzinfo=pytz.UTC),
'1992-08-19T15:10:00Z',
),
( # Aware local datetime.
datetime.datetime(1992, 8, 19, 15, 10, tzinfo=pytz.FixedOffset(8 * 60)),
'1992-08-19T15:10:00+08:00',
),
])
def test_token_date(dt, content):
token = create_primitive_token(dt)
assert token == tokens.Token(tokens.TYPE_DATE, content)