Skip to content

Commit a7d0f05

Browse files
committed
simplified pathlib
1 parent 7fa747a commit a7d0f05

File tree

1 file changed

+15
-219
lines changed

1 file changed

+15
-219
lines changed

pathlib/pathlib.py

Lines changed: 15 additions & 219 deletions
Original file line numberDiff line numberDiff line change
@@ -17,20 +17,11 @@
1717

1818

1919
supports_symlinks = True
20-
if os.name == 'nt':
21-
import nt
22-
if sys.getwindowsversion()[:2] >= (6, 0):
23-
from nt import _getfinalpathname
24-
else:
25-
supports_symlinks = False
26-
_getfinalpathname = None
27-
else:
28-
nt = None
2920

3021

3122
__all__ = [
32-
"PurePath", "PurePosixPath", "PureWindowsPath",
33-
"Path", "PosixPath", "WindowsPath",
23+
"PurePath", "PurePosixPath",
24+
"Path", "PosixPath",
3425
]
3526

3627
#
@@ -119,178 +110,13 @@ def join_parsed_parts(self, drv, root, parts, drv2, root2, parts2):
119110
return drv2, root2, parts2
120111

121112

122-
class _WindowsFlavour(_Flavour):
123-
# Reference for Windows paths can be found at
124-
# http://msdn.microsoft.com/en-us/library/aa365247%28v=vs.85%29.aspx
125-
126-
sep = '\\'
127-
altsep = '/'
128-
has_drv = True
129-
pathmod = ntpath
130-
131-
is_supported = (os.name == 'nt')
132-
133-
drive_letters = set('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ')
134-
ext_namespace_prefix = '\\\\?\\'
135-
136-
reserved_names = (
137-
{'CON', 'PRN', 'AUX', 'NUL'} |
138-
{'COM%d' % i for i in range(1, 10)} |
139-
{'LPT%d' % i for i in range(1, 10)}
140-
)
141-
142-
# Interesting findings about extended paths:
143-
# - '\\?\c:\a', '//?/c:\a' and '//?/c:/a' are all supported
144-
# but '\\?\c:/a' is not
145-
# - extended paths are always absolute; "relative" extended paths will
146-
# fail.
147-
148-
def splitroot(self, part, sep=sep):
149-
first = part[0:1]
150-
second = part[1:2]
151-
if (second == sep and first == sep):
152-
# XXX extended paths should also disable the collapsing of "."
153-
# components (according to MSDN docs).
154-
prefix, part = self._split_extended_path(part)
155-
first = part[0:1]
156-
second = part[1:2]
157-
else:
158-
prefix = ''
159-
third = part[2:3]
160-
if (second == sep and first == sep and third != sep):
161-
# is a UNC path:
162-
# vvvvvvvvvvvvvvvvvvvvv root
163-
# \\machine\mountpoint\directory\etc\...
164-
# directory ^^^^^^^^^^^^^^
165-
index = part.find(sep, 2)
166-
if index != -1:
167-
index2 = part.find(sep, index + 1)
168-
# a UNC path can't have two slashes in a row
169-
# (after the initial two)
170-
if index2 != index + 1:
171-
if index2 == -1:
172-
index2 = len(part)
173-
if prefix:
174-
return prefix + part[1:index2], sep, part[index2+1:]
175-
else:
176-
return part[:index2], sep, part[index2+1:]
177-
drv = root = ''
178-
if second == ':' and first in self.drive_letters:
179-
drv = part[:2]
180-
part = part[2:]
181-
first = third
182-
if first == sep:
183-
root = first
184-
part = part.lstrip(sep)
185-
return prefix + drv, root, part
186-
187-
def casefold(self, s):
188-
return s.lower()
189-
190-
def casefold_parts(self, parts):
191-
return [p.lower() for p in parts]
192-
193-
def compile_pattern(self, pattern):
194-
return re.compile(fnmatch.translate(pattern), re.IGNORECASE).fullmatch
195-
196-
def resolve(self, path, strict=False):
197-
s = str(path)
198-
if not s:
199-
return os.getcwd()
200-
previous_s = None
201-
if _getfinalpathname is not None:
202-
if strict:
203-
return self._ext_to_normal(_getfinalpathname(s))
204-
else:
205-
tail_parts = [] # End of the path after the first one not found
206-
while True:
207-
try:
208-
s = self._ext_to_normal(_getfinalpathname(s))
209-
except FileNotFoundError:
210-
previous_s = s
211-
s, tail = os.path.split(s)
212-
tail_parts.append(tail)
213-
if previous_s == s:
214-
return path
215-
else:
216-
return os.path.join(s, *reversed(tail_parts))
217-
# Means fallback on absolute
218-
return None
219-
220-
def _split_extended_path(self, s, ext_prefix=ext_namespace_prefix):
221-
prefix = ''
222-
if s.startswith(ext_prefix):
223-
prefix = s[:4]
224-
s = s[4:]
225-
if s.startswith('UNC\\'):
226-
prefix += s[:3]
227-
s = '\\' + s[3:]
228-
return prefix, s
229-
230-
def _ext_to_normal(self, s):
231-
# Turn back an extended path into a normal DOS-like path
232-
return self._split_extended_path(s)[1]
233-
234-
def is_reserved(self, parts):
235-
# NOTE: the rules for reserved names seem somewhat complicated
236-
# (e.g. r"..\NUL" is reserved but not r"foo\NUL").
237-
# We err on the side of caution and return True for paths which are
238-
# not considered reserved by Windows.
239-
if not parts:
240-
return False
241-
if parts[0].startswith('\\\\'):
242-
# UNC paths are never reserved
243-
return False
244-
return parts[-1].partition('.')[0].upper() in self.reserved_names
245-
246-
def make_uri(self, path):
247-
# Under Windows, file URIs use the UTF-8 encoding.
248-
drive = path.drive
249-
if len(drive) == 2 and drive[1] == ':':
250-
# It's a path on a local drive => 'file:///c:/a/b'
251-
rest = path.as_posix()[2:].lstrip('/')
252-
return 'file:///%s/%s' % (
253-
drive, urlquote_from_bytes(rest.encode('utf-8')))
254-
else:
255-
# It's a path on a network drive => 'file://host/share/a/b'
256-
return 'file:' + urlquote_from_bytes(path.as_posix().encode('utf-8'))
257-
258-
def gethomedir(self, username):
259-
if 'USERPROFILE' in os.environ:
260-
userhome = os.environ['USERPROFILE']
261-
elif 'HOMEPATH' in os.environ:
262-
try:
263-
drv = os.environ['HOMEDRIVE']
264-
except KeyError:
265-
drv = ''
266-
userhome = drv + os.environ['HOMEPATH']
267-
else:
268-
raise RuntimeError("Can't determine home directory")
269-
270-
if username:
271-
# Try to guess user home directory. By default all users
272-
# directories are located in the same place and are named by
273-
# corresponding usernames. If current user home directory points
274-
# to nonstandard place, this guess is likely wrong.
275-
if os.environ['USERNAME'] != username:
276-
drv, root, parts = self.parse_parts((userhome,))
277-
if parts[-1] != os.environ['USERNAME']:
278-
raise RuntimeError("Can't determine home directory "
279-
"for %r" % username)
280-
parts[-1] = username
281-
if drv or root:
282-
userhome = drv + root + self.join(parts[1:])
283-
else:
284-
userhome = self.join(parts)
285-
return userhome
286-
287113
class _PosixFlavour(_Flavour):
288114
sep = '/'
289115
altsep = ''
290116
has_drv = False
291117
pathmod = posixpath
292118

293-
is_supported = (os.name != 'nt')
119+
is_supported = True
294120

295121
def splitroot(self, part, sep=sep):
296122
if part and part[0] == sep:
@@ -449,17 +275,10 @@ def replace(self, src, dst):
449275

450276
mkdir = os.mkdir
451277

452-
if nt:
453-
if supports_symlinks:
454-
symlink = os.symlink
455-
else:
456-
def symlink(a, b, target_is_directory):
457-
raise NotImplementedError("symlink() not available on this system")
458-
else:
459-
# Under POSIX, os.symlink() takes two args
460-
@staticmethod
461-
def symlink(a, b, target_is_directory):
462-
return os.symlink(a, b)
278+
# Under POSIX, os.symlink() takes two args
279+
@staticmethod
280+
def symlink(a, b, target_is_directory):
281+
return os.symlink(a, b)
463282

464283
utime = os.utime
465284

@@ -660,10 +479,9 @@ class PurePath(object):
660479
"""Base class for manipulating paths without I/O.
661480
662481
PurePath represents a filesystem path and offers operations which
663-
don't imply any actual filesystem I/O. Depending on your system,
664-
instantiating a PurePath will return either a PurePosixPath or a
665-
PureWindowsPath object. You can also instantiate either of these classes
666-
directly, regardless of your system.
482+
don't imply any actual filesystem I/O. Instantiating a PurePath will
483+
return a PurePosixPath object. You can also instantiate either of
484+
these classes directly, regardless of your system.
667485
"""
668486
__slots__ = (
669487
'_drv', '_root', '_parts',
@@ -677,7 +495,7 @@ def __new__(cls, *args):
677495
new PurePath object.
678496
"""
679497
if cls is PurePath:
680-
cls = PureWindowsPath if os.name == 'nt' else PurePosixPath
498+
cls = PurePosixPath
681499
return cls._from_parts(args)
682500

683501
def __reduce__(self):
@@ -1059,35 +877,24 @@ class PurePosixPath(PurePath):
1059877
__slots__ = ()
1060878

1061879

1062-
class PureWindowsPath(PurePath):
1063-
"""PurePath subclass for Windows systems.
1064-
1065-
On a Windows system, instantiating a PurePath should return this object.
1066-
However, you can also instantiate it directly on any system.
1067-
"""
1068-
_flavour = _windows_flavour
1069-
__slots__ = ()
1070-
1071-
1072880
# Filesystem-accessing classes
1073881

1074882

1075883
class Path(PurePath):
1076884
"""PurePath subclass that can make system calls.
1077885
1078886
Path represents a filesystem path but unlike PurePath, also offers
1079-
methods to do system calls on path objects. Depending on your system,
1080-
instantiating a Path will return either a PosixPath or a WindowsPath
1081-
object. You can also instantiate a PosixPath or WindowsPath directly,
1082-
but cannot instantiate a WindowsPath on a POSIX system or vice versa.
887+
methods to do system calls on path objects. Instantiating a Path will
888+
return a PosixPath object. You can also instantiate a PosixPath
889+
directly.
1083890
"""
1084891
__slots__ = (
1085892
'_accessor',
1086893
)
1087894

1088895
def __new__(cls, *args, **kwargs):
1089896
if cls is Path:
1090-
cls = WindowsPath if os.name == 'nt' else PosixPath
897+
cls = PosixPath
1091898
self = cls._from_parts(args, init=False)
1092899
if not self._flavour.is_supported:
1093900
raise NotImplementedError("cannot instantiate %r on your system"
@@ -1209,8 +1016,6 @@ def absolute(self):
12091016
# XXX untested yet!
12101017
if self.is_absolute():
12111018
return self
1212-
# FIXME this must defer to the specific flavour (and, under Windows,
1213-
# use nt._getfullpathname())
12141019
obj = self._from_parts([os.getcwd()] + self._parts, init=False)
12151020
obj._init(template=self)
12161021
return obj
@@ -1585,12 +1390,3 @@ class PosixPath(Path, PurePosixPath):
15851390
"""
15861391
__slots__ = ()
15871392

1588-
class WindowsPath(Path, PureWindowsPath):
1589-
"""Path subclass for Windows systems.
1590-
1591-
On a Windows system, instantiating a Path should return this object.
1592-
"""
1593-
__slots__ = ()
1594-
1595-
def is_mount(self):
1596-
raise NotImplementedError("Path.is_mount() is unsupported on this system")

0 commit comments

Comments
 (0)