@@ -93,7 +93,7 @@ Liskov substitutability or detecting problematic overloads.
9393It may be instructive to examine `typeshed <https://github.com/python/typeshed/ >`__'s
9494`setup for testing stubs <https://github.com/python/typeshed/blob/main/tests/README.md >`__.
9595
96- To suppress type errors in stubs, use `# type: ignore ` comments. Refer to the style guide for
96+ To suppress type errors in stubs, use `# type: ignore ` comments. Refer to the :ref: ` type-checker-error-suppression ` section of the style guide for
9797error suppression formats specific to individual typecheckers.
9898
9999..
@@ -213,15 +213,28 @@ to use them freely to describe simple structural types.
213213Incomplete Stubs
214214----------------
215215
216+ When writing new stubs, it is not necessary to fully annotate all arguments,
217+ return types, and fields. Some items may be left unannotated or
218+ annotated with `_typeshed.Incomplete ` (`documentation <https://github.com/python/typeshed/blob/main/stdlib/_typeshed/README.md >`_).::
219+
220+ from _typeshed import Incomplete
221+
222+ field: Incomplete # unannotated
223+
224+ def foo(x): ... # unannotated argument and return type
225+
226+ `Incomplete ` can also be used for partially known types::
227+
228+ def foo(x: Incomplete | None = None) -> list[Incomplete]: ...
229+
216230Partial stubs can be useful, especially for larger packages, but they should
217231follow the following guidelines:
218232
219233* Included functions and methods should list all arguments, but the arguments
220234 can be left unannotated.
221235* Do not use ``Any `` to mark unannotated or partially annotated values. Leave
222236 function parameters and return values unannotated. In all other cases, use
223- ``_typeshed.Incomplete ``
224- (`documentation <https://github.com/python/typeshed/blob/main/stdlib/_typeshed/README.md >`_)::
237+ ``_typeshed.Incomplete ``::
225238
226239 from _typeshed import Incomplete
227240
@@ -254,6 +267,40 @@ annotated function ``bar()``::
254267
255268 def bar(x: str, y, *, z=...): ...
256269
270+ `Any ` vs. `Incomplete `
271+ ----------------------
272+
273+ While `Incomplete ` is a type alias of `Any `, they serve difference purposes:
274+ `Incomplete ` is a placeholder where a proper type might be substituted.
275+ It's a "to do" item and should be replaced if possible. `Any ` is used when
276+ it's not possible to accurately type an item using the current type system.
277+ It should be used sparingly.
278+
279+ The `Any ` trick
280+ ---------------
281+
282+ In cases where a function or method can return `None `, but where forcing the
283+ user to explicitly check for `None ` can be detrimental, use
284+ `_typeshed.MaybeNone ` (an alias to `Any `), instead of `None `.
285+
286+ Consider the following (simplified) signature of `re.Match[str].group `::
287+
288+ class Match:
289+ def group(self, group: str | int, /) -> str | MaybeNone: ...
290+
291+ This avoid forcing the user to check for `None `::
292+
293+ match = re.fullmatch(r"\d+_(.*)", some_string)
294+ assert match is not None
295+ name_group = match.group(1) # The user knows that this will never be None
296+ return name_group.uper() # This typo will be flagged by the type checker
297+
298+ In this case, the user of `match.group() ` must be prepared to handle a `str `,
299+ but type checkers are happy with `if name_group is None ` checks, because we're
300+ saying it can also be something else than an `str `.
301+
302+ This is sometimes called "the Any trick".
303+
257304Attribute Access
258305----------------
259306
@@ -800,7 +847,9 @@ into any of those categories, use your best judgement.
800847* Use `HasX ` for protocols that have readable and/or writable attributes
801848 or getter/setter methods (e.g. `HasItems `, `HasFileno `).
802849
803- Type Checker Error Suppression formats
850+ :: _type-checker-error-suppression:
851+
852+ Type Checker Error Suppression Formats
804853--------------------------------------
805854
806855* Use mypy error codes for mypy-specific `# type: ignore ` annotations, e.g. `# type: ignore[override] ` for Liskov Substitution Principle violations.
0 commit comments