diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index 69e5dad2..e1530fcc 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -1,4 +1,4 @@ -Be sure to check the existing issues (both open and closed!). +Be sure to check the existing issues (both open and closed!), and make sure you are running the latest version of Pipenv. If you're requesting a new feature or leaving feedback, please use this forum instead: diff --git a/.github/ISSUE_TEMPLATE/Bug_report.md b/.github/ISSUE_TEMPLATE/Bug_report.md index 229919b8..0a9b3421 100644 --- a/.github/ISSUE_TEMPLATE/Bug_report.md +++ b/.github/ISSUE_TEMPLATE/Bug_report.md @@ -3,7 +3,7 @@ name: Bug report about: Create a report to help us improve --- -Be sure to check the existing issues (both open and closed!). +Be sure to check the existing issues (both open and closed!), and make sure you are running the latest version of Pipenv. If you're requesting a new feature or leaving feedback, please use this forum instead: diff --git a/.github/ISSUE_TEMPLATE/Feature_request.md b/.github/ISSUE_TEMPLATE/Feature_request.md index 5418f88e..4292912e 100644 --- a/.github/ISSUE_TEMPLATE/Feature_request.md +++ b/.github/ISSUE_TEMPLATE/Feature_request.md @@ -3,7 +3,7 @@ name: Feature request about: Suggest an idea for this project --- -Be sure to check the existing issues (both open and closed!). +Be sure to check the existing issues (both open and closed!), and make sure you are running the latest version of Pipenv. If you're requesting a new feature or leaving feedback, please use this forum instead: diff --git a/README.md b/README.md index 0b224e16..c674d80c 100644 --- a/README.md +++ b/README.md @@ -44,20 +44,11 @@ If you\'re on MacOS, you can install Pipenv easily with Homebrew: $ brew install pipenv -If you\'re using Ubuntu 17.10: - - $ sudo apt install software-properties-common python-software-properties - $ sudo add-apt-repository ppa:pypa/ppa - $ sudo apt update - $ sudo apt install pipenv - Or, if you\'re using Fedora 28: $ sudo dnf install pipenv -Otherwise, just use pip: - - $ pip install pipenv +Otherwise, refer to the [documentation](https://docs.pipenv.org/install/) for instructions. ✨🍰✨ diff --git a/docs/conf.py b/docs/conf.py index d3e5c222..f3d0b6e2 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -17,7 +17,6 @@ # documentation root, use os.path.abspath to make it absolute, like shown here. # import os -import sys # Path hackery to get current version number. here = os.path.abspath(os.path.dirname(__file__)) @@ -182,7 +181,6 @@ texinfo_documents = [ ] - # -- Options for Epub output ---------------------------------------------- # Bibliographic Dublin Core info. @@ -202,5 +200,3 @@ epub_copyright = copyright # A list of files that should not be packed into the epub file. epub_exclude_files = ['search.html'] - - diff --git a/docs/dev/philosophy.rst b/docs/dev/philosophy.rst index bf7146a4..9d364e84 100644 --- a/docs/dev/philosophy.rst +++ b/docs/dev/philosophy.rst @@ -7,9 +7,9 @@ Pipenv is an open but opinionated tool, created by an open but opinionated devel Management Style ~~~~~~~~~~~~~~~~ -`Kenneth Reitz `_ is the BDFL. He has final say in any decision related to the Pipenv project. Kenneth is responsible for the direction and form of the library, as well as its presentation. In addition to making decisions based on technical merit, he is responsible for making decisions based on the development philosophy of Pipenv. +`Kenneth Reitz `__ is the BDFL. He has final say in any decision related to the Pipenv project. Kenneth is responsible for the direction and form of the library, as well as its presentation. In addition to making decisions based on technical merit, he is responsible for making decisions based on the development philosophy of Pipenv. -`Dan Ryan`_, `Tzu-ping Chung`_, and `Nate Prewitt`_ are the core contributors. +`Dan Ryan `__, `Tzu-ping Chung `__, and `Nate Prewitt `__ are the core contributors. They are responsible for triaging bug reports, reviewing pull requests and ensuring that Kenneth is kept up to speed with developments around the library. The day-to-day managing of the project is done by the core contributors. They are responsible for making judgements about whether or not a feature request is likely to be accepted by Kenneth. diff --git a/docs/diagnose.rst b/docs/diagnose.rst index 650e70a1..5cc47f4c 100644 --- a/docs/diagnose.rst +++ b/docs/diagnose.rst @@ -45,7 +45,7 @@ in your Pipfile. This is usually a result of mixing Pipenv with system packages. We *strongly* recommend installing Pipenv in an isolated environment. Uninstall all existing -Pipenv installations, and see :ref:`proper_installation` to choose one of the +Pipenv installations, and see :ref:`installing-pipenv` to choose one of the recommended way to install Pipenv instead. ☤ My pyenv-installed Python is not found diff --git a/docs/index.rst b/docs/index.rst index 840ae6ff..957d6c8c 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -43,20 +43,15 @@ The problems that Pipenv seeks to solve are multi-faceted: Install Pipenv Today! --------------------- -Just use pip:: +If you're on MacOS, you can install Pipenv easily with Homebrew:: - $ pip install pipenv + $ brew install pipenv -Or, if you're using Ubuntu 17.10:: +Or, if you're using Fedora 28:: - $ sudo apt install software-properties-common python-software-properties - $ sudo add-apt-repository ppa:pypa/ppa - $ sudo apt update - $ sudo apt install pipenv + $ sudo dnf install pipenv -Otherwise, if you're on MacOS, you can install Pipenv easily with Homebrew:: - - $ brew install pipenv +Otherwise, refer to the :ref:`installing-pipenv` chapter for instructions. ✨🍰✨ @@ -122,6 +117,15 @@ Further Documentation Guides advanced diagnose +Contribution Guides +------------------- + +.. toctree:: + :maxdepth: 2 + + dev/philosophy + dev/contributing + ☤ Pipenv Usage -------------- diff --git a/docs/install.rst b/docs/install.rst index 4766030d..9df6a5fc 100644 --- a/docs/install.rst +++ b/docs/install.rst @@ -1,5 +1,6 @@ .. _virtualenvironments-ref: +============================= Pipenv & Virtual Environments ============================= @@ -19,13 +20,11 @@ managing development and testing environments for any kind of project. should work fine on Python 2.7—if you are still using it, for some reason. -☤ Make sure you've got Python & pip ------------------------------------- +☤ Make sure you've got Python & pip +=================================== Before you go any further, make sure you have Python and that it's available -from your command line. You can check this by simply running: - -.. code-block:: bash +from your command line. You can check this by simply running:: $ python --version @@ -35,7 +34,7 @@ install the latest 3.x version from `python.org`_ or refer to the .. Note:: If you're newcomer and you get an error like this: - .. code-block:: python + .. code-block:: pycon >>> python Traceback (most recent call last): @@ -47,10 +46,8 @@ install the latest 3.x version from `python.org`_ or refer to the `getting started tutorial`_ for an introduction to using your operating system's shell and interacting with Python. -Additionally, you'll need to make sure you have :ref:`pip` available. You can -check this by running: - -.. code-block:: bash +Additionally, you'll need to make sure you have pip available. You can +check this by running:: $ pip --version pip 9.0.1 @@ -59,7 +56,7 @@ If you installed Python from source, with an installer from `python.org`_, or via `Homebrew`_ you should already have pip. If you're on Linux and installed using your OS package manager, you may have to `install pip `_ separately. -If you plan to install pipenv using Homebrew you can skip this step. The +If you plan to install Pipenv using Homebrew you can skip this step. The Homebrew installer takes care of pip for you. .. _getting started tutorial: https://opentechschool.github.io/python-beginners/en/getting_started.html#what-is-python-exactly @@ -68,23 +65,48 @@ Homebrew installer takes care of pip for you. .. _Installing Python: http://docs.python-guide.org/en/latest/starting/installation/ -☤ Installing Pipenv -------------------- +.. _installing-pipenv: -:ref:`Pipenv` is a dependency manager for Python projects. If you're familiar +☤ Installing Pipenv +=================== + +Pipenv is a dependency manager for Python projects. If you're familiar with Node.js' `npm`_ or Ruby's `bundler`_, it is similar in spirit to those -tools. While :ref:`pip` can install Python packages, Pipenv is recommended as +tools. While pip can install Python packages, Pipenv is recommended as it's a higher-level tool that simplifies dependency management for common use cases. -Use ``pip`` to install Pipenv: +.. _npm: https://www.npmjs.com/ +.. _bundler: http://bundler.io/ -.. code-block:: python + +☤ Homebrew Installation of Pipenv +--------------------------------- + +Homebrew is a popular open-source package management system for macOS. + +Installing pipenv via Homebrew will keep pipenv and all of its dependencies in +an isolated virtual environment so it doesn't interfere with the rest of your +Python installation. + +Once you have installed `Homebrew`_ simply run:: + + $ brew install pipenv + +To upgrade pipenv at any time:: + + $ brew upgrade pipenv + + +☤ Pragmatic Installation of Pipenv +---------------------------------- + +If you have a working installation of pip, and maintain certain "toolchain" type Python modules as global utilities in your user environment, pip `user installs `_ allow for installation into your home directory. Note that due to interaction between dependencies, you should limit tools installed in this way to basic building blocks for a Python workflow like virtualenv, pipenv, tox, and similar software. + +To install:: $ pip install --user pipenv - - .. Note:: This does a `user installation`_ to prevent breaking any system-wide packages. If ``pipenv`` isn't available in your shell after installation, you'll need to add the `user base`_'s binary directory to your ``PATH``. @@ -105,32 +127,43 @@ Use ``pip`` to install Pipenv: user ``PATH`` permanently in the `Control Panel`_. You may need to log out for the ``PATH`` changes to take effect. -.. _npm: https://www.npmjs.com/ -.. _bundler: http://bundler.io/ + For more information, see the `user installs documentation `_. + + .. _user base: https://docs.python.org/3/library/site.html#site.USER_BASE .. _user installation: https://pip.pypa.io/en/stable/user_guide/#user-installs .. _modifying ~/.profile: https://stackoverflow.com/a/14638025 .. _Control Panel: https://msdn.microsoft.com/en-us/library/windows/desktop/bb776899(v=vs.85).aspx + +To upgrade pipenv at any time:: + + $ pip install --user --upgrade pipenv + + +☤ Crude Installation of Pipenv +------------------------------ + +If you don't even have pip installed, you can use this crude installation method, which will bootstrap your whole system:: + + $ curl https://raw.githubusercontent.com/kennethreitz/pipenv/master/get-pipenv.py | python + + ☤ Installing packages for your project --------------------------------------- +====================================== Pipenv manages dependencies on a per-project basis. To install packages, change into your project's directory (or just an empty directory for this -tutorial) and run: - -.. code-block:: bash +tutorial) and run:: $ cd myproject $ pipenv install requests Pipenv will install the excellent `Requests`_ library and create a ``Pipfile`` -for you in your project's directory. The :ref:`Pipfile` is used to track which +for you in your project's directory. The ``Pipfile`` is used to track which dependencies your project needs in case you need to re-install them, such as when you share your project with others. You should get output similar to this -(although the exact paths shown will vary): - -.. code-block:: text +(although the exact paths shown will vary):: Creating a Pipfile for this project... Creating a virtualenv for this project... @@ -161,7 +194,7 @@ when you share your project with others. You should get output similar to this ☤ Using installed packages --------------------------- +========================== Now that Requests is installed you can create a simple ``main.py`` file to use it: @@ -174,9 +207,7 @@ use it: print('Your IP is {0}'.format(response.json()['origin'])) -Then you can run this script using ``pipenv run``: - -.. code-block:: bash +Then you can run this script using ``pipenv run``:: $ pipenv run python main.py @@ -192,57 +223,6 @@ have access to your installed packages with ``$ pipenv shell``. ☤ Next steps ------------- +============ Congratulations, you now know how to install and use Python packages! ✨ 🍰 ✨ - -.. _proper_installation: - - -☤ Homebrew Installation of Pipenv -================================= - -Homebrew is a popular open-source package management system for macOS. - -Installing pipenv via Homebrew will keep pipenv and all of its dependencies in -an isolated virtual environment so it doesn't interfere with the rest of your -Python installation. - -Once you have installed `Homebrew `_ simply run:: - - $ brew install pipenv - -To upgrade pipenv at any time:: - - $ brew upgrade pipenv - -.. _pragmatic_installation: - -☤ Pragmatic Installation of Pipenv -================================== - -If you have a working installation of pip, and maintain certain "toolchain" type Python modules as global utilities in your user environment, pip `user installs `_ allow for installation into your home directory. Note that due to interaction between dependencies, you should limit tools installed in this way to basic building blocks for a Python workflow like virtualenv, pipenv, tox, and similar software. - -To install:: - - $ pip install --user pipenv - -For more information see the `user installs documentation `_, but to add the installed cli tools from a pip user install to your path, add the output of:: - - $ python -c "import site; import os; print(os.path.join(site.USER_BASE, 'bin'))" - -To upgrade pipenv at any time:: - - $ pip install --user --upgrade pipenv - -.. _crude_installation: - -☤ Crude Installation of Pipenv -============================== - -If you don't even have pip installed, you can use this crude installation method, which will bootstrap your whole system:: - - $ curl https://raw.githubusercontent.com/kennethreitz/pipenv/master/get-pipenv.py | python - -Congratulations, you now have pip and Pipenv installed! - diff --git a/news/2563.bugfix b/news/2563.bugfix new file mode 100644 index 00000000..4d2e6570 --- /dev/null +++ b/news/2563.bugfix @@ -0,0 +1,2 @@ +Improve quoting logic for ``pipenv run`` so it works better with Windows +built-in commands. diff --git a/news/2564.bugfix b/news/2564.bugfix new file mode 100644 index 00000000..31fc0b1a --- /dev/null +++ b/news/2564.bugfix @@ -0,0 +1,2 @@ +Fixed a bug related to parsing vcs requirements with both extras and subdirectory fragments. +Corrected an issue in the ``requirementslib`` parser which led to some markers being discarded rather than evaluated. diff --git a/pipenv/cmdparse.py b/pipenv/cmdparse.py index aa3442b8..087a95b1 100644 --- a/pipenv/cmdparse.py +++ b/pipenv/cmdparse.py @@ -55,11 +55,18 @@ class Script(object): The result is then quoted into a pair of double quotes to be grouped. + An argument is intentionally not quoted if it does not contain + whitespaces. This is done to be compatible with Windows built-in + commands that don't work well with quotes, e.g. everything with `echo`, + and DOS-style (forward slash) switches. + The intended use of this function is to pre-process an argument list before passing it into ``subprocess.Popen(..., shell=True)``. See also: https://docs.python.org/3/library/subprocess.html#converting-argument-sequence """ return " ".join( - '"{0}"'.format(re.sub(r'(\\*)"', r'\1\1\\"', arg)) for arg in self._parts + arg if not next(re.finditer(r'\s', arg), None) + else '"{0}"'.format(re.sub(r'(\\*)"', r'\1\1\\"', arg)) + for arg in self._parts ) diff --git a/pipenv/vendor/requirementslib/__init__.py b/pipenv/vendor/requirementslib/__init__.py index 776d2a15..063458dc 100644 --- a/pipenv/vendor/requirementslib/__init__.py +++ b/pipenv/vendor/requirementslib/__init__.py @@ -1,5 +1,5 @@ # -*- coding=utf-8 -*- -__version__ = "1.0.9" +__version__ = "1.0.10" from .exceptions import RequirementError diff --git a/pipenv/vendor/requirementslib/models/baserequirement.py b/pipenv/vendor/requirementslib/models/baserequirement.py index 0cac987a..b97dee40 100644 --- a/pipenv/vendor/requirementslib/models/baserequirement.py +++ b/pipenv/vendor/requirementslib/models/baserequirement.py @@ -28,3 +28,10 @@ class BaseRequirement: @classmethod def attr_fields(cls): return [field.name for field in attr.fields(cls)] + + @property + def extras_as_pip(self): + if self.extras: + return "[{0}]".format(",".join(self.extras)) + + return "" diff --git a/pipenv/vendor/requirementslib/models/markers.py b/pipenv/vendor/requirementslib/models/markers.py index c3df4499..70adc21f 100644 --- a/pipenv/vendor/requirementslib/models/markers.py +++ b/pipenv/vendor/requirementslib/models/markers.py @@ -66,21 +66,14 @@ class PipenvMarkers(BaseRequirement): raise RequirementError( "Invalid requirement: Invalid marker %r" % marker_string ) - marker_dict = {} - for m in marker._markers: - if isinstance(m, six.string_types): - continue - var, op, val = m - if var.value in cls.attr_fields(): - marker_dict[var.value] = '{0} "{1}"'.format(op, val) - return marker_dict + return marker @classmethod def from_line(cls, line): if ";" in line: line = line.rsplit(";", 1)[1].strip() - marker_dict = cls.make_marker(line) - return cls(**marker_dict) + marker = cls.make_marker(line) + return marker @classmethod def from_pipfile(cls, name, pipfile): @@ -88,9 +81,13 @@ class PipenvMarkers(BaseRequirement): marker_strings = ["{0} {1}".format(k, pipfile[k]) for k in found_keys] if pipfile.get("markers"): marker_strings.append(pipfile.get("markers")) - markers = {} + markers = [] for marker in marker_strings: - marker_dict = cls.make_marker(marker) - if marker_dict: - markers.update(marker_dict) - return cls(**markers) + markers.append(marker) + marker = '' + try: + marker = cls.make_marker(" and ".join(markers)) + except RequirementError: + pass + else: + return marker diff --git a/pipenv/vendor/requirementslib/models/requirements.py b/pipenv/vendor/requirementslib/models/requirements.py index d49ce494..177bd454 100644 --- a/pipenv/vendor/requirementslib/models/requirements.py +++ b/pipenv/vendor/requirementslib/models/requirements.py @@ -27,6 +27,7 @@ from .utils import ( filter_none, optional_instance_of, split_markers_from_line, + parse_extras, ) from .._compat import ( Link, @@ -56,6 +57,7 @@ class NamedRequirement(BaseRequirement): name = attr.ib() version = attr.ib(validator=attr.validators.optional(validate_specifiers)) req = attr.ib() + extras = attr.ib(default=attr.Factory(list)) @req.default def get_requirement(self): @@ -114,6 +116,7 @@ class FileRequirement(BaseRequirement): path = attr.ib(default=None, validator=attr.validators.optional(validate_path)) # : path to hit - without any of the VCS prefixes (like git+ / http+ / etc) editable = attr.ib(default=None) + extras = attr.ib(default=attr.Factory(list)) uri = attr.ib() link = attr.ib() name = attr.ib() @@ -501,6 +504,7 @@ class VCSRequirement(FileRequirement): name=self.name, ref=self.ref, subdirectory=self.subdirectory, + extras=self.extras ) @name.default @@ -546,6 +550,8 @@ class VCSRequirement(FileRequirement): req.vcs = self.vcs if self.ref and not req.revision: req.revision = self.ref + if self.extras and not req.extras: + req.extras = self.extras return req @classmethod @@ -553,7 +559,7 @@ class VCSRequirement(FileRequirement): creation_args = {} pipfile_keys = [ k - for k in ("ref", "vcs", "subdirectory", "path", "editable", "file", "uri") + for k in ("ref", "vcs", "subdirectory", "path", "editable", "file", "uri", "extras") + VCS_LIST if k in pipfile ] @@ -572,13 +578,18 @@ class VCSRequirement(FileRequirement): return cls(**creation_args) @classmethod - def from_line(cls, line, editable=None): + def from_line(cls, line, editable=None, extras=None): relpath = None if line.startswith("-e "): editable = True line = line.split(" ", 1)[1] vcs_type, prefer, relpath, path, uri, link = cls.get_link_from_line(line) - name = link.egg_fragment + if not extras and link.egg_fragment: + name, extras = _strip_extras(link.egg_fragment) + if extras: + extras = parse_extras(extras) + else: + name = link.egg_fragment subdirectory = link.subdirectory_fragment ref = None if "@" in link.show_url and "@" in uri: @@ -594,6 +605,7 @@ class VCSRequirement(FileRequirement): path=relpath or path, editable=editable, uri=uri, + extras=extras, ) @property @@ -623,7 +635,7 @@ class VCSRequirement(FileRequirement): pipfile_dict = attr.asdict(self, filter=filter_none).copy() if "vcs" in pipfile_dict: pipfile_dict = self._choose_vcs_source(pipfile_dict) - name = pipfile_dict.pop("name") + name, _ = _strip_extras(pipfile_dict.pop("name")) return {name: pipfile_dict} @@ -659,7 +671,7 @@ class Requirement(object): @property def markers_as_pip(self): if self.markers: - return "; {0}".format(self.markers.replace('"', "'")) + return "; {0}".format(self.markers).replace('"', "'") return "" @@ -702,6 +714,8 @@ class Requirement(object): line = line.split(" ", 1)[1] if editable else line line, markers = split_markers_from_line(line) line, extras = _strip_extras(line) + if extras: + extras = parse_extras(extras) line = line.strip('"').strip("'").strip() line_with_prefix = "-e {0}".format(line) if editable else line vcs = None @@ -710,7 +724,7 @@ class Requirement(object): if is_installable_file(line) or (is_valid_url(line) and not is_vcs(line)): r = FileRequirement.from_line(line_with_prefix) elif is_vcs(line): - r = VCSRequirement.from_line(line_with_prefix) + r = VCSRequirement.from_line(line_with_prefix, extras=extras) vcs = r.vcs elif line == "." and not is_installable_file(line): raise RequirementError( @@ -727,14 +741,11 @@ class Requirement(object): version = line[spec_idx:] if not extras: name, extras = _strip_extras(name) + if extras: + extras = parse_extras(extras) if version: name = "{0}{1}".format(name, version) r = NamedRequirement.from_line(line) - if extras: - extras = first( - requirements.parse("fakepkg{0}".format(extras_to_string(extras))) - ).extras - r.req.extras = extras if markers: r.req.markers = markers args = { @@ -746,6 +757,10 @@ class Requirement(object): } if extras: args["extras"] = extras + r.req.extras = extras + r.extras = extras + elif r.extras: + args["extras"] = r.extras if hashes: args["hashes"] = hashes return cls(**args) @@ -764,11 +779,14 @@ class Requirement(object): r = FileRequirement.from_pipfile(name, pipfile) else: r = NamedRequirement.from_pipfile(name, pipfile) + markers = PipenvMarkers.from_pipfile(name, _pipfile) + if markers: + markers = str(markers) args = { "name": r.name, "vcs": vcs, "req": r, - "markers": PipenvMarkers.from_pipfile(name, _pipfile).line_part, + "markers": markers, "extras": _pipfile.get("extras"), "editable": _pipfile.get("editable", False), "index": _pipfile.get("index"), @@ -788,7 +806,7 @@ class Requirement(object): """ line = "{0}{1}{2}{3}{4}".format( self.req.line_part, - self.extras_as_pip, + self.extras_as_pip if not self.is_vcs else "", self.specifiers if self.specifiers else "", self.markers_as_pip, self.hashes_as_pip, diff --git a/pipenv/vendor/requirementslib/models/utils.py b/pipenv/vendor/requirementslib/models/utils.py index 82309e9b..44692399 100644 --- a/pipenv/vendor/requirementslib/models/utils.py +++ b/pipenv/vendor/requirementslib/models/utils.py @@ -32,6 +32,15 @@ def extras_to_string(extras): return "[{0}]".format(",".join(extras)) +def parse_extras(extras_str): + """Turn a string of extras into a parsed extras list""" + import requirements + extras = first( + requirements.parse("fakepkg{0}".format(extras_to_string(extras_str))) + ).extras + return extras + + def specs_to_string(specs): """Turn a list of specifier tuples into a string""" if specs: @@ -133,6 +142,7 @@ def validate_markers(instance, attr_, value): def validate_specifiers(instance, attr_, value): from packaging.specifiers import SpecifierSet, InvalidSpecifier + from packaging.markers import InvalidMarker if value == "": return True try: diff --git a/pipenv/vendor/vendor.txt b/pipenv/vendor/vendor.txt index 2f278dff..2b7781ce 100644 --- a/pipenv/vendor/vendor.txt +++ b/pipenv/vendor/vendor.txt @@ -27,7 +27,7 @@ requests==2.19.1 idna==2.7 urllib3==1.23 certifi==2018.4.16 -requirementslib==1.0.9 +requirementslib==1.0.10 attrs==18.1.0 distlib==0.2.7 packaging==17.1 diff --git a/tests/unit/test_cmdparse.py b/tests/unit/test_cmdparse.py index 064eda79..06012d07 100644 --- a/tests/unit/test_cmdparse.py +++ b/tests/unit/test_cmdparse.py @@ -30,9 +30,9 @@ def test_extend(): @pytest.mark.run @pytest.mark.script def test_cmdify(): - script = Script('python', ['-c', "print('hello')"]) + script = Script('python', ['-c', "print('hello world')"]) cmd = script.cmdify() - assert cmd == '"python" "-c" "print(\'hello\')"', script + assert cmd == 'python -c "print(\'hello world\')"', script @pytest.mark.run @@ -44,6 +44,6 @@ def test_cmdify_complex(): ])) assert script.cmdify() == ' '.join([ '"C:\\Program Files\\Python36\\python.exe"', - '"-c"', + '-c', """ "print(\'Double quote: \\\"\')" """.strip(), ]), script