Skip to content

Commit 230ccf2

Browse files
committed
Use _StrPath in sphinx.environment
1 parent e834327 commit 230ccf2

File tree

2 files changed

+32
-19
lines changed

2 files changed

+32
-19
lines changed

sphinx/environment/__init__.py

Lines changed: 16 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44

55
import functools
66
import os
7-
import os.path
87
import pickle
98
from collections import defaultdict
109
from copy import copy
@@ -28,7 +27,7 @@
2827
from sphinx.util.docutils import LoggingReporter
2928
from sphinx.util.i18n import CatalogRepository, docname_to_domain
3029
from sphinx.util.nodes import is_translatable
31-
from sphinx.util.osutil import _last_modified_time, canon_path, os_path
30+
from sphinx.util.osutil import _last_modified_time, _relative_path, canon_path
3231

3332
if TYPE_CHECKING:
3433
from collections.abc import Callable, Iterable, Iterator
@@ -419,17 +418,15 @@ def relfn2path(self, filename: str, docname: str | None = None) -> tuple[str, st
419418
source dir, while relative filenames are relative to the dir of the
420419
containing document.
421420
"""
422-
filename = os_path(filename)
423-
if filename.startswith(('/', os.sep)):
424-
rel_fn = filename[1:]
421+
filename = canon_path(filename)
422+
if filename.startswith('/'):
423+
abs_fn = (self.srcdir / filename[1:]).resolve()
425424
else:
426-
docdir = os.path.dirname(self.doc2path(docname or self.docname, base=False))
427-
rel_fn = os.path.join(docdir, filename)
425+
doc_dir = self.doc2path(docname or self.docname, base=False).parent
426+
abs_fn = (self.srcdir / doc_dir / filename).resolve()
428427

429-
return (
430-
canon_path(os.path.normpath(rel_fn)),
431-
os.path.normpath(os.path.join(self.srcdir, rel_fn)),
432-
)
428+
rel_fn = _relative_path(abs_fn, self.srcdir)
429+
return canon_path(rel_fn), os.fspath(abs_fn)
433430

434431
@property
435432
def found_docs(self) -> set[str]:
@@ -492,8 +489,8 @@ def get_outdated_files(
492489
added.add(docname)
493490
continue
494491
# if the doctree file is not there, rebuild
495-
filename = os.path.join(self.doctreedir, docname + '.doctree')
496-
if not os.path.isfile(filename):
492+
filename = self.doctreedir / f'{docname}.doctree'
493+
if not filename.is_file():
497494
logger.debug('[build target] changed %r', docname)
498495
changed.add(docname)
499496
continue
@@ -518,21 +515,21 @@ def get_outdated_files(
518515
for dep in self.dependencies[docname]:
519516
try:
520517
# this will do the right thing when dep is absolute too
521-
deppath = os.path.join(self.srcdir, dep)
522-
if not os.path.isfile(deppath):
518+
dep_path = self.srcdir / dep
519+
if not dep_path.is_file():
523520
logger.debug(
524521
'[build target] changed %r missing dependency %r',
525522
docname,
526-
deppath,
523+
dep_path,
527524
)
528525
changed.add(docname)
529526
break
530-
depmtime = _last_modified_time(deppath)
527+
depmtime = _last_modified_time(dep_path)
531528
if depmtime > mtime:
532529
logger.debug(
533530
'[build target] outdated %r from dependency %r: %s -> %s',
534531
docname,
535-
deppath,
532+
dep_path,
536533
_format_rfc3339_microseconds(mtime),
537534
_format_rfc3339_microseconds(depmtime),
538535
)
@@ -632,7 +629,7 @@ def get_doctree(self, docname: str) -> nodes.document:
632629
try:
633630
serialised = self._pickled_doctree_cache[docname]
634631
except KeyError:
635-
filename = os.path.join(self.doctreedir, docname + '.doctree')
632+
filename = self.doctreedir / f'{docname}.doctree'
636633
with open(filename, 'rb') as f:
637634
serialised = self._pickled_doctree_cache[docname] = f.read()
638635

sphinx/util/osutil.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,22 @@ def relpath(
169169
return str(path)
170170

171171

172+
def _relative_path(path: Path, root: Path, /) -> Path:
173+
"""Return a relative filepath to *path* from the given *root* directory.
174+
175+
This is an alternative of ``Path.relative_to``.
176+
It returns the original path if *path* and *root* are on different drives,
177+
which may happen on Windows.
178+
"""
179+
if path.anchor != root.anchor or '..' in root.parts:
180+
# If the drives are different, no relative path exists.
181+
# Path.relative_to() requires fully-resolved paths (no '..').
182+
return path
183+
if sys.version_info[:2] < (3, 12):
184+
return Path(os.path.relpath(path, root))
185+
return path.relative_to(root, walk_up=True)
186+
187+
172188
safe_relpath = relpath # for compatibility
173189
fs_encoding = sys.getfilesystemencoding() or sys.getdefaultencoding()
174190

0 commit comments

Comments
 (0)