From 13ab07c2dcfac268f59515ca22f499a87313a69d Mon Sep 17 00:00:00 2001 From: Nicola Soranzo Date: Wed, 26 Feb 2020 11:26:22 +0100 Subject: [PATCH] support entry point paths with space (#1660) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fix creation of entry points when path contains spaces Co-authored-by: Bernát Gábor --- docs/changelog/1660.bugfix.rst | 1 + src/virtualenv/seed/via_app_data/pip_install/base.py | 9 +++++---- tests/unit/seed/test_boostrap_link_via_app_data.py | 11 ++++++----- tox.ini | 2 +- 4 files changed, 13 insertions(+), 10 deletions(-) create mode 100644 docs/changelog/1660.bugfix.rst diff --git a/docs/changelog/1660.bugfix.rst b/docs/changelog/1660.bugfix.rst new file mode 100644 index 000000000..0fe88ac04 --- /dev/null +++ b/docs/changelog/1660.bugfix.rst @@ -0,0 +1 @@ +Fix creation of entry points when path contains spaces - by :user:`nsoranzo`. diff --git a/src/virtualenv/seed/via_app_data/pip_install/base.py b/src/virtualenv/seed/via_app_data/pip_install/base.py index 8963e62fb..4ca20135d 100644 --- a/src/virtualenv/seed/via_app_data/pip_install/base.py +++ b/src/virtualenv/seed/via_app_data/pip_install/base.py @@ -9,6 +9,8 @@ from tempfile import mkdtemp from threading import Lock +# noinspection PyProtectedMember +from distlib.scripts import ScriptMaker, _enquote_executable from six import PY3, add_metaclass from virtualenv.util import ConfigParser @@ -129,13 +131,12 @@ def _console_scripts(self): def _create_console_entry_point(self, name, value, to_folder, version_info): result = [] - from distlib.scripts import ScriptMaker - maker = ScriptMaker(None, str(to_folder)) maker.clobber = True # overwrite - maker.variants = {""} + maker.variants = {""} # set within patch_distlib_correct_variants maker.set_mode = True # ensure they are executable - maker.executable = str(self._creator.exe) + # calling private until https://bitbucket.org/pypa/distlib/issues/135/expose-_enquote_executable-as-public + maker.executable = _enquote_executable(str(self._creator.exe)) specification = "{} = {}".format(name, value) with self.patch_distlib_correct_variants(version_info, maker): new_files = maker.make(specification) diff --git a/tests/unit/seed/test_boostrap_link_via_app_data.py b/tests/unit/seed/test_boostrap_link_via_app_data.py index 3d8f7dde2..3c4c6697a 100644 --- a/tests/unit/seed/test_boostrap_link_via_app_data.py +++ b/tests/unit/seed/test_boostrap_link_via_app_data.py @@ -16,12 +16,12 @@ @pytest.mark.slow -@pytest.mark.parametrize("copies", [True, False] if fs_supports_symlink() else [True]) +@pytest.mark.parametrize("copies", [False, True] if fs_supports_symlink() else [True]) def test_base_bootstrap_link_via_app_data(tmp_path, coverage_env, current_fastest, copies): current = PythonInfo.current_system() bundle_ver = BUNDLE_SUPPORT[current.version_release_str] create_cmd = [ - ensure_text(str(tmp_path / "env")), + ensure_text(str(tmp_path / "en v")), # space in the name to ensure generated scripts work when path has space "--seeder", "app-data", "--extra-search-dir", @@ -64,9 +64,7 @@ def test_base_bootstrap_link_via_app_data(tmp_path, coverage_env, current_fastes assert not process.returncode remove_cmd = [ - str(result.creator.exe), - "-m", - "pip", + str(result.creator.script("pip")), "--verbose", "--disable-pip-version-check", "uninstall", @@ -89,6 +87,9 @@ def test_base_bootstrap_link_via_app_data(tmp_path, coverage_env, current_fastes files_post_second_create = list(site_package.iterdir()) assert files_post_first_create == files_post_second_create + # Windows does not allow removing a executable while running it, so when uninstalling pip we need to do it via + # python -m pip + remove_cmd = [str(result.creator.exe), "-m", "pip"] + remove_cmd[1:] process = Popen(remove_cmd + ["pip", "wheel"]) _, __ = process.communicate() assert not process.returncode diff --git a/tox.ini b/tox.ini index b7945bdcf..c60574fdf 100644 --- a/tox.ini +++ b/tox.ini @@ -117,7 +117,7 @@ force_grid_wrap = 0 line_length = 120 known_standard_library = ConfigParser known_first_party = virtualenv -known_third_party = _subprocess,appdirs,coverage,docutils,filelock,git,packaging,pytest,setuptools,six,sphinx,sphinx_rtd_theme,sphinxarg +known_third_party = _subprocess,appdirs,coverage,distlib,docutils,filelock,git,packaging,pytest,setuptools,six,sphinx,sphinx_rtd_theme,sphinxarg [flake8] max-complexity = 22