Skip to content

Add a structseq class to _typeshed #6560

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 82 commits into from
Dec 17, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
82 commits
Select commit Hold shift + click to select a range
4ff8300
Add `structseq` definition
AlexWaygood Dec 10, 2021
6e3c091
Update OS classes
AlexWaygood Dec 10, 2021
04597a4
Update OS: linux classes
AlexWaygood Dec 10, 2021
fdea229
Update grp.pyi
AlexWaygood Dec 10, 2021
d03b868
Update resource.pyi
AlexWaygood Dec 10, 2021
179d8b9
Update signal.pyi
AlexWaygood Dec 10, 2021
1bcb0a3
Update spwd.pyi
AlexWaygood Dec 10, 2021
a185520
Update _thread.pyi
AlexWaygood Dec 10, 2021
4142495
Improve `structseq.__new__`, add comments
AlexWaygood Dec 10, 2021
e339c1f
Update grp.pyi
AlexWaygood Dec 10, 2021
7d754eb
Update spwd.pyi
AlexWaygood Dec 10, 2021
68ec604
Update darwin.txt
AlexWaygood Dec 10, 2021
b38bd59
Update linux.txt
AlexWaygood Dec 10, 2021
4016ce2
Update py310.txt
AlexWaygood Dec 10, 2021
3c5d398
Update py39.txt
AlexWaygood Dec 10, 2021
3617196
Update py3_common.txt
AlexWaygood Dec 10, 2021
cea53fa
Update pwd.pyi
AlexWaygood Dec 10, 2021
4bfaac1
Update time.pyi
AlexWaygood Dec 10, 2021
ee3b28d
Update __init__.pyi
AlexWaygood Dec 10, 2021
f48b97e
Remove fictitious `_struct_time` class from mro
AlexWaygood Dec 10, 2021
21d6ee5
Update _thread.pyi
AlexWaygood Dec 10, 2021
c2cdc4d
Update grp.pyi
AlexWaygood Dec 10, 2021
5b8dc7d
Update __init__.pyi
AlexWaygood Dec 10, 2021
7bcfc3c
Update pwd.pyi
AlexWaygood Dec 10, 2021
5cfbeb4
Update resource.pyi
AlexWaygood Dec 10, 2021
e3c06a1
Update signal.pyi
AlexWaygood Dec 10, 2021
fc212cb
Update spwd.pyi
AlexWaygood Dec 10, 2021
6ab37ea
`sequence` parameter actually takes an iterable...
AlexWaygood Dec 10, 2021
4e6d045
Update _thread.pyi
AlexWaygood Dec 10, 2021
7e0a068
Update grp.pyi
AlexWaygood Dec 10, 2021
e926dbd
Update __init__.pyi
AlexWaygood Dec 10, 2021
aab3d50
Update pwd.pyi
AlexWaygood Dec 10, 2021
afd0cf9
Update resource.pyi
AlexWaygood Dec 10, 2021
0a37e00
Update signal.pyi
AlexWaygood Dec 10, 2021
0630fd3
Update spwd.pyi
AlexWaygood Dec 10, 2021
9248d44
Update grp.pyi
AlexWaygood Dec 10, 2021
10bbe0a
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Dec 10, 2021
4510fd7
Update resource.pyi
AlexWaygood Dec 10, 2021
e4d350a
Update signal.pyi
AlexWaygood Dec 10, 2021
abb9815
Update spwd.pyi
AlexWaygood Dec 10, 2021
2f921b4
Update time.pyi
AlexWaygood Dec 10, 2021
e3e9fdf
Syntax errors
AlexWaygood Dec 10, 2021
8a4ab13
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Dec 10, 2021
2a4f14b
Update __init__.pyi
AlexWaygood Dec 10, 2021
350b00a
Update time.pyi
AlexWaygood Dec 10, 2021
9d9d45f
Update _thread.pyi
AlexWaygood Dec 10, 2021
0a8d6d0
Update __init__.pyi
AlexWaygood Dec 10, 2021
0c5cf81
Update grp.pyi
AlexWaygood Dec 10, 2021
719378c
Update pwd.pyi
AlexWaygood Dec 10, 2021
93ba6c6
Update spwd.pyi
AlexWaygood Dec 10, 2021
2e5a8a8
Update time.pyi
AlexWaygood Dec 10, 2021
9b6399e
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Dec 10, 2021
77db4ae
Update _thread.pyi
AlexWaygood Dec 10, 2021
fa8acd3
Update __init__.pyi
AlexWaygood Dec 10, 2021
330b24c
Update time.pyi
AlexWaygood Dec 10, 2021
30920aa
Beautify
AlexWaygood Dec 10, 2021
2b0b758
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Dec 10, 2021
819e195
Refactor based on Jukka's suggestion
AlexWaygood Dec 10, 2021
126b2ea
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Dec 10, 2021
805fc6e
pyright errors
AlexWaygood Dec 10, 2021
4b32760
Merge branch 'structseq' of https://github.com/AlexWaygood/typeshed i…
AlexWaygood Dec 10, 2021
94e6cf9
Use old syntax in type aliases
AlexWaygood Dec 10, 2021
5acec5d
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Dec 10, 2021
ecfdb7b
Remove attributes that do not exist at runtime
AlexWaygood Dec 10, 2021
0e7bcc4
Remove unused allowlist entries
AlexWaygood Dec 10, 2021
25ab4a4
More unused entries
AlexWaygood Dec 10, 2021
3a6c7cf
Quell pytype and flake8
AlexWaygood Dec 10, 2021
7ef375e
Update stdlib/os/__init__.pyi
AlexWaygood Dec 11, 2021
dead782
Update stdlib/_typeshed/__init__.pyi
AlexWaygood Dec 11, 2021
d342427
Delete redundant comment
AlexWaygood Dec 11, 2021
10301cf
`struct_time` has 9 elements
AlexWaygood Dec 11, 2021
82fce49
Improve `os.stat_result`
AlexWaygood Dec 11, 2021
494bdc7
Remove many comments
AlexWaygood Dec 11, 2021
ecfab5b
Improve comment in `_typeshed`
AlexWaygood Dec 11, 2021
9a7dffe
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Dec 11, 2021
3a4f887
Improve `os.statvfs_result`
AlexWaygood Dec 11, 2021
3e283f4
Merge branch 'structseq' of https://github.com/AlexWaygood/typeshed i…
AlexWaygood Dec 11, 2021
c807646
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Dec 11, 2021
28995dc
Update stdlib/_typeshed/__init__.pyi
AlexWaygood Dec 11, 2021
29b9800
Remove no-longer-needed type alias
AlexWaygood Dec 11, 2021
201d05e
Merge remote-tracking branch 'origin/master' into structseq
AlexWaygood Dec 17, 2021
db20660
Merge branch 'master' into structseq
AlexWaygood Dec 17, 2021
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
5 changes: 4 additions & 1 deletion stdlib/_thread.pyi
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import sys
from _typeshed import structseq
from threading import Thread
from types import TracebackType
from typing import Any, Callable, NoReturn, Optional, Tuple, Type
Expand Down Expand Up @@ -32,7 +33,9 @@ TIMEOUT_MAX: float
if sys.version_info >= (3, 8):
def get_native_id() -> int: ... # only available on some platforms
@final
class _ExceptHookArgs(Tuple[Type[BaseException], Optional[BaseException], Optional[TracebackType], Optional[Thread]]):
class _ExceptHookArgs(
structseq[Any], Tuple[Type[BaseException], Optional[BaseException], Optional[TracebackType], Optional[Thread]]
):
@property
def exc_type(self) -> Type[BaseException]: ...
@property
Expand Down
19 changes: 18 additions & 1 deletion stdlib/_typeshed/__init__.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import ctypes
import mmap
import sys
from os import PathLike
from typing import AbstractSet, Any, Awaitable, Container, Iterable, Protocol, TypeVar, Union
from typing import AbstractSet, Any, Awaitable, ClassVar, Container, Generic, Iterable, Protocol, Type, TypeVar, Union
from typing_extensions import Literal, final

_KT = TypeVar("_KT")
Expand Down Expand Up @@ -199,3 +199,20 @@ else:
@final
class NoneType:
def __bool__(self) -> Literal[False]: ...

# This is an internal CPython type that is like, but subtly different from, a NamedTuple
# Subclasses of this type are found in multiple modules.
# In typeshed, `structseq` is only ever used as a mixin in combination with a fixed-length `Tuple`
# See discussion at #6546 & #6560
# `structseq` classes are unsubclassable, so are all decorated with `@final`.
class structseq(Generic[_T_co]):
n_fields: ClassVar[int]
n_unnamed_fields: ClassVar[int]
n_sequence_fields: ClassVar[int]
# The first parameter will generally only take an iterable of a specific length.
# E.g. `os.uname_result` takes any iterable of length exactly 5.
#
# The second parameter will accept a dict of any kind without raising an exception,
# but only has any meaning if you supply it a dict where the keys are strings.
# https://github.com/python/typeshed/pull/6560#discussion_r767149830
def __new__(cls: Type[_T], sequence: Iterable[_T_co], dict: dict[str, Any] = ...) -> _T: ...
19 changes: 13 additions & 6 deletions stdlib/grp.pyi
Original file line number Diff line number Diff line change
@@ -1,10 +1,17 @@
from typing import NamedTuple
from _typeshed import structseq
from typing import Any, List, Optional, Tuple
from typing_extensions import final

class struct_group(NamedTuple):
gr_name: str
gr_passwd: str | None
gr_gid: int
gr_mem: list[str]
@final
class struct_group(structseq[Any], Tuple[str, Optional[str], int, List[str]]):
@property
def gr_name(self) -> str: ...
@property
def gr_passwd(self) -> str | None: ...
@property
def gr_gid(self) -> int: ...
@property
def gr_mem(self) -> list[str]: ...

def getgrall() -> list[struct_group]: ...
def getgrgid(id: int) -> struct_group: ...
Expand Down
263 changes: 158 additions & 105 deletions stdlib/os/__init__.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ from _typeshed import (
Self,
StrOrBytesPath,
StrPath,
structseq,
)
from builtins import OSError
from contextlib import AbstractContextManager
Expand All @@ -26,7 +27,6 @@ from typing import (
List,
Mapping,
MutableMapping,
NamedTuple,
NoReturn,
Protocol,
Sequence,
Expand Down Expand Up @@ -284,49 +284,71 @@ TMP_MAX: int # Undocumented, but used by tempfile

# ----- os classes (structures) -----
@final
class stat_result:
# For backward compatibility, the return value of stat() is also
# accessible as a tuple of at least 10 integers giving the most important
# (and portable) members of the stat structure, in the order 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.

st_mode: int # protection bits,
st_ino: int # inode number,
st_dev: int # device,
st_nlink: int # number of hard links,
st_uid: int # user id of owner,
st_gid: int # group id of owner,
st_size: int # size of file, in bytes,
st_atime: float # time of most recent access,
st_mtime: float # time of most recent content modification,
st_ctime: float # platform dependent (time of most recent metadata change on Unix, or the time of creation on Windows)
st_atime_ns: int # time of most recent access, in nanoseconds
st_mtime_ns: int # time of most recent content modification in nanoseconds
st_ctime_ns: int # platform dependent (time of most recent metadata change on Unix, or the time of creation on Windows) in nanoseconds
if sys.version_info >= (3, 8) and sys.platform == "win32":
st_reparse_tag: int
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.
@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)
@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":
st_file_attributes: int
def __getitem__(self, i: int) -> int: ...
# not documented
def __init__(self, tuple: Tuple[int, ...]) -> None: ...
# On some Unix systems (such as Linux), the following attributes may also
# be available:
st_blocks: int # number of blocks allocated for file
st_blksize: int # filesystem blocksize
st_rdev: int # type of device if an inode device
st_flags: int # user defined flags for file

# 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):
st_gen: int # file generation number
st_birthtime: int # time of file creation

# On Mac OS systems, the following attributes may also be available:
st_rsize: int
st_creator: int
st_type: int
@property
def st_file_attributes(self) -> int: ...
if sys.version_info >= (3, 8):
@property
def st_reparse_tag(self) -> int: ...
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 on Windows or 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) -> int: ... # time of file creation
if sys.platform == "darwin":
@property
def st_flags(self) -> int: ... # user defined flags for file
# Atributes 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

@runtime_checkable
class PathLike(Protocol[_AnyStr_co]):
Expand Down Expand Up @@ -359,45 +381,55 @@ class DirEntry(Generic[AnyStr]):
if sys.version_info >= (3, 9):
def __class_getitem__(cls, item: Any) -> GenericAlias: ...

if sys.platform != "win32":
_Tuple10Int = Tuple[int, int, int, int, int, int, int, int, int, int]
_Tuple11Int = Tuple[int, int, int, int, int, int, int, int, int, int, int]
if sys.version_info >= (3, 7):
# f_fsid was added in https://github.com/python/cpython/pull/4571
@final
class statvfs_result(_Tuple10Int): # Unix only
def __new__(cls, seq: _Tuple10Int | _Tuple11Int, dict: dict[str, int] = ...) -> statvfs_result: ...
n_fields: int
n_sequence_fields: int
n_unnamed_fields: int

f_bsize: int
f_frsize: int
f_blocks: int
f_bfree: int
f_bavail: int
f_files: int
f_ffree: int
f_favail: int
f_flag: int
f_namemax: int
f_fsid: int
else:
class statvfs_result(_Tuple10Int): # Unix only
n_fields: int
n_sequence_fields: int
n_unnamed_fields: int

f_bsize: int
f_frsize: int
f_blocks: int
f_bfree: int
f_bavail: int
f_files: int
f_ffree: int
f_favail: int
f_flag: int
f_namemax: int
if sys.version_info >= (3, 7):
@final
class statvfs_result(structseq[int], Tuple[int, int, int, int, int, int, int, int, int, int, int]):
@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: ...

else:
@final
class statvfs_result(structseq[int], Tuple[int, int, int, int, int, int, int, int, int, int]):
@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: ...

# ----- os function stubs -----
def fsencode(filename: StrOrBytesPath) -> bytes: ...
Expand All @@ -415,12 +447,17 @@ def getppid() -> int: ...
def strerror(__code: int) -> str: ...
def umask(__mask: int) -> int: ...
@final
class uname_result(NamedTuple):
sysname: str
nodename: str
release: str
version: str
machine: str
class uname_result(structseq[str], Tuple[str, str, str, str, str]):
@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: ...
Expand Down Expand Up @@ -602,9 +639,11 @@ if sys.platform != "win32":
def writev(__fd: int, __buffers: Sequence[bytes]) -> int: ...

@final
class terminal_size(Tuple[int, int]):
columns: int
lines: int
class terminal_size(structseq[int], Tuple[int, int]):
@property
def columns(self) -> int: ...
@property
def lines(self) -> int: ...

def get_terminal_size(fd: int = ...) -> terminal_size: ...
def get_inheritable(__fd: int) -> bool: ...
Expand Down Expand Up @@ -819,12 +858,17 @@ else:

def system(command: StrOrBytesPath) -> int: ...
@final
class times_result(NamedTuple):
user: float
system: float
children_user: float
children_system: float
elapsed: float
class times_result(structseq[float], Tuple[float, float, float, float, float]):
@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]: ...
Expand All @@ -839,12 +883,18 @@ else:
def spawnvpe(mode: int, file: StrOrBytesPath, args: _ExecVArgs, env: _ExecEnv) -> int: ...
def wait() -> tuple[int, int]: ... # Unix only
if sys.platform != "darwin":
class waitid_result(NamedTuple):
si_pid: int
si_uid: int
si_signo: int
si_status: int
si_code: int
@final
class waitid_result(structseq[int], Tuple[int, int, int, int, int]):
@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: ...
def wait3(options: int) -> tuple[int, int, Any]: ...
def wait4(pid: int, options: int) -> tuple[int, int, Any]: ...
Expand Down Expand Up @@ -885,8 +935,11 @@ else:
) -> int: ...

if sys.platform != "win32":
class sched_param(NamedTuple):
sched_priority: int
@final
class sched_param(structseq[int], Tuple[int]):
def __new__(cls, sched_priority: int) -> sched_param: ...
@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
Expand Down
Loading