Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

support long path names for the app-data seeder generates console entry points #1579

Merged
merged 1 commit into from
Feb 11, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions docs/changelog/997.bugfix.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Support long path names for generated virtual environment console entry points (such as ``pip``) when using the
``app-data`` :option:`seeder` - by :user:`gaborbernat`.
2 changes: 1 addition & 1 deletion setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,10 @@ project_urls =
packages = find:
install_requires =
appdirs>=1.4.3,<2
distlib>=0.3.0,<1
filelock>=3.0.0,<4
six>=1.12.0,<2
contextlib2>=0.6.0,<1;python_version<"3.3"
distlib>=0.3.0,<1;sys.platform == 'win32'
importlib-metadata>=0.12,<2;python_version<"3.8"
importlib-resources>=1.0,<2;python_version<"3.7"
pathlib2>=2.3.3,<3;python_version < '3.4' and sys.platform != 'win32'
Expand Down
57 changes: 11 additions & 46 deletions src/virtualenv/seed/via_app_data/pip_install/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,12 @@
import zipfile
from abc import ABCMeta, abstractmethod
from tempfile import mkdtemp
from textwrap import dedent

import six
from six import PY3

from virtualenv.info import IS_WIN
from virtualenv.util import ConfigParser
from virtualenv.util.path import Path, make_exe
from virtualenv.util.path import Path


@six.add_metaclass(ABCMeta)
Expand Down Expand Up @@ -131,49 +129,16 @@ def _console_scripts(self):

def _create_console_entry_point(self, name, value, to_folder):
result = []
if IS_WIN:
# windows doesn't support simple script files, so fallback to more complicated exe generator
from distlib.scripts import ScriptMaker

maker = ScriptMaker(None, str(to_folder))
maker.clobber = True # overwrite
maker.variants = {"", "X", "X.Y"} # create all variants
maker.set_mode = True # ensure they are executable
maker.executable = str(self._creator.exe)
specification = "{} = {}".format(name, value)
new_files = maker.make(specification)
result.extend(Path(i) for i in new_files)
else:
module, func = value.split(":")
content = (
dedent(
"""
#!{0}
# -*- coding: utf-8 -*-
import re
import sys

from {1} import {2}

if __name__ == "__main__":
sys.argv[0] = re.sub(r"(-script.pyw?|.exe)?$", "", sys.argv[0])
sys.exit({2}())
"""
)
.lstrip()
.format(self._creator.exe, module, func)
)

version = self._creator.interpreter.version_info
for new_name in (
name,
"{}{}".format(name, version.major),
"{}-{}.{}".format(name, version.major, version.minor),
):
exe = to_folder / new_name
exe.write_text(content, encoding="utf-8")
make_exe(exe)
result.append(exe)
from distlib.scripts import ScriptMaker

maker = ScriptMaker(None, str(to_folder))
maker.clobber = True # overwrite
maker.variants = {"", "X", "X.Y"} # create all variants
maker.set_mode = True # ensure they are executable
maker.executable = str(self._creator.exe)
specification = "{} = {}".format(name, value)
new_files = maker.make(specification)
result.extend(Path(i) for i in new_files)
return result

def clear(self):
Expand Down
15 changes: 15 additions & 0 deletions tests/unit/create/test_creator.py
Original file line number Diff line number Diff line change
Expand Up @@ -297,3 +297,18 @@ def test_creator_input_passed_is_abs(tmp_path, monkeypatch):
monkeypatch.chdir(tmp_path)
result = Creator.validate_dest("venv")
assert str(result) == str(tmp_path / "venv")


def test_create_long_path(current_fastest, tmp_path):
if sys.platform == "darwin":
max_shebang_length = 512
else:
max_shebang_length = 127
gaborbernat marked this conversation as resolved.
Show resolved Hide resolved
# filenames can be at most 255 long on macOS, so split to to levels
count = max_shebang_length - len(str(tmp_path))
folder = tmp_path / ("a" * (count // 2)) / ("b" * (count // 2)) / "c"
folder.mkdir(parents=True)

cmd = [str(folder)]
result = run_via_cli(cmd)
subprocess.check_call([str(result.creator.exe.parent / "pip"), "--version"])