import sys
from _typeshed import (
    AnyStr_co,
    BytesPath,
    FileDescriptor,
    FileDescriptorLike,
    FileDescriptorOrPath,
    GenericPath,
    OpenBinaryMode,
    OpenBinaryModeReading,
    OpenBinaryModeUpdating,
    OpenBinaryModeWriting,
    OpenTextMode,
    ReadableBuffer,
    StrOrBytesPath,
    StrPath,
    SupportsLenAndGetItem,
    Unused,
    WriteableBuffer,
    structseq,
)
from abc import ABC, abstractmethod
from builtins import OSError
from collections.abc import Callable, Iterable, Iterator, Mapping, MutableMapping, Sequence
from io import BufferedRandom, BufferedReader, BufferedWriter, FileIO, TextIOWrapper
from subprocess import Popen
from types import GenericAlias, TracebackType
from typing import (
    IO,
    Any,
    AnyStr,
    BinaryIO,
    Final,
    Generic,
    Literal,
    NoReturn,
    Protocol,
    TypeAlias,
    TypeVar,
    final,
    overload,
    runtime_checkable,
    type_check_only,
)
from typing_extensions import LiteralString, Self, Unpack, deprecated

from . import path as _path

# Re-export common definitions from os.path to reduce duplication
from .path import (
    altsep as altsep,
    curdir as curdir,
    defpath as defpath,
    devnull as devnull,
    extsep as extsep,
    pardir as pardir,
    pathsep as pathsep,
    sep as sep,
)

__all__ = [
    "F_OK",
    "O_APPEND",
    "O_CREAT",
    "O_EXCL",
    "O_RDONLY",
    "O_RDWR",
    "O_TRUNC",
    "O_WRONLY",
    "P_NOWAIT",
    "P_NOWAITO",
    "P_WAIT",
    "R_OK",
    "SEEK_CUR",
    "SEEK_END",
    "SEEK_SET",
    "TMP_MAX",
    "W_OK",
    "X_OK",
    "DirEntry",
    "_exit",
    "abort",
    "access",
    "altsep",
    "chdir",
    "chmod",
    "close",
    "closerange",
    "cpu_count",
    "curdir",
    "defpath",
    "device_encoding",
    "devnull",
    "dup",
    "dup2",
    "environ",
    "error",
    "execl",
    "execle",
    "execlp",
    "execlpe",
    "execv",
    "execve",
    "execvp",
    "execvpe",
    "extsep",
    "fdopen",
    "fsdecode",
    "fsencode",
    "fspath",
    "fstat",
    "fsync",
    "ftruncate",
    "get_exec_path",
    "get_inheritable",
    "get_terminal_size",
    "getcwd",
    "getcwdb",
    "getenv",
    "getlogin",
    "getpid",
    "getppid",
    "isatty",
    "kill",
    "linesep",
    "link",
    "listdir",
    "lseek",
    "lstat",
    "makedirs",
    "mkdir",
    "name",
    "open",
    "pardir",
    "path",
    "pathsep",
    "pipe",
    "popen",
    "putenv",
    "read",
    "readlink",
    "remove",
    "removedirs",
    "rename",
    "renames",
    "replace",
    "rmdir",
    "scandir",
    "sep",
    "set_inheritable",
    "spawnl",
    "spawnle",
    "spawnv",
    "spawnve",
    "stat",
    "stat_result",
    "statvfs_result",
    "strerror",
    "supports_bytes_environ",
    "symlink",
    "system",
    "terminal_size",
    "times",
    "times_result",
    "truncate",
    "umask",
    "uname_result",
    "unlink",
    "unsetenv",
    "urandom",
    "utime",
    "waitpid",
    "waitstatus_to_exitcode",
    "walk",
    "write",
]
if sys.version_info >= (3, 14):
    # reload_environ was added to __all__ in Python 3.14.1
    __all__ += ["readinto", "reload_environ"]
if sys.platform == "linux" and sys.version_info >= (3, 15):
    __all__ += ["_clearenv"]
if sys.platform == "darwin" and sys.version_info >= (3, 12):
    __all__ += ["PRIO_DARWIN_BG", "PRIO_DARWIN_NONUI", "PRIO_DARWIN_PROCESS", "PRIO_DARWIN_THREAD"]
if sys.platform == "darwin":
    __all__ += ["O_EVTONLY", "O_NOFOLLOW_ANY", "O_SYMLINK"]
if sys.platform == "linux":
    __all__ += [
        "GRND_NONBLOCK",
        "GRND_RANDOM",
        "MFD_ALLOW_SEALING",
        "MFD_CLOEXEC",
        "MFD_HUGETLB",
        "MFD_HUGE_16GB",
        "MFD_HUGE_16MB",
        "MFD_HUGE_1GB",
        "MFD_HUGE_1MB",
        "MFD_HUGE_256MB",
        "MFD_HUGE_2GB",
        "MFD_HUGE_2MB",
        "MFD_HUGE_32MB",
        "MFD_HUGE_512KB",
        "MFD_HUGE_512MB",
        "MFD_HUGE_64KB",
        "MFD_HUGE_8MB",
        "MFD_HUGE_MASK",
        "MFD_HUGE_SHIFT",
        "O_DIRECT",
        "O_LARGEFILE",
        "O_NOATIME",
        "O_PATH",
        "O_RSYNC",
        "O_TMPFILE",
        "P_PIDFD",
        "RTLD_DEEPBIND",
        "SCHED_BATCH",
        "SCHED_IDLE",
        "SCHED_RESET_ON_FORK",
        "XATTR_CREATE",
        "XATTR_REPLACE",
        "XATTR_SIZE_MAX",
        "copy_file_range",
        "getrandom",
        "getxattr",
        "listxattr",
        "memfd_create",
        "pidfd_open",
        "removexattr",
        "setxattr",
    ]
if sys.platform == "linux" and sys.version_info >= (3, 14):
    __all__ += ["SCHED_DEADLINE", "SCHED_NORMAL"]
if sys.platform == "linux" and sys.version_info >= (3, 15):
    __all__ += [
        "AT_NO_AUTOMOUNT",
        "AT_STATX_DONT_SYNC",
        "AT_STATX_FORCE_SYNC",
        "AT_STATX_SYNC_AS_STAT",
        "STATX_ATIME",
        "STATX_BASIC_STATS",
        "STATX_BLOCKS",
        "STATX_BTIME",
        "STATX_CTIME",
        "STATX_DIOALIGN",
        "STATX_GID",
        "STATX_INO",
        "STATX_MNT_ID",
        "STATX_MNT_ID_UNIQUE",
        "STATX_MODE",
        "STATX_MTIME",
        "STATX_NLINK",
        "STATX_SIZE",
        "STATX_TYPE",
        "STATX_UID",
        "statx",
        "statx_result",
    ]
if sys.platform == "linux" and sys.version_info >= (3, 13):
    __all__ += [
        "POSIX_SPAWN_CLOSEFROM",
        "TFD_CLOEXEC",
        "TFD_NONBLOCK",
        "TFD_TIMER_ABSTIME",
        "TFD_TIMER_CANCEL_ON_SET",
        "timerfd_create",
        "timerfd_gettime",
        "timerfd_gettime_ns",
        "timerfd_settime",
        "timerfd_settime_ns",
    ]
if sys.platform == "linux" and sys.version_info >= (3, 12):
    __all__ += [
        "CLONE_FILES",
        "CLONE_FS",
        "CLONE_NEWCGROUP",
        "CLONE_NEWIPC",
        "CLONE_NEWNET",
        "CLONE_NEWNS",
        "CLONE_NEWPID",
        "CLONE_NEWTIME",
        "CLONE_NEWUSER",
        "CLONE_NEWUTS",
        "CLONE_SIGHAND",
        "CLONE_SYSVSEM",
        "CLONE_THREAD",
        "CLONE_VM",
        "setns",
        "unshare",
        "PIDFD_NONBLOCK",
    ]
if sys.platform == "linux":
    __all__ += [
        "EFD_CLOEXEC",
        "EFD_NONBLOCK",
        "EFD_SEMAPHORE",
        "RWF_APPEND",
        "SPLICE_F_MORE",
        "SPLICE_F_MOVE",
        "SPLICE_F_NONBLOCK",
        "eventfd",
        "eventfd_read",
        "eventfd_write",
        "splice",
    ]
if sys.platform == "win32":
    __all__ += [
        "O_BINARY",
        "O_NOINHERIT",
        "O_RANDOM",
        "O_SEQUENTIAL",
        "O_SHORT_LIVED",
        "O_TEMPORARY",
        "O_TEXT",
        "P_DETACH",
        "P_OVERLAY",
        "get_handle_inheritable",
        "set_handle_inheritable",
        "startfile",
    ]
if sys.platform == "win32" and sys.version_info >= (3, 12):
    __all__ += ["listdrives", "listmounts", "listvolumes"]
if sys.platform != "win32":
    __all__ += [
        "CLD_CONTINUED",
        "CLD_DUMPED",
        "CLD_EXITED",
        "CLD_KILLED",
        "CLD_STOPPED",
        "CLD_TRAPPED",
        "EX_CANTCREAT",
        "EX_CONFIG",
        "EX_DATAERR",
        "EX_IOERR",
        "EX_NOHOST",
        "EX_NOINPUT",
        "EX_NOPERM",
        "EX_NOUSER",
        "EX_OSERR",
        "EX_OSFILE",
        "EX_PROTOCOL",
        "EX_SOFTWARE",
        "EX_TEMPFAIL",
        "EX_UNAVAILABLE",
        "EX_USAGE",
        "F_LOCK",
        "F_TEST",
        "F_TLOCK",
        "F_ULOCK",
        "NGROUPS_MAX",
        "O_ACCMODE",
        "O_ASYNC",
        "O_CLOEXEC",
        "O_DIRECTORY",
        "O_DSYNC",
        "O_NDELAY",
        "O_NOCTTY",
        "O_NOFOLLOW",
        "O_NONBLOCK",
        "O_SYNC",
        "POSIX_SPAWN_CLOSE",
        "POSIX_SPAWN_DUP2",
        "POSIX_SPAWN_OPEN",
        "PRIO_PGRP",
        "PRIO_PROCESS",
        "PRIO_USER",
        "P_ALL",
        "P_PGID",
        "P_PID",
        "RTLD_GLOBAL",
        "RTLD_LAZY",
        "RTLD_LOCAL",
        "RTLD_NODELETE",
        "RTLD_NOLOAD",
        "RTLD_NOW",
        "SCHED_FIFO",
        "SCHED_OTHER",
        "SCHED_RR",
        "SEEK_DATA",
        "SEEK_HOLE",
        "ST_NOSUID",
        "ST_RDONLY",
        "WCONTINUED",
        "WCOREDUMP",
        "WEXITED",
        "WEXITSTATUS",
        "WIFCONTINUED",
        "WIFEXITED",
        "WIFSIGNALED",
        "WIFSTOPPED",
        "WNOHANG",
        "WNOWAIT",
        "WSTOPPED",
        "WSTOPSIG",
        "WTERMSIG",
        "WUNTRACED",
        "chown",
        "chroot",
        "confstr",
        "confstr_names",
        "ctermid",
        "environb",
        "fchdir",
        "fchown",
        "fork",
        "forkpty",
        "fpathconf",
        "fstatvfs",
        "fwalk",
        "getegid",
        "getenvb",
        "geteuid",
        "getgid",
        "getgrouplist",
        "getgroups",
        "getloadavg",
        "getpgid",
        "getpgrp",
        "getpriority",
        "getsid",
        "getuid",
        "initgroups",
        "killpg",
        "lchown",
        "lockf",
        "major",
        "makedev",
        "minor",
        "mkfifo",
        "mknod",
        "nice",
        "openpty",
        "pathconf",
        "pathconf_names",
        "posix_spawn",
        "posix_spawnp",
        "pread",
        "preadv",
        "pwrite",
        "pwritev",
        "readv",
        "register_at_fork",
        "sched_get_priority_max",
        "sched_get_priority_min",
        "sched_yield",
        "sendfile",
        "setegid",
        "seteuid",
        "setgid",
        "setgroups",
        "setpgid",
        "setpgrp",
        "setpriority",
        "setregid",
        "setreuid",
        "setsid",
        "setuid",
        "spawnlp",
        "spawnlpe",
        "spawnvp",
        "spawnvpe",
        "statvfs",
        "sync",
        "sysconf",
        "sysconf_names",
        "tcgetpgrp",
        "tcsetpgrp",
        "ttyname",
        "uname",
        "wait",
        "wait3",
        "wait4",
        "writev",
    ]
if sys.platform != "win32" and sys.version_info >= (3, 13):
    __all__ += ["grantpt", "posix_openpt", "ptsname", "unlockpt"]
if sys.platform != "win32" and sys.version_info >= (3, 11):
    __all__ += ["login_tty"]
if sys.platform != "win32" and sys.version_info >= (3, 15):
    __all__ += ["NODEV", "O_FSYNC"]
elif sys.platform != "win32":
    __all__ += ["O_FSYNC"]
if sys.platform != "darwin" and sys.platform != "win32":
    __all__ += [
        "POSIX_FADV_DONTNEED",
        "POSIX_FADV_NOREUSE",
        "POSIX_FADV_NORMAL",
        "POSIX_FADV_RANDOM",
        "POSIX_FADV_SEQUENTIAL",
        "POSIX_FADV_WILLNEED",
        "RWF_DSYNC",
        "RWF_HIPRI",
        "RWF_NOWAIT",
        "RWF_SYNC",
        "ST_APPEND",
        "ST_MANDLOCK",
        "ST_NOATIME",
        "ST_NODEV",
        "ST_NODIRATIME",
        "ST_NOEXEC",
        "ST_RELATIME",
        "ST_SYNCHRONOUS",
        "ST_WRITE",
        "fdatasync",
        "getresgid",
        "getresuid",
        "pipe2",
        "posix_fadvise",
        "posix_fallocate",
        "sched_getaffinity",
        "sched_getparam",
        "sched_getscheduler",
        "sched_param",
        "sched_rr_get_interval",
        "sched_setaffinity",
        "sched_setparam",
        "sched_setscheduler",
        "setresgid",
        "setresuid",
    ]
if sys.platform != "linux" and sys.platform != "win32":
    __all__ += ["O_EXLOCK", "O_SHLOCK", "chflags", "lchflags"]
if sys.platform != "linux" and sys.platform != "win32" and sys.version_info >= (3, 13):
    __all__ += ["O_EXEC", "O_SEARCH"]
if sys.platform != "darwin" or sys.version_info >= (3, 13):
    if sys.platform != "win32":
        __all__ += ["waitid", "waitid_result"]
if sys.platform != "win32" or sys.version_info >= (3, 13):
    __all__ += ["fchmod"]
    if sys.platform != "linux":
        __all__ += ["lchmod"]
if sys.platform != "win32" or sys.version_info >= (3, 12):
    __all__ += ["get_blocking", "set_blocking"]
if sys.platform != "win32" or sys.version_info >= (3, 11):
    __all__ += ["EX_OK"]

# This unnecessary alias is to work around various errors
path = _path

_T = TypeVar("_T")
_T1 = TypeVar("_T1")
_T2 = TypeVar("_T2")

# ----- os variables -----

error = OSError

supports_bytes_environ: bool

supports_dir_fd: set[Callable[..., Any]]
supports_fd: set[Callable[..., Any]]
supports_effective_ids: set[Callable[..., Any]]
supports_follow_symlinks: set[Callable[..., Any]]

if sys.platform != "win32":
    # Unix only
    PRIO_PROCESS: Final[int]
    PRIO_PGRP: Final[int]
    PRIO_USER: Final[int]

    F_LOCK: Final[int]
    F_TLOCK: Final[int]
    F_ULOCK: Final[int]
    F_TEST: Final[int]

    if sys.platform != "darwin":
        POSIX_FADV_NORMAL: Final[int]
        POSIX_FADV_SEQUENTIAL: Final[int]
        POSIX_FADV_RANDOM: Final[int]
        POSIX_FADV_NOREUSE: Final[int]
        POSIX_FADV_WILLNEED: Final[int]
        POSIX_FADV_DONTNEED: Final[int]

    if sys.platform != "linux" and sys.platform != "darwin":
        # In the os-module docs, these are marked as being available
        # on "Unix, not Emscripten, not WASI."
        # However, in the source code, a comment indicates they're "FreeBSD constants".
        # sys.platform could have one of many values on a FreeBSD Python build,
        # so the sys-module docs recommend doing `if sys.platform.startswith('freebsd')`
        # to detect FreeBSD builds. Unfortunately that would be too dynamic
        # for type checkers, however.
        SF_NODISKIO: Final[int]
        SF_MNOWAIT: Final[int]
        SF_SYNC: Final[int]

        if sys.version_info >= (3, 11):
            SF_NOCACHE: Final[int]

    if sys.platform == "linux":
        XATTR_SIZE_MAX: Final[int]
        XATTR_CREATE: Final[int]
        XATTR_REPLACE: Final[int]

    P_PID: Final[int]
    P_PGID: Final[int]
    P_ALL: Final[int]

    if sys.platform == "linux":
        P_PIDFD: Final[int]

    WEXITED: Final[int]
    WSTOPPED: Final[int]
    WNOWAIT: Final[int]

    CLD_EXITED: Final[int]
    CLD_DUMPED: Final[int]
    CLD_TRAPPED: Final[int]
    CLD_CONTINUED: Final[int]
    CLD_KILLED: Final[int]
    CLD_STOPPED: Final[int]

    SCHED_OTHER: Final[int]
    SCHED_FIFO: Final[int]
    SCHED_RR: Final[int]
    if sys.platform != "darwin" and sys.platform != "linux":
        SCHED_SPORADIC: Final[int]

if sys.platform == "linux":
    SCHED_BATCH: Final[int]
    SCHED_IDLE: Final[int]
    SCHED_RESET_ON_FORK: Final[int]

if sys.version_info >= (3, 14) and sys.platform == "linux":
    SCHED_DEADLINE: Final[int]
    SCHED_NORMAL: Final[int]

if sys.platform != "win32":
    RTLD_LAZY: Final[int]
    RTLD_NOW: Final[int]
    RTLD_GLOBAL: Final[int]
    RTLD_LOCAL: Final[int]
    RTLD_NODELETE: Final[int]
    RTLD_NOLOAD: Final[int]

if sys.platform == "linux":
    RTLD_DEEPBIND: Final[int]
    GRND_NONBLOCK: Final[int]
    GRND_RANDOM: Final[int]

if sys.platform == "darwin" and sys.version_info >= (3, 12):
    PRIO_DARWIN_BG: Final[int]
    PRIO_DARWIN_NONUI: Final[int]
    PRIO_DARWIN_PROCESS: Final[int]
    PRIO_DARWIN_THREAD: Final[int]

SEEK_SET: Final = 0
SEEK_CUR: Final = 1
SEEK_END: Final = 2
if sys.platform == "linux":
    SEEK_DATA: Final = 3
    SEEK_HOLE: Final = 4
elif sys.platform == "darwin":
    SEEK_HOLE: Final = 3
    SEEK_DATA: Final = 4

O_RDONLY: Final[int]
O_WRONLY: Final[int]
O_RDWR: Final[int]
O_APPEND: Final[int]
O_CREAT: Final[int]
O_EXCL: Final[int]
O_TRUNC: Final[int]
if sys.platform == "win32":
    O_BINARY: Final[int]
    O_NOINHERIT: Final[int]
    O_SHORT_LIVED: Final[int]
    O_TEMPORARY: Final[int]
    O_RANDOM: Final[int]
    O_SEQUENTIAL: Final[int]
    O_TEXT: Final[int]

if sys.platform != "win32":
    O_DSYNC: Final[int]
    O_SYNC: Final[int]
    O_NDELAY: Final[int]
    O_NONBLOCK: Final[int]
    O_NOCTTY: Final[int]
    O_CLOEXEC: Final[int]
    O_ASYNC: Final[int]  # Gnu extension if in C library
    O_DIRECTORY: Final[int]  # Gnu extension if in C library
    O_NOFOLLOW: Final[int]  # Gnu extension if in C library
    O_ACCMODE: Final[int]  # TODO: when does this exist?

if sys.platform == "linux":
    O_RSYNC: Final[int]
    O_DIRECT: Final[int]  # Gnu extension if in C library
    O_NOATIME: Final[int]  # Gnu extension if in C library
    O_PATH: Final[int]  # Gnu extension if in C library
    O_TMPFILE: Final[int]  # Gnu extension if in C library
    O_LARGEFILE: Final[int]  # Gnu extension if in C library

if sys.platform != "linux" and sys.platform != "win32":
    O_SHLOCK: Final[int]
    O_EXLOCK: Final[int]

if sys.platform == "darwin":
    O_EVTONLY: Final[int]
    O_NOFOLLOW_ANY: Final[int]
    O_SYMLINK: Final[int]

if sys.platform != "win32" and sys.version_info >= (3, 15):
    NODEV: Final[int]

if sys.platform == "linux" and sys.version_info >= (3, 15):
    AT_NO_AUTOMOUNT: Final[int]
    AT_STATX_DONT_SYNC: Final[int]
    AT_STATX_FORCE_SYNC: Final[int]
    AT_STATX_SYNC_AS_STAT: Final[int]
    STATX_ATIME: Final[int]
    STATX_BASIC_STATS: Final[int]
    STATX_BLOCKS: Final[int]
    STATX_BTIME: Final[int]
    STATX_CTIME: Final[int]
    STATX_DIOALIGN: Final[int]
    STATX_GID: Final[int]
    STATX_INO: Final[int]
    STATX_MNT_ID: Final[int]
    STATX_MNT_ID_UNIQUE: Final[int]
    STATX_MODE: Final[int]
    STATX_MTIME: Final[int]
    STATX_NLINK: Final[int]
    STATX_SIZE: Final[int]
    STATX_TYPE: Final[int]
    STATX_UID: Final[int]

if sys.platform != "win32":
    O_FSYNC: Final[int]

if sys.platform != "linux" and sys.platform != "win32" and sys.version_info >= (3, 13):
    O_EXEC: Final[int]
    O_SEARCH: Final[int]

if sys.platform != "win32" and sys.platform != "darwin":
    # posix, but apparently missing on macos
    ST_APPEND: Final[int]
    ST_MANDLOCK: Final[int]
    ST_NOATIME: Final[int]
    ST_NODEV: Final[int]
    ST_NODIRATIME: Final[int]
    ST_NOEXEC: Final[int]
    ST_RELATIME: Final[int]
    ST_SYNCHRONOUS: Final[int]
    ST_WRITE: Final[int]

if sys.platform != "win32":
    NGROUPS_MAX: Final[int]
    ST_NOSUID: Final[int]
    ST_RDONLY: Final[int]

linesep: Literal["\n", "\r\n"]
name: LiteralString

F_OK: Final = 0
R_OK: Final = 4
W_OK: Final = 2
X_OK: Final = 1

_EnvironCodeFunc: TypeAlias = Callable[[AnyStr], AnyStr]

class _Environ(MutableMapping[AnyStr, AnyStr], Generic[AnyStr]):
    encodekey: _EnvironCodeFunc[AnyStr]
    decodekey: _EnvironCodeFunc[AnyStr]
    encodevalue: _EnvironCodeFunc[AnyStr]
    decodevalue: _EnvironCodeFunc[AnyStr]
    def __init__(
        self,
        data: MutableMapping[AnyStr, AnyStr],
        encodekey: _EnvironCodeFunc[AnyStr],
        decodekey: _EnvironCodeFunc[AnyStr],
        encodevalue: _EnvironCodeFunc[AnyStr],
        decodevalue: _EnvironCodeFunc[AnyStr],
    ) -> None: ...

    @overload
    def get(self, key: AnyStr, default: None = None) -> AnyStr | None: ...
    @overload
    def get(self, key: AnyStr, default: AnyStr) -> AnyStr: ...
    @overload
    def get(self, key: AnyStr, default: _T) -> AnyStr | _T: ...

    @overload
    def pop(self, key: AnyStr) -> AnyStr: ...
    @overload
    def pop(self, key: AnyStr, default: AnyStr) -> AnyStr: ...
    @overload
    def pop(self, key: AnyStr, default: _T) -> AnyStr | _T: ...

    def setdefault(self, key: AnyStr, value: AnyStr) -> AnyStr: ...
    def copy(self) -> dict[AnyStr, AnyStr]: ...
    def __delitem__(self, key: AnyStr) -> None: ...
    def __getitem__(self, key: AnyStr) -> AnyStr: ...
    def __setitem__(self, key: AnyStr, value: AnyStr) -> None: ...
    def __iter__(self) -> Iterator[AnyStr]: ...
    def __len__(self) -> int: ...
    def __or__(self, other: Mapping[_T1, _T2]) -> dict[AnyStr | _T1, AnyStr | _T2]: ...
    def __ror__(self, other: Mapping[_T1, _T2]) -> dict[AnyStr | _T1, AnyStr | _T2]: ...

    # We use @overload instead of a Union for reasons similar to those given for
    # overloading MutableMapping.update in stdlib/typing.pyi
    # The type: ignore is needed due to incompatible __or__/__ior__ signatures
    @overload  # type: ignore[misc]
    def __ior__(self, other: Mapping[AnyStr, AnyStr]) -> Self: ...
    @overload
    def __ior__(self, other: Iterable[tuple[AnyStr, AnyStr]]) -> Self: ...

environ: _Environ[str]
if sys.platform != "win32":
    environb: _Environ[bytes]

if sys.version_info >= (3, 14):
    def reload_environ() -> None: ...

if sys.platform == "linux" and sys.version_info >= (3, 15):
    def _clearenv() -> None: ...

if sys.version_info >= (3, 11) or sys.platform != "win32":
    EX_OK: Final[int]

if sys.platform != "win32":
    confstr_names: dict[str, int]
    pathconf_names: dict[str, int]
    sysconf_names: dict[str, int]

    EX_USAGE: Final[int]
    EX_DATAERR: Final[int]
    EX_NOINPUT: Final[int]
    EX_NOUSER: Final[int]
    EX_NOHOST: Final[int]
    EX_UNAVAILABLE: Final[int]
    EX_SOFTWARE: Final[int]
    EX_OSERR: Final[int]
    EX_OSFILE: Final[int]
    EX_CANTCREAT: Final[int]
    EX_IOERR: Final[int]
    EX_TEMPFAIL: Final[int]
    EX_PROTOCOL: Final[int]
    EX_NOPERM: Final[int]
    EX_CONFIG: Final[int]

# Exists on some Unix platforms, e.g. Solaris.
if sys.platform != "win32" and sys.platform != "darwin" and sys.platform != "linux":
    EX_NOTFOUND: Final[int]

P_NOWAIT: Final[int]
P_NOWAITO: Final[int]
P_WAIT: Final[int]
if sys.platform == "win32":
    P_DETACH: Final[int]
    P_OVERLAY: Final[int]

# wait()/waitpid() options
if sys.platform != "win32":
    WNOHANG: Final[int]  # Unix only
    WCONTINUED: Final[int]  # some Unix systems
    WUNTRACED: Final[int]  # Unix only

TMP_MAX: Final[int]  # Undocumented, but used by tempfile

# ----- os classes (structures) -----
@final
class stat_result(structseq[float], tuple[int, int, int, int, int, int, int, float, float, float]):
    # The constructor of this class takes an iterable of variable length (though it must be at least 10).
    #
    # However, this class behaves like a tuple of 10 elements,
    # no matter how long the iterable supplied to the constructor is.
    # https://github.com/python/typeshed/pull/6560#discussion_r767162532
    #
    # The 10 elements always present are st_mode, st_ino, st_dev, st_nlink,
    # st_uid, st_gid, st_size, st_atime, st_mtime, st_ctime.
    #
    # More items may be added at the end by some implementations.
    __match_args__: Final = ("st_mode", "st_ino", "st_dev", "st_nlink", "st_uid", "st_gid", "st_size")

    @property
    def st_mode(self) -> int: ...  # protection bits,
    @property
    def st_ino(self) -> int: ...  # inode number,
    @property
    def st_dev(self) -> int: ...  # device,
    @property
    def st_nlink(self) -> int: ...  # number of hard links,
    @property
    def st_uid(self) -> int: ...  # user id of owner,
    @property
    def st_gid(self) -> int: ...  # group id of owner,
    @property
    def st_size(self) -> int: ...  # size of file, in bytes,
    @property
    def st_atime(self) -> float: ...  # time of most recent access,
    @property
    def st_mtime(self) -> float: ...  # time of most recent content modification,
    # platform dependent (time of most recent metadata change on Unix, or the time of creation on Windows)
    if sys.version_info >= (3, 12) and sys.platform == "win32":
        @property
        @deprecated("""\
Use st_birthtime instead to retrieve the file creation time. \
In the future, this property will contain the last metadata change time.""")
        def st_ctime(self) -> float: ...
    else:
        @property
        def st_ctime(self) -> float: ...

    @property
    def st_atime_ns(self) -> int: ...  # time of most recent access, in nanoseconds
    @property
    def st_mtime_ns(self) -> int: ...  # time of most recent content modification in nanoseconds
    # platform dependent (time of most recent metadata change on Unix, or the time of creation on Windows) in nanoseconds
    @property
    def st_ctime_ns(self) -> int: ...
    if sys.platform == "win32":
        @property
        def st_file_attributes(self) -> int: ...
        @property
        def st_reparse_tag(self) -> int: ...
        if sys.version_info >= (3, 12):
            @property
            def st_birthtime(self) -> float: ...  # time of file creation in seconds
            @property
            def st_birthtime_ns(self) -> int: ...  # time of file creation in nanoseconds
    else:
        @property
        def st_blocks(self) -> int: ...  # number of blocks allocated for file
        @property
        def st_blksize(self) -> int: ...  # filesystem blocksize
        @property
        def st_rdev(self) -> int: ...  # type of device if an inode device
        if sys.platform != "linux":
            # These properties are available on MacOS, but not Ubuntu.
            # On other Unix systems (such as FreeBSD), the following attributes may be
            # available (but may be only filled out if root tries to use them):
            @property
            def st_gen(self) -> int: ...  # file generation number
            @property
            def st_birthtime(self) -> float: ...  # time of file creation in seconds
    if sys.platform == "darwin":
        @property
        def st_flags(self) -> int: ...  # user defined flags for file
    # Attributes documented as sometimes appearing, but deliberately omitted from the stub: `st_creator`, `st_rsize`, `st_type`.
    # See https://github.com/python/typeshed/pull/6560#issuecomment-991253327

# mypy and pyright object to this being both ABC and Protocol.
# At runtime it inherits from ABC and is not a Protocol, but it will be
# on the allowlist for use as a Protocol starting in 3.14.
@runtime_checkable
class PathLike(ABC, Protocol[AnyStr_co]):  # type: ignore[misc]  # pyright: ignore[reportGeneralTypeIssues]
    __slots__ = ()
    @abstractmethod
    def __fspath__(self) -> AnyStr_co: ...

@overload
def listdir(path: StrPath | None = None) -> list[str]: ...
@overload
def listdir(path: BytesPath) -> list[bytes]: ...
@overload
def listdir(path: int) -> list[str]: ...

@final
class DirEntry(Generic[AnyStr]):
    # This is what the scandir iterator yields
    # The constructor is hidden

    @property
    def name(self) -> AnyStr: ...
    @property
    def path(self) -> AnyStr: ...
    def inode(self) -> int: ...
    def is_dir(self, *, follow_symlinks: bool = True) -> bool: ...
    def is_file(self, *, follow_symlinks: bool = True) -> bool: ...
    def is_symlink(self) -> bool: ...
    def stat(self, *, follow_symlinks: bool = True) -> stat_result: ...
    def __fspath__(self) -> AnyStr: ...
    def __class_getitem__(cls, item: Any, /) -> GenericAlias: ...
    if sys.version_info >= (3, 12):
        def is_junction(self) -> bool: ...

@final
class statvfs_result(structseq[int], tuple[int, int, int, int, int, int, int, int, int, int, int]):
    __match_args__: Final = (
        "f_bsize",
        "f_frsize",
        "f_blocks",
        "f_bfree",
        "f_bavail",
        "f_files",
        "f_ffree",
        "f_favail",
        "f_flag",
        "f_namemax",
    )

    @property
    def f_bsize(self) -> int: ...
    @property
    def f_frsize(self) -> int: ...
    @property
    def f_blocks(self) -> int: ...
    @property
    def f_bfree(self) -> int: ...
    @property
    def f_bavail(self) -> int: ...
    @property
    def f_files(self) -> int: ...
    @property
    def f_ffree(self) -> int: ...
    @property
    def f_favail(self) -> int: ...
    @property
    def f_flag(self) -> int: ...
    @property
    def f_namemax(self) -> int: ...
    @property
    def f_fsid(self) -> int: ...

# ----- os function stubs -----
def fsencode(filename: StrOrBytesPath) -> bytes: ...
def fsdecode(filename: StrOrBytesPath) -> str: ...

@overload
def fspath(path: str) -> str: ...
@overload
def fspath(path: bytes) -> bytes: ...
@overload
def fspath(path: PathLike[AnyStr]) -> AnyStr: ...

def get_exec_path(env: Mapping[str, str] | None = None) -> list[str]: ...
def getlogin() -> str: ...
def getpid() -> int: ...
def getppid() -> int: ...
def strerror(code: int, /) -> str: ...
def umask(mask: int, /) -> int: ...

@final
class uname_result(structseq[str], tuple[str, str, str, str, str]):
    __match_args__: Final = ("sysname", "nodename", "release", "version", "machine")

    @property
    def sysname(self) -> str: ...
    @property
    def nodename(self) -> str: ...
    @property
    def release(self) -> str: ...
    @property
    def version(self) -> str: ...
    @property
    def machine(self) -> str: ...

if sys.platform != "win32":
    def ctermid() -> str: ...
    def getegid() -> int: ...
    def geteuid() -> int: ...
    def getgid() -> int: ...
    def getgrouplist(user: str, group: int, /) -> list[int]: ...
    def getgroups() -> list[int]: ...  # Unix only, behaves differently on Mac
    def initgroups(username: str, gid: int, /) -> None: ...
    def getpgid(pid: int) -> int: ...
    def getpgrp() -> int: ...
    def getpriority(which: int, who: int) -> int: ...
    def setpriority(which: int, who: int, priority: int) -> None: ...
    if sys.platform != "darwin":
        def getresuid() -> tuple[int, int, int]: ...
        def getresgid() -> tuple[int, int, int]: ...

    def getuid() -> int: ...
    def setegid(egid: int, /) -> None: ...
    def seteuid(euid: int, /) -> None: ...
    def setgid(gid: int, /) -> None: ...
    def setgroups(groups: Sequence[int], /) -> None: ...
    def setpgrp() -> None: ...
    def setpgid(pid: int, pgrp: int, /) -> None: ...
    def setregid(rgid: int, egid: int, /) -> None: ...
    if sys.platform != "darwin":
        def setresgid(rgid: int, egid: int, sgid: int, /) -> None: ...
        def setresuid(ruid: int, euid: int, suid: int, /) -> None: ...

    def setreuid(ruid: int, euid: int, /) -> None: ...
    def getsid(pid: int, /) -> int: ...
    def setsid() -> None: ...
    def setuid(uid: int, /) -> None: ...
    def uname() -> uname_result: ...

@overload
def getenv(key: str) -> str | None: ...
@overload
def getenv(key: str, default: _T) -> str | _T: ...

if sys.platform != "win32":
    @overload
    def getenvb(key: bytes) -> bytes | None: ...
    @overload
    def getenvb(key: bytes, default: _T) -> bytes | _T: ...

    def putenv(name: StrOrBytesPath, value: StrOrBytesPath, /) -> None: ...
    def unsetenv(name: StrOrBytesPath, /) -> None: ...

else:
    def putenv(name: str, value: str, /) -> None: ...
    def unsetenv(name: str, /) -> None: ...

_Opener: TypeAlias = Callable[[str, int], int]

@overload
def fdopen(
    fd: int,
    mode: OpenTextMode = "r",
    buffering: int = -1,
    encoding: str | None = None,
    errors: str | None = None,
    newline: str | None = None,
    closefd: bool = True,
    opener: _Opener | None = None,
) -> TextIOWrapper: ...
@overload
def fdopen(
    fd: int,
    mode: OpenBinaryMode,
    buffering: Literal[0],
    encoding: None = None,
    errors: None = None,
    newline: None = None,
    closefd: bool = True,
    opener: _Opener | None = None,
) -> FileIO: ...
@overload
def fdopen(
    fd: int,
    mode: OpenBinaryModeUpdating,
    buffering: Literal[-1, 1] = -1,
    encoding: None = None,
    errors: None = None,
    newline: None = None,
    closefd: bool = True,
    opener: _Opener | None = None,
) -> BufferedRandom: ...
@overload
def fdopen(
    fd: int,
    mode: OpenBinaryModeWriting,
    buffering: Literal[-1, 1] = -1,
    encoding: None = None,
    errors: None = None,
    newline: None = None,
    closefd: bool = True,
    opener: _Opener | None = None,
) -> BufferedWriter: ...
@overload
def fdopen(
    fd: int,
    mode: OpenBinaryModeReading,
    buffering: Literal[-1, 1] = -1,
    encoding: None = None,
    errors: None = None,
    newline: None = None,
    closefd: bool = True,
    opener: _Opener | None = None,
) -> BufferedReader: ...
@overload
def fdopen(
    fd: int,
    mode: OpenBinaryMode,
    buffering: int = -1,
    encoding: None = None,
    errors: None = None,
    newline: None = None,
    closefd: bool = True,
    opener: _Opener | None = None,
) -> BinaryIO: ...
@overload
def fdopen(
    fd: int,
    mode: str,
    buffering: int = -1,
    encoding: str | None = None,
    errors: str | None = None,
    newline: str | None = None,
    closefd: bool = True,
    opener: _Opener | None = None,
) -> IO[Any]: ...

def close(fd: int) -> None: ...
def closerange(fd_low: int, fd_high: int, /) -> None: ...
def device_encoding(fd: int) -> str | None: ...
def dup(fd: int, /) -> int: ...
def dup2(fd: int, fd2: int, inheritable: bool = True) -> int: ...
def fstat(fd: int) -> stat_result: ...
def ftruncate(fd: int, length: int, /) -> None: ...
def fsync(fd: FileDescriptorLike) -> None: ...
def isatty(fd: int, /) -> bool: ...

if sys.platform != "win32" and sys.version_info >= (3, 11):
    def login_tty(fd: int, /) -> None: ...

if sys.version_info >= (3, 11):
    def lseek(fd: int, position: int, whence: int, /) -> int: ...

else:
    def lseek(fd: int, position: int, how: int, /) -> int: ...

def open(path: StrOrBytesPath, flags: int, mode: int = 0o777, *, dir_fd: int | None = None) -> int: ...
def pipe() -> tuple[int, int]: ...
def read(fd: int, length: int, /) -> bytes: ...

if sys.version_info >= (3, 12) or sys.platform != "win32":
    def get_blocking(fd: int, /) -> bool: ...
    def set_blocking(fd: int, blocking: bool, /) -> None: ...

if sys.platform != "win32":
    def fchown(fd: int, uid: int, gid: int) -> None: ...
    def fpathconf(fd: int, name: str | int, /) -> int: ...
    def fstatvfs(fd: int, /) -> statvfs_result: ...
    def lockf(fd: int, command: int, length: int, /) -> None: ...
    def openpty() -> tuple[int, int]: ...  # some flavors of Unix
    if sys.platform != "darwin":
        def fdatasync(fd: FileDescriptorLike) -> None: ...
        def pipe2(flags: int, /) -> tuple[int, int]: ...  # some flavors of Unix
        def posix_fallocate(fd: int, offset: int, length: int, /) -> None: ...
        def posix_fadvise(fd: int, offset: int, length: int, advice: int, /) -> None: ...

    def pread(fd: int, length: int, offset: int, /) -> bytes: ...
    def pwrite(fd: int, buffer: ReadableBuffer, offset: int, /) -> int: ...
    # In CI, stubtest sometimes reports that these are available on MacOS, sometimes not
    def preadv(fd: int, buffers: SupportsLenAndGetItem[WriteableBuffer], offset: int, flags: int = 0, /) -> int: ...
    def pwritev(fd: int, buffers: SupportsLenAndGetItem[ReadableBuffer], offset: int, flags: int = 0, /) -> int: ...
    if sys.platform != "darwin":
        RWF_APPEND: Final[int]
        RWF_DSYNC: Final[int]
        RWF_SYNC: Final[int]
        RWF_HIPRI: Final[int]
        RWF_NOWAIT: Final[int]

    if sys.platform == "linux":
        def sendfile(out_fd: FileDescriptor, in_fd: FileDescriptor, offset: int | None, count: int) -> int: ...
    else:
        def sendfile(
            out_fd: FileDescriptor,
            in_fd: FileDescriptor,
            offset: int,
            count: int,
            headers: Sequence[ReadableBuffer] = (),
            trailers: Sequence[ReadableBuffer] = (),
            flags: int = 0,
        ) -> int: ...  # FreeBSD and Mac OS X only

    def readv(fd: int, buffers: SupportsLenAndGetItem[WriteableBuffer], /) -> int: ...
    def writev(fd: int, buffers: SupportsLenAndGetItem[ReadableBuffer], /) -> int: ...

if sys.version_info >= (3, 14):
    def readinto(fd: int, buffer: ReadableBuffer, /) -> int: ...

@final
class terminal_size(structseq[int], tuple[int, int]):
    __match_args__: Final = ("columns", "lines")

    @property
    def columns(self) -> int: ...
    @property
    def lines(self) -> int: ...

def get_terminal_size(fd: int = ..., /) -> terminal_size: ...
def get_inheritable(fd: int, /) -> bool: ...
def set_inheritable(fd: int, inheritable: bool, /) -> None: ...

if sys.platform == "win32":
    def get_handle_inheritable(handle: int, /) -> bool: ...
    def set_handle_inheritable(handle: int, inheritable: bool, /) -> None: ...

if sys.platform != "win32":
    # Unix only
    def tcgetpgrp(fd: int, /) -> int: ...
    def tcsetpgrp(fd: int, pgid: int, /) -> None: ...
    def ttyname(fd: int, /) -> str: ...

def write(fd: int, data: ReadableBuffer, /) -> int: ...
def access(
    path: FileDescriptorOrPath, mode: int, *, dir_fd: int | None = None, effective_ids: bool = False, follow_symlinks: bool = True
) -> bool: ...
def chdir(path: FileDescriptorOrPath) -> None: ...

if sys.platform != "win32":
    def fchdir(fd: FileDescriptorLike) -> None: ...

def getcwd() -> str: ...
def getcwdb() -> bytes: ...
def chmod(path: FileDescriptorOrPath, mode: int, *, dir_fd: int | None = None, follow_symlinks: bool = True) -> None: ...

if sys.platform != "win32" and sys.platform != "linux":
    def chflags(path: StrOrBytesPath, flags: int, follow_symlinks: bool = True) -> None: ...  # some flavors of Unix
    def lchflags(path: StrOrBytesPath, flags: int) -> None: ...

if sys.platform != "win32":
    def chroot(path: StrOrBytesPath) -> None: ...
    def chown(
        path: FileDescriptorOrPath, uid: int, gid: int, *, dir_fd: int | None = None, follow_symlinks: bool = True
    ) -> None: ...
    def lchown(path: StrOrBytesPath, uid: int, gid: int) -> None: ...

def link(
    src: StrOrBytesPath,
    dst: StrOrBytesPath,
    *,
    src_dir_fd: int | None = None,
    dst_dir_fd: int | None = None,
    follow_symlinks: bool = True,
) -> None: ...
def lstat(path: StrOrBytesPath, *, dir_fd: int | None = None) -> stat_result: ...
def mkdir(path: StrOrBytesPath, mode: int = 0o777, *, dir_fd: int | None = None) -> None: ...

if sys.platform != "win32":
    def mkfifo(path: StrOrBytesPath, mode: int = 0o666, *, dir_fd: int | None = None) -> None: ...  # Unix only

if sys.version_info >= (3, 15):
    def makedirs(name: StrOrBytesPath, mode: int = 0o777, exist_ok: bool = False, *, parent_mode: int | None = None) -> None: ...

else:
    def makedirs(name: StrOrBytesPath, mode: int = 0o777, exist_ok: bool = False) -> None: ...

if sys.platform != "win32":
    def mknod(path: StrOrBytesPath, mode: int = 0o600, device: int = 0, *, dir_fd: int | None = None) -> None: ...
    def major(device: int, /) -> int: ...
    def minor(device: int, /) -> int: ...
    def makedev(major: int, minor: int, /) -> int: ...
    def pathconf(path: FileDescriptorOrPath, name: str | int) -> int: ...  # Unix only

def readlink(path: GenericPath[AnyStr], *, dir_fd: int | None = None) -> AnyStr: ...
def remove(path: StrOrBytesPath, *, dir_fd: int | None = None) -> None: ...
def removedirs(name: StrOrBytesPath) -> None: ...
def rename(src: StrOrBytesPath, dst: StrOrBytesPath, *, src_dir_fd: int | None = None, dst_dir_fd: int | None = None) -> None: ...
def renames(old: StrOrBytesPath, new: StrOrBytesPath) -> None: ...
def replace(
    src: StrOrBytesPath, dst: StrOrBytesPath, *, src_dir_fd: int | None = None, dst_dir_fd: int | None = None
) -> None: ...
def rmdir(path: StrOrBytesPath, *, dir_fd: int | None = None) -> None: ...

@final
@type_check_only
class _ScandirIterator(Generic[AnyStr]):
    def __del__(self) -> None: ...
    def __iter__(self) -> Self: ...
    def __next__(self) -> DirEntry[AnyStr]: ...
    def __enter__(self) -> Self: ...
    def __exit__(self, *args: Unused) -> None: ...
    def close(self) -> None: ...

@overload
def scandir(path: None = None) -> _ScandirIterator[str]: ...
@overload
def scandir(path: int) -> _ScandirIterator[str]: ...
@overload
def scandir(path: GenericPath[AnyStr]) -> _ScandirIterator[AnyStr]: ...

def stat(path: FileDescriptorOrPath, *, dir_fd: int | None = None, follow_symlinks: bool = True) -> stat_result: ...

if sys.platform != "win32":
    def statvfs(path: FileDescriptorOrPath) -> statvfs_result: ...  # Unix only

if sys.platform == "linux" and sys.version_info >= (3, 15):
    @final
    class statx_result:
        @property
        def stx_mask(self) -> int: ...
        @property
        def stx_blksize(self) -> int: ...
        @property
        def stx_attributes(self) -> int: ...
        @property
        def stx_attributes_mask(self) -> int: ...
        @property
        def stx_rdev_major(self) -> int: ...
        @property
        def stx_rdev_minor(self) -> int: ...
        @property
        def stx_rdev(self) -> int: ...
        @property
        def stx_dev_major(self) -> int: ...
        @property
        def stx_dev_minor(self) -> int: ...
        @property
        def stx_dev(self) -> int: ...
        @property
        def stx_mode(self) -> int | None: ...
        @property
        def stx_nlink(self) -> int | None: ...
        @property
        def stx_uid(self) -> int | None: ...
        @property
        def stx_gid(self) -> int | None: ...
        @property
        def stx_ino(self) -> int | None: ...
        @property
        def stx_size(self) -> int | None: ...
        @property
        def stx_blocks(self) -> int | None: ...
        @property
        def stx_atime(self) -> float | None: ...
        @property
        def stx_atime_ns(self) -> int | None: ...
        @property
        def stx_btime(self) -> float | None: ...
        @property
        def stx_btime_ns(self) -> int | None: ...
        @property
        def stx_ctime(self) -> float | None: ...
        @property
        def stx_ctime_ns(self) -> int | None: ...
        @property
        def stx_mtime(self) -> float | None: ...
        @property
        def stx_mtime_ns(self) -> int | None: ...
        @property
        def stx_mnt_id(self) -> int | None: ...
        @property
        def stx_dio_mem_align(self) -> int | None: ...
        @property
        def stx_dio_offset_align(self) -> int | None: ...

    def statx(
        path: FileDescriptorOrPath, mask: int, *, flags: int = 0, dir_fd: int | None = None, follow_symlinks: bool = True
    ) -> statx_result: ...

def symlink(
    src: StrOrBytesPath, dst: StrOrBytesPath, target_is_directory: bool = False, *, dir_fd: int | None = None
) -> None: ...

if sys.platform != "win32":
    def sync() -> None: ...  # Unix only

def truncate(path: FileDescriptorOrPath, length: int) -> None: ...  # Unix only up to version 3.4
def unlink(path: StrOrBytesPath, *, dir_fd: int | None = None) -> None: ...
def utime(
    path: FileDescriptorOrPath,
    times: tuple[int, int] | tuple[float, float] | None = None,
    *,
    ns: tuple[int, int] = ...,
    dir_fd: int | None = None,
    follow_symlinks: bool = True,
) -> None: ...

_OnError: TypeAlias = Callable[[OSError], object]

def walk(
    top: GenericPath[AnyStr], topdown: bool = True, onerror: _OnError | None = None, followlinks: bool = False
) -> Iterator[tuple[AnyStr, list[AnyStr], list[AnyStr]]]: ...

if sys.platform != "win32":
    @overload
    def fwalk(
        top: StrPath = ".",
        topdown: bool = True,
        onerror: _OnError | None = None,
        *,
        follow_symlinks: bool = False,
        dir_fd: int | None = None,
    ) -> Iterator[tuple[str, list[str], list[str], int]]: ...
    @overload
    def fwalk(
        top: BytesPath,
        topdown: bool = True,
        onerror: _OnError | None = None,
        *,
        follow_symlinks: bool = False,
        dir_fd: int | None = None,
    ) -> Iterator[tuple[bytes, list[bytes], list[bytes], int]]: ...

    if sys.platform == "linux":
        def getxattr(path: FileDescriptorOrPath, attribute: StrOrBytesPath, *, follow_symlinks: bool = True) -> bytes: ...
        def listxattr(path: FileDescriptorOrPath | None = None, *, follow_symlinks: bool = True) -> list[str]: ...
        def removexattr(path: FileDescriptorOrPath, attribute: StrOrBytesPath, *, follow_symlinks: bool = True) -> None: ...
        def setxattr(
            path: FileDescriptorOrPath,
            attribute: StrOrBytesPath,
            value: ReadableBuffer,
            flags: int = 0,
            *,
            follow_symlinks: bool = True,
        ) -> None: ...

def abort() -> NoReturn: ...

# These are defined as execl(file, *args) but the first *arg is mandatory.
def execl(file: StrOrBytesPath, *args: Unpack[tuple[StrOrBytesPath, Unpack[tuple[StrOrBytesPath, ...]]]]) -> NoReturn: ...
def execlp(file: StrOrBytesPath, *args: Unpack[tuple[StrOrBytesPath, Unpack[tuple[StrOrBytesPath, ...]]]]) -> NoReturn: ...

# These are: execle(file, *args, env) but env is pulled from the last element of the args.
def execle(
    file: StrOrBytesPath, *args: Unpack[tuple[StrOrBytesPath, Unpack[tuple[StrOrBytesPath, ...]], _ExecEnv]]
) -> NoReturn: ...
def execlpe(
    file: StrOrBytesPath, *args: Unpack[tuple[StrOrBytesPath, Unpack[tuple[StrOrBytesPath, ...]], _ExecEnv]]
) -> NoReturn: ...

# The docs say `args: tuple or list of strings`
# The implementation enforces tuple or list so we can't use Sequence.
# Not separating out PathLike[str] and PathLike[bytes] here because it doesn't make much difference
# in practice, and doing so would explode the number of combinations in this already long union.
# All these combinations are necessary due to list being invariant.
_ExecVArgs: TypeAlias = (
    tuple[StrOrBytesPath, ...]
    | list[bytes]
    | list[str]
    | list[PathLike[Any]]
    | list[bytes | str]
    | list[bytes | PathLike[Any]]
    | list[str | PathLike[Any]]
    | list[bytes | str | PathLike[Any]]
)
# Depending on the OS, the keys and values are passed either to
# PyUnicode_FSDecoder (which accepts str | ReadableBuffer) or to
# PyUnicode_FSConverter (which accepts StrOrBytesPath). For simplicity,
# we limit to str | bytes.
_ExecEnv: TypeAlias = Mapping[bytes, bytes | str] | Mapping[str, bytes | str]

def execv(path: StrOrBytesPath, argv: _ExecVArgs, /) -> NoReturn: ...
def execve(path: FileDescriptorOrPath, argv: _ExecVArgs, env: _ExecEnv) -> NoReturn: ...
def execvp(file: StrOrBytesPath, args: _ExecVArgs) -> NoReturn: ...
def execvpe(file: StrOrBytesPath, args: _ExecVArgs, env: _ExecEnv) -> NoReturn: ...
def _exit(status: int) -> NoReturn: ...
def kill(pid: int, signal: int, /) -> None: ...

if sys.platform != "win32":
    # Unix only
    def fork() -> int: ...
    def forkpty() -> tuple[int, int]: ...  # some flavors of Unix
    def killpg(pgid: int, signal: int, /) -> None: ...
    def nice(increment: int, /) -> int: ...
    if sys.platform != "darwin" and sys.platform != "linux":
        def plock(op: int, /) -> None: ...

class _wrap_close:
    def __init__(self, stream: TextIOWrapper, proc: Popen[str]) -> None: ...
    def close(self) -> int | None: ...
    def __enter__(self) -> Self: ...
    def __exit__(
        self, exc_type: type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None
    ) -> None: ...
    def __iter__(self) -> Iterator[str]: ...
    # Methods below here don't exist directly on the _wrap_close object, but
    # are copied from the wrapped TextIOWrapper object via __getattr__.
    # The full set of TextIOWrapper methods are technically available this way,
    # but undocumented. Only a subset are currently included here.
    def read(self, size: int | None = -1, /) -> str: ...
    def readable(self) -> bool: ...
    def readline(self, size: int = -1, /) -> str: ...
    def readlines(self, hint: int = -1, /) -> list[str]: ...
    def writable(self) -> bool: ...
    def write(self, s: str, /) -> int: ...
    def writelines(self, lines: Iterable[str], /) -> None: ...

@deprecated("Soft deprecated. Use the subprocess module instead.")
def popen(cmd: str, mode: str = "r", buffering: int = -1) -> _wrap_close: ...
@deprecated("Soft deprecated. Use the subprocess module instead.")
def spawnl(mode: int, file: StrOrBytesPath, arg0: StrOrBytesPath, *args: StrOrBytesPath) -> int: ...
@deprecated("Soft deprecated. Use the subprocess module instead.")
def spawnle(mode: int, file: StrOrBytesPath, arg0: StrOrBytesPath, *args: Any) -> int: ...  # Imprecise sig

if sys.platform != "win32":
    @deprecated("Soft deprecated. Use the subprocess module instead.")
    def spawnv(mode: int, file: StrOrBytesPath, args: _ExecVArgs) -> int: ...
    @deprecated("Soft deprecated. Use the subprocess module instead.")
    def spawnve(mode: int, file: StrOrBytesPath, args: _ExecVArgs, env: _ExecEnv) -> int: ...
else:
    @deprecated("Soft deprecated. Use the subprocess module instead.")
    def spawnv(mode: int, path: StrOrBytesPath, argv: _ExecVArgs, /) -> int: ...
    @deprecated("Soft deprecated. Use the subprocess module instead.")
    def spawnve(mode: int, path: StrOrBytesPath, argv: _ExecVArgs, env: _ExecEnv, /) -> int: ...

@deprecated("Soft deprecated. Use the subprocess module instead.")
def system(command: StrOrBytesPath) -> int: ...

@final
class times_result(structseq[float], tuple[float, float, float, float, float]):
    __match_args__: Final = ("user", "system", "children_user", "children_system", "elapsed")

    @property
    def user(self) -> float: ...
    @property
    def system(self) -> float: ...
    @property
    def children_user(self) -> float: ...
    @property
    def children_system(self) -> float: ...
    @property
    def elapsed(self) -> float: ...

def times() -> times_result: ...
def waitpid(pid: int, options: int, /) -> tuple[int, int]: ...

if sys.platform == "win32":
    def startfile(
        filepath: StrOrBytesPath, operation: str = ..., arguments: str = "", cwd: StrOrBytesPath | None = None, show_cmd: int = 1
    ) -> None: ...

else:
    @deprecated("Soft deprecated. Use the subprocess module instead.")
    def spawnlp(mode: int, file: StrOrBytesPath, arg0: StrOrBytesPath, *args: StrOrBytesPath) -> int: ...
    @deprecated("Soft deprecated. Use the subprocess module instead.")
    def spawnlpe(mode: int, file: StrOrBytesPath, arg0: StrOrBytesPath, *args: Any) -> int: ...  # Imprecise signature
    @deprecated("Soft deprecated. Use the subprocess module instead.")
    def spawnvp(mode: int, file: StrOrBytesPath, args: _ExecVArgs) -> int: ...
    @deprecated("Soft deprecated. Use the subprocess module instead.")
    def spawnvpe(mode: int, file: StrOrBytesPath, args: _ExecVArgs, env: _ExecEnv) -> int: ...
    def wait() -> tuple[int, int]: ...  # Unix only
    # Added to MacOS in 3.13
    if sys.platform != "darwin" or sys.version_info >= (3, 13):
        @final
        class waitid_result(structseq[int], tuple[int, int, int, int, int]):
            __match_args__: Final = ("si_pid", "si_uid", "si_signo", "si_status", "si_code")

            @property
            def si_pid(self) -> int: ...
            @property
            def si_uid(self) -> int: ...
            @property
            def si_signo(self) -> int: ...
            @property
            def si_status(self) -> int: ...
            @property
            def si_code(self) -> int: ...

        def waitid(idtype: int, ident: int, options: int, /) -> waitid_result | None: ...

    from resource import struct_rusage

    def wait3(options: int) -> tuple[int, int, struct_rusage]: ...
    def wait4(pid: int, options: int) -> tuple[int, int, struct_rusage]: ...
    def WCOREDUMP(status: int, /) -> bool: ...
    def WIFCONTINUED(status: int) -> bool: ...
    def WIFSTOPPED(status: int) -> bool: ...
    def WIFSIGNALED(status: int) -> bool: ...
    def WIFEXITED(status: int) -> bool: ...
    def WEXITSTATUS(status: int) -> int: ...
    def WSTOPSIG(status: int) -> int: ...
    def WTERMSIG(status: int) -> int: ...

    if sys.version_info >= (3, 15):
        def posix_spawn(
            path: StrOrBytesPath,
            argv: _ExecVArgs,
            env: _ExecEnv | None,
            /,
            *,
            file_actions: Sequence[tuple[Any, ...]] | None = (),
            setpgroup: int | None = None,  # None allowed starting in 3.15
            resetids: bool = False,
            setsid: bool = False,
            setsigmask: Iterable[int] = (),
            setsigdef: Iterable[int] = (),
            scheduler: tuple[Any, sched_param] | None = None,  # None allowed starting in 3.15
        ) -> int: ...
        def posix_spawnp(
            path: StrOrBytesPath,
            argv: _ExecVArgs,
            env: _ExecEnv | None,
            /,
            *,
            file_actions: Sequence[tuple[Any, ...]] | None = (),
            setpgroup: int | None = None,  # None allowed starting in 3.15
            resetids: bool = False,
            setsid: bool = False,
            setsigmask: Iterable[int] = (),
            setsigdef: Iterable[int] = (),
            scheduler: tuple[Any, sched_param] | None = None,  # None allowed starting in 3.15
        ) -> int: ...
    elif sys.version_info >= (3, 13):
        def posix_spawn(
            path: StrOrBytesPath,
            argv: _ExecVArgs,
            env: _ExecEnv | None,  # None allowed starting in 3.13
            /,
            *,
            file_actions: Sequence[tuple[Any, ...]] | None = (),
            setpgroup: int = ...,
            resetids: bool = False,
            setsid: bool = False,
            setsigmask: Iterable[int] = (),
            setsigdef: Iterable[int] = (),
            scheduler: tuple[Any, sched_param] = ...,
        ) -> int: ...
        def posix_spawnp(
            path: StrOrBytesPath,
            argv: _ExecVArgs,
            env: _ExecEnv | None,  # None allowed starting in 3.13
            /,
            *,
            file_actions: Sequence[tuple[Any, ...]] | None = (),
            setpgroup: int = ...,
            resetids: bool = False,
            setsid: bool = False,
            setsigmask: Iterable[int] = (),
            setsigdef: Iterable[int] = (),
            scheduler: tuple[Any, sched_param] = ...,
        ) -> int: ...
    else:
        def posix_spawn(
            path: StrOrBytesPath,
            argv: _ExecVArgs,
            env: _ExecEnv,
            /,
            *,
            file_actions: Sequence[tuple[Any, ...]] | None = (),
            setpgroup: int = ...,
            resetids: bool = False,
            setsid: bool = False,
            setsigmask: Iterable[int] = (),
            setsigdef: Iterable[int] = (),
            scheduler: tuple[Any, sched_param] = ...,
        ) -> int: ...
        def posix_spawnp(
            path: StrOrBytesPath,
            argv: _ExecVArgs,
            env: _ExecEnv,
            /,
            *,
            file_actions: Sequence[tuple[Any, ...]] | None = (),
            setpgroup: int = ...,
            resetids: bool = False,
            setsid: bool = False,
            setsigmask: Iterable[int] = (),
            setsigdef: Iterable[int] = (),
            scheduler: tuple[Any, sched_param] = ...,
        ) -> int: ...

    POSIX_SPAWN_OPEN: Final = 0
    POSIX_SPAWN_CLOSE: Final = 1
    POSIX_SPAWN_DUP2: Final = 2

if sys.platform != "win32":
    @final
    class sched_param(structseq[int], tuple[int]):
        __match_args__: Final = ("sched_priority",)

        def __new__(cls, sched_priority: int) -> Self: ...
        @property
        def sched_priority(self) -> int: ...

    def sched_get_priority_min(policy: int) -> int: ...  # some flavors of Unix
    def sched_get_priority_max(policy: int) -> int: ...  # some flavors of Unix
    def sched_yield() -> None: ...  # some flavors of Unix
    if sys.platform != "darwin":
        def sched_setscheduler(pid: int, policy: int, param: sched_param, /) -> None: ...  # some flavors of Unix
        def sched_getscheduler(pid: int, /) -> int: ...  # some flavors of Unix
        def sched_rr_get_interval(pid: int, /) -> float: ...  # some flavors of Unix
        def sched_setparam(pid: int, param: sched_param, /) -> None: ...  # some flavors of Unix
        def sched_getparam(pid: int, /) -> sched_param: ...  # some flavors of Unix
        def sched_setaffinity(pid: int, mask: Iterable[int], /) -> None: ...  # some flavors of Unix
        def sched_getaffinity(pid: int, /) -> set[int]: ...  # some flavors of Unix

def cpu_count() -> int | None: ...

if sys.version_info >= (3, 13):
    # Documented to return `int | None`, but falls back to `len(sched_getaffinity(0))` when
    # available. See https://github.com/python/cpython/blob/417c130/Lib/os.py#L1175-L1186.
    if sys.platform != "win32" and sys.platform != "darwin":
        def process_cpu_count() -> int: ...
    else:
        def process_cpu_count() -> int | None: ...

if sys.platform != "win32":
    # Unix only
    def confstr(name: str | int, /) -> str | None: ...
    def getloadavg() -> tuple[float, float, float]: ...
    def sysconf(name: str | int, /) -> int: ...

if sys.platform == "linux":
    def getrandom(size: int, flags: int = 0) -> bytes: ...

def urandom(size: int, /) -> bytes: ...

if sys.platform != "win32":
    def register_at_fork(
        *,
        before: Callable[..., Any] | None = ...,
        after_in_parent: Callable[..., Any] | None = ...,
        after_in_child: Callable[..., Any] | None = ...,
    ) -> None: ...

if sys.platform == "win32":
    class _AddedDllDirectory:
        path: str | None
        def __init__(self, path: str | None, cookie: _T, remove_dll_directory: Callable[[_T], object]) -> None: ...
        def close(self) -> None: ...
        def __enter__(self) -> Self: ...
        def __exit__(self, *args: Unused) -> None: ...

    def add_dll_directory(path: str) -> _AddedDllDirectory: ...

if sys.platform == "linux":
    MFD_CLOEXEC: Final[int]
    MFD_ALLOW_SEALING: Final[int]
    MFD_HUGETLB: Final[int]
    MFD_HUGE_SHIFT: Final[int]
    MFD_HUGE_MASK: Final[int]
    MFD_HUGE_64KB: Final[int]
    MFD_HUGE_512KB: Final[int]
    MFD_HUGE_1MB: Final[int]
    MFD_HUGE_2MB: Final[int]
    MFD_HUGE_8MB: Final[int]
    MFD_HUGE_16MB: Final[int]
    MFD_HUGE_32MB: Final[int]
    MFD_HUGE_256MB: Final[int]
    MFD_HUGE_512MB: Final[int]
    MFD_HUGE_1GB: Final[int]
    MFD_HUGE_2GB: Final[int]
    MFD_HUGE_16GB: Final[int]
    def memfd_create(name: str, flags: int = ...) -> int: ...
    def copy_file_range(src: int, dst: int, count: int, offset_src: int | None = None, offset_dst: int | None = None) -> int: ...

def waitstatus_to_exitcode(status: int) -> int: ...

if sys.platform == "linux":
    def pidfd_open(pid: int, flags: int = 0) -> int: ...

if sys.version_info >= (3, 12) and sys.platform == "linux":
    PIDFD_NONBLOCK: Final = 2048

if sys.version_info >= (3, 12) and sys.platform == "win32":
    def listdrives() -> list[str]: ...
    def listmounts(volume: str) -> list[str]: ...
    def listvolumes() -> list[str]: ...

if sys.platform == "linux":
    EFD_CLOEXEC: Final[int]
    EFD_NONBLOCK: Final[int]
    EFD_SEMAPHORE: Final[int]
    SPLICE_F_MORE: Final[int]
    SPLICE_F_MOVE: Final[int]
    SPLICE_F_NONBLOCK: Final[int]
    def eventfd(initval: int, flags: int = 524288) -> FileDescriptor: ...
    def eventfd_read(fd: FileDescriptor) -> int: ...
    def eventfd_write(fd: FileDescriptor, value: int) -> None: ...
    def splice(
        src: FileDescriptor,
        dst: FileDescriptor,
        count: int,
        offset_src: int | None = None,
        offset_dst: int | None = None,
        flags: int = 0,
    ) -> int: ...

if sys.version_info >= (3, 12) and sys.platform == "linux":
    CLONE_FILES: Final[int]
    CLONE_FS: Final[int]
    CLONE_NEWCGROUP: Final[int]  # Linux 4.6+
    CLONE_NEWIPC: Final[int]  # Linux 2.6.19+
    CLONE_NEWNET: Final[int]  # Linux 2.6.24+
    CLONE_NEWNS: Final[int]
    CLONE_NEWPID: Final[int]  # Linux 3.8+
    CLONE_NEWTIME: Final[int]  # Linux 5.6+
    CLONE_NEWUSER: Final[int]  # Linux 3.8+
    CLONE_NEWUTS: Final[int]  # Linux 2.6.19+
    CLONE_SIGHAND: Final[int]
    CLONE_SYSVSEM: Final[int]  # Linux 2.6.26+
    CLONE_THREAD: Final[int]
    CLONE_VM: Final[int]
    def unshare(flags: int) -> None: ...
    def setns(fd: FileDescriptorLike, nstype: int = 0) -> None: ...

if sys.version_info >= (3, 13) and sys.platform != "win32":
    def posix_openpt(oflag: int, /) -> int: ...
    def grantpt(fd: FileDescriptorLike, /) -> None: ...
    def unlockpt(fd: FileDescriptorLike, /) -> None: ...
    def ptsname(fd: FileDescriptorLike, /) -> str: ...

if sys.version_info >= (3, 13) and sys.platform == "linux":
    TFD_TIMER_ABSTIME: Final = 1
    TFD_TIMER_CANCEL_ON_SET: Final = 2
    TFD_NONBLOCK: Final[int]
    TFD_CLOEXEC: Final[int]
    POSIX_SPAWN_CLOSEFROM: Final[int]

    def timerfd_create(clockid: int, /, *, flags: int = 0) -> int: ...
    def timerfd_settime(
        fd: FileDescriptor, /, *, flags: int = 0, initial: float = 0.0, interval: float = 0.0
    ) -> tuple[float, float]: ...
    def timerfd_settime_ns(fd: FileDescriptor, /, *, flags: int = 0, initial: int = 0, interval: int = 0) -> tuple[int, int]: ...
    def timerfd_gettime(fd: FileDescriptor, /) -> tuple[float, float]: ...
    def timerfd_gettime_ns(fd: FileDescriptor, /) -> tuple[int, int]: ...

if sys.version_info >= (3, 13) or sys.platform != "win32":
    # Added to Windows in 3.13.
    def fchmod(fd: int, mode: int) -> None: ...

if sys.platform != "linux":
    if sys.version_info >= (3, 13) or sys.platform != "win32":
        # Added to Windows in 3.13.
        def lchmod(path: StrOrBytesPath, mode: int) -> None: ...
