mirror of
https://github.com/kennethreitz/pipenv.git
synced 2026-06-05 22:50:18 +00:00
Merge branch 'master' of github.com:pypa/pipenv
This commit is contained in:
@@ -1,15 +1,11 @@
|
||||
Be sure to check the existing issues (both open and closed!).
|
||||
|
||||
Describe the issue briefly here.
|
||||
|
||||
Please run `$ python -m pipenv.help`, and paste the results here.
|
||||
|
||||
If you're on MacOS, just run the following:
|
||||
|
||||
$ python -m pipenv.help | pbcopy
|
||||
|
||||
------------
|
||||
|
||||
##### Issue description
|
||||
|
||||
Describe the issue briefly here.
|
||||
|
||||
##### Expected result
|
||||
|
||||
Describe what you expected.
|
||||
@@ -21,3 +17,15 @@ When possible, provide the verbose output (`--verbose`), especially for locking
|
||||
##### Steps to replicate
|
||||
|
||||
Provide the steps to replicate (which usually at least includes the commands and the Pipfile).
|
||||
|
||||
-------------
|
||||
|
||||
Please run `$ pipenv --support`, and paste the results here. Don't put backticks (`` ` ``) around it! The output already contains Markdown formatting.
|
||||
|
||||
If you're on macOS, run the following:
|
||||
|
||||
$ pipenv --support | pbcopy
|
||||
|
||||
If you're on Windows, run the following:
|
||||
|
||||
> pipenv --support | clip
|
||||
|
||||
@@ -1,29 +1,37 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us improve
|
||||
|
||||
---
|
||||
|
||||
Be sure to check the existing issues (both open and closed!).
|
||||
|
||||
Describe the issue briefly here.
|
||||
|
||||
Please run `$ python -m pipenv.help`, and paste the results here.
|
||||
|
||||
If you're on MacOS, just run the following:
|
||||
|
||||
$ python -m pipenv.help | pbcopy
|
||||
|
||||
------------
|
||||
|
||||
##### Expected result
|
||||
|
||||
Describe what you expected.
|
||||
|
||||
##### Actual result
|
||||
|
||||
When possible, provide the verbose output (`--verbose`), especially for locking and dependencies resolving issues.
|
||||
|
||||
##### Steps to replicate
|
||||
|
||||
Provide the steps to replicate (which usually at least includes the commands and the Pipfile).
|
||||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us improve
|
||||
|
||||
---
|
||||
|
||||
Be sure to check the existing issues (both open and closed!).
|
||||
|
||||
------------
|
||||
|
||||
##### Issue description
|
||||
|
||||
Describe the issue briefly here.
|
||||
|
||||
##### Expected result
|
||||
|
||||
Describe what you expected.
|
||||
|
||||
##### Actual result
|
||||
|
||||
When possible, provide the verbose output (`--verbose`), especially for locking and dependencies resolving issues.
|
||||
|
||||
##### Steps to replicate
|
||||
|
||||
Provide the steps to replicate (which usually at least includes the commands and the Pipfile).
|
||||
|
||||
-------------
|
||||
|
||||
Please run `$ pipenv --support`, and paste the results here. Don't put backticks (`` ` ``) around it! The output already contains Markdown formatting.
|
||||
|
||||
If you're on macOS, run the following:
|
||||
|
||||
$ pipenv --support | pbcopy
|
||||
|
||||
If you're on Windows, run the following:
|
||||
|
||||
> pipenv --support | clip
|
||||
|
||||
@@ -1,7 +1,22 @@
|
||||
---
|
||||
name: Usage / Requests for Help
|
||||
about: Requests for assistance or general usage guidance.
|
||||
|
||||
---
|
||||
|
||||
Please refer to our [StackOverflow tag](https://stackoverflow.com/questions/tagged/pipenv) for more information.
|
||||
---
|
||||
name: Usage / Requests for Help
|
||||
about: Requests for assistance or general usage guidance.
|
||||
|
||||
---
|
||||
|
||||
Please refer to our [StackOverflow tag](https://stackoverflow.com/questions/tagged/pipenv) for more information.
|
||||
|
||||
If Pipenv is not functioning as you would like it to, consider filing either a bug report, or a feature request instead.
|
||||
|
||||
|
||||
-------------
|
||||
|
||||
Please run `$ pipenv --support`, and paste the results here. Don't put backticks (`` ` ``) around it! The output already contains Markdown formatting.
|
||||
|
||||
If you're on macOS, run the following:
|
||||
|
||||
$ pipenv --support | pbcopy
|
||||
|
||||
If you're on Windows, run the following:
|
||||
|
||||
> pipenv --support | clip
|
||||
|
||||
@@ -1,17 +1,23 @@
|
||||
---
|
||||
name: Feature request
|
||||
about: Suggest an idea for this project
|
||||
|
||||
---
|
||||
|
||||
**Is your feature request related to a problem? Please describe.**
|
||||
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||
|
||||
**Describe the solution you'd like**
|
||||
A clear and concise description of what you want to happen.
|
||||
|
||||
**Describe alternatives you've considered**
|
||||
A clear and concise description of any alternative solutions or features you've considered.
|
||||
|
||||
**Additional context**
|
||||
Add any other context or screenshots about the feature request here.
|
||||
---
|
||||
name: Feature request
|
||||
about: Suggest an idea for this project
|
||||
|
||||
---
|
||||
|
||||
Be sure to check the existing issues (both open and closed!).
|
||||
|
||||
##### Is your feature request related to a problem? Please describe.
|
||||
|
||||
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||
|
||||
##### Describe the solution you'd like
|
||||
|
||||
A clear and concise description of what you want to happen.
|
||||
|
||||
##### Describe alternatives you've considered
|
||||
|
||||
A clear and concise description of any alternative solutions or features you've considered.
|
||||
|
||||
##### Additional context
|
||||
|
||||
Add any other context or screenshots about the feature request here. It may be a good idea to mention that platform and Python version you are on.
|
||||
|
||||
+73
-16
@@ -1,24 +1,40 @@
|
||||
build: off
|
||||
version: 1.0.{build}
|
||||
|
||||
skip_branch_with_pr: true
|
||||
|
||||
init:
|
||||
- ps: >-
|
||||
|
||||
git config --global core.sharedRepository true
|
||||
|
||||
git config --global core.longpaths true
|
||||
|
||||
git config --global core.autocrlf input
|
||||
|
||||
if ($env:APPVEYOR_PULL_REQUEST_NUMBER -and $env:APPVEYOR_BUILD_NUMBER -ne ((Invoke-RestMethod `
|
||||
https://ci.appveyor.com/api/projects/$env:APPVEYOR_ACCOUNT_NAME/$env:APPVEYOR_PROJECT_SLUG/history?recordsNumber=50).builds | `
|
||||
Where-Object pullRequestId -eq $env:APPVEYOR_PULL_REQUEST_NUMBER)[0].buildNumber) { `
|
||||
Write-Host "There are newer queued builds for this pull request, skipping build."
|
||||
Exit-AppveyorBuild
|
||||
}
|
||||
|
||||
If (($env:SKIP_NOTAG -eq "true") -and ($env:APPVEYOR_REPO_TAG -ne "true")) {
|
||||
Write-Host "Skipping build, not at a tag."
|
||||
Exit-AppveyorBuild
|
||||
}
|
||||
|
||||
- git config --global core.sharedRepository true
|
||||
- git config --global core.longpaths true
|
||||
- git config --global core.autocrlf input
|
||||
|
||||
environment:
|
||||
|
||||
PYPI_VENDOR_DIR: '.\tests\pypi\'
|
||||
GIT_ASK_YESNO: 'false'
|
||||
APPVEYOR_SAVE_CACHE_ON_ERROR: 'true'
|
||||
APPVEYOR_SKIP_FINALIZE_ON_EXIT: 'true'
|
||||
SHELL: 'windows'
|
||||
PYTHON_ARCH: '64'
|
||||
PYTHONIOENCODING: 'utf-8'
|
||||
|
||||
matrix:
|
||||
|
||||
- PYTHON: 'C:\Python27-x64'
|
||||
PYTHON_VERSION: '2.7.x'
|
||||
TEST_SUITE: 'not install'
|
||||
@@ -39,19 +55,60 @@ environment:
|
||||
PYTEST_ADDOPTS: '--cache-clear'
|
||||
RUN_INTEGRATION_TESTS: 'True'
|
||||
|
||||
- PYTHON: 'C:\Python37-x64'
|
||||
PYTHON_VERSION: '3.7.x'
|
||||
TEST_SUITE: 'not install'
|
||||
|
||||
- PYTHON: 'C:\Python37-x64'
|
||||
PYTHON_VERSION: '3.7.x'
|
||||
TEST_SUITE: 'install'
|
||||
PYTEST_ADDOPTS: '--cache-clear'
|
||||
RUN_INTEGRATION_TESTS: 'True'
|
||||
|
||||
install:
|
||||
- 'set PATH=%PYTHON%;%PYTHON%\Scripts;%PATH%'
|
||||
- '%PYTHON%\python.exe -m pip install --upgrade pip'
|
||||
- '%PYTHON%\python.exe -m pip install -e .'
|
||||
- '%PYTHON%\python.exe -m pipenv run pip install -e .'
|
||||
- '%PYTHON%\python.exe -m pipenv install --dev'
|
||||
- '%PYTHON%\python.exe -m pipenv --venv'
|
||||
- '%PYTHON%\python.exe -m pipenv --py'
|
||||
- '%PYTHON%\python.exe -m pipenv run python --version'
|
||||
- ps: >-
|
||||
|
||||
$script_path = Join-Path -path $env:PYTHON -childpath Scripts
|
||||
|
||||
$py_exe = Join-Path -path $env:PYTHON -childpath python.exe
|
||||
|
||||
$pipenv_exe = Join-Path -path $script_path -childpath pipenv.exe
|
||||
|
||||
$env:PATH = "$py_path;$script_path;$env:PATH"
|
||||
|
||||
Invoke-Expression "$py_exe -m pip install --upgrade pip invoke"
|
||||
|
||||
Invoke-Expression "$py_exe -m pip install -e ."
|
||||
|
||||
Invoke-Expression "$pipenv_exe install --dev"
|
||||
|
||||
Invoke-Expression "$pipenv_exe --venv"
|
||||
|
||||
Invoke-Expression "$pipenv_exe --py"
|
||||
|
||||
cache:
|
||||
- '%LocalAppData%\pip\cache'
|
||||
- '%LocalAppData%\pip\cache'
|
||||
- '%LocalAppData%\pipenv\cache'
|
||||
|
||||
test_script:
|
||||
- 'if "%RUN_INTEGRATION_TESTS%" == "True" (rmdir /s /q %LocalAppData%\pip\cache)'
|
||||
- '%PYTHON%\python.exe -m pipenv run pytest -v -n 4 -m "%TEST_SUITE%" tests'
|
||||
|
||||
- ps: >-
|
||||
$script_path = Join-Path -path $env:PYTHON -childpath Scripts
|
||||
|
||||
$py_exe = Join-Path -path $env:PYTHON -childpath python.exe
|
||||
|
||||
$pipenv_exe = Join-Path -path $script_path -childpath pipenv.exe
|
||||
|
||||
$env:PATH = "$py_path;$script_path;$env:PATH"
|
||||
|
||||
$invoke_path = Join-Path -path $script_path -childpath invoke.exe
|
||||
|
||||
Invoke-Expression "$pipenv_exe run pytest -v -n 4 --ignore=pipenv\patched --ignore=pipenv\vendor -m `"$env:TEST_SUITE`" tests"
|
||||
|
||||
If ($env:RUN_INTEGRATION_TESTS -and ($env:PYTHON_VERSION -eq "3.6.x")) {
|
||||
|
||||
Invoke-Expression "$py_exe -m pip install invoke parver"
|
||||
|
||||
Invoke-Expression "$invoke_path vendoring.update"
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
All calls to ``pipenv shell`` are now implemented from the ground up using `shellingham <https://github.com/sarugaku/shellingham>`_, a custom library which was purpose built to handle edge cases and shell detection.
|
||||
@@ -0,0 +1 @@
|
||||
All calls to ``pipenv shell`` are now implemented from the ground up using `shellingham <https://github.com/sarugaku/shellingham>`_, a custom library which was purpose built to handle edge cases and shell detection.
|
||||
@@ -0,0 +1 @@
|
||||
Added new flag ``pipenv --support`` to replace the diagnostic command ``python -m pipenv.help``.
|
||||
@@ -37,6 +37,11 @@ if sys.version_info[:2] >= (3, 5):
|
||||
else:
|
||||
from .vendor.pathlib2 import Path
|
||||
|
||||
# Backport required for earlier versions of Python.
|
||||
if sys.version_info < (3, 3):
|
||||
from .vendor.backports.shutil_get_terminal_size import get_terminal_size
|
||||
else:
|
||||
from shutil import get_terminal_size
|
||||
|
||||
try:
|
||||
from weakref import finalize
|
||||
|
||||
@@ -152,6 +152,11 @@ def validate_pypi_mirror(ctx, param, value):
|
||||
callback=validate_pypi_mirror,
|
||||
help="Specify a PyPI mirror.",
|
||||
)
|
||||
@option(
|
||||
'--support',
|
||||
is_flag=True,
|
||||
help="Output diagnostic information for use in Github issues."
|
||||
)
|
||||
@version_option(
|
||||
prog_name=crayons.normal('pipenv', bold=True), version=__version__
|
||||
)
|
||||
@@ -171,6 +176,7 @@ def cli(
|
||||
man=False,
|
||||
completion=False,
|
||||
pypi_mirror=None,
|
||||
support=None
|
||||
):
|
||||
if completion: # Handle this ASAP to make shell startup fast.
|
||||
from . import shells
|
||||
@@ -229,6 +235,11 @@ def cli(
|
||||
elif py:
|
||||
do_py()
|
||||
sys.exit()
|
||||
# --support was passed...
|
||||
elif support:
|
||||
from .help import get_pipenv_diagnostics
|
||||
get_pipenv_diagnostics()
|
||||
sys.exit(0)
|
||||
# --venv was passed...
|
||||
elif venv:
|
||||
# There is no virtualenv yet.
|
||||
|
||||
+25
-107
@@ -79,11 +79,6 @@ from .environments import (
|
||||
PIPENV_CACHE_DIR,
|
||||
)
|
||||
|
||||
# Backport required for earlier versions of Python.
|
||||
if sys.version_info < (3, 3):
|
||||
from .vendor.backports.shutil_get_terminal_size import get_terminal_size
|
||||
else:
|
||||
from shutil import get_terminal_size
|
||||
# Packages that should be ignored later.
|
||||
BAD_PACKAGES = ('setuptools', 'pip', 'wheel', 'packaging', 'distribute')
|
||||
# Are we using the default Python?
|
||||
@@ -480,7 +475,8 @@ def ensure_python(three=None, python=None):
|
||||
'3.3': '3.3.7',
|
||||
'3.4': '3.4.8',
|
||||
'3.5': '3.5.5',
|
||||
'3.6': '3.6.5',
|
||||
'3.6': '3.6.6',
|
||||
'3.7': '3.7.0',
|
||||
}
|
||||
try:
|
||||
if len(python.split('.')) == 2:
|
||||
@@ -1169,29 +1165,6 @@ def do_lock(
|
||||
return lockfile
|
||||
|
||||
|
||||
def activate_virtualenv(source=True):
|
||||
"""Returns the string to activate a virtualenv."""
|
||||
# Suffix and source command for other shells.
|
||||
suffix = ''
|
||||
command = ' .' if source else ''
|
||||
# Support for fish shell.
|
||||
if PIPENV_SHELL and 'fish' in PIPENV_SHELL:
|
||||
suffix = '.fish'
|
||||
command = 'source'
|
||||
# Support for csh shell.
|
||||
if PIPENV_SHELL and 'csh' in PIPENV_SHELL:
|
||||
suffix = '.csh'
|
||||
command = 'source'
|
||||
# Escape any spaces located within the virtualenv path to allow
|
||||
# for proper activation.
|
||||
venv_location = project.virtualenv_location.replace(' ', r'\ ')
|
||||
if source:
|
||||
return '{2} {0}/bin/activate{1}'.format(venv_location, suffix, command)
|
||||
|
||||
else:
|
||||
return '{0}/bin/activate'.format(venv_location)
|
||||
|
||||
|
||||
def do_purge(bare=False, downloads=False, allow_global=False, verbose=False):
|
||||
"""Executes the purge functionality."""
|
||||
if downloads:
|
||||
@@ -2169,94 +2142,39 @@ def do_uninstall(
|
||||
do_lock(system=system, keep_outdated=keep_outdated, pypi_mirror=pypi_mirror)
|
||||
|
||||
|
||||
def do_shell(three=None, python=False, fancy=False, shell_args=None, pypi_mirror=None):
|
||||
from .patched.pew import pew
|
||||
|
||||
def do_shell(three=None, python=False, fancy=False, shell_args=None, pypi_mirror=None):
|
||||
# Ensure that virtualenv is available.
|
||||
ensure_project(three=three, python=python, validate=False, pypi_mirror=pypi_mirror)
|
||||
# Set an environment variable, so we know we're in the environment.
|
||||
os.environ['PIPENV_ACTIVE'] = '1'
|
||||
compat = (not fancy)
|
||||
# Support shell compatibility mode.
|
||||
if PIPENV_SHELL_FANCY:
|
||||
compat = False
|
||||
# Compatibility mode:
|
||||
if compat:
|
||||
if PIPENV_SHELL:
|
||||
shell = os.path.abspath(PIPENV_SHELL)
|
||||
else:
|
||||
click.echo(
|
||||
crayons.red(
|
||||
'Please ensure that the {0} environment variable '
|
||||
'is set before activating shell.'.format(
|
||||
crayons.normal('SHELL', bold=True)
|
||||
)
|
||||
),
|
||||
err=True,
|
||||
)
|
||||
sys.exit(1)
|
||||
fancy = True
|
||||
|
||||
from .shells import choose_shell
|
||||
shell = choose_shell()
|
||||
click.echo("Launching subshell in virtual environment…", err=True)
|
||||
|
||||
fork_args = (
|
||||
project.virtualenv_location,
|
||||
project.project_directory,
|
||||
shell_args,
|
||||
)
|
||||
|
||||
if fancy:
|
||||
shell.fork(*fork_args)
|
||||
return
|
||||
|
||||
try:
|
||||
shell.fork_compat(*fork_args)
|
||||
except (AttributeError, ImportError):
|
||||
click.echo(
|
||||
crayons.normal(
|
||||
'Spawning environment shell ({0}). Use {1} to leave.'.format(
|
||||
crayons.red(shell), crayons.normal("'exit'", bold=True)
|
||||
),
|
||||
bold=True,
|
||||
),
|
||||
u'Compatibility mode not supported. '
|
||||
u'Trying to continue as well-configured shell…',
|
||||
err=True,
|
||||
)
|
||||
cmd = "{0} -i'".format(shell)
|
||||
args = []
|
||||
# Standard (properly configured shell) mode:
|
||||
else:
|
||||
if project.is_venv_in_project():
|
||||
# use .venv as the target virtualenv name
|
||||
workon_name = '.venv'
|
||||
else:
|
||||
workon_name = project.virtualenv_name
|
||||
cmd = sys.executable
|
||||
args = ['-m', 'pipenv.pew', 'workon', workon_name]
|
||||
# Grab current terminal dimensions to replace the hardcoded default
|
||||
# dimensions of pexpect
|
||||
terminal_dimensions = get_terminal_size()
|
||||
try:
|
||||
with temp_environ():
|
||||
if project.is_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
|
||||
# Tell pew to use the project directory as its workon_home
|
||||
with temp_environ():
|
||||
if project.is_venv_in_project():
|
||||
os.environ['WORKON_HOME'] = project.project_directory
|
||||
pew.workon_cmd([workon_name])
|
||||
sys.exit(0)
|
||||
# Activate the virtualenv if in compatibility mode.
|
||||
if compat:
|
||||
c.sendline(activate_virtualenv())
|
||||
# Send additional arguments to the subshell.
|
||||
if shell_args:
|
||||
c.sendline(' '.join(shell_args))
|
||||
|
||||
# Handler for terminal resizing events
|
||||
# Must be defined here to have the shell process in its context, since we
|
||||
# can't pass it as an argument
|
||||
def sigwinch_passthrough(sig, data):
|
||||
terminal_dimensions = get_terminal_size()
|
||||
c.setwinsize(terminal_dimensions.lines, terminal_dimensions.columns)
|
||||
|
||||
signal.signal(signal.SIGWINCH, sigwinch_passthrough)
|
||||
# Interact with the new shell.
|
||||
c.interact(escape_character=None)
|
||||
c.close()
|
||||
sys.exit(c.exitstatus)
|
||||
shell.fork(*fork_args)
|
||||
|
||||
|
||||
def inline_activate_virtualenv():
|
||||
|
||||
@@ -76,6 +76,7 @@ PYENV_INSTALLED = (
|
||||
SESSION_IS_INTERACTIVE = bool(os.isatty(sys.stdout.fileno()))
|
||||
PIPENV_SHELL_EXPLICIT = os.environ.get('PIPENV_SHELL')
|
||||
PIPENV_SHELL = os.environ.get('SHELL') or os.environ.get('PYENV_SHELL')
|
||||
PIPENV_EMULATOR = os.environ.get('PIPENV_EMULATOR')
|
||||
PIPENV_CACHE_DIR = os.environ.get('PIPENV_CACHE_DIR', user_cache_dir('pipenv'))
|
||||
# Tells pipenv to override PyPI index urls with a mirror.
|
||||
PIPENV_PYPI_MIRROR = os.environ.get('PIPENV_PYPI_MIRROR')
|
||||
|
||||
+3
-3
@@ -16,8 +16,8 @@ def print_utf(line):
|
||||
print(line.encode('utf-8'))
|
||||
|
||||
|
||||
def main():
|
||||
print('<details><summary>$ python -m pipenv.help output</summary>')
|
||||
def get_pipenv_diagnostics():
|
||||
print('<details><summary>$ pipenv --support</summary>')
|
||||
print('')
|
||||
print('Pipenv version: `{0!r}`'.format(__version__))
|
||||
print('')
|
||||
@@ -93,5 +93,5 @@ def main():
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
get_pipenv_diagnostics()
|
||||
|
||||
|
||||
+198
-3
@@ -1,11 +1,17 @@
|
||||
import collections
|
||||
import contextlib
|
||||
import os
|
||||
import signal
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
from .environments import PIPENV_SHELL_EXPLICIT, PIPENV_SHELL
|
||||
from ._compat import get_terminal_size, Path
|
||||
from .environments import PIPENV_SHELL_EXPLICIT, PIPENV_SHELL, PIPENV_EMULATOR
|
||||
from .utils import temp_environ
|
||||
from .vendor import shellingham
|
||||
|
||||
|
||||
class ShellDetectionFailure(shellingham.ShellDetectionFailure):
|
||||
pass
|
||||
ShellDetectionFailure = shellingham.ShellDetectionFailure
|
||||
|
||||
|
||||
def _build_info(value):
|
||||
@@ -21,3 +27,192 @@ def detect_info():
|
||||
if PIPENV_SHELL:
|
||||
return _build_info(PIPENV_SHELL)
|
||||
raise ShellDetectionFailure
|
||||
|
||||
|
||||
def _get_activate_script(venv):
|
||||
"""Returns the string to activate a virtualenv.
|
||||
|
||||
This is POSIX-only at the moment since the compat (pexpect-based) shell
|
||||
does not work elsewhere anyway.
|
||||
"""
|
||||
# Suffix and source command for other shells.
|
||||
# Support for fish shell.
|
||||
if PIPENV_SHELL and 'fish' in PIPENV_SHELL:
|
||||
suffix = '.fish'
|
||||
command = 'source'
|
||||
# Support for csh shell.
|
||||
elif PIPENV_SHELL and 'csh' in PIPENV_SHELL:
|
||||
suffix = '.csh'
|
||||
command = 'source'
|
||||
else:
|
||||
suffix = ''
|
||||
command = '.'
|
||||
# Escape any spaces located within the virtualenv path to allow
|
||||
# for proper activation.
|
||||
venv_location = str(venv).replace(' ', r'\ ')
|
||||
# The leading space can make history cleaner in some shells.
|
||||
return ' {2} {0}/bin/activate{1}'.format(venv_location, suffix, command)
|
||||
|
||||
|
||||
def _handover(cmd, args):
|
||||
args = [cmd] + args
|
||||
if os.name != 'nt':
|
||||
os.execvp(cmd, args)
|
||||
else:
|
||||
proc = subprocess.run(args, shell=True, universal_newlines=True)
|
||||
sys.exit(proc.returncode)
|
||||
|
||||
|
||||
class Shell(object):
|
||||
|
||||
def __init__(self, cmd):
|
||||
self.cmd = cmd
|
||||
self.args = []
|
||||
|
||||
@contextlib.contextmanager
|
||||
def inject_path(self, venv):
|
||||
with temp_environ():
|
||||
os.environ['PATH'] = '{0}{1}{2}'.format(
|
||||
os.pathsep.join(str(p.parent) for p in _iter_python(venv)),
|
||||
os.pathsep,
|
||||
os.environ['PATH'],
|
||||
)
|
||||
yield
|
||||
|
||||
def fork(self, venv, cwd, args):
|
||||
# FIXME: This isn't necessarily the correct prompt. We should read the
|
||||
# actual prompt by peeking into the activation script.
|
||||
name = os.path.basename(venv)
|
||||
os.environ['VIRTUAL_ENV'] = str(venv)
|
||||
if 'PROMPT' in os.environ:
|
||||
os.environ['PROMPT'] = '({0}) {1}'.format(
|
||||
name, os.environ['PROMPT'],
|
||||
)
|
||||
if 'PS1' in os.environ:
|
||||
os.environ['PS1'] = '({0}) {1}'.format(
|
||||
name, os.environ['PS1'],
|
||||
)
|
||||
with self.inject_path(venv):
|
||||
os.chdir(cwd)
|
||||
_handover(self.cmd, self.args + list(args))
|
||||
|
||||
def fork_compat(self, venv, cwd, args):
|
||||
from .vendor import pexpect
|
||||
|
||||
# Grab current terminal dimensions to replace the hardcoded default
|
||||
# dimensions of pexpect.
|
||||
dims = get_terminal_size()
|
||||
with temp_environ():
|
||||
c = pexpect.spawn(
|
||||
self.cmd, ['-i'], dimensions=(dims.lines, dims.columns),
|
||||
)
|
||||
c.sendline(_get_activate_script(venv))
|
||||
if args:
|
||||
c.sendline(' '.join(args))
|
||||
|
||||
# Handler for terminal resizing events
|
||||
# Must be defined here to have the shell process in its context, since
|
||||
# we can't pass it as an argument
|
||||
def sigwinch_passthrough(sig, data):
|
||||
dims = get_terminal_size()
|
||||
c.setwinsize(dims.lines, dims.columns)
|
||||
|
||||
signal.signal(signal.SIGWINCH, sigwinch_passthrough)
|
||||
|
||||
# Interact with the new shell.
|
||||
c.interact(escape_character=None)
|
||||
c.close()
|
||||
sys.exit(c.exitstatus)
|
||||
|
||||
|
||||
POSSIBLE_ENV_PYTHON = [
|
||||
Path('bin', 'python'),
|
||||
Path('Scripts', 'python.exe'),
|
||||
]
|
||||
|
||||
|
||||
def _iter_python(venv):
|
||||
for path in POSSIBLE_ENV_PYTHON:
|
||||
full_path = Path(venv, path)
|
||||
if full_path.is_file():
|
||||
yield full_path
|
||||
|
||||
|
||||
class Bash(Shell):
|
||||
# The usual PATH injection technique does not work with Bash.
|
||||
# https://github.com/berdario/pew/issues/58#issuecomment-102182346
|
||||
@contextlib.contextmanager
|
||||
def inject_path(self, venv):
|
||||
from ._compat import NamedTemporaryFile
|
||||
bashrc_path = Path.home().joinpath('.bashrc')
|
||||
with NamedTemporaryFile('w+') as rcfile:
|
||||
if bashrc_path.is_file():
|
||||
base_rc_src = 'source "{0}"\n'.format(bashrc_path.as_posix())
|
||||
rcfile.write(base_rc_src)
|
||||
|
||||
export_path = 'export PATH="{0}:$PATH"\n'.format(':'.join(
|
||||
python.parent.as_posix()
|
||||
for python in _iter_python(venv)
|
||||
))
|
||||
rcfile.write(export_path)
|
||||
rcfile.flush()
|
||||
self.args.extend(['--rcfile', rcfile.name])
|
||||
yield
|
||||
|
||||
|
||||
class CmderEmulatedShell(Shell):
|
||||
def fork(self, venv, cwd, args):
|
||||
if cwd:
|
||||
os.environ['CMDER_START'] = cwd
|
||||
super(CmderEmulatedShell, self).fork(venv, cwd, args)
|
||||
|
||||
|
||||
class CmderCommandPrompt(CmderEmulatedShell):
|
||||
def fork(self, venv, cwd, args):
|
||||
rc = os.path.expandvars('%CMDER_ROOT%\\vendor\\init.bat')
|
||||
if os.path.exists(rc):
|
||||
self.args.extend(['/k', rc])
|
||||
super(CmderCommandPrompt, self).fork(venv, cwd, args)
|
||||
|
||||
|
||||
class CmderPowershell(Shell):
|
||||
def fork(self, venv, cwd, args):
|
||||
rc = os.path.expandvars('%CMDER_ROOT%\\vendor\\profile.ps1')
|
||||
if os.path.exists(rc):
|
||||
self.args.extend([
|
||||
'-ExecutionPolicy', 'Bypass', '-NoLogo', '-NoProfile',
|
||||
'-NoExit', '-Command',
|
||||
"Invoke-Expression '. ''{0}'''".format(rc),
|
||||
])
|
||||
super(CmderPowershell, self).fork(venv, cwd, args)
|
||||
|
||||
|
||||
# Two dimensional dict. First is the shell type, second is the emulator type.
|
||||
# Example: SHELL_LOOKUP['powershell']['cmder'] => CmderPowershell.
|
||||
SHELL_LOOKUP = collections.defaultdict(
|
||||
lambda: collections.defaultdict(lambda: Shell),
|
||||
{
|
||||
'bash': collections.defaultdict(lambda: Bash),
|
||||
'cmd': collections.defaultdict(lambda: Shell, {
|
||||
'cmder': CmderCommandPrompt,
|
||||
}),
|
||||
'powershell': collections.defaultdict(lambda: Shell, {
|
||||
'cmder': CmderPowershell,
|
||||
}),
|
||||
'pwsh': collections.defaultdict(lambda: Shell, {
|
||||
'cmder': CmderPowershell,
|
||||
}),
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
def _detect_emulator():
|
||||
if os.environ.get('CMDER_ROOT'):
|
||||
return 'cmder'
|
||||
return ''
|
||||
|
||||
|
||||
def choose_shell():
|
||||
emulator = PIPENV_EMULATOR or _detect_emulator()
|
||||
type_, command = detect_info()
|
||||
return SHELL_LOOKUP[type_][emulator](command)
|
||||
|
||||
@@ -19,6 +19,7 @@ if [[ ! -z "$TEST_SUITE" ]]; then
|
||||
fi
|
||||
|
||||
export PATH="~/.local/bin:$PATH"
|
||||
pip uninstall -y pipenv
|
||||
echo "Installing Pipenv…"
|
||||
pip install -e "$(pwd)" --upgrade
|
||||
pipenv install --deploy --dev
|
||||
@@ -50,5 +51,9 @@ echo "$ pipenv run time pytest -v -n auto tests -m \"$TEST_SUITE\""
|
||||
# Better to run them sequentially.
|
||||
PIPENV_PYTHON=2.7 pipenv run time pytest -v -n auto tests -m "$TEST_SUITE"
|
||||
PIPENV_PYTHON=3.6 pipenv run time pytest -v -n auto tests -m "$TEST_SUITE"
|
||||
|
||||
# test revendoring
|
||||
pip3 install --upgrade invoke requests parver
|
||||
python3 -m invoke vendoring.update
|
||||
# Cleanup junk.
|
||||
rm -fr .venv
|
||||
|
||||
@@ -31,6 +31,12 @@ def test_pipenv_py(PipenvInstance):
|
||||
assert os.path.basename(python).startswith('python')
|
||||
|
||||
|
||||
@pytest.mark.cli
|
||||
def test_pipenv_support(PipenvInstance):
|
||||
with PipenvInstance() as p:
|
||||
assert p.pipenv('--support').out
|
||||
|
||||
|
||||
@pytest.mark.cli
|
||||
def test_pipenv_rm(PipenvInstance):
|
||||
with PipenvInstance() as p:
|
||||
|
||||
@@ -2,13 +2,14 @@
|
||||
|
||||
XXX: Try our best to reduce tests in this file.
|
||||
"""
|
||||
|
||||
import os
|
||||
from tempfile import gettempdir, mkdtemp
|
||||
from tempfile import mkdtemp
|
||||
|
||||
import mock
|
||||
import pytest
|
||||
|
||||
from pipenv.core import activate_virtualenv
|
||||
from pipenv.utils import temp_environ
|
||||
from pipenv.project import Project
|
||||
from pipenv.vendor import delegator
|
||||
from pipenv._compat import Path
|
||||
@@ -25,15 +26,6 @@ def test_code_import_manual(PipenvInstance):
|
||||
assert 'requests' in p.pipfile['packages']
|
||||
|
||||
|
||||
@pytest.mark.code
|
||||
@pytest.mark.virtualenv
|
||||
@pytest.mark.project
|
||||
def test_activate_virtualenv_no_source():
|
||||
command = activate_virtualenv(source=False)
|
||||
venv = Project().virtualenv_location
|
||||
assert command == '{0}/bin/activate'.format(venv)
|
||||
|
||||
|
||||
@pytest.mark.lock
|
||||
@pytest.mark.deploy
|
||||
@pytest.mark.cli
|
||||
@@ -103,14 +95,11 @@ def test_proper_names_unamanged_virtualenv(PipenvInstance, pypi):
|
||||
def test_directory_with_leading_dash(PipenvInstance):
|
||||
def mocked_mkdtemp(suffix, prefix, dir):
|
||||
if suffix == '-project':
|
||||
temp_dir = Path(gettempdir()) / '-dir-with-leading-dash'
|
||||
temp_dir.mkdir()
|
||||
return str(temp_dir)
|
||||
else:
|
||||
return mkdtemp(suffix, prefix, dir)
|
||||
prefix = '-dir-with-leading-dash'
|
||||
return mkdtemp(suffix, prefix, dir)
|
||||
|
||||
with mock.patch('pipenv._compat.mkdtemp', side_effect=mocked_mkdtemp):
|
||||
with PipenvInstance(chdir=True) as p:
|
||||
with temp_environ(), PipenvInstance(chdir=True) as p:
|
||||
# This environment variable is set in the context manager and will
|
||||
# cause pipenv to use virtualenv, not pew.
|
||||
del os.environ['PIPENV_VENV_IN_PROJECT']
|
||||
|
||||
Reference in New Issue
Block a user