Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
94 commits
Select commit Hold shift + click to select a range
59f7fde
GH-118289: Fix handling of non-directories in `os.path.realpath()`
barneygale Apr 25, 2024
382b31a
Skip test on Windows.
barneygale Apr 25, 2024
5ac4469
Avoid catching and re-throwing exception.
barneygale Apr 25, 2024
84e7c32
reversed() --> slice.
barneygale May 18, 2024
8fa3426
Merge branch 'main' into gh-118289
barneygale May 18, 2024
82b25a9
Expand tests
barneygale May 18, 2024
eb9bfd6
Simplify changes
barneygale May 18, 2024
5854d72
Use native ELOOP string.
barneygale May 29, 2024
3390dbc
Clarify news
barneygale May 29, 2024
e327b81
Merge branch 'main' into gh-118289
barneygale May 29, 2024
f889383
Revert "Clarify news"
barneygale May 29, 2024
2362e22
Apply suggestions from code review
barneygale May 29, 2024
53a81ce
Merge branch 'main' into gh-118289
barneygale May 31, 2024
4dc3fed
statistics.fmean(): speed-up code path for non-sizeable inputs. (gh-1…
rhettinger May 31, 2024
5c79eb4
gh-74929: PEP 667 C API documentation (gh-119379)
ncoghlan Jun 1, 2024
1e0b92e
gh-118888: Further PEP 667 docs updates (gh-119893)
ncoghlan Jun 1, 2024
d56d198
build(deps-dev): bump types-setuptools from 69.5.0.20240423 to 70.0.0…
dependabot[bot] Jun 1, 2024
79ad8f3
Bump types-psutil from 5.9.5.20240423 to 5.9.5.20240516 in /Tools (#1…
dependabot[bot] Jun 1, 2024
fe0d997
gh-117657: Fix TSAN race in free-threaded GC (#119883)
colesbury Jun 1, 2024
d60317e
gh-117657: Fix TSAN race in QSBR assertion (#119887)
colesbury Jun 1, 2024
2364923
Minor speed/accuracy improvement for kde() (gh-119910)
rhettinger Jun 1, 2024
525722c
gh-113892: Add a extra check to `ProactorEventLoop.sock_connect` to e…
Eclips4 Jun 1, 2024
50f9637
gh-117657: Add TSAN suppression for `set_discard_entry` (#119908)
colesbury Jun 1, 2024
33db150
Add unique() recipe to itertools docs (gh-119911)
rhettinger Jun 1, 2024
39998dd
GH-89727: Fix `shutil.rmtree()` recursion error on deep trees (#119808)
barneygale Jun 1, 2024
c7a70cd
gh-119016: Remove outdated sentences from the "classes" tutorial (#11…
nineteendo Jun 1, 2024
afe17fd
Refactor (mostly rearrange) the statistics module (gh-119930)
rhettinger Jun 2, 2024
bb2c6c5
gh-118934: Fix PyEval_GetLocals docs (PEP 667) (#119932)
ncoghlan Jun 2, 2024
d4aba40
gh-119775: Remove ability to create immutable types with mutable base…
sobolevn Jun 2, 2024
c0c837a
gh-119740: Remove deprecated trunc delegation (#119743)
mdickinson Jun 2, 2024
e2633ae
gh-117657: Fix TSAN reported race in `_PyEval_IsGILEnabled`. (#119921)
colesbury Jun 2, 2024
0b2cb6a
Improve documentation for typing.get_type_hints (#119928)
JelleZijlstra Jun 2, 2024
75992d8
GH-119054: Add "Reading and writing files" section to pathlib docs (#…
barneygale Jun 2, 2024
e9cef42
gh-109975: What's New in Python 3.13: fix broken link for `telnetlib`…
TechSolomon Jun 3, 2024
ad9cff9
gh-117657: Fix data races report by TSAN unicode-hash (gh-119907)
corona10 Jun 3, 2024
d5cc722
gh-119961: Fix test workflow status badge in README (#119962)
wookie184 Jun 3, 2024
dba3cb1
gh-119396: Optimize unicode_decode_utf8_writer() (#119957)
vstinner Jun 3, 2024
cdebef6
gh-119506: fix `_io.TextIOWrapper.write()` write during flush (#119507)
chgnrdv Jun 3, 2024
1a2aa10
gh-118827: Remove `Quoter` from `urllib.parse` (#118828)
sobolevn Jun 3, 2024
1831319
gh-116991: Improve `pygen --help` for `python` subparser (#116992)
sobolevn Jun 3, 2024
ef4c264
gh-119856: Support exiting help() with just "exit" (#119858)
vstinner Jun 3, 2024
02f2a16
gh-112026: Deprecate _PyDict_GetItemStringWithError() function (#119855)
vstinner Jun 3, 2024
1f52e84
gh-119838: Treat Fraction as a real value in mixed arithmetic operati…
serhiy-storchaka Jun 3, 2024
6c84d03
gh-119968: Improved monitoring c-api docs (#119969)
SweetyAngel Jun 3, 2024
400bfbd
gh-119786: move exception handling doc to InternalDocs (#119815)
iritkatriel Jun 3, 2024
204a262
gh-116560: Add PyLong_GetSign() public function (#116561)
skirpichev Jun 3, 2024
ba68289
gh-102511: Amend 3.13.0b1.rst (GH-119895)
nineteendo Jun 3, 2024
add5b46
gh-119679: Ensures correct import libraries are included in Windows i…
zooba Jun 3, 2024
25d0a68
gh-119588: Implement zipfile.Path.is_symlink (zipp 3.19.0). (#119591)
jaraco Jun 3, 2024
e286062
Use Cirrus M1 macOS runners for CI (GH-119979)
ambv Jun 3, 2024
26671c1
gh-119981: Use do while(0) in some symtable.c multi-line macros (#119…
picnixz Jun 3, 2024
bd3d2ef
gh-119057: Use better error messages for zero division (#119066)
sobolevn Jun 3, 2024
713d900
gh-119727: Add --single-process option to regrtest (#119728)
vstinner Jun 3, 2024
d70fb19
gh-118835: pyrepl: Fix prompt length computation for custom prompts c…
danielhollas Jun 3, 2024
a232d05
gh-117657: Avoid `sem_clockwait` in TSAN (#119915)
colesbury Jun 3, 2024
6a14a98
update CODEOWNERS (#120003)
iritkatriel Jun 3, 2024
cc875fa
gh-117657: Fix race involving immortalizing objects (#119927)
colesbury Jun 3, 2024
40099b3
gh-117398: Add datetime Module State (gh-119810)
ericsnowcurrently Jun 3, 2024
e8ee15c
gh-117142: Support Importing ctypes in Isolated Interpreters (gh-119991)
ericsnowcurrently Jun 3, 2024
5a98e86
gh-117398: Use Per-Interpreter State for the _datetime Static Types (…
ericsnowcurrently Jun 3, 2024
e560568
gh-119724: Revert "bpo-45759: Better error messages for non-matching …
encukou Jun 4, 2024
3a5a5a5
gh-106531: Apply changes from importlib_resources 6.3.2 (#117054)
jaraco Jun 4, 2024
9b3fc31
gh-119879: str.find(): Utilize last character gap for two-way periodi…
Jun 4, 2024
74e1755
gh-119070: Update test_shebang_executable_extension to always use non…
zooba Jun 4, 2024
1f2c6eb
gh-119613: Soft deprecate the Py_MEMCPY() macro (#120020)
vstinner Jun 4, 2024
2313a8f
gh-111499: Fix PYTHONMALLOCSTATS at Python exit (#120021)
vstinner Jun 4, 2024
2007509
Fix typos in documentation and comments (#119763)
xyb Jun 4, 2024
74bbf0e
gh-118868: logging QueueHandler fix passing of kwargs (GH-118869)
Kaundur Jun 4, 2024
aff9a10
gh-119819: Fix regression to allow logging configuration with multipr…
vsajip Jun 4, 2024
d811474
gh-94808: Reorganize _make_posargs and mark unused code (GH-119227)
mjdominus Jun 4, 2024
9073dbb
gh-117657: Fix race involving GC and heap initialization (#119923)
colesbury Jun 4, 2024
f71ed10
gh-120029: export `DEF_TYPE_PARAM` compiler flag (#120028)
picnixz Jun 4, 2024
d34608d
gh-119588: Update docs to reflect decision to include the change with…
jaraco Jun 4, 2024
fbef7b9
gh-120041: Do not use append_to_screen when completions are visible (…
lysnikolaou Jun 4, 2024
74b7978
Fix incorrect pull GitHub link in What's New (#120045)
treyhunner Jun 4, 2024
234a5df
gh-89928: Fix integer conversion of device numbers (GH-31794)
serhiy-storchaka Jun 4, 2024
faefa59
gh-112672: Fix builtin Tkinter with Tcl 9.0 (GH-112681)
chrstphrchvz Jun 4, 2024
bb615c6
gh-120041: Refactor check for visible completion menu in completing_r…
lysnikolaou Jun 4, 2024
14567b1
gh-120039: Reduce expected timeout in test_siginterrupt_off (#120047)
colesbury Jun 4, 2024
456b92f
gh-119553: Clear reader on Ctrl-C command (GH-119801)
lysnikolaou Jun 4, 2024
59e59db
doc: Mention the missing reflected special methods for all binary ope…
paulofreitas Jun 4, 2024
6f95ea9
gh-119842: Honor PyOS_InputHook in the new REPL (GH-119843)
pablogsal Jun 4, 2024
bde52f1
gh-120048: Make `test_imaplib` faster (#120050)
colesbury Jun 4, 2024
a6fb23a
gh-119819: Update test to skip if _multiprocessing is unavailable. (G…
vsajip Jun 4, 2024
dd8d1d1
gh-119999: Fix potential race condition in `_Py_ExplicitMergeRefcount…
colesbury Jun 4, 2024
00e04cc
gh-119553: Fix console when pressing Ctrl-C within a multiline block …
lysnikolaou Jun 4, 2024
5d3fc6e
gh-114616: Improve docs regarding changes to caches representation in…
iritkatriel Jun 4, 2024
ac78acf
gh-120078: Fix struct_time attr typo tm_day -> tm_mday in Doc/library…
shoenot Jun 5, 2024
0cdb827
gh-119819: Update logging configuration to support joinable multiproc…
vsajip Jun 5, 2024
edb13f3
gh-119287: clarify doc on BaseExceptionGroup.derive and link to it fr…
iritkatriel Jun 5, 2024
ea9287b
gh-120065: Increase `collect_in_thread` period to 5 ms. (#120068)
colesbury Jun 5, 2024
37f92ed
gh-119786: add links to code in exception handling doc (#120077)
iritkatriel Jun 5, 2024
982da2a
gh-115225: Raise error on unsupported ISO 8601 time strings (#119339)
benchatt Jun 5, 2024
f974bc1
pathlib ABCs: remove duplicate `realpath()` implementation. (#119178)
barneygale Jun 5, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
GH-118289: Fix handling of non-directories in os.path.realpath()
In strict mode, raise `NotADirectoryError` if a file path is given with a
trailing slash, or subsequent dot segments.

We use a `part_count` variable rather than `len(rest)` because the `rest`
stack also contains markers for unresolved symlinks.
  • Loading branch information
barneygale committed Apr 25, 2024
commit 59f7fde03aa8659a42b23fab72737d8e47c3cedc
17 changes: 13 additions & 4 deletions Lib/posixpath.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
altsep = None
devnull = '/dev/null'

import errno
import os
import sys
import stat
Expand Down Expand Up @@ -421,6 +422,7 @@ def realpath(filename, *, strict=False):
# symlink path can be retrieved by popping again. The [::-1] slice is a
# very fast way of spelling list(reversed(...)).
rest = filename.split(sep)[::-1]
part_count = len(rest)

# The resolved path, which is absolute throughout this function.
# Note: getcwd() returns a normalized and symlink-free path.
Expand All @@ -432,12 +434,13 @@ def realpath(filename, *, strict=False):
# the same links.
seen = {}

while rest:
while part_count:
name = rest.pop()
if name is None:
# resolved symlink target
seen[rest.pop()] = path
continue
part_count -= 1
if not name or name == curdir:
# current dir
continue
Expand All @@ -450,8 +453,12 @@ def realpath(filename, *, strict=False):
else:
newpath = path + sep + name
try:
st = os.lstat(newpath)
if not stat.S_ISLNK(st.st_mode):
st_mode = os.lstat(newpath).st_mode
if stat.S_ISLNK(st_mode):
pass
elif part_count and not stat.S_ISDIR(st_mode):
raise NotADirectoryError(errno.ENOTDIR, "Not a directory", newpath)
else:
path = newpath
continue
except OSError:
Expand All @@ -474,6 +481,7 @@ def realpath(filename, *, strict=False):
continue
seen[newpath] = None # not resolved symlink
target = os.readlink(newpath)
target_parts = target.split(sep)
if target.startswith(sep):
# Symlink target is absolute; reset resolved path.
path = sep
Expand All @@ -483,7 +491,8 @@ def realpath(filename, *, strict=False):
rest.append(newpath)
rest.append(None)
# Push the unresolved symlink target parts onto the stack.
rest.extend(target.split(sep)[::-1])
rest.extend(reversed(target_parts))
part_count += len(target_parts)

return path

Expand Down
14 changes: 14 additions & 0 deletions Lib/test/test_posixpath.py
Original file line number Diff line number Diff line change
Expand Up @@ -660,6 +660,20 @@ def test_realpath_resolve_first(self):
safe_rmdir(ABSTFN + "/k")
safe_rmdir(ABSTFN)

def test_realpath_strict_nondir(self):
try:
with open(ABSTFN, 'w') as f:
f.write('test_posixpath wuz ere')
self.assertEqual(realpath(ABSTFN, strict=True), ABSTFN)
with self.assertRaises(NotADirectoryError):
realpath(ABSTFN + "/", strict=True)
with self.assertRaises(NotADirectoryError):
realpath(ABSTFN + "/.", strict=True)
with self.assertRaises(NotADirectoryError):
realpath(ABSTFN + "/subdir", strict=True)
finally:
os_helper.unlink(ABSTFN)

def test_relpath(self):
(real_getcwd, os.getcwd) = (os.getcwd, lambda: r"/home/user/bar")
try:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
:func:`os.path.realpath` now raises :exc:`NotADirectoryError` when *strict*
mode is enabled and a non-directory path with a trailing slash is supplied.