Skip to content

Commit d8db30f

Browse files
committed
fix: Normalize paths among documents without resolving symlinks
1 parent 847ad0c commit d8db30f

File tree

2 files changed

+13
-5
lines changed

2 files changed

+13
-5
lines changed

sphinx/environment/__init__.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
from sphinx.util.docutils import LoggingReporter
3030
from sphinx.util.i18n import CatalogRepository, docname_to_domain
3131
from sphinx.util.nodes import is_translatable
32-
from sphinx.util.osutil import _last_modified_time, _relative_path
32+
from sphinx.util.osutil import _last_modified_time, _relative_path, normalize_path
3333

3434
if TYPE_CHECKING:
3535
from collections.abc import Callable, Iterable, Iterator, Mapping
@@ -438,7 +438,7 @@ def relfn2path(
438438
"""
439439
file_name = Path(filename)
440440
if file_name.parts[:1] in {('/',), ('\\',)}:
441-
abs_fn = self.srcdir.joinpath(*file_name.parts[1:]).resolve()
441+
abs_fn = normalize_path(self.srcdir.joinpath(*file_name.parts[1:]))
442442
else:
443443
if not docname:
444444
if self.docname:
@@ -447,7 +447,7 @@ def relfn2path(
447447
msg = 'docname'
448448
raise KeyError(msg)
449449
doc_dir = self.doc2path(docname, base=False).parent
450-
abs_fn = self.srcdir.joinpath(doc_dir, file_name).resolve()
450+
abs_fn = normalizepath(self.srcdir.joinpath(doc_dir, file_name))
451451

452452
rel_fn = _relative_path(abs_fn, self.srcdir)
453453
return rel_fn.as_posix(), os.fspath(abs_fn)

sphinx/util/osutil.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,14 @@ def path_stabilize(filepath: str | os.PathLike[str], /) -> str:
4343
return unicodedata.normalize('NFC', new_path)
4444

4545

46+
def normalize_path(filepath: Path, /) -> Path:
47+
"""Normalize path by removing redundant separators and up-level references.
48+
49+
This *does not* resolve symbolic links.
50+
"""
51+
return filepath.__class__(os.path.normpath(filepath))
52+
53+
4654
def relative_uri(base: str, to: str) -> str:
4755
"""Return a relative URL from ``base`` to ``to``."""
4856
if to.startswith(SEP):
@@ -179,9 +187,9 @@ def _relative_path(path: Path, root: Path, /) -> Path:
179187
"""
180188
# Path.relative_to() requires fully-resolved paths (no '..').
181189
if '..' in path.parts:
182-
path = path.resolve()
190+
path = normalize_path(path)
183191
if '..' in root.parts:
184-
root = root.resolve()
192+
root = normalize_path(root)
185193

186194
if path.anchor != root.anchor or '..' in root.parts:
187195
# If the drives are different, no relative path exists.

0 commit comments

Comments
 (0)