-
Notifications
You must be signed in to change notification settings - Fork 3.2k
Use robust shebang code for all shebang modification #13390
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
base: main
Are you sure you want to change the base?
Changes from 4 commits
6da1037
b5917be
cb9d513
1f3452f
a460e1f
fa92def
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,2 @@ | ||
| Python scripts added as :file:`data` files (e.g. via ``setuptools``\ ’ ``scripts=`` parameter) | ||
| now get their shebang modified like regular scripts, and no longer break for venv paths with spaces. | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -90,14 +90,13 @@ def fix_script(path: str) -> bool: | |
| assert os.path.isfile(path) | ||
|
|
||
| with open(path, "rb") as script: | ||
| firstline = script.readline() | ||
| if not firstline.startswith(b"#!python"): | ||
| prelude = script.readline() | ||
| if (m := re.match(rb"^#!python[^\s]*(\s.*)?$", prelude)) is None: | ||
|
||
| return False | ||
| exename = sys.executable.encode(sys.getfilesystemencoding()) | ||
| firstline = b"#!" + exename + os.linesep.encode("ascii") | ||
| prelude = ScriptMaker(None, None)._get_shebang("utf-8", m.group(1) or b"") | ||
|
||
| rest = script.read() | ||
| with open(path, "wb") as script: | ||
| script.write(firstline) | ||
| script.write(prelude) | ||
| script.write(rest) | ||
| return True | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,17 +1,26 @@ | ||
| from __future__ import annotations | ||
|
|
||
| import base64 | ||
| import csv | ||
| import hashlib | ||
| import os | ||
| import shutil | ||
| import sysconfig | ||
| from pathlib import Path | ||
| from typing import Any | ||
| from typing import TYPE_CHECKING, Any | ||
|
|
||
| import pytest | ||
|
|
||
| from tests.lib import PipTestEnvironment, TestData, create_basic_wheel_for_package | ||
| from tests.lib import create_basic_wheel_for_package | ||
| from tests.lib.wheel import WheelBuilder, make_wheel | ||
|
|
||
| from ..lib.venv import VirtualEnvironment | ||
|
|
||
| if TYPE_CHECKING: | ||
| from collections.abc import Callable | ||
|
|
||
| from tests.lib import PipTestEnvironment, ScriptFactory, TestData | ||
|
|
||
|
|
||
| # assert_installed expects a package subdirectory, so give it to them | ||
| def make_wheel_with_file(name: str, version: str, **kwargs: Any) -> WheelBuilder: | ||
|
|
@@ -366,13 +375,22 @@ def test_wheel_record_lines_have_hash_for_data_files( | |
| ] | ||
|
|
||
|
|
||
| @pytest.mark.parametrize( | ||
| "ws_dirname", ["work space", "workspace"], ids=["spaces", "no_spaces"] | ||
| ) | ||
| def test_wheel_record_lines_have_updated_hash_for_scripts( | ||
| script: PipTestEnvironment, | ||
| tmpdir: Path, | ||
| virtualenv_factory: Callable[[Path], VirtualEnvironment], | ||
| script_factory: ScriptFactory, | ||
| ws_dirname: str, | ||
| ) -> None: | ||
| """ | ||
| pip rewrites "#!python" shebang lines in scripts when it installs them; | ||
| make sure it updates the RECORD file correspondingly. | ||
| """ | ||
| (tmpdir / ws_dirname).mkdir(exist_ok=True, parents=True) | ||
| virtualenv = virtualenv_factory(tmpdir / ws_dirname / "venv") | ||
| script = script_factory(tmpdir / ws_dirname, virtualenv) | ||
| package = make_wheel( | ||
| "simple", | ||
| "0.1.0", | ||
|
|
@@ -388,7 +406,12 @@ def test_wheel_record_lines_have_updated_hash_for_scripts( | |
|
|
||
| script_path = script.bin_path / "dostuff" | ||
| script_contents = script_path.read_bytes() | ||
| assert not script_contents.startswith(b"#!python\n") | ||
| expected_prefix = ( | ||
| b"#!/bin/sh\n'''exec'" | ||
|
||
| if " " in ws_dirname | ||
| else f"#!{script.bin_path}{os.path.sep}python".encode() | ||
| ) | ||
| assert script_contents.startswith(expected_prefix) | ||
|
|
||
| script_digest = hashlib.sha256(script_contents).digest() | ||
| script_digest_b64 = ( | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.