Skip to main content

Lib/pathlib/__init__.py

cpython 3.14 @ ab2d84fe1023/Lib/pathlib/__init__.py

The file implements all six public path types: PurePosixPath, PureWindowsPath, and their concrete counterparts, plus the abstract bases PurePath and Path. It relies on Lib/pathlib/_os.py for low-level helpers and on glob._StringGlobber for pattern matching.

Map

LinesSymbolRole
46-50UnsupportedOperationException raised for platform-unsupported operations
52-79_PathParentsSequence view over logical ancestors of a path
81-593PurePathBase class: parsing, comparison, pure manipulation; no I/O
128-159PurePath.__new__ / __init__Accepts positional segments and joins them
175-185PurePath.__truediv__ / __rtruediv__/ operator path joining via with_segments
285-326PurePath._parse_path / _parse_patternLow-level split of raw strings into drive/root/tail
345-400drive / root / anchor / parts / parent / parentsCore path component properties
402-473name / stem / suffix / suffixesFilename component properties
409-445with_name / with_stem / with_suffixImmutable path manipulation returning new instances
479-510relative_to / is_relative_toSubpath relationship tests with optional walk_up
547-593full_match / matchGlob-style pattern matching against path components
595-615PurePosixPath / PureWindowsPathFlavour subclasses that fix parser to posixpath/ntpath
618-759_InfoCached os.stat wrapper shared across Path method calls
761-818_copy_infoInternal helper: copies stat metadata between paths
820-960Path (existence tests)stat, lstat, exists, is_dir, is_file, is_symlink, etc.
962-1014Path.open / read_bytes / read_text / write_bytes / write_textFile content helpers delegating to io.open
1030-1090Path.iterdir / glob / rglobDirectory scanning via os.scandir and _StringGlobber
1095-1185Path.absolute / cwd / resolvePath resolution against the working directory or the filesystem
1207-1295Path.mkdir / chmod / unlink / rmdirFilesystem mutation: create, chmod, delete
1265-1335Path.rename / replace / copy / copy_intoMove and copy operations
1370-1440Path.move / move_intoRename-based move with cross-device fallback
1440-1506Path.expanduser / home / as_uri / from_uriHome-dir expansion and URI conversions

Reading

PurePath: the flavour system

PurePath stores nothing but the raw string segments passed to __new__. Every method derives its result from _parse_path, which calls self.parser (either posixpath or ntpath) to split the string into drive, root, and tail components. Subclasses set the parser at class level; no state is carried at instance level beyond the raw strings.

# CPython: Lib/pathlib/__init__.py:128 PurePath.__new__
def __new__(cls, *args, **kwargs):
if cls is PurePath:
cls = PureWindowsPath if os.name == 'nt' else PurePosixPath
return object.__new__(cls)

def __init__(self, *args):
paths = []
for arg in args:
try:
if isinstance(arg, PurePath):
paths += arg._raw_paths
else:
paths.append(arg)
except TypeError:
raise TypeError(
"argument should be str or os.PathLike, not %r"
% type(arg))
self._raw_paths = paths

__truediv__: path joining with the / operator

The / operator creates a new path by forwarding both operands to with_segments. Because with_segments simply passes the arguments to cls(), the join semantics come entirely from _parse_path and mirror os.path.join: an absolute right-hand operand discards everything on the left.

# CPython: Lib/pathlib/__init__.py:175 PurePath.__truediv__
def __truediv__(self, key):
try:
return self.with_segments(self, key)
except TypeError:
return NotImplemented

def __rtruediv__(self, key):
try:
return self.with_segments(key, self)
except TypeError:
return NotImplemented

iterdir and glob: scandir-based traversal

iterdir wraps a single os.scandir call and maps each DirEntry back to a Path using _from_dir_entry. glob builds a selector chain from a parsed pattern via _StringGlobber, then feeds it the root directory. rglob prepends ** to the pattern before delegating to glob.

# CPython: Lib/pathlib/__init__.py:1030 Path.iterdir
def iterdir(self):
root_dir = str(self)
with os.scandir(root_dir) as scandir_it:
entries = list(scandir_it)
if root_dir == '.':
return (self._from_dir_entry(e, e.name) for e in entries)
else:
return (self._from_dir_entry(e, e.path) for e in entries)

mkdir: recursive parent creation

mkdir calls os.mkdir directly and catches FileNotFoundError to optionally recurse up the parent chain when parents=True. The exist_ok flag is handled by catching OSError and re-raising only when the target is not already a directory.

# CPython: Lib/pathlib/__init__.py:1207 Path.mkdir
def mkdir(self, mode=0o777, parents=False, exist_ok=False):
try:
os.mkdir(self, mode)
except FileNotFoundError:
if not parents or self.parent == self:
raise
self.parent.mkdir(parents=True, exist_ok=True)
self.mkdir(mode, parents=False, exist_ok=exist_ok)
except OSError:
if not exist_ok or not self.is_dir():
raise

gopy notes

gopy does not yet ship a pathlib port. The pure manipulation half (PurePath, with_name, with_suffix, path joining) maps cleanly onto Go string operations and is a realistic near-term target. The concrete Path I/O methods wrap os.* syscalls that gopy already exposes through the os module stubs, so they can be wired in once the class machinery supports properties and __truediv__.