This commit is contained in:
Hamad alghanim
2017-10-17 23:14:54 -07:00
7 changed files with 170 additions and 56 deletions
+11 -11
View File
@@ -1,24 +1,24 @@
FROM python:3.6.2
FROM python:3.6.3
# -- Install Pipenv:
RUN pip install pipenv --upgrade
RUN set -ex && pip install pipenv --upgrade
# -- Install Application into container:
RUN mkdir /app
RUN set -ex && mkdir /app
WORKDIR /app
# -- Adding Pipfiles
ONBUILD COPY Pipfile Pipfile
ONBUILD COPY Pipfile.lock Pipfile.lock
# -- Install dependencies:
ONBUILD RUN set -ex && pipenv install --deploy --system
# --------------------
# - Using This File: -
# --------------------
# FROM kennethreitz/pipenv
# COPY Pipfile Pipfile
# COPY Pipfile.lock Pipfile.lock
# COPY . /app
# -- Install dependencies:
# RUN pipenv install --deploy --system
ENTRYPOINT []
CMD [ "/bin/bash" ]
+1
View File
@@ -1,4 +1,5 @@
include README.rst LICENSE NOTICES HISTORY.txt pipenv/patched/safety.zip
include pipenv/patched/pip/_vendor/requests/cacert.pem
include pipenv/vendor/pipreqs/stdlib
include pipenv/vendor/pipreqs/mapping
include pipenv/pipenv.1
+10
View File
@@ -220,6 +220,16 @@ To upgrade pipenv at any time::
This will install both ``pipenv`` and ``pew`` (one of our dependencies) in an isolated virtualenv, so it doesn't interfere with the rest of your Python installation!
.. _more_proper_installation:
☤ Referentially Transparent Installation of Pipenv
==================================================
Nix provides atomic upgrades and rollbacks, it's reliable and reproducible thanks to keeping all dependencies isolated all the way down to libc.
`Once installed <https://nixos.org/nix/>`_ simply run::
$ nix-env --install --attr pipenv
.. _pragmatic_installation:
+32 -16
View File
@@ -25,19 +25,17 @@ import pipdeptree
import requirements
import semver
import flake8.main.cli
from pipreqs import pipreqs
from blindspin import spinner
from urllib3.exceptions import InsecureRequestWarning
from pip.req.req_file import parse_requirements
from click_didyoumean import DYMCommandCollection
from .project import Project
from .utils import (
convert_deps_from_pip, convert_deps_to_pip, is_required_version,
proper_case, pep423_name, split_vcs, resolve_deps, shellquote, is_vcs,
python_version, suggest_package, find_windows_executable, is_file,
prepare_pip_source_args, is_valid_url, download_file
prepare_pip_source_args, temp_environ, is_valid_url, download_file
)
from .__version__ import __version__
from . import pep508checker, progress
@@ -565,11 +563,15 @@ def ensure_virtualenv(three=None, python=None, site_packages=False):
# If --three, --two, or --python were passed...
elif (python) or (three is not None) or (site_packages is not False):
click.echo(crayons.red('Virtualenv already exists!'), err=True)
click.echo(crayons.normal(u'Removing existing virtualenv…', bold=True), err=True)
USING_DEFAULT_PYTHON = False
# Ensure python is installed before deleting existing virtual env
ensure_python(three=three, python=python)
click.echo(crayons.red('Virtualenv already exists!'), err=True)
click.echo(crayons.normal(u'Removing existing virtualenv…', bold=True), err=True)
# Remove the virtualenv.
cleanup_virtualenv(bare=True)
@@ -2030,29 +2032,43 @@ def do_shell(three=None, python=False, fancy=False, shell_args=None):
# Standard (properly configured shell) mode:
else:
if PIPENV_VENV_IN_PROJECT:
# use .venv as the target virtualenv name
workon_name = '.venv'
else:
workon_name = project.virtualenv_name
cmd = 'pew'
args = ["workon", project.virtualenv_name]
args = ["workon", workon_name]
# Grab current terminal dimensions to replace the hardcoded default
# dimensions of pexpect
terminal_dimensions = get_terminal_size()
try:
c = pexpect.spawn(
cmd,
args,
dimensions=(
terminal_dimensions.lines,
terminal_dimensions.columns
with temp_environ():
if PIPENV_VENV_IN_PROJECT:
os.environ['WORKON_HOME'] = project.project_directory
c = pexpect.spawn(
cmd,
args,
dimensions=(
terminal_dimensions.lines,
terminal_dimensions.columns
)
)
)
# Windows!
except AttributeError:
import subprocess
p = subprocess.Popen([cmd] + list(args), shell=True, universal_newlines=True)
p.communicate()
sys.exit(p.returncode)
# Tell pew to use the project directory as its workon_home
with temp_environ():
if PIPENV_VENV_IN_PROJECT:
os.environ['WORKON_HOME'] = project.project_directory
p = subprocess.Popen([cmd] + list(args), shell=True, universal_newlines=True)
p.communicate()
sys.exit(p.returncode)
# Activate the virtualenv if in compatibility mode.
if compat:
+19 -4
View File
@@ -23,6 +23,7 @@ try:
except ImportError:
from urlparse import urlparse
from contextlib import contextmanager
from piptools.resolver import Resolver
from piptools.repositories.pypi import PyPIRepository
from piptools.scripts.compile import get_pip_command
@@ -341,6 +342,9 @@ def shellquote(s):
"""Prepares a string for the shell (on Windows too!)"""
if s is None:
return None
# Additional escaping for windows paths
if os.name == 'nt':
s = "{}".format(s.replace("\\", "\\\\"))
return '"' + s.replace("'", "'\\''") + '"'
@@ -530,8 +534,8 @@ def convert_deps_from_pip(dep):
extras = {'extras': req.extras}
# File installs.
if (req.uri or (os.path.exists(req.path) if req.path else False) or
os.path.exists(req.name)) and not req.vcs:
if (req.uri or (os.path.isfile(req.path) if req.path else False) or
os.path.isfile(req.name)) and not req.vcs:
# Assign a package name to the file, last 7 of it's sha256 hex digest.
if not req.uri and not req.path:
req.path = os.path.abspath(req.name)
@@ -850,8 +854,7 @@ def get_windows_path(*args):
"""Sanitize a path for windows environments
Accepts an arbitrary list of arguments and makes a clean windows path"""
clean_path = os.path.join(*args)
return os.path.normpath(clean_path)
return os.path.normpath(os.path.join(*args))
def find_windows_executable(bin_path, exe_name):
@@ -915,6 +918,18 @@ def find_requirements(max_depth=3):
raise RuntimeError('No requirements.txt found!')
# Borrowed from pew to avoid importing pew which imports psutil
# See https://github.com/berdario/pew/blob/master/pew/_utils.py#L82
@contextmanager
def temp_environ():
"""Allow the ability to set os.environ temporarily"""
environ = dict(os.environ)
try:
yield
finally:
os.environ.clear()
os.environ.update(environ)
def is_valid_url(url):
"""Checks if a given string is an url"""
pieces = urlparse(url)
+89 -25
View File
@@ -6,6 +6,7 @@ import json
import pytest
from pipenv.cli import activate_virtualenv
from pipenv.utils import temp_environ, get_windows_path
from pipenv.vendor import toml
from pipenv.vendor import delegator
from pipenv.project import Project
@@ -227,6 +228,24 @@ class TestPipenv:
c = p.pipenv('run python -m requests.help')
assert c.return_code > 0
@pytest.mark.files
@pytest.mark.run
@pytest.mark.uninstall
def test_uninstall_all_local_files(self):
file_name = 'tablib-0.12.1.tar.gz'
# Not sure where travis/appveyor run tests from
test_dir = os.path.dirname(os.path.abspath(__file__))
source_path = os.path.abspath(os.path.join(test_dir, 'test_artifacts', file_name))
with PipenvInstance() as p:
shutil.copy(source_path, os.path.join(p.path, file_name))
os.mkdir(os.path.join(p.path, "tablib"))
c = p.pipenv('install {}'.format(file_name))
c = p.pipenv('uninstall --all --verbose')
assert c.return_code == 0
assert 'tablib' in c.out
assert 'tablib' not in p.pipfile['packages']
@pytest.mark.extras
@pytest.mark.install
def test_extras_install(self):
@@ -271,33 +290,32 @@ class TestPipenv:
@pytest.mark.run
@pytest.mark.install
def test_multiprocess_bug_and_install(self):
os.environ['PIPENV_MAX_SUBPROCESS'] = '2'
with temp_environ():
os.environ['PIPENV_MAX_SUBPROCESS'] = '2'
with PipenvInstance() as p:
with open(p.pipfile_path, 'w') as f:
contents = """
with PipenvInstance() as p:
with open(p.pipfile_path, 'w') as f:
contents = """
[packages]
requests = "*"
records = "*"
tpfd = "*"
""".strip()
f.write(contents)
""".strip()
f.write(contents)
c = p.pipenv('install')
assert c.return_code == 0
c = p.pipenv('install')
assert c.return_code == 0
assert 'requests' in p.lockfile['default']
assert 'idna' in p.lockfile['default']
assert 'urllib3' in p.lockfile['default']
assert 'certifi' in p.lockfile['default']
assert 'records' in p.lockfile['default']
assert 'tpfd' in p.lockfile['default']
assert 'parse' in p.lockfile['default']
assert 'requests' in p.lockfile['default']
assert 'idna' in p.lockfile['default']
assert 'urllib3' in p.lockfile['default']
assert 'certifi' in p.lockfile['default']
assert 'records' in p.lockfile['default']
assert 'tpfd' in p.lockfile['default']
assert 'parse' in p.lockfile['default']
c = p.pipenv('run python -c "import requests; import idna; import certifi; import records; import tpfd; import parse;"')
assert c.return_code == 0
del os.environ['PIPENV_MAX_SUBPROCESS']
c = p.pipenv('run python -c "import requests; import idna; import certifi; import records; import tpfd; import parse;"')
assert c.return_code == 0
@pytest.mark.sequential
@pytest.mark.install
@@ -445,14 +463,60 @@ requests = {version = "*"}
@pytest.mark.dotvenv
def test_venv_in_project(self):
os.environ['PIPENV_VENV_IN_PROJECT'] = '1'
with PipenvInstance() as p:
c = p.pipenv('install requests')
assert c.return_code == 0
with temp_environ():
os.environ['PIPENV_VENV_IN_PROJECT'] = '1'
with PipenvInstance() as p:
c = p.pipenv('install requests')
assert c.return_code == 0
assert p.path in p.pipenv('--venv').out
assert p.path in p.pipenv('--venv').out
@pytest.mark.dotvenv
@pytest.mark.install
@pytest.mark.complex
@pytest.mark.shell
@pytest.mark.windows
@pytest.mark.pew
def test_shell_nested_venv_in_project(self):
import subprocess
with temp_environ():
os.environ['PIPENV_VENV_IN_PROJECT'] = '1'
os.environ['PIPENV_IGNORE_VIRTUALENVS'] = '1'
os.environ['PIPENV_SHELL_COMPAT'] = '1'
with PipenvInstance(chdir=True) as p:
# Signal to pew to look in the project directory for the environment
os.environ['WORKON_HOME'] = p.path
project = Project()
c = p.pipenv('install requests')
assert c.return_code == 0
assert 'requests' in p.pipfile['packages']
assert 'requests' in p.lockfile['default']
# Check that .venv now shows in pew's managed list
pew_list = delegator.run('pew ls')
assert '.venv' in pew_list.out
# Check for the venv directory
c = delegator.run('pew dir .venv')
# Compare pew's virtualenv path to what we expect
venv_path = get_windows_path(project.project_directory, '.venv')
# os.path.normpath will normalize slashes
assert venv_path == os.path.normpath(c.out.strip())
# Have pew run 'pip freeze' in the virtualenv
# This is functionally the same as spawning a subshell
# If we can do this we can theoretically amke a subshell
# This test doesn't work on *nix
if os.name == 'nt':
args = ['pew', 'in', '.venv', 'pip', 'freeze']
process = subprocess.Popen(
args,
shell=True,
universal_newlines=True,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE
)
out, _ = process.communicate()
assert any(req.startswith('requests') for req in out.splitlines()) is True
del os.environ['PIPENV_VENV_IN_PROJECT']
@pytest.mark.run
@pytest.mark.dotenv
+8
View File
@@ -1,5 +1,6 @@
# -*- coding: utf-8 -*-
import os
import pytest
from mock import patch, Mock
@@ -165,3 +166,10 @@ class TestUtils:
run_ret.out = version_output
mocked_delegator.return_value = run_ret
assert pipenv.utils.python_version('some/path') == version
@pytest.mark.windows
@pytest.mark.skipif(os.name != 'nt', reason='Windows test only')
def test_windows_shellquote(self):
test_path = 'C:\Program Files\Python36\python.exe'
expected_path = '"C:\\\\Program Files\\\\Python36\\\\python.exe"'
assert pipenv.utils.shellquote(test_path) == expected_path