Skip to content

Commit addf17b

Browse files
authored
Merge branch 'main' into uploaded-prior-to
2 parents ecbc4fb + 7e49dca commit addf17b

File tree

9 files changed

+63
-8
lines changed

9 files changed

+63
-8
lines changed

news/13407.bugfix.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Revisions in version control URLs now must be percent-encoded.
2+
For example, use ``git+https://example.com/repo.git@issue%231`` to specify the branch ``issue#1``.
3+
If you previously used a branch name containing a ``%`` character in a version control URL, you now need to replace it with ``%25`` to ensure correct percent-encoding.

news/13555.bugfix.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fix bash completion when the ``$IFS`` variable has been modified from its default.

news/6823.bugfix.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Better preserve original casing when a path is displayed.

src/pip/_internal/commands/completion.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,10 @@
1414
"bash": """
1515
_pip_completion()
1616
{{
17+
local IFS=$' \\t\\n'
1718
COMPREPLY=( $( COMP_WORDS="${{COMP_WORDS[*]}}" \\
1819
COMP_CWORD=$COMP_CWORD \\
19-
PIP_AUTO_COMPLETE=1 $1 2>/dev/null ) )
20+
PIP_AUTO_COMPLETE=1 "$1" 2>/dev/null ) )
2021
}}
2122
complete -o default -F _pip_completion {prog}
2223
""",

src/pip/_internal/utils/misc.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -182,10 +182,12 @@ def rmtree_errorhandler(
182182
def display_path(path: str) -> str:
183183
"""Gives the display value for a given path, making it relative to cwd
184184
if possible."""
185-
path = os.path.normcase(os.path.abspath(path))
186-
if path.startswith(os.getcwd() + os.path.sep):
187-
path = "." + path[len(os.getcwd()) :]
188-
return path
185+
try:
186+
relative = Path(path).relative_to(Path.cwd())
187+
except ValueError:
188+
# If the path isn't relative to the CWD, leave it alone
189+
return path
190+
return os.path.join(".", relative)
189191

190192

191193
def backup_dir(dir: str, ext: str = ".bak") -> str:

src/pip/_internal/vcs/versioncontrol.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,8 +62,9 @@ def make_vcs_requirement_url(
6262
repo_url: the remote VCS url, with any needed VCS prefix (e.g. "git+").
6363
project_name: the (unescaped) project name.
6464
"""
65+
quoted_rev = urllib.parse.quote(rev, "/")
6566
egg_project_name = project_name.replace("-", "_")
66-
req = f"{repo_url}@{rev}#egg={egg_project_name}"
67+
req = f"{repo_url}@{quoted_rev}#egg={egg_project_name}"
6768
if subdir:
6869
req += f"&subdirectory={subdir}"
6970

@@ -397,6 +398,7 @@ def get_url_rev_and_auth(cls, url: str) -> tuple[str, str | None, AuthInfo]:
397398
"which is not supported. Include a revision after @ "
398399
"or remove @ from the URL."
399400
)
401+
rev = urllib.parse.unquote(rev)
400402
url = urllib.parse.urlunsplit((scheme, netloc, path, query, ""))
401403
return url, rev, user_pass
402404

tests/functional/test_completion.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,10 @@
1515
"""\
1616
_pip_completion()
1717
{
18+
local IFS=$' \\t\\n'
1819
COMPREPLY=( $( COMP_WORDS="${COMP_WORDS[*]}" \\
1920
COMP_CWORD=$COMP_CWORD \\
20-
PIP_AUTO_COMPLETE=1 $1 2>/dev/null ) )
21+
PIP_AUTO_COMPLETE=1 "$1" 2>/dev/null ) )
2122
}
2223
complete -o default -F _pip_completion pip""",
2324
),

tests/unit/test_utils.py

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
from io import BytesIO
1515
from pathlib import Path
1616
from typing import Any, Callable, NoReturn
17-
from unittest.mock import Mock
17+
from unittest.mock import Mock, patch
1818

1919
import pytest
2020

@@ -33,6 +33,7 @@
3333
HiddenText,
3434
build_netloc,
3535
build_url_from_netloc,
36+
display_path,
3637
format_size,
3738
get_prog,
3839
hide_url,
@@ -320,6 +321,39 @@ def test_rmtree_retries_for_3sec(monkeypatch: pytest.MonkeyPatch) -> None:
320321
)
321322

322323

324+
class Test_display_path:
325+
on_unix = pytest.mark.skipif("sys.platform == 'win32'")
326+
on_win32 = pytest.mark.skipif("sys.platform != 'win32'")
327+
328+
@pytest.mark.parametrize(
329+
"path, fake_cwd, expected",
330+
[
331+
pytest.param(
332+
*("/home/name/project", Path("/home/name"), "./project"),
333+
marks=on_unix,
334+
),
335+
pytest.param(
336+
*("/home", Path("/home/name"), "/home"),
337+
marks=on_unix,
338+
id="not-go-up",
339+
),
340+
pytest.param(
341+
*("C:\\Name\\Project", Path("C:\\Name"), ".\\Project"),
342+
marks=on_win32,
343+
),
344+
pytest.param(
345+
*("D:\\Data", Path("C:\\Name"), "D:\\Data"),
346+
marks=on_win32,
347+
),
348+
],
349+
)
350+
def test_display(self, path: str, fake_cwd: Path, expected: str) -> None:
351+
with patch("pathlib.Path.cwd") as cwd_func:
352+
cwd_func.return_value = fake_cwd
353+
got = display_path(path)
354+
assert got == expected
355+
356+
323357
class Test_normalize_path:
324358
# Technically, symlinks are possible on Windows, but you need a special
325359
# permission bit to create them, and Python 2 doesn't support it anyway, so

tests/unit/test_vcs.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,11 @@ def test_ensure_svn_available() -> None:
5252
("git+https://example.com/pkg", "dev", "zope-interface"),
5353
"git+https://example.com/pkg@dev#egg=zope_interface",
5454
),
55+
# Test a revision with special characters.
56+
(
57+
("git+https://example.com/pkg", "dev@1#2", "myproj"),
58+
"git+https://example.com/pkg@dev%401%232#egg=myproj",
59+
),
5560
],
5661
)
5762
def test_make_vcs_requirement_url(args: tuple[Any, ...], expected: str) -> None:
@@ -394,6 +399,11 @@ def test_git__get_url_rev__idempotent() -> None:
394399
"svn+https://svn.example.com/My+Project",
395400
("https://svn.example.com/My+Project", None, (None, None)),
396401
),
402+
# Test percent-encoded characters in revision.
403+
(
404+
"svn+https://svn.example.com/MyProject@dev%401%232",
405+
("https://svn.example.com/MyProject", "dev@1#2", (None, None)),
406+
),
397407
],
398408
)
399409
def test_version_control__get_url_rev_and_auth(

0 commit comments

Comments
 (0)