pathlib.py 53 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593
  1. import fnmatch
  2. import functools
  3. import io
  4. import ntpath
  5. import os
  6. import posixpath
  7. import re
  8. import sys
  9. from _collections_abc import Sequence
  10. from errno import EINVAL, ENOENT, ENOTDIR, EBADF, ELOOP
  11. from operator import attrgetter
  12. from stat import S_ISDIR, S_ISLNK, S_ISREG, S_ISSOCK, S_ISBLK, S_ISCHR, S_ISFIFO
  13. from urllib.parse import quote_from_bytes as urlquote_from_bytes
  14. supports_symlinks = True
  15. if os.name == 'nt':
  16. import nt
  17. if sys.getwindowsversion()[:2] >= (6, 0):
  18. from nt import _getfinalpathname
  19. else:
  20. supports_symlinks = False
  21. _getfinalpathname = None
  22. else:
  23. nt = None
  24. __all__ = [
  25. "PurePath", "PurePosixPath", "PureWindowsPath",
  26. "Path", "PosixPath", "WindowsPath",
  27. ]
  28. #
  29. # Internals
  30. #
  31. # EBADF - guard against macOS `stat` throwing EBADF
  32. _IGNORED_ERROS = (ENOENT, ENOTDIR, EBADF, ELOOP)
  33. _IGNORED_WINERRORS = (
  34. 21, # ERROR_NOT_READY - drive exists but is not accessible
  35. 123, # ERROR_INVALID_NAME - fix for bpo-35306
  36. 1921, # ERROR_CANT_RESOLVE_FILENAME - fix for broken symlink pointing to itself
  37. )
  38. def _ignore_error(exception):
  39. return (getattr(exception, 'errno', None) in _IGNORED_ERROS or
  40. getattr(exception, 'winerror', None) in _IGNORED_WINERRORS)
  41. def _is_wildcard_pattern(pat):
  42. # Whether this pattern needs actual matching using fnmatch, or can
  43. # be looked up directly as a file.
  44. return "*" in pat or "?" in pat or "[" in pat
  45. class _Flavour(object):
  46. """A flavour implements a particular (platform-specific) set of path
  47. semantics."""
  48. def __init__(self):
  49. self.join = self.sep.join
  50. def parse_parts(self, parts):
  51. parsed = []
  52. sep = self.sep
  53. altsep = self.altsep
  54. drv = root = ''
  55. it = reversed(parts)
  56. for part in it:
  57. if not part:
  58. continue
  59. if altsep:
  60. part = part.replace(altsep, sep)
  61. drv, root, rel = self.splitroot(part)
  62. if sep in rel:
  63. for x in reversed(rel.split(sep)):
  64. if x and x != '.':
  65. parsed.append(sys.intern(x))
  66. else:
  67. if rel and rel != '.':
  68. parsed.append(sys.intern(rel))
  69. if drv or root:
  70. if not drv:
  71. # If no drive is present, try to find one in the previous
  72. # parts. This makes the result of parsing e.g.
  73. # ("C:", "/", "a") reasonably intuitive.
  74. for part in it:
  75. if not part:
  76. continue
  77. if altsep:
  78. part = part.replace(altsep, sep)
  79. drv = self.splitroot(part)[0]
  80. if drv:
  81. break
  82. break
  83. if drv or root:
  84. parsed.append(drv + root)
  85. parsed.reverse()
  86. return drv, root, parsed
  87. def join_parsed_parts(self, drv, root, parts, drv2, root2, parts2):
  88. """
  89. Join the two paths represented by the respective
  90. (drive, root, parts) tuples. Return a new (drive, root, parts) tuple.
  91. """
  92. if root2:
  93. if not drv2 and drv:
  94. return drv, root2, [drv + root2] + parts2[1:]
  95. elif drv2:
  96. if drv2 == drv or self.casefold(drv2) == self.casefold(drv):
  97. # Same drive => second path is relative to the first
  98. return drv, root, parts + parts2[1:]
  99. else:
  100. # Second path is non-anchored (common case)
  101. return drv, root, parts + parts2
  102. return drv2, root2, parts2
  103. class _WindowsFlavour(_Flavour):
  104. # Reference for Windows paths can be found at
  105. # http://msdn.microsoft.com/en-us/library/aa365247%28v=vs.85%29.aspx
  106. sep = '\\'
  107. altsep = '/'
  108. has_drv = True
  109. pathmod = ntpath
  110. is_supported = (os.name == 'nt')
  111. drive_letters = set('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ')
  112. ext_namespace_prefix = '\\\\?\\'
  113. reserved_names = (
  114. {'CON', 'PRN', 'AUX', 'NUL', 'CONIN$', 'CONOUT$'} |
  115. {'COM%s' % c for c in '123456789\xb9\xb2\xb3'} |
  116. {'LPT%s' % c for c in '123456789\xb9\xb2\xb3'}
  117. )
  118. # Interesting findings about extended paths:
  119. # * '\\?\c:\a' is an extended path, which bypasses normal Windows API
  120. # path processing. Thus relative paths are not resolved and slash is not
  121. # translated to backslash. It has the native NT path limit of 32767
  122. # characters, but a bit less after resolving device symbolic links,
  123. # such as '\??\C:' => '\Device\HarddiskVolume2'.
  124. # * '\\?\c:/a' looks for a device named 'C:/a' because slash is a
  125. # regular name character in the object namespace.
  126. # * '\\?\c:\foo/bar' is invalid because '/' is illegal in NT filesystems.
  127. # The only path separator at the filesystem level is backslash.
  128. # * '//?/c:\a' and '//?/c:/a' are effectively equivalent to '\\.\c:\a' and
  129. # thus limited to MAX_PATH.
  130. # * Prior to Windows 8, ANSI API bytes paths are limited to MAX_PATH,
  131. # even with the '\\?\' prefix.
  132. def splitroot(self, part, sep=sep):
  133. first = part[0:1]
  134. second = part[1:2]
  135. if (second == sep and first == sep):
  136. # XXX extended paths should also disable the collapsing of "."
  137. # components (according to MSDN docs).
  138. prefix, part = self._split_extended_path(part)
  139. first = part[0:1]
  140. second = part[1:2]
  141. else:
  142. prefix = ''
  143. third = part[2:3]
  144. if (second == sep and first == sep and third != sep):
  145. # is a UNC path:
  146. # vvvvvvvvvvvvvvvvvvvvv root
  147. # \\machine\mountpoint\directory\etc\...
  148. # directory ^^^^^^^^^^^^^^
  149. index = part.find(sep, 2)
  150. if index != -1:
  151. index2 = part.find(sep, index + 1)
  152. # a UNC path can't have two slashes in a row
  153. # (after the initial two)
  154. if index2 != index + 1:
  155. if index2 == -1:
  156. index2 = len(part)
  157. if prefix:
  158. return prefix + part[1:index2], sep, part[index2+1:]
  159. else:
  160. return part[:index2], sep, part[index2+1:]
  161. drv = root = ''
  162. if second == ':' and first in self.drive_letters:
  163. drv = part[:2]
  164. part = part[2:]
  165. first = third
  166. if first == sep:
  167. root = first
  168. part = part.lstrip(sep)
  169. return prefix + drv, root, part
  170. def casefold(self, s):
  171. return s.lower()
  172. def casefold_parts(self, parts):
  173. return [p.lower() for p in parts]
  174. def compile_pattern(self, pattern):
  175. return re.compile(fnmatch.translate(pattern), re.IGNORECASE).fullmatch
  176. def resolve(self, path, strict=False):
  177. s = str(path)
  178. if not s:
  179. return os.getcwd()
  180. previous_s = None
  181. if _getfinalpathname is not None:
  182. if strict:
  183. return self._ext_to_normal(_getfinalpathname(s))
  184. else:
  185. tail_parts = [] # End of the path after the first one not found
  186. while True:
  187. try:
  188. s = self._ext_to_normal(_getfinalpathname(s))
  189. except FileNotFoundError:
  190. previous_s = s
  191. s, tail = os.path.split(s)
  192. tail_parts.append(tail)
  193. if previous_s == s:
  194. return path
  195. else:
  196. return os.path.join(s, *reversed(tail_parts))
  197. # Means fallback on absolute
  198. return None
  199. def _split_extended_path(self, s, ext_prefix=ext_namespace_prefix):
  200. prefix = ''
  201. if s.startswith(ext_prefix):
  202. prefix = s[:4]
  203. s = s[4:]
  204. if s.startswith('UNC\\'):
  205. prefix += s[:3]
  206. s = '\\' + s[3:]
  207. return prefix, s
  208. def _ext_to_normal(self, s):
  209. # Turn back an extended path into a normal DOS-like path
  210. return self._split_extended_path(s)[1]
  211. def is_reserved(self, parts):
  212. # NOTE: the rules for reserved names seem somewhat complicated
  213. # (e.g. r"..\NUL" is reserved but not r"foo\NUL" if "foo" does not
  214. # exist). We err on the side of caution and return True for paths
  215. # which are not considered reserved by Windows.
  216. if not parts:
  217. return False
  218. if parts[0].startswith('\\\\'):
  219. # UNC paths are never reserved
  220. return False
  221. name = parts[-1].partition('.')[0].partition(':')[0].rstrip(' ')
  222. return name.upper() in self.reserved_names
  223. def make_uri(self, path):
  224. # Under Windows, file URIs use the UTF-8 encoding.
  225. drive = path.drive
  226. if len(drive) == 2 and drive[1] == ':':
  227. # It's a path on a local drive => 'file:///c:/a/b'
  228. rest = path.as_posix()[2:].lstrip('/')
  229. return 'file:///%s/%s' % (
  230. drive, urlquote_from_bytes(rest.encode('utf-8')))
  231. else:
  232. # It's a path on a network drive => 'file://host/share/a/b'
  233. return 'file:' + urlquote_from_bytes(path.as_posix().encode('utf-8'))
  234. def gethomedir(self, username):
  235. if 'USERPROFILE' in os.environ:
  236. userhome = os.environ['USERPROFILE']
  237. elif 'HOMEPATH' in os.environ:
  238. try:
  239. drv = os.environ['HOMEDRIVE']
  240. except KeyError:
  241. drv = ''
  242. userhome = drv + os.environ['HOMEPATH']
  243. else:
  244. raise RuntimeError("Can't determine home directory")
  245. if username:
  246. # Try to guess user home directory. By default all users
  247. # directories are located in the same place and are named by
  248. # corresponding usernames. If current user home directory points
  249. # to nonstandard place, this guess is likely wrong.
  250. if os.environ['USERNAME'] != username:
  251. drv, root, parts = self.parse_parts((userhome,))
  252. if parts[-1] != os.environ['USERNAME']:
  253. raise RuntimeError("Can't determine home directory "
  254. "for %r" % username)
  255. parts[-1] = username
  256. if drv or root:
  257. userhome = drv + root + self.join(parts[1:])
  258. else:
  259. userhome = self.join(parts)
  260. return userhome
  261. class _PosixFlavour(_Flavour):
  262. sep = '/'
  263. altsep = ''
  264. has_drv = False
  265. pathmod = posixpath
  266. is_supported = (os.name != 'nt')
  267. def splitroot(self, part, sep=sep):
  268. if part and part[0] == sep:
  269. stripped_part = part.lstrip(sep)
  270. # According to POSIX path resolution:
  271. # http://pubs.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap04.html#tag_04_11
  272. # "A pathname that begins with two successive slashes may be
  273. # interpreted in an implementation-defined manner, although more
  274. # than two leading slashes shall be treated as a single slash".
  275. if len(part) - len(stripped_part) == 2:
  276. return '', sep * 2, stripped_part
  277. else:
  278. return '', sep, stripped_part
  279. else:
  280. return '', '', part
  281. def casefold(self, s):
  282. return s
  283. def casefold_parts(self, parts):
  284. return parts
  285. def compile_pattern(self, pattern):
  286. return re.compile(fnmatch.translate(pattern)).fullmatch
  287. def resolve(self, path, strict=False):
  288. sep = self.sep
  289. accessor = path._accessor
  290. seen = {}
  291. def _resolve(path, rest):
  292. if rest.startswith(sep):
  293. path = ''
  294. for name in rest.split(sep):
  295. if not name or name == '.':
  296. # current dir
  297. continue
  298. if name == '..':
  299. # parent dir
  300. path, _, _ = path.rpartition(sep)
  301. continue
  302. if path.endswith(sep):
  303. newpath = path + name
  304. else:
  305. newpath = path + sep + name
  306. if newpath in seen:
  307. # Already seen this path
  308. path = seen[newpath]
  309. if path is not None:
  310. # use cached value
  311. continue
  312. # The symlink is not resolved, so we must have a symlink loop.
  313. raise RuntimeError("Symlink loop from %r" % newpath)
  314. # Resolve the symbolic link
  315. try:
  316. target = accessor.readlink(newpath)
  317. except OSError as e:
  318. if e.errno != EINVAL and strict:
  319. raise
  320. # Not a symlink, or non-strict mode. We just leave the path
  321. # untouched.
  322. path = newpath
  323. else:
  324. seen[newpath] = None # not resolved symlink
  325. path = _resolve(path, target)
  326. seen[newpath] = path # resolved symlink
  327. return path
  328. # NOTE: according to POSIX, getcwd() cannot contain path components
  329. # which are symlinks.
  330. base = '' if path.is_absolute() else os.getcwd()
  331. return _resolve(base, str(path)) or sep
  332. def is_reserved(self, parts):
  333. return False
  334. def make_uri(self, path):
  335. # We represent the path using the local filesystem encoding,
  336. # for portability to other applications.
  337. bpath = bytes(path)
  338. return 'file://' + urlquote_from_bytes(bpath)
  339. def gethomedir(self, username):
  340. if not username:
  341. try:
  342. return os.environ['HOME']
  343. except KeyError:
  344. import pwd
  345. return pwd.getpwuid(os.getuid()).pw_dir
  346. else:
  347. import pwd
  348. try:
  349. return pwd.getpwnam(username).pw_dir
  350. except KeyError:
  351. raise RuntimeError("Can't determine home directory "
  352. "for %r" % username)
  353. _windows_flavour = _WindowsFlavour()
  354. _posix_flavour = _PosixFlavour()
  355. class _Accessor:
  356. """An accessor implements a particular (system-specific or not) way of
  357. accessing paths on the filesystem."""
  358. class _NormalAccessor(_Accessor):
  359. stat = os.stat
  360. lstat = os.lstat
  361. open = os.open
  362. listdir = os.listdir
  363. scandir = os.scandir
  364. chmod = os.chmod
  365. if hasattr(os, "lchmod"):
  366. lchmod = os.lchmod
  367. else:
  368. def lchmod(self, pathobj, mode):
  369. raise NotImplementedError("lchmod() not available on this system")
  370. mkdir = os.mkdir
  371. unlink = os.unlink
  372. if hasattr(os, "link"):
  373. link_to = os.link
  374. else:
  375. @staticmethod
  376. def link_to(self, target):
  377. raise NotImplementedError("os.link() not available on this system")
  378. rmdir = os.rmdir
  379. rename = os.rename
  380. replace = os.replace
  381. if nt:
  382. if supports_symlinks:
  383. symlink = os.symlink
  384. else:
  385. def symlink(a, b, target_is_directory):
  386. raise NotImplementedError("symlink() not available on this system")
  387. else:
  388. # Under POSIX, os.symlink() takes two args
  389. @staticmethod
  390. def symlink(a, b, target_is_directory):
  391. return os.symlink(a, b)
  392. utime = os.utime
  393. # Helper for resolve()
  394. def readlink(self, path):
  395. return os.readlink(path)
  396. def owner(self, path):
  397. try:
  398. import pwd
  399. return pwd.getpwuid(self.stat(path).st_uid).pw_name
  400. except ImportError:
  401. raise NotImplementedError("Path.owner() is unsupported on this system")
  402. def group(self, path):
  403. try:
  404. import grp
  405. return grp.getgrgid(self.stat(path).st_gid).gr_name
  406. except ImportError:
  407. raise NotImplementedError("Path.group() is unsupported on this system")
  408. _normal_accessor = _NormalAccessor()
  409. #
  410. # Globbing helpers
  411. #
  412. def _make_selector(pattern_parts, flavour):
  413. pat = pattern_parts[0]
  414. child_parts = pattern_parts[1:]
  415. if pat == '**':
  416. cls = _RecursiveWildcardSelector
  417. elif '**' in pat:
  418. raise ValueError("Invalid pattern: '**' can only be an entire path component")
  419. elif _is_wildcard_pattern(pat):
  420. cls = _WildcardSelector
  421. else:
  422. cls = _PreciseSelector
  423. return cls(pat, child_parts, flavour)
  424. if hasattr(functools, "lru_cache"):
  425. _make_selector = functools.lru_cache()(_make_selector)
  426. class _Selector:
  427. """A selector matches a specific glob pattern part against the children
  428. of a given path."""
  429. def __init__(self, child_parts, flavour):
  430. self.child_parts = child_parts
  431. if child_parts:
  432. self.successor = _make_selector(child_parts, flavour)
  433. self.dironly = True
  434. else:
  435. self.successor = _TerminatingSelector()
  436. self.dironly = False
  437. def select_from(self, parent_path):
  438. """Iterate over all child paths of `parent_path` matched by this
  439. selector. This can contain parent_path itself."""
  440. path_cls = type(parent_path)
  441. is_dir = path_cls.is_dir
  442. exists = path_cls.exists
  443. scandir = parent_path._accessor.scandir
  444. if not is_dir(parent_path):
  445. return iter([])
  446. return self._select_from(parent_path, is_dir, exists, scandir)
  447. class _TerminatingSelector:
  448. def _select_from(self, parent_path, is_dir, exists, scandir):
  449. yield parent_path
  450. class _PreciseSelector(_Selector):
  451. def __init__(self, name, child_parts, flavour):
  452. self.name = name
  453. _Selector.__init__(self, child_parts, flavour)
  454. def _select_from(self, parent_path, is_dir, exists, scandir):
  455. try:
  456. path = parent_path._make_child_relpath(self.name)
  457. if (is_dir if self.dironly else exists)(path):
  458. for p in self.successor._select_from(path, is_dir, exists, scandir):
  459. yield p
  460. except PermissionError:
  461. return
  462. class _WildcardSelector(_Selector):
  463. def __init__(self, pat, child_parts, flavour):
  464. self.match = flavour.compile_pattern(pat)
  465. _Selector.__init__(self, child_parts, flavour)
  466. def _select_from(self, parent_path, is_dir, exists, scandir):
  467. try:
  468. with scandir(parent_path) as scandir_it:
  469. entries = list(scandir_it)
  470. for entry in entries:
  471. if self.dironly:
  472. try:
  473. # "entry.is_dir()" can raise PermissionError
  474. # in some cases (see bpo-38894), which is not
  475. # among the errors ignored by _ignore_error()
  476. if not entry.is_dir():
  477. continue
  478. except OSError as e:
  479. if not _ignore_error(e):
  480. raise
  481. continue
  482. name = entry.name
  483. if self.match(name):
  484. path = parent_path._make_child_relpath(name)
  485. for p in self.successor._select_from(path, is_dir, exists, scandir):
  486. yield p
  487. except PermissionError:
  488. return
  489. class _RecursiveWildcardSelector(_Selector):
  490. def __init__(self, pat, child_parts, flavour):
  491. _Selector.__init__(self, child_parts, flavour)
  492. def _iterate_directories(self, parent_path, is_dir, scandir):
  493. yield parent_path
  494. try:
  495. with scandir(parent_path) as scandir_it:
  496. entries = list(scandir_it)
  497. for entry in entries:
  498. entry_is_dir = False
  499. try:
  500. entry_is_dir = entry.is_dir()
  501. except OSError as e:
  502. if not _ignore_error(e):
  503. raise
  504. if entry_is_dir and not entry.is_symlink():
  505. path = parent_path._make_child_relpath(entry.name)
  506. for p in self._iterate_directories(path, is_dir, scandir):
  507. yield p
  508. except PermissionError:
  509. return
  510. def _select_from(self, parent_path, is_dir, exists, scandir):
  511. try:
  512. yielded = set()
  513. try:
  514. successor_select = self.successor._select_from
  515. for starting_point in self._iterate_directories(parent_path, is_dir, scandir):
  516. for p in successor_select(starting_point, is_dir, exists, scandir):
  517. if p not in yielded:
  518. yield p
  519. yielded.add(p)
  520. finally:
  521. yielded.clear()
  522. except PermissionError:
  523. return
  524. #
  525. # Public API
  526. #
  527. class _PathParents(Sequence):
  528. """This object provides sequence-like access to the logical ancestors
  529. of a path. Don't try to construct it yourself."""
  530. __slots__ = ('_pathcls', '_drv', '_root', '_parts')
  531. def __init__(self, path):
  532. # We don't store the instance to avoid reference cycles
  533. self._pathcls = type(path)
  534. self._drv = path._drv
  535. self._root = path._root
  536. self._parts = path._parts
  537. def __len__(self):
  538. if self._drv or self._root:
  539. return len(self._parts) - 1
  540. else:
  541. return len(self._parts)
  542. def __getitem__(self, idx):
  543. if idx < 0 or idx >= len(self):
  544. raise IndexError(idx)
  545. return self._pathcls._from_parsed_parts(self._drv, self._root,
  546. self._parts[:-idx - 1])
  547. def __repr__(self):
  548. return "<{}.parents>".format(self._pathcls.__name__)
  549. class PurePath(object):
  550. """Base class for manipulating paths without I/O.
  551. PurePath represents a filesystem path and offers operations which
  552. don't imply any actual filesystem I/O. Depending on your system,
  553. instantiating a PurePath will return either a PurePosixPath or a
  554. PureWindowsPath object. You can also instantiate either of these classes
  555. directly, regardless of your system.
  556. """
  557. __slots__ = (
  558. '_drv', '_root', '_parts',
  559. '_str', '_hash', '_pparts', '_cached_cparts',
  560. )
  561. def __new__(cls, *args):
  562. """Construct a PurePath from one or several strings and or existing
  563. PurePath objects. The strings and path objects are combined so as
  564. to yield a canonicalized path, which is incorporated into the
  565. new PurePath object.
  566. """
  567. if cls is PurePath:
  568. cls = PureWindowsPath if os.name == 'nt' else PurePosixPath
  569. return cls._from_parts(args)
  570. def __reduce__(self):
  571. # Using the parts tuple helps share interned path parts
  572. # when pickling related paths.
  573. return (self.__class__, tuple(self._parts))
  574. @classmethod
  575. def _parse_args(cls, args):
  576. # This is useful when you don't want to create an instance, just
  577. # canonicalize some constructor arguments.
  578. parts = []
  579. for a in args:
  580. if isinstance(a, PurePath):
  581. parts += a._parts
  582. else:
  583. a = os.fspath(a)
  584. if isinstance(a, str):
  585. # Force-cast str subclasses to str (issue #21127)
  586. parts.append(str(a))
  587. else:
  588. raise TypeError(
  589. "argument should be a str object or an os.PathLike "
  590. "object returning str, not %r"
  591. % type(a))
  592. return cls._flavour.parse_parts(parts)
  593. @classmethod
  594. def _from_parts(cls, args, init=True):
  595. # We need to call _parse_args on the instance, so as to get the
  596. # right flavour.
  597. self = object.__new__(cls)
  598. drv, root, parts = self._parse_args(args)
  599. self._drv = drv
  600. self._root = root
  601. self._parts = parts
  602. if init:
  603. self._init()
  604. return self
  605. @classmethod
  606. def _from_parsed_parts(cls, drv, root, parts, init=True):
  607. self = object.__new__(cls)
  608. self._drv = drv
  609. self._root = root
  610. self._parts = parts
  611. if init:
  612. self._init()
  613. return self
  614. @classmethod
  615. def _format_parsed_parts(cls, drv, root, parts):
  616. if drv or root:
  617. return drv + root + cls._flavour.join(parts[1:])
  618. else:
  619. return cls._flavour.join(parts)
  620. def _init(self):
  621. # Overridden in concrete Path
  622. pass
  623. def _make_child(self, args):
  624. drv, root, parts = self._parse_args(args)
  625. drv, root, parts = self._flavour.join_parsed_parts(
  626. self._drv, self._root, self._parts, drv, root, parts)
  627. return self._from_parsed_parts(drv, root, parts)
  628. def __str__(self):
  629. """Return the string representation of the path, suitable for
  630. passing to system calls."""
  631. try:
  632. return self._str
  633. except AttributeError:
  634. self._str = self._format_parsed_parts(self._drv, self._root,
  635. self._parts) or '.'
  636. return self._str
  637. def __fspath__(self):
  638. return str(self)
  639. def as_posix(self):
  640. """Return the string representation of the path with forward (/)
  641. slashes."""
  642. f = self._flavour
  643. return str(self).replace(f.sep, '/')
  644. def __bytes__(self):
  645. """Return the bytes representation of the path. This is only
  646. recommended to use under Unix."""
  647. return os.fsencode(self)
  648. def __repr__(self):
  649. return "{}({!r})".format(self.__class__.__name__, self.as_posix())
  650. def as_uri(self):
  651. """Return the path as a 'file' URI."""
  652. if not self.is_absolute():
  653. raise ValueError("relative path can't be expressed as a file URI")
  654. return self._flavour.make_uri(self)
  655. @property
  656. def _cparts(self):
  657. # Cached casefolded parts, for hashing and comparison
  658. try:
  659. return self._cached_cparts
  660. except AttributeError:
  661. self._cached_cparts = self._flavour.casefold_parts(self._parts)
  662. return self._cached_cparts
  663. def __eq__(self, other):
  664. if not isinstance(other, PurePath):
  665. return NotImplemented
  666. return self._cparts == other._cparts and self._flavour is other._flavour
  667. def __hash__(self):
  668. try:
  669. return self._hash
  670. except AttributeError:
  671. self._hash = hash(tuple(self._cparts))
  672. return self._hash
  673. def __lt__(self, other):
  674. if not isinstance(other, PurePath) or self._flavour is not other._flavour:
  675. return NotImplemented
  676. return self._cparts < other._cparts
  677. def __le__(self, other):
  678. if not isinstance(other, PurePath) or self._flavour is not other._flavour:
  679. return NotImplemented
  680. return self._cparts <= other._cparts
  681. def __gt__(self, other):
  682. if not isinstance(other, PurePath) or self._flavour is not other._flavour:
  683. return NotImplemented
  684. return self._cparts > other._cparts
  685. def __ge__(self, other):
  686. if not isinstance(other, PurePath) or self._flavour is not other._flavour:
  687. return NotImplemented
  688. return self._cparts >= other._cparts
  689. def __class_getitem__(cls, type):
  690. return cls
  691. drive = property(attrgetter('_drv'),
  692. doc="""The drive prefix (letter or UNC path), if any.""")
  693. root = property(attrgetter('_root'),
  694. doc="""The root of the path, if any.""")
  695. @property
  696. def anchor(self):
  697. """The concatenation of the drive and root, or ''."""
  698. anchor = self._drv + self._root
  699. return anchor
  700. @property
  701. def name(self):
  702. """The final path component, if any."""
  703. parts = self._parts
  704. if len(parts) == (1 if (self._drv or self._root) else 0):
  705. return ''
  706. return parts[-1]
  707. @property
  708. def suffix(self):
  709. """
  710. The final component's last suffix, if any.
  711. This includes the leading period. For example: '.txt'
  712. """
  713. name = self.name
  714. i = name.rfind('.')
  715. if 0 < i < len(name) - 1:
  716. return name[i:]
  717. else:
  718. return ''
  719. @property
  720. def suffixes(self):
  721. """
  722. A list of the final component's suffixes, if any.
  723. These include the leading periods. For example: ['.tar', '.gz']
  724. """
  725. name = self.name
  726. if name.endswith('.'):
  727. return []
  728. name = name.lstrip('.')
  729. return ['.' + suffix for suffix in name.split('.')[1:]]
  730. @property
  731. def stem(self):
  732. """The final path component, minus its last suffix."""
  733. name = self.name
  734. i = name.rfind('.')
  735. if 0 < i < len(name) - 1:
  736. return name[:i]
  737. else:
  738. return name
  739. def with_name(self, name):
  740. """Return a new path with the file name changed."""
  741. if not self.name:
  742. raise ValueError("%r has an empty name" % (self,))
  743. drv, root, parts = self._flavour.parse_parts((name,))
  744. if (not name or name[-1] in [self._flavour.sep, self._flavour.altsep]
  745. or drv or root or len(parts) != 1):
  746. raise ValueError("Invalid name %r" % (name))
  747. return self._from_parsed_parts(self._drv, self._root,
  748. self._parts[:-1] + [name])
  749. def with_stem(self, stem):
  750. """Return a new path with the stem changed."""
  751. return self.with_name(stem + self.suffix)
  752. def with_suffix(self, suffix):
  753. """Return a new path with the file suffix changed. If the path
  754. has no suffix, add given suffix. If the given suffix is an empty
  755. string, remove the suffix from the path.
  756. """
  757. f = self._flavour
  758. if f.sep in suffix or f.altsep and f.altsep in suffix:
  759. raise ValueError("Invalid suffix %r" % (suffix,))
  760. if suffix and not suffix.startswith('.') or suffix == '.':
  761. raise ValueError("Invalid suffix %r" % (suffix))
  762. name = self.name
  763. if not name:
  764. raise ValueError("%r has an empty name" % (self,))
  765. old_suffix = self.suffix
  766. if not old_suffix:
  767. name = name + suffix
  768. else:
  769. name = name[:-len(old_suffix)] + suffix
  770. return self._from_parsed_parts(self._drv, self._root,
  771. self._parts[:-1] + [name])
  772. def relative_to(self, *other):
  773. """Return the relative path to another path identified by the passed
  774. arguments. If the operation is not possible (because this is not
  775. a subpath of the other path), raise ValueError.
  776. """
  777. # For the purpose of this method, drive and root are considered
  778. # separate parts, i.e.:
  779. # Path('c:/').relative_to('c:') gives Path('/')
  780. # Path('c:/').relative_to('/') raise ValueError
  781. if not other:
  782. raise TypeError("need at least one argument")
  783. parts = self._parts
  784. drv = self._drv
  785. root = self._root
  786. if root:
  787. abs_parts = [drv, root] + parts[1:]
  788. else:
  789. abs_parts = parts
  790. to_drv, to_root, to_parts = self._parse_args(other)
  791. if to_root:
  792. to_abs_parts = [to_drv, to_root] + to_parts[1:]
  793. else:
  794. to_abs_parts = to_parts
  795. n = len(to_abs_parts)
  796. cf = self._flavour.casefold_parts
  797. if (root or drv) if n == 0 else cf(abs_parts[:n]) != cf(to_abs_parts):
  798. formatted = self._format_parsed_parts(to_drv, to_root, to_parts)
  799. raise ValueError("{!r} is not in the subpath of {!r}"
  800. " OR one path is relative and the other is absolute."
  801. .format(str(self), str(formatted)))
  802. return self._from_parsed_parts('', root if n == 1 else '',
  803. abs_parts[n:])
  804. def is_relative_to(self, *other):
  805. """Return True if the path is relative to another path or False.
  806. """
  807. try:
  808. self.relative_to(*other)
  809. return True
  810. except ValueError:
  811. return False
  812. @property
  813. def parts(self):
  814. """An object providing sequence-like access to the
  815. components in the filesystem path."""
  816. # We cache the tuple to avoid building a new one each time .parts
  817. # is accessed. XXX is this necessary?
  818. try:
  819. return self._pparts
  820. except AttributeError:
  821. self._pparts = tuple(self._parts)
  822. return self._pparts
  823. def joinpath(self, *args):
  824. """Combine this path with one or several arguments, and return a
  825. new path representing either a subpath (if all arguments are relative
  826. paths) or a totally different path (if one of the arguments is
  827. anchored).
  828. """
  829. return self._make_child(args)
  830. def __truediv__(self, key):
  831. try:
  832. return self._make_child((key,))
  833. except TypeError:
  834. return NotImplemented
  835. def __rtruediv__(self, key):
  836. try:
  837. return self._from_parts([key] + self._parts)
  838. except TypeError:
  839. return NotImplemented
  840. @property
  841. def parent(self):
  842. """The logical parent of the path."""
  843. drv = self._drv
  844. root = self._root
  845. parts = self._parts
  846. if len(parts) == 1 and (drv or root):
  847. return self
  848. return self._from_parsed_parts(drv, root, parts[:-1])
  849. @property
  850. def parents(self):
  851. """A sequence of this path's logical parents."""
  852. return _PathParents(self)
  853. def is_absolute(self):
  854. """True if the path is absolute (has both a root and, if applicable,
  855. a drive)."""
  856. if not self._root:
  857. return False
  858. return not self._flavour.has_drv or bool(self._drv)
  859. def is_reserved(self):
  860. """Return True if the path contains one of the special names reserved
  861. by the system, if any."""
  862. return self._flavour.is_reserved(self._parts)
  863. def match(self, path_pattern):
  864. """
  865. Return True if this path matches the given pattern.
  866. """
  867. cf = self._flavour.casefold
  868. path_pattern = cf(path_pattern)
  869. drv, root, pat_parts = self._flavour.parse_parts((path_pattern,))
  870. if not pat_parts:
  871. raise ValueError("empty pattern")
  872. if drv and drv != cf(self._drv):
  873. return False
  874. if root and root != cf(self._root):
  875. return False
  876. parts = self._cparts
  877. if drv or root:
  878. if len(pat_parts) != len(parts):
  879. return False
  880. pat_parts = pat_parts[1:]
  881. elif len(pat_parts) > len(parts):
  882. return False
  883. for part, pat in zip(reversed(parts), reversed(pat_parts)):
  884. if not fnmatch.fnmatchcase(part, pat):
  885. return False
  886. return True
  887. # Can't subclass os.PathLike from PurePath and keep the constructor
  888. # optimizations in PurePath._parse_args().
  889. os.PathLike.register(PurePath)
  890. class PurePosixPath(PurePath):
  891. """PurePath subclass for non-Windows systems.
  892. On a POSIX system, instantiating a PurePath should return this object.
  893. However, you can also instantiate it directly on any system.
  894. """
  895. _flavour = _posix_flavour
  896. __slots__ = ()
  897. class PureWindowsPath(PurePath):
  898. """PurePath subclass for Windows systems.
  899. On a Windows system, instantiating a PurePath should return this object.
  900. However, you can also instantiate it directly on any system.
  901. """
  902. _flavour = _windows_flavour
  903. __slots__ = ()
  904. # Filesystem-accessing classes
  905. class Path(PurePath):
  906. """PurePath subclass that can make system calls.
  907. Path represents a filesystem path but unlike PurePath, also offers
  908. methods to do system calls on path objects. Depending on your system,
  909. instantiating a Path will return either a PosixPath or a WindowsPath
  910. object. You can also instantiate a PosixPath or WindowsPath directly,
  911. but cannot instantiate a WindowsPath on a POSIX system or vice versa.
  912. """
  913. __slots__ = (
  914. '_accessor',
  915. )
  916. def __new__(cls, *args, **kwargs):
  917. if cls is Path:
  918. cls = WindowsPath if os.name == 'nt' else PosixPath
  919. self = cls._from_parts(args, init=False)
  920. if not self._flavour.is_supported:
  921. raise NotImplementedError("cannot instantiate %r on your system"
  922. % (cls.__name__,))
  923. self._init()
  924. return self
  925. def _init(self,
  926. # Private non-constructor arguments
  927. template=None,
  928. ):
  929. if template is not None:
  930. self._accessor = template._accessor
  931. else:
  932. self._accessor = _normal_accessor
  933. def _make_child_relpath(self, part):
  934. # This is an optimization used for dir walking. `part` must be
  935. # a single part relative to this path.
  936. parts = self._parts + [part]
  937. return self._from_parsed_parts(self._drv, self._root, parts)
  938. def __enter__(self):
  939. return self
  940. def __exit__(self, t, v, tb):
  941. # https://bugs.python.org/issue39682
  942. # In previous versions of pathlib, this method marked this path as
  943. # closed; subsequent attempts to perform I/O would raise an IOError.
  944. # This functionality was never documented, and had the effect of
  945. # making Path objects mutable, contrary to PEP 428. In Python 3.9 the
  946. # _closed attribute was removed, and this method made a no-op.
  947. # This method and __enter__()/__exit__() should be deprecated and
  948. # removed in the future.
  949. pass
  950. def _opener(self, name, flags, mode=0o666):
  951. # A stub for the opener argument to built-in open()
  952. return self._accessor.open(self, flags, mode)
  953. def _raw_open(self, flags, mode=0o777):
  954. """
  955. Open the file pointed by this path and return a file descriptor,
  956. as os.open() does.
  957. """
  958. return self._accessor.open(self, flags, mode)
  959. # Public API
  960. @classmethod
  961. def cwd(cls):
  962. """Return a new path pointing to the current working directory
  963. (as returned by os.getcwd()).
  964. """
  965. return cls(os.getcwd())
  966. @classmethod
  967. def home(cls):
  968. """Return a new path pointing to the user's home directory (as
  969. returned by os.path.expanduser('~')).
  970. """
  971. return cls(cls()._flavour.gethomedir(None))
  972. def samefile(self, other_path):
  973. """Return whether other_path is the same or not as this file
  974. (as returned by os.path.samefile()).
  975. """
  976. st = self.stat()
  977. try:
  978. other_st = other_path.stat()
  979. except AttributeError:
  980. other_st = self._accessor.stat(other_path)
  981. return os.path.samestat(st, other_st)
  982. def iterdir(self):
  983. """Iterate over the files in this directory. Does not yield any
  984. result for the special paths '.' and '..'.
  985. """
  986. for name in self._accessor.listdir(self):
  987. if name in {'.', '..'}:
  988. # Yielding a path object for these makes little sense
  989. continue
  990. yield self._make_child_relpath(name)
  991. def glob(self, pattern):
  992. """Iterate over this subtree and yield all existing files (of any
  993. kind, including directories) matching the given relative pattern.
  994. """
  995. sys.audit("pathlib.Path.glob", self, pattern)
  996. if not pattern:
  997. raise ValueError("Unacceptable pattern: {!r}".format(pattern))
  998. drv, root, pattern_parts = self._flavour.parse_parts((pattern,))
  999. if drv or root:
  1000. raise NotImplementedError("Non-relative patterns are unsupported")
  1001. selector = _make_selector(tuple(pattern_parts), self._flavour)
  1002. for p in selector.select_from(self):
  1003. yield p
  1004. def rglob(self, pattern):
  1005. """Recursively yield all existing files (of any kind, including
  1006. directories) matching the given relative pattern, anywhere in
  1007. this subtree.
  1008. """
  1009. sys.audit("pathlib.Path.rglob", self, pattern)
  1010. drv, root, pattern_parts = self._flavour.parse_parts((pattern,))
  1011. if drv or root:
  1012. raise NotImplementedError("Non-relative patterns are unsupported")
  1013. selector = _make_selector(("**",) + tuple(pattern_parts), self._flavour)
  1014. for p in selector.select_from(self):
  1015. yield p
  1016. def absolute(self):
  1017. """Return an absolute version of this path. This function works
  1018. even if the path doesn't point to anything.
  1019. No normalization is done, i.e. all '.' and '..' will be kept along.
  1020. Use resolve() to get the canonical path to a file.
  1021. """
  1022. # XXX untested yet!
  1023. if self.is_absolute():
  1024. return self
  1025. # FIXME this must defer to the specific flavour (and, under Windows,
  1026. # use nt._getfullpathname())
  1027. obj = self._from_parts([os.getcwd()] + self._parts, init=False)
  1028. obj._init(template=self)
  1029. return obj
  1030. def resolve(self, strict=False):
  1031. """
  1032. Make the path absolute, resolving all symlinks on the way and also
  1033. normalizing it (for example turning slashes into backslashes under
  1034. Windows).
  1035. """
  1036. s = self._flavour.resolve(self, strict=strict)
  1037. if s is None:
  1038. # No symlink resolution => for consistency, raise an error if
  1039. # the path doesn't exist or is forbidden
  1040. self.stat()
  1041. s = str(self.absolute())
  1042. # Now we have no symlinks in the path, it's safe to normalize it.
  1043. normed = self._flavour.pathmod.normpath(s)
  1044. obj = self._from_parts((normed,), init=False)
  1045. obj._init(template=self)
  1046. return obj
  1047. def stat(self):
  1048. """
  1049. Return the result of the stat() system call on this path, like
  1050. os.stat() does.
  1051. """
  1052. return self._accessor.stat(self)
  1053. def owner(self):
  1054. """
  1055. Return the login name of the file owner.
  1056. """
  1057. return self._accessor.owner(self)
  1058. def group(self):
  1059. """
  1060. Return the group name of the file gid.
  1061. """
  1062. return self._accessor.group(self)
  1063. def open(self, mode='r', buffering=-1, encoding=None,
  1064. errors=None, newline=None):
  1065. """
  1066. Open the file pointed by this path and return a file object, as
  1067. the built-in open() function does.
  1068. """
  1069. return io.open(self, mode, buffering, encoding, errors, newline,
  1070. opener=self._opener)
  1071. def read_bytes(self):
  1072. """
  1073. Open the file in bytes mode, read it, and close the file.
  1074. """
  1075. with self.open(mode='rb') as f:
  1076. return f.read()
  1077. def read_text(self, encoding=None, errors=None):
  1078. """
  1079. Open the file in text mode, read it, and close the file.
  1080. """
  1081. with self.open(mode='r', encoding=encoding, errors=errors) as f:
  1082. return f.read()
  1083. def write_bytes(self, data):
  1084. """
  1085. Open the file in bytes mode, write to it, and close the file.
  1086. """
  1087. # type-check for the buffer interface before truncating the file
  1088. view = memoryview(data)
  1089. with self.open(mode='wb') as f:
  1090. return f.write(view)
  1091. def write_text(self, data, encoding=None, errors=None):
  1092. """
  1093. Open the file in text mode, write to it, and close the file.
  1094. """
  1095. if not isinstance(data, str):
  1096. raise TypeError('data must be str, not %s' %
  1097. data.__class__.__name__)
  1098. with self.open(mode='w', encoding=encoding, errors=errors) as f:
  1099. return f.write(data)
  1100. def readlink(self):
  1101. """
  1102. Return the path to which the symbolic link points.
  1103. """
  1104. path = self._accessor.readlink(self)
  1105. obj = self._from_parts((path,), init=False)
  1106. obj._init(template=self)
  1107. return obj
  1108. def touch(self, mode=0o666, exist_ok=True):
  1109. """
  1110. Create this file with the given access mode, if it doesn't exist.
  1111. """
  1112. if exist_ok:
  1113. # First try to bump modification time
  1114. # Implementation note: GNU touch uses the UTIME_NOW option of
  1115. # the utimensat() / futimens() functions.
  1116. try:
  1117. self._accessor.utime(self, None)
  1118. except OSError:
  1119. # Avoid exception chaining
  1120. pass
  1121. else:
  1122. return
  1123. flags = os.O_CREAT | os.O_WRONLY
  1124. if not exist_ok:
  1125. flags |= os.O_EXCL
  1126. fd = self._raw_open(flags, mode)
  1127. os.close(fd)
  1128. def mkdir(self, mode=0o777, parents=False, exist_ok=False):
  1129. """
  1130. Create a new directory at this given path.
  1131. """
  1132. try:
  1133. self._accessor.mkdir(self, mode)
  1134. except FileNotFoundError:
  1135. if not parents or self.parent == self:
  1136. raise
  1137. self.parent.mkdir(parents=True, exist_ok=True)
  1138. self.mkdir(mode, parents=False, exist_ok=exist_ok)
  1139. except OSError:
  1140. # Cannot rely on checking for EEXIST, since the operating system
  1141. # could give priority to other errors like EACCES or EROFS
  1142. if not exist_ok or not self.is_dir():
  1143. raise
  1144. def chmod(self, mode):
  1145. """
  1146. Change the permissions of the path, like os.chmod().
  1147. """
  1148. self._accessor.chmod(self, mode)
  1149. def lchmod(self, mode):
  1150. """
  1151. Like chmod(), except if the path points to a symlink, the symlink's
  1152. permissions are changed, rather than its target's.
  1153. """
  1154. self._accessor.lchmod(self, mode)
  1155. def unlink(self, missing_ok=False):
  1156. """
  1157. Remove this file or link.
  1158. If the path is a directory, use rmdir() instead.
  1159. """
  1160. try:
  1161. self._accessor.unlink(self)
  1162. except FileNotFoundError:
  1163. if not missing_ok:
  1164. raise
  1165. def rmdir(self):
  1166. """
  1167. Remove this directory. The directory must be empty.
  1168. """
  1169. self._accessor.rmdir(self)
  1170. def lstat(self):
  1171. """
  1172. Like stat(), except if the path points to a symlink, the symlink's
  1173. status information is returned, rather than its target's.
  1174. """
  1175. return self._accessor.lstat(self)
  1176. def rename(self, target):
  1177. """
  1178. Rename this path to the target path.
  1179. The target path may be absolute or relative. Relative paths are
  1180. interpreted relative to the current working directory, *not* the
  1181. directory of the Path object.
  1182. Returns the new Path instance pointing to the target path.
  1183. """
  1184. self._accessor.rename(self, target)
  1185. return self.__class__(target)
  1186. def replace(self, target):
  1187. """
  1188. Rename this path to the target path, overwriting if that path exists.
  1189. The target path may be absolute or relative. Relative paths are
  1190. interpreted relative to the current working directory, *not* the
  1191. directory of the Path object.
  1192. Returns the new Path instance pointing to the target path.
  1193. """
  1194. self._accessor.replace(self, target)
  1195. return self.__class__(target)
  1196. def symlink_to(self, target, target_is_directory=False):
  1197. """
  1198. Make this path a symlink pointing to the target path.
  1199. Note the order of arguments (link, target) is the reverse of os.symlink.
  1200. """
  1201. self._accessor.symlink(target, self, target_is_directory)
  1202. def link_to(self, target):
  1203. """
  1204. Make the target path a hard link pointing to this path.
  1205. Note this function does not make this path a hard link to *target*,
  1206. despite the implication of the function and argument names. The order
  1207. of arguments (target, link) is the reverse of Path.symlink_to, but
  1208. matches that of os.link.
  1209. """
  1210. self._accessor.link_to(self, target)
  1211. # Convenience functions for querying the stat results
  1212. def exists(self):
  1213. """
  1214. Whether this path exists.
  1215. """
  1216. try:
  1217. self.stat()
  1218. except OSError as e:
  1219. if not _ignore_error(e):
  1220. raise
  1221. return False
  1222. except ValueError:
  1223. # Non-encodable path
  1224. return False
  1225. return True
  1226. def is_dir(self):
  1227. """
  1228. Whether this path is a directory.
  1229. """
  1230. try:
  1231. return S_ISDIR(self.stat().st_mode)
  1232. except OSError as e:
  1233. if not _ignore_error(e):
  1234. raise
  1235. # Path doesn't exist or is a broken symlink
  1236. # (see http://web.archive.org/web/20200623061726/https://bitbucket.org/pitrou/pathlib/issues/12/ )
  1237. return False
  1238. except ValueError:
  1239. # Non-encodable path
  1240. return False
  1241. def is_file(self):
  1242. """
  1243. Whether this path is a regular file (also True for symlinks pointing
  1244. to regular files).
  1245. """
  1246. try:
  1247. return S_ISREG(self.stat().st_mode)
  1248. except OSError as e:
  1249. if not _ignore_error(e):
  1250. raise
  1251. # Path doesn't exist or is a broken symlink
  1252. # (see http://web.archive.org/web/20200623061726/https://bitbucket.org/pitrou/pathlib/issues/12/ )
  1253. return False
  1254. except ValueError:
  1255. # Non-encodable path
  1256. return False
  1257. def is_mount(self):
  1258. """
  1259. Check if this path is a POSIX mount point
  1260. """
  1261. # Need to exist and be a dir
  1262. if not self.exists() or not self.is_dir():
  1263. return False
  1264. try:
  1265. parent_dev = self.parent.stat().st_dev
  1266. except OSError:
  1267. return False
  1268. dev = self.stat().st_dev
  1269. if dev != parent_dev:
  1270. return True
  1271. ino = self.stat().st_ino
  1272. parent_ino = self.parent.stat().st_ino
  1273. return ino == parent_ino
  1274. def is_symlink(self):
  1275. """
  1276. Whether this path is a symbolic link.
  1277. """
  1278. try:
  1279. return S_ISLNK(self.lstat().st_mode)
  1280. except OSError as e:
  1281. if not _ignore_error(e):
  1282. raise
  1283. # Path doesn't exist
  1284. return False
  1285. except ValueError:
  1286. # Non-encodable path
  1287. return False
  1288. def is_block_device(self):
  1289. """
  1290. Whether this path is a block device.
  1291. """
  1292. try:
  1293. return S_ISBLK(self.stat().st_mode)
  1294. except OSError as e:
  1295. if not _ignore_error(e):
  1296. raise
  1297. # Path doesn't exist or is a broken symlink
  1298. # (see http://web.archive.org/web/20200623061726/https://bitbucket.org/pitrou/pathlib/issues/12/ )
  1299. return False
  1300. except ValueError:
  1301. # Non-encodable path
  1302. return False
  1303. def is_char_device(self):
  1304. """
  1305. Whether this path is a character device.
  1306. """
  1307. try:
  1308. return S_ISCHR(self.stat().st_mode)
  1309. except OSError as e:
  1310. if not _ignore_error(e):
  1311. raise
  1312. # Path doesn't exist or is a broken symlink
  1313. # (see http://web.archive.org/web/20200623061726/https://bitbucket.org/pitrou/pathlib/issues/12/ )
  1314. return False
  1315. except ValueError:
  1316. # Non-encodable path
  1317. return False
  1318. def is_fifo(self):
  1319. """
  1320. Whether this path is a FIFO.
  1321. """
  1322. try:
  1323. return S_ISFIFO(self.stat().st_mode)
  1324. except OSError as e:
  1325. if not _ignore_error(e):
  1326. raise
  1327. # Path doesn't exist or is a broken symlink
  1328. # (see http://web.archive.org/web/20200623061726/https://bitbucket.org/pitrou/pathlib/issues/12/ )
  1329. return False
  1330. except ValueError:
  1331. # Non-encodable path
  1332. return False
  1333. def is_socket(self):
  1334. """
  1335. Whether this path is a socket.
  1336. """
  1337. try:
  1338. return S_ISSOCK(self.stat().st_mode)
  1339. except OSError as e:
  1340. if not _ignore_error(e):
  1341. raise
  1342. # Path doesn't exist or is a broken symlink
  1343. # (see http://web.archive.org/web/20200623061726/https://bitbucket.org/pitrou/pathlib/issues/12/ )
  1344. return False
  1345. except ValueError:
  1346. # Non-encodable path
  1347. return False
  1348. def expanduser(self):
  1349. """ Return a new path with expanded ~ and ~user constructs
  1350. (as returned by os.path.expanduser)
  1351. """
  1352. if (not (self._drv or self._root) and
  1353. self._parts and self._parts[0][:1] == '~'):
  1354. homedir = self._flavour.gethomedir(self._parts[0][1:])
  1355. return self._from_parts([homedir] + self._parts[1:])
  1356. return self
  1357. class PosixPath(Path, PurePosixPath):
  1358. """Path subclass for non-Windows systems.
  1359. On a POSIX system, instantiating a Path should return this object.
  1360. """
  1361. __slots__ = ()
  1362. class WindowsPath(Path, PureWindowsPath):
  1363. """Path subclass for Windows systems.
  1364. On a Windows system, instantiating a Path should return this object.
  1365. """
  1366. __slots__ = ()
  1367. def is_mount(self):
  1368. raise NotImplementedError("Path.is_mount() is unsupported on this system")