Rework cmdparse.Script API

The API now requires a command argument from signature. Parsing errors
(no command from input) is thrown as a custom exception, and caught by
the outmost possible invocation to emit a message from click.
This commit is contained in:
Tzu-ping Chung
2018-04-06 17:34:14 +08:00
committed by Dan Ryan
parent d1eeeced45
commit 483bf175cf
4 changed files with 38 additions and 29 deletions
+11 -6
View File
@@ -4,22 +4,27 @@ import shlex
import six
class ScriptEmptyError(ValueError):
pass
class Script(object):
"""Parse a script line (in Pipfile's [scripts] section).
This always works in POSIX mode, even on Windows.
"""
def __init__(self, parts):
if not parts:
raise ValueError('invalid script')
self._parts = parts
def __init__(self, command, args=None):
self._parts = [command]
if args:
self._parts.extend(args)
@classmethod
def parse(cls, value):
if isinstance(value, six.string_types):
value = shlex.split(value)
return cls(value)
if not value:
raise ScriptEmptyError(value)
return cls(value[0], value[1:])
def __repr__(self):
return 'Script({0!r})'.format(self._parts)
+14 -15
View File
@@ -4,7 +4,6 @@ import logging
import os
import sys
import shutil
import shlex
import signal
import time
import tempfile
@@ -25,6 +24,7 @@ from blindspin import spinner
from requests.packages import urllib3
from requests.packages.urllib3.exceptions import InsecureRequestWarning
from .cmdparse import ScriptEmptyError
from .project import Project
from .utils import (
convert_deps_from_pip,
@@ -2195,23 +2195,14 @@ def inline_activate_virtualenv():
)
def do_run_nt(command, args):
"""Run command by appending space-joined args to it!"""
def do_run_nt(script):
import subprocess
p = subprocess.Popen(
project.build_script(command, args).cmdify(),
shell=True, universal_newlines=True,
)
p = subprocess.Popen(script.cmdify(), shell=True, universal_newlines=True)
p.communicate()
sys.exit(p.returncode)
def do_run_posix(command, args):
"""Attempt to run command either pulling from project or interpreting as executable.
Args are appended to the command in [scripts] section of project if found.
"""
script = project.build_script(command, args)
def do_run_posix(script, command):
command_path = system_which(script.command)
if not command_path:
if project.has_script(command):
@@ -2241,15 +2232,23 @@ def do_run_posix(command, args):
def do_run(command, args, three=None, python=False):
"""Attempt to run command either pulling from project or interpreting as executable.
Args are appended to the command in [scripts] section of project if found.
"""
# Ensure that virtualenv is available.
ensure_project(three=three, python=python, validate=False)
load_dot_env()
# Activate virtualenv under the current interpreter's environment
inline_activate_virtualenv()
try:
script = project.build_script(command, args)
except ScriptEmptyError:
click.echo("Can't run script {0!r}—it's empty?", err=True)
if os.name == 'nt':
do_run_nt(command, args)
do_run_nt(script)
else:
do_run_posix(command, args)
do_run_posix(script, command=command)
def do_check(three=None, python=False, system=False, unused=False, args=None):
+1 -3
View File
@@ -399,9 +399,7 @@ class Project(object):
try:
script = Script.parse(self.parsed_pipfile['scripts'][name])
except KeyError:
script = Script([name])
except ValueError:
raise ValueError('invalid script entry {0!r}'.format(name))
script = Script(name)
if extra_args:
script.extend(extra_args)
return script
+12 -5
View File
@@ -1,8 +1,7 @@
import textwrap
from pipenv.cmdparse import Script
import pytest
from pipenv.cmdparse import Script, ScriptEmptyError
@pytest.mark.run
@pytest.mark.script
@@ -12,9 +11,17 @@ def test_parse():
assert script.args == ['-c', "print('hello')"], script
@pytest.mark.run
@pytest.mark.script
def test_parse_error():
with pytest.raises(ScriptEmptyError) as e:
Script.parse('')
assert str(e.value) == "[]"
@pytest.mark.run
def test_extend():
script = Script.parse(['python', '-c', "print('hello')"])
script = Script('python', ['-c', "print('hello')"])
script.extend(['--verbose'])
assert script.command == 'python'
assert script.args == ['-c', "print('hello')", "--verbose"], script
@@ -23,7 +30,7 @@ def test_extend():
@pytest.mark.run
@pytest.mark.script
def test_cmdify():
script = Script.parse(['python', '-c', "print('hello')"])
script = Script('python', ['-c', "print('hello')"])
cmd = script.cmdify()
assert cmd == '"python" "-c" "print(\'hello\')"', script