Skip to content

Commit b641825

Browse files
authored
gh-118507 : Refactor nt._path_is* to improve applicability for other cases (GH-118755)
1 parent de8f530 commit b641825

File tree

6 files changed

+453
-365
lines changed

6 files changed

+453
-365
lines changed

Lib/ntpath.py

Lines changed: 4 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -288,21 +288,6 @@ def dirname(p):
288288
return split(p)[0]
289289

290290

291-
# Is a path a junction?
292-
293-
if hasattr(os.stat_result, 'st_reparse_tag'):
294-
def isjunction(path):
295-
"""Test whether a path is a junction"""
296-
try:
297-
st = os.lstat(path)
298-
except (OSError, ValueError, AttributeError):
299-
return False
300-
return st.st_reparse_tag == stat.IO_REPARSE_TAG_MOUNT_POINT
301-
else:
302-
# Use genericpath.isjunction as imported above
303-
pass
304-
305-
306291
# Is a path a mount point?
307292
# Any drive letter root (eg c:\)
308293
# Any share UNC (eg \\server\share)
@@ -911,13 +896,15 @@ def commonpath(paths):
911896

912897

913898
try:
914-
# The isdir(), isfile(), islink() and exists() implementations in
915-
# genericpath use os.stat(). This is overkill on Windows. Use simpler
899+
# The isdir(), isfile(), islink(), exists() and lexists() implementations
900+
# in genericpath use os.stat(). This is overkill on Windows. Use simpler
916901
# builtin functions if they are available.
917902
from nt import _path_isdir as isdir
918903
from nt import _path_isfile as isfile
919904
from nt import _path_islink as islink
905+
from nt import _path_isjunction as isjunction
920906
from nt import _path_exists as exists
907+
from nt import _path_lexists as lexists
921908
except ImportError:
922909
# Use genericpath.* as imported above
923910
pass

Lib/test/test_genericpath.py

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,9 @@ def test_exists(self):
135135
self.assertIs(self.pathmodule.exists(filename), False)
136136
self.assertIs(self.pathmodule.exists(bfilename), False)
137137

138+
self.assertIs(self.pathmodule.lexists(filename), False)
139+
self.assertIs(self.pathmodule.lexists(bfilename), False)
140+
138141
create_file(filename)
139142

140143
self.assertIs(self.pathmodule.exists(filename), True)
@@ -145,14 +148,13 @@ def test_exists(self):
145148
self.assertIs(self.pathmodule.exists(filename + '\x00'), False)
146149
self.assertIs(self.pathmodule.exists(bfilename + b'\x00'), False)
147150

148-
if self.pathmodule is not genericpath:
149-
self.assertIs(self.pathmodule.lexists(filename), True)
150-
self.assertIs(self.pathmodule.lexists(bfilename), True)
151+
self.assertIs(self.pathmodule.lexists(filename), True)
152+
self.assertIs(self.pathmodule.lexists(bfilename), True)
151153

152-
self.assertIs(self.pathmodule.lexists(filename + '\udfff'), False)
153-
self.assertIs(self.pathmodule.lexists(bfilename + b'\xff'), False)
154-
self.assertIs(self.pathmodule.lexists(filename + '\x00'), False)
155-
self.assertIs(self.pathmodule.lexists(bfilename + b'\x00'), False)
154+
self.assertIs(self.pathmodule.lexists(filename + '\udfff'), False)
155+
self.assertIs(self.pathmodule.lexists(bfilename + b'\xff'), False)
156+
self.assertIs(self.pathmodule.lexists(filename + '\x00'), False)
157+
self.assertIs(self.pathmodule.lexists(bfilename + b'\x00'), False)
156158

157159
@unittest.skipUnless(hasattr(os, "pipe"), "requires os.pipe()")
158160
@unittest.skipIf(is_emscripten, "Emscripten pipe fds have no stat")

Lib/test/test_ntpath.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1095,6 +1095,27 @@ def test_isfile_driveletter(self):
10951095
raise unittest.SkipTest('SystemDrive is not defined or malformed')
10961096
self.assertFalse(os.path.isfile('\\\\.\\' + drive))
10971097

1098+
@unittest.skipUnless(hasattr(os, 'pipe'), "need os.pipe()")
1099+
def test_isfile_anonymous_pipe(self):
1100+
pr, pw = os.pipe()
1101+
try:
1102+
self.assertFalse(ntpath.isfile(pr))
1103+
finally:
1104+
os.close(pr)
1105+
os.close(pw)
1106+
1107+
@unittest.skipIf(sys.platform != 'win32', "windows only")
1108+
def test_isfile_named_pipe(self):
1109+
import _winapi
1110+
named_pipe = f'//./PIPE/python_isfile_test_{os.getpid()}'
1111+
h = _winapi.CreateNamedPipe(named_pipe,
1112+
_winapi.PIPE_ACCESS_INBOUND,
1113+
0, 1, 0, 0, 0, 0)
1114+
try:
1115+
self.assertFalse(ntpath.isfile(named_pipe))
1116+
finally:
1117+
_winapi.CloseHandle(h)
1118+
10981119
@unittest.skipIf(sys.platform != 'win32', "windows only")
10991120
def test_con_device(self):
11001121
self.assertFalse(os.path.isfile(r"\\.\CON"))
@@ -1114,8 +1135,12 @@ def test_fast_paths_in_use(self):
11141135
self.assertFalse(inspect.isfunction(os.path.isfile))
11151136
self.assertTrue(os.path.islink is nt._path_islink)
11161137
self.assertFalse(inspect.isfunction(os.path.islink))
1138+
self.assertTrue(os.path.isjunction is nt._path_isjunction)
1139+
self.assertFalse(inspect.isfunction(os.path.isjunction))
11171140
self.assertTrue(os.path.exists is nt._path_exists)
11181141
self.assertFalse(inspect.isfunction(os.path.exists))
1142+
self.assertTrue(os.path.lexists is nt._path_lexists)
1143+
self.assertFalse(inspect.isfunction(os.path.lexists))
11191144

11201145
@unittest.skipIf(os.name != 'nt', "Dev Drives only exist on Win32")
11211146
def test_isdevdrive(self):
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Speedup :func:`os.path.isjunction` and :func:`os.path.lexists` on Windows with a native implementation.

Modules/clinic/posixmodule.c.h

Lines changed: 124 additions & 32 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy