Skip to content

gh-136437: Make several functions in os.path pos-only #136949

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Jul 23, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
14 changes: 7 additions & 7 deletions Lib/genericpath.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,28 +81,28 @@ def isdevdrive(path):
return False


def getsize(filename):
def getsize(filename, /):
"""Return the size of a file, reported by os.stat()."""
return os.stat(filename).st_size


def getmtime(filename):
def getmtime(filename, /):
"""Return the last modification time of a file, reported by os.stat()."""
return os.stat(filename).st_mtime


def getatime(filename):
def getatime(filename, /):
"""Return the last access time of a file, reported by os.stat()."""
return os.stat(filename).st_atime


def getctime(filename):
def getctime(filename, /):
"""Return the metadata change time of a file, reported by os.stat()."""
return os.stat(filename).st_ctime


# Return the longest prefix of all list elements.
def commonprefix(m):
def commonprefix(m, /):
"Given a list of pathnames, returns the longest common leading component"
if not m: return ''
# Some people pass in a list of pathname parts to operate in an OS-agnostic
Expand All @@ -120,14 +120,14 @@ def commonprefix(m):

# Are two stat buffers (obtained from stat, fstat or lstat)
# describing the same file?
def samestat(s1, s2):
def samestat(s1, s2, /):
"""Test whether two stat buffers reference the same file"""
return (s1.st_ino == s2.st_ino and
s1.st_dev == s2.st_dev)


# Are two filenames really pointing to the same file?
def samefile(f1, f2):
def samefile(f1, f2, /):
"""Test whether two pathnames reference the same actual file or directory

This is determined by the device number and i-node number and
Expand Down
24 changes: 12 additions & 12 deletions Lib/ntpath.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ def _get_bothseps(path):
LOCALE_NAME_INVARIANT as _LOCALE_NAME_INVARIANT,
LCMAP_LOWERCASE as _LCMAP_LOWERCASE)

def normcase(s):
def normcase(s, /):
"""Normalize case of pathname.

Makes all characters lowercase and all slashes into backslashes.
Expand All @@ -66,7 +66,7 @@ def normcase(s):
_LCMAP_LOWERCASE,
s.replace('/', '\\'))
except ImportError:
def normcase(s):
def normcase(s, /):
"""Normalize case of pathname.

Makes all characters lowercase and all slashes into backslashes.
Expand All @@ -77,7 +77,7 @@ def normcase(s):
return s.replace('/', '\\').lower()


def isabs(s):
def isabs(s, /):
"""Test whether a path is absolute"""
s = os.fspath(s)
if isinstance(s, bytes):
Expand All @@ -96,7 +96,7 @@ def isabs(s):


# Join two (or more) paths.
def join(path, *paths):
def join(path, /, *paths):
path = os.fspath(path)
if isinstance(path, bytes):
sep = b'\\'
Expand Down Expand Up @@ -143,7 +143,7 @@ def join(path, *paths):
# Split a path in a drive specification (a drive letter followed by a
# colon) and the path specification.
# It is always true that drivespec + pathspec == p
def splitdrive(p):
def splitdrive(p, /):
"""Split a pathname into drive/UNC sharepoint and relative path specifiers.
Returns a 2-tuple (drive_or_unc, path); either part may be empty.

Expand All @@ -169,7 +169,7 @@ def splitdrive(p):
try:
from nt import _path_splitroot_ex as splitroot
except ImportError:
def splitroot(p):
def splitroot(p, /):
"""Split a pathname into drive, root and tail.

The tail contains anything after the root."""
Expand Down Expand Up @@ -219,7 +219,7 @@ def splitroot(p):
# join(head, tail) == p holds.
# The resulting head won't end in '/' unless it is the root.

def split(p):
def split(p, /):
"""Split a pathname.

Return tuple (head, tail) where tail is everything after the final slash.
Expand All @@ -240,7 +240,7 @@ def split(p):
# pathname component; the root is everything before that.
# It is always true that root + ext == p.

def splitext(p):
def splitext(p, /):
p = os.fspath(p)
if isinstance(p, bytes):
return genericpath._splitext(p, b'\\', b'/', b'.')
Expand All @@ -251,14 +251,14 @@ def splitext(p):

# Return the tail (basename) part of a path.

def basename(p):
def basename(p, /):
"""Returns the final component of a pathname"""
return split(p)[1]


# Return the head (dirname) part of a path.

def dirname(p):
def dirname(p, /):
"""Returns the directory component of a pathname"""
return split(p)[0]

Expand Down Expand Up @@ -601,7 +601,7 @@ def abspath(path):
from nt import _findfirstfile, _getfinalpathname, readlink as _nt_readlink
except ImportError:
# realpath is a no-op on systems without _getfinalpathname support.
def realpath(path, *, strict=False):
def realpath(path, /, *, strict=False):
return abspath(path)
else:
def _readlink_deep(path, ignored_error=OSError):
Expand Down Expand Up @@ -702,7 +702,7 @@ def _getfinalpathname_nonstrict(path, ignored_error=OSError):
tail = join(name, tail) if tail else name
return tail

def realpath(path, *, strict=False):
def realpath(path, /, *, strict=False):
path = normpath(path)
if isinstance(path, bytes):
prefix = b'\\\\?\\'
Expand Down
20 changes: 10 additions & 10 deletions Lib/posixpath.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,15 +50,15 @@ def _get_sep(path):
# normalizations (such as optimizing '../' away) are not allowed
# (another function should be defined to do that).

def normcase(s):
def normcase(s, /):
"""Normalize case of pathname. Has no effect under Posix"""
return os.fspath(s)


# Return whether a path is absolute.
# Trivial in Posix, harder on the Mac or MS-DOS.

def isabs(s):
def isabs(s, /):
"""Test whether a path is absolute"""
s = os.fspath(s)
sep = _get_sep(s)
Expand All @@ -69,7 +69,7 @@ def isabs(s):
# Ignore the previous parts if a part is absolute.
# Insert a '/' unless the first part is empty or already ends in '/'.

def join(a, *p):
def join(a, /, *p):
"""Join two or more pathname components, inserting '/' as needed.
If any component is an absolute path, all previous path components
will be discarded. An empty last part will result in a path that
Expand Down Expand Up @@ -97,7 +97,7 @@ def join(a, *p):
# '/' in the path, head will be empty.
# Trailing '/'es are stripped from head unless it is the root.

def split(p):
def split(p, /):
"""Split a pathname. Returns tuple "(head, tail)" where "tail" is
everything after the final slash. Either part may be empty."""
p = os.fspath(p)
Expand All @@ -114,7 +114,7 @@ def split(p):
# pathname component; the root is everything before that.
# It is always true that root + ext == p.

def splitext(p):
def splitext(p, /):
p = os.fspath(p)
if isinstance(p, bytes):
sep = b'/'
Expand All @@ -128,7 +128,7 @@ def splitext(p):
# Split a pathname into a drive specification and the rest of the
# path. Useful on DOS/Windows/NT; on Unix, the drive is always empty.

def splitdrive(p):
def splitdrive(p, /):
"""Split a pathname into drive and path. On Posix, drive is always
empty."""
p = os.fspath(p)
Expand All @@ -138,7 +138,7 @@ def splitdrive(p):
try:
from posix import _path_splitroot_ex as splitroot
except ImportError:
def splitroot(p):
def splitroot(p, /):
"""Split a pathname into drive, root and tail.

The tail contains anything after the root."""
Expand All @@ -163,7 +163,7 @@ def splitroot(p):

# Return the tail (basename) part of a path, same as split(path)[1].

def basename(p):
def basename(p, /):
"""Returns the final component of a pathname"""
p = os.fspath(p)
sep = _get_sep(p)
Expand All @@ -173,7 +173,7 @@ def basename(p):

# Return the head (dirname) part of a path, same as split(path)[0].

def dirname(p):
def dirname(p, /):
"""Returns the directory component of a pathname"""
p = os.fspath(p)
sep = _get_sep(p)
Expand Down Expand Up @@ -388,7 +388,7 @@ def abspath(path):
# Return a canonical path (i.e. the absolute location of a file on the
# filesystem).

def realpath(filename, *, strict=False):
def realpath(filename, /, *, strict=False):
"""Return the canonical path of the specified filename, eliminating any
symbolic links encountered in the path."""
filename = os.fspath(filename)
Expand Down
Loading
Loading