-
-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Add pyrefly type checking. #3412
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
base: main
Are you sure you want to change the base?
Changes from all commits
c1b419d
e1f1797
2203c59
513f72c
2f16bf1
a703361
b4ca68a
e6cfbbf
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -10,6 +10,15 @@ | |||||||||||||||||||||||||||||||||||||||||||||||||
| from types import TracebackType | ||||||||||||||||||||||||||||||||||||||||||||||||||
| from weakref import WeakKeyDictionary | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| if t.TYPE_CHECKING: | ||||||||||||||||||||||||||||||||||||||||||||||||||
| from _typeshed import OpenBinaryMode | ||||||||||||||||||||||||||||||||||||||||||||||||||
| from _typeshed import OpenTextMode | ||||||||||||||||||||||||||||||||||||||||||||||||||
| else: | ||||||||||||||||||||||||||||||||||||||||||||||||||
| OpenBinaryMode = OpenTextMode = str | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| AnyStr = t.TypeVar("AnyStr", str, bytes) | ||||||||||||||||||||||||||||||||||||||||||||||||||
| OpenFileMode = OpenTextMode | OpenBinaryMode | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| CYGWIN = sys.platform.startswith("cygwin") | ||||||||||||||||||||||||||||||||||||||||||||||||||
| WIN = sys.platform.startswith("win") | ||||||||||||||||||||||||||||||||||||||||||||||||||
| auto_wrap_for_ansi: t.Callable[[t.TextIO], t.TextIO] | None = None | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -355,26 +364,64 @@ def get_text_stderr(encoding: str | None = None, errors: str | None = None) -> t | |||||||||||||||||||||||||||||||||||||||||||||||||
| return _force_correct_text_writer(sys.stderr, encoding, errors, force_writable=True) | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| @t.overload | ||||||||||||||||||||||||||||||||||||||||||||||||||
| def _wrap_io_open( | ||||||||||||||||||||||||||||||||||||||||||||||||||
| file: str | os.PathLike[str] | int, | ||||||||||||||||||||||||||||||||||||||||||||||||||
| mode: str, | ||||||||||||||||||||||||||||||||||||||||||||||||||
| mode: OpenBinaryMode, | ||||||||||||||||||||||||||||||||||||||||||||||||||
| encoding: str | None, | ||||||||||||||||||||||||||||||||||||||||||||||||||
| errors: str | None, | ||||||||||||||||||||||||||||||||||||||||||||||||||
| ) -> t.IO[t.Any]: | ||||||||||||||||||||||||||||||||||||||||||||||||||
| ) -> t.BinaryIO: ... | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| @t.overload | ||||||||||||||||||||||||||||||||||||||||||||||||||
| def _wrap_io_open( | ||||||||||||||||||||||||||||||||||||||||||||||||||
| file: str | os.PathLike[str] | int, | ||||||||||||||||||||||||||||||||||||||||||||||||||
| mode: OpenTextMode = "r", | ||||||||||||||||||||||||||||||||||||||||||||||||||
| encoding: str | None = None, | ||||||||||||||||||||||||||||||||||||||||||||||||||
| errors: str | None = "strict", | ||||||||||||||||||||||||||||||||||||||||||||||||||
| ) -> t.TextIO: ... | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| def _wrap_io_open( | ||||||||||||||||||||||||||||||||||||||||||||||||||
| file: str | os.PathLike[str] | int, | ||||||||||||||||||||||||||||||||||||||||||||||||||
| mode: OpenFileMode = "r", | ||||||||||||||||||||||||||||||||||||||||||||||||||
| encoding: str | None = None, | ||||||||||||||||||||||||||||||||||||||||||||||||||
| errors: str | None = "strict", | ||||||||||||||||||||||||||||||||||||||||||||||||||
| ) -> t.BinaryIO | t.TextIO: | ||||||||||||||||||||||||||||||||||||||||||||||||||
| """Handles not passing ``encoding`` and ``errors`` in binary mode.""" | ||||||||||||||||||||||||||||||||||||||||||||||||||
| if "b" in mode: | ||||||||||||||||||||||||||||||||||||||||||||||||||
| return open(file, mode) | ||||||||||||||||||||||||||||||||||||||||||||||||||
| return t.cast(t.BinaryIO, open(file, mode)) | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| return open(file, mode, encoding=encoding, errors=errors) | ||||||||||||||||||||||||||||||||||||||||||||||||||
| return t.cast(t.TextIO, open(file, mode, encoding=encoding, errors=errors)) | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| @t.overload | ||||||||||||||||||||||||||||||||||||||||||||||||||
| def open_stream( | ||||||||||||||||||||||||||||||||||||||||||||||||||
| filename: str | os.PathLike[str], | ||||||||||||||||||||||||||||||||||||||||||||||||||
| mode: str = "r", | ||||||||||||||||||||||||||||||||||||||||||||||||||
| mode: OpenBinaryMode, | ||||||||||||||||||||||||||||||||||||||||||||||||||
| encoding: str | None = None, | ||||||||||||||||||||||||||||||||||||||||||||||||||
| errors: str | None = "strict", | ||||||||||||||||||||||||||||||||||||||||||||||||||
| atomic: bool = False, | ||||||||||||||||||||||||||||||||||||||||||||||||||
| ) -> tuple[t.IO[t.Any], bool]: | ||||||||||||||||||||||||||||||||||||||||||||||||||
| ) -> tuple[t.IO[bytes], bool]: ... | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| @t.overload | ||||||||||||||||||||||||||||||||||||||||||||||||||
| def open_stream( | ||||||||||||||||||||||||||||||||||||||||||||||||||
| filename: str | os.PathLike[str], | ||||||||||||||||||||||||||||||||||||||||||||||||||
| mode: OpenTextMode = "r", | ||||||||||||||||||||||||||||||||||||||||||||||||||
| encoding: str | None = None, | ||||||||||||||||||||||||||||||||||||||||||||||||||
| errors: str | None = "strict", | ||||||||||||||||||||||||||||||||||||||||||||||||||
| atomic: bool = False, | ||||||||||||||||||||||||||||||||||||||||||||||||||
| ) -> tuple[t.IO[str], bool]: ... | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| def open_stream( | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+405
to
+418
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: those newlines here aren't necessary, and makes things easier to read IMO.
Suggested change
(btw, I like these overloads) |
||||||||||||||||||||||||||||||||||||||||||||||||||
| filename: str | os.PathLike[str], | ||||||||||||||||||||||||||||||||||||||||||||||||||
| mode: OpenFileMode = "r", | ||||||||||||||||||||||||||||||||||||||||||||||||||
| encoding: str | None = None, | ||||||||||||||||||||||||||||||||||||||||||||||||||
| errors: str | None = "strict", | ||||||||||||||||||||||||||||||||||||||||||||||||||
| atomic: bool = False, | ||||||||||||||||||||||||||||||||||||||||||||||||||
| ) -> tuple[t.IO[bytes] | t.IO[str], bool]: | ||||||||||||||||||||||||||||||||||||||||||||||||||
| binary = "b" in mode | ||||||||||||||||||||||||||||||||||||||||||||||||||
| filename = os.fspath(filename) | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -444,17 +491,25 @@ def open_stream( | |||||||||||||||||||||||||||||||||||||||||||||||||
| if perm is not None: | ||||||||||||||||||||||||||||||||||||||||||||||||||
| os.chmod(tmp_filename, perm) # in case perm includes bits in umask | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| f = _wrap_io_open(fd, mode, encoding, errors) | ||||||||||||||||||||||||||||||||||||||||||||||||||
| af = _AtomicFile(f, tmp_filename, os.path.realpath(filename)) | ||||||||||||||||||||||||||||||||||||||||||||||||||
| return t.cast(t.IO[t.Any], af), True | ||||||||||||||||||||||||||||||||||||||||||||||||||
| if binary: | ||||||||||||||||||||||||||||||||||||||||||||||||||
| binary_f = _wrap_io_open(fd, t.cast("OpenBinaryMode", mode), encoding, errors) | ||||||||||||||||||||||||||||||||||||||||||||||||||
| binary_af = _AtomicFile(binary_f, tmp_filename, os.path.realpath(filename)) | ||||||||||||||||||||||||||||||||||||||||||||||||||
| return binary_af, True | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| text_f = _wrap_io_open(fd, t.cast("OpenTextMode", mode), encoding, errors) | ||||||||||||||||||||||||||||||||||||||||||||||||||
| text_af = _AtomicFile(text_f, tmp_filename, os.path.realpath(filename)) | ||||||||||||||||||||||||||||||||||||||||||||||||||
| return t.cast(t.IO[t.Any], text_af), True | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| class _AtomicFile: | ||||||||||||||||||||||||||||||||||||||||||||||||||
| def __init__(self, f: t.IO[t.Any], tmp_filename: str, real_filename: str) -> None: | ||||||||||||||||||||||||||||||||||||||||||||||||||
| self._f = f | ||||||||||||||||||||||||||||||||||||||||||||||||||
| class _AtomicFile(t.IO[AnyStr], t.Generic[AnyStr]): | ||||||||||||||||||||||||||||||||||||||||||||||||||
| def __init__(self, f: t.IO[AnyStr], tmp_filename: str, real_filename: str) -> None: | ||||||||||||||||||||||||||||||||||||||||||||||||||
| self._f: t.IO[AnyStr] = f | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+504
to
+506
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's almost always better to avoid using _FileT_co = t.TypeVar("_FileT_co", bound=t.IO[Any], covariant=True)This way you capture more typing information, avoid issues with invariance, and avoid having to deal with the awkward |
||||||||||||||||||||||||||||||||||||||||||||||||||
| self._tmp_filename = tmp_filename | ||||||||||||||||||||||||||||||||||||||||||||||||||
| self._real_filename = real_filename | ||||||||||||||||||||||||||||||||||||||||||||||||||
| self.closed = False | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| @property | ||||||||||||||||||||||||||||||||||||||||||||||||||
| def closed(self) -> bool: | ||||||||||||||||||||||||||||||||||||||||||||||||||
| return self._f.closed | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| @property | ||||||||||||||||||||||||||||||||||||||||||||||||||
| def name(self) -> str: | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -465,12 +520,11 @@ def close(self, delete: bool = False) -> None: | |||||||||||||||||||||||||||||||||||||||||||||||||
| return | ||||||||||||||||||||||||||||||||||||||||||||||||||
| self._f.close() | ||||||||||||||||||||||||||||||||||||||||||||||||||
| os.replace(self._tmp_filename, self._real_filename) | ||||||||||||||||||||||||||||||||||||||||||||||||||
| self.closed = True | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| def __getattr__(self, name: str) -> t.Any: | ||||||||||||||||||||||||||||||||||||||||||||||||||
| return getattr(self._f, name) | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| def __enter__(self) -> _AtomicFile: | ||||||||||||||||||||||||||||||||||||||||||||||||||
| def __enter__(self) -> _AtomicFile[AnyStr]: | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| return self | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| def __exit__( | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -70,19 +70,18 @@ | |||||
| MAX_BYTES_WRITTEN = 32767 | ||||||
|
|
||||||
| if t.TYPE_CHECKING: | ||||||
| try: | ||||||
| # Using `typing_extensions.Buffer` instead of `collections.abc` | ||||||
| # on Windows for some reason does not have `Sized` implemented. | ||||||
| from collections.abc import Buffer # type: ignore | ||||||
| except ImportError: | ||||||
| from typing_extensions import Buffer | ||||||
| from typing_extensions import Buffer | ||||||
|
|
||||||
| class _MSVCRTModule(t.Protocol): | ||||||
| def get_osfhandle(self, fd: int) -> int: ... | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit:
Suggested change
|
||||||
|
|
||||||
| try: | ||||||
| from ctypes import pythonapi | ||||||
| except ImportError: | ||||||
| # On PyPy we cannot get buffers so our ability to operate here is | ||||||
| # severely limited. | ||||||
| get_buffer = None | ||||||
| def get_buffer(obj: Buffer, writable: bool = False) -> Array[c_char]: | ||||||
| raise TypeError("PyPy does not support the buffer API used by Click") | ||||||
| else: | ||||||
|
|
||||||
| class Py_buffer(Structure): | ||||||
|
|
@@ -130,7 +129,8 @@ def readable(self) -> t.Literal[True]: | |||||
| return True | ||||||
|
|
||||||
| def readinto(self, b: Buffer) -> int: | ||||||
| bytes_to_be_read = len(b) | ||||||
| bytes_to_be_read = memoryview(b).nbytes | ||||||
|
|
||||||
| if not bytes_to_be_read: | ||||||
| return 0 | ||||||
| elif bytes_to_be_read % 2: | ||||||
|
|
@@ -173,7 +173,7 @@ def _get_error_message(errno: int) -> str: | |||||
| return _("Windows error: {error}").format(error=errno) | ||||||
|
|
||||||
| def write(self, b: Buffer) -> int: | ||||||
| bytes_to_be_written = len(b) | ||||||
| bytes_to_be_written = memoryview(b).nbytes | ||||||
| buf = get_buffer(b) | ||||||
| code_units_to_be_written = min(bytes_to_be_written, MAX_BYTES_WRITTEN) // 2 | ||||||
| code_units_written = c_ulong() | ||||||
|
|
@@ -201,7 +201,7 @@ def __init__(self, text_stream: t.TextIO, byte_stream: t.BinaryIO) -> None: | |||||
| def name(self) -> str: | ||||||
| return self.buffer.name | ||||||
|
|
||||||
| def write(self, x: t.AnyStr) -> int: | ||||||
| def write(self, x: str | bytes) -> int: | ||||||
| if isinstance(x, str): | ||||||
| return self._text_stream.write(x) | ||||||
| try: | ||||||
|
|
@@ -210,7 +210,7 @@ def write(self, x: t.AnyStr) -> int: | |||||
| pass | ||||||
| return self.buffer.write(x) | ||||||
|
|
||||||
| def writelines(self, lines: cabc.Iterable[t.AnyStr]) -> None: | ||||||
| def writelines(self, lines: cabc.Iterable[str] | cabc.Iterable[bytes]) -> None: | ||||||
| for line in lines: | ||||||
| self.write(line) | ||||||
|
|
||||||
|
|
@@ -270,16 +270,15 @@ def _is_console(f: t.TextIO) -> bool: | |||||
| except (OSError, io.UnsupportedOperation): | ||||||
| return False | ||||||
|
|
||||||
| handle = msvcrt.get_osfhandle(fileno) | ||||||
| handle = t.cast(_MSVCRTModule, msvcrt).get_osfhandle(fileno) | ||||||
| return bool(GetConsoleMode(handle, byref(DWORD()))) | ||||||
|
|
||||||
|
|
||||||
| def _get_windows_console_stream( | ||||||
| f: t.TextIO, encoding: str | None, errors: str | None | ||||||
| ) -> t.TextIO | None: | ||||||
| if ( | ||||||
| get_buffer is None | ||||||
| or encoding not in {"utf-16-le", None} | ||||||
| encoding not in {"utf-16-le", None} | ||||||
| or errors not in {"strict", None} | ||||||
| or not _is_console(f) | ||||||
| ): | ||||||
|
|
||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -436,7 +436,7 @@ def format_completion(self, item: CompletionItem) -> str: | |
| return f"{item.type}\n{value}\n{help_escaped}" | ||
|
|
||
|
|
||
| ShellCompleteType = t.TypeVar("ShellCompleteType", bound="type[ShellComplete]") | ||
| ShellCompleteType = t.TypeVar("ShellCompleteType", bound="ShellComplete") | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: Now that it's no longer bound to a |
||
|
|
||
|
|
||
| _available_shells: dict[str, type[ShellComplete]] = { | ||
|
|
@@ -447,8 +447,8 @@ def format_completion(self, item: CompletionItem) -> str: | |
|
|
||
|
|
||
| def add_completion_class( | ||
| cls: ShellCompleteType, name: str | None = None | ||
| ) -> ShellCompleteType: | ||
| cls: type[ShellCompleteType], name: str | None = None | ||
| ) -> type[ShellCompleteType]: | ||
| """Register a :class:`ShellComplete` subclass under the given name. | ||
| The name will be provided by the completion instruction environment | ||
| variable during completion. | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -696,7 +696,7 @@ def unstyle(text: str) -> str: | |||||
|
|
||||||
| def secho( | ||||||
| message: t.Any | None = None, | ||||||
| file: t.IO[t.AnyStr] | None = None, | ||||||
| file: t.TextIO | t.BinaryIO | None = None, | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. t.TextIO | t.BinaryIO
Suggested change
|
||||||
| nl: bool = True, | ||||||
| err: bool = False, | ||||||
| color: bool | None = None, | ||||||
|
|
||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's no need for
setup-pythonif you're usingsetup-uv