-
Notifications
You must be signed in to change notification settings - Fork 3.1k
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
Preserve original letter-casing for displaying #13205
base: main
Are you sure you want to change the base?
Conversation
src/pip/_internal/utils/misc.py
Outdated
path = os.path.abspath(path) | ||
if path.startswith(os.getcwd() + os.path.sep): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This comparison would break when path
uses a compatible but not canonical casing. Case normalisation should be done for comparision, but not for the return value.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Case normalisation should be done for comparision, but not for the return value.
Maybe we can try this solution
--- a/src/pip/_internal/utils/misc.py
+++ b/src/pip/_internal/utils/misc.py
@@ -190,9 +190,10 @@ def rmtree_errorhandler(
def display_path(path: str) -> str:
"""Gives the display value for a given path, making it relative to cwd
if possible."""
- path = os.path.normcase(os.path.abspath(path))
- if path.startswith(os.getcwd() + os.path.sep):
- path = "." + path[len(os.getcwd()) :]
+ norm = os.path.normcase
+ abs_path = os.path.abspath(path)
+ if norm(abs_path).startswith(norm(os.getcwd()) + os.path.sep):
+ return "." + abs_path[len(os.getcwd()) :]
return path
So the original value is return when our heuristic matching fails,
and when the matching successes, we can return the part starting from current path untouched.
Does that look good?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds reasonable to me. Or we can use os.path.commonpath
to do the comparison instead.
news/6823.bugfix.rst
Outdated
@@ -0,0 +1 @@ | |||
This change will preserve path in it's original letter-case during displaying. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This change will preserve path in it's original letter-case during displaying. | |
Better preserve original casing when a path is displayed. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No problem, will be fixed in next revision.
Simplify input path as a relative path to current working directory, while preserving the original letter-casing at best effort.
bb3f5ba
to
c0c9596
Compare
Modified according to review feedbacks. Since that from typing import NamedTuple
import os
def display_path(path: str) -> str:
"""Gives the display value for a given path, making it relative to cwd
if possible."""
abs_path, cwd = os.path.abspath(path), os.getcwd()
common = os.path.commonpath([cwd, abs_path])
if len(common) == len(cwd):
return "." + abs_path[len(common) :]
return path
class Case(NamedTuple):
input: str
expected: str
testCases = [
Case(
input=r"C:\Users\weida\Projects\pip\main.py",
expected=r".\main.py",
),
Case(
input=r"C:\Users\weida\Projects\pip\main.PY",
expected=r".\main.PY",
),
Case(
input=r"C:\Users\weida\Projects\PIP\main.py",
expected=r".\main.py",
),
Case(
input=r"C:\Users\WeiDa\Projects\ABC\main.PY",
expected=r"C:\Users\WeiDa\Projects\ABC\main.PY",
),
]
# modify this path if needed
assert os.getcwd() == r"C:\Users\weida\Projects\pip"
for idx, test in enumerate(testCases):
result = display_path(test.input)
if result == test.expected:
print(f"Test case {idx} passed.")
else:
print(f"Test case {idx} failed: got {result}, expected {test.expected}.") |
This change will preserve path in it's original letter-case during displaying.
Related to: #6823
Becauseos.getcwd
andos.path.abspath
both honors original letter-case,we should not normalize case again when calculating the relative path.
(Edited) As suggested, we match input path with cwd in normalized-casing,
while returning the relative part in original-casing.
Original path is returned untouched if the match fails.
And this change actually fix the (harmless) bug in Windows that relative path is not shown correctly,
as a side effect.
Before:
After:
All the testcase in unit test still passed. (And it should, because it's just a cosmetic change.)
I tried to locate the first commit that use
os.path.normcase
, but it turns out that it's already therewhen this project migrated from svn to git in 2018.
Maybe there are some good reason to normalize case for the path in the past, but it should be ok to remove it now. :D