Skip to content

Commit 9f90182

Browse files
authored
Remove stub content/style section from CONTRIBUTING.md (#13332)
1 parent 70cf067 commit 9f90182

File tree

1 file changed

+51
-282
lines changed

1 file changed

+51
-282
lines changed

CONTRIBUTING.md

Lines changed: 51 additions & 282 deletions
Original file line numberDiff line numberDiff line change
@@ -240,19 +240,60 @@ recommend starting by opening an issue laying out what you want to do.
240240
That lets a conversation happen early in case other contributors disagree
241241
with what you'd like to do or have ideas that will help you do it.
242242

243-
### Format
243+
### Stub Content and Style
244244

245-
Each Python module is represented by a `.pyi` "stub file". This is a
246-
syntactically valid Python file, although it usually cannot be run by
247-
Python (since forward references don't require string quotes). All
248-
the methods are empty.
245+
Each Python module is represented by a .pyi "stub file". This is a syntactically valid Python file, where all methods are empty and [type annotations](https://typing.readthedocs.io/en/latest/spec/annotations.html) are used to describe function signatures and variable types.
249246

250-
Python function annotations ([PEP 3107](https://www.python.org/dev/peps/pep-3107/))
251-
are used to describe the signature of each function or method.
247+
Typeshed follows the standard type system guidelines for [stub content](https://typing.readthedocs.io/en/latest/guides/writing_stubs.html#stub-content) and [coding style](https://typing.readthedocs.io/en/latest/guides/writing_stubs.html#style-guide).
252248

253-
See [PEP 484](http://www.python.org/dev/peps/pep-0484/) for the exact
254-
syntax of the stub files and [below](#stub-file-coding-style) for the
255-
coding style used in typeshed.
249+
### What to include
250+
251+
Stubs should include the complete interface (classes, functions,
252+
constants, etc.) of the module they cover, but it is not always
253+
clear exactly what is part of the interface.
254+
255+
The following should always be included:
256+
- All objects listed in the module's documentation.
257+
- All objects included in ``__all__`` (if present).
258+
259+
Other objects may be included if they are being used in practice
260+
or if they are not prefixed with an underscore. This means
261+
that typeshed will generally accept contributions that add missing
262+
objects, even if they are undocumented. Undocumented objects should
263+
be marked with a comment of the form ``# undocumented``.
264+
265+
### Incomplete Annotations
266+
267+
When submitting new stubs, it is not necessary to annotate all arguments,
268+
return types, and fields. Such items should either be left unannotated or
269+
use `_typeshed.Incomplete` if this is not possible:
270+
271+
```python
272+
from _typeshed import Incomplete
273+
274+
field: Incomplete # unannotated
275+
276+
def foo(x): ... # unannotated argument and return type
277+
```
278+
279+
`Incomplete` can also be used for partially known types:
280+
281+
```python
282+
def foo(x: Incomplete | None = None) -> list[Incomplete]: ...
283+
```
284+
285+
### What to do when a project's documentation and implementation disagree
286+
287+
Type stubs are meant to be external type annotations for a given
288+
library. While they are useful documentation in its own merit, they
289+
augment the project's concrete implementation, not the project's
290+
documentation. Whenever you find them disagreeing, model the type
291+
information after the actual implementation and file an issue on the
292+
project's tracker to fix their documentation.
293+
294+
### Docstrings
295+
296+
Typeshed stubs should not include duplicated docstrings from the source code.
256297

257298
### Auto-generating stub files
258299

@@ -323,278 +364,6 @@ do not happen, so a parameter that accepts either `bytes` or
323364
Often one of the aliases from `_typeshed`, such as
324365
`_typeshed.ReadableBuffer`, can be used instead.
325366

326-
### What to include
327-
328-
Stubs should include the complete interface (classes, functions,
329-
constants, etc.) of the module they cover, but it is not always
330-
clear exactly what is part of the interface.
331-
332-
The following should always be included:
333-
- All objects listed in the module's documentation.
334-
- All objects included in ``__all__`` (if present).
335-
336-
Other objects may be included if they are being used in practice
337-
or if they are not prefixed with an underscore. This means
338-
that typeshed will generally accept contributions that add missing
339-
objects, even if they are undocumented. Undocumented objects should
340-
be marked with a comment of the form ``# undocumented``.
341-
Example:
342-
343-
```python
344-
def list2cmdline(seq: Sequence[str]) -> str: ... # undocumented
345-
```
346-
347-
We accept such undocumented objects because omitting objects can confuse
348-
users. Users who see an error like "module X has no attribute Y" will
349-
not know whether the error appeared because their code had a bug or
350-
because the stub is wrong. Although it may also be helpful for a type
351-
checker to point out usage of private objects, we usually prefer false
352-
negatives (no errors for wrong code) over false positives (type errors
353-
for correct code). In addition, even for private objects a type checker
354-
can be helpful in pointing out that an incorrect type was used.
355-
356-
### What to do when a project's documentation and implementation disagree
357-
358-
Type stubs are meant to be external type annotations for a given
359-
library. While they are useful documentation in its own merit, they
360-
augment the project's concrete implementation, not the project's
361-
documentation. Whenever you find them disagreeing, model the type
362-
information after the actual implementation and file an issue on the
363-
project's tracker to fix their documentation.
364-
365-
### Stub versioning
366-
367-
You can use checks
368-
like `if sys.version_info >= (3, 12):` to denote new functionality introduced
369-
in a given Python version or solve type differences. When doing so, only use
370-
two-tuples. Because of this, if a given functionality was
371-
introduced in, say, Python 3.11.4, your check:
372-
373-
* should be expressed as `if sys.version_info >= (3, 11):`
374-
* should NOT be expressed as `if sys.version_info >= (3, 11, 4):`
375-
* should NOT be expressed as `if sys.version_info >= (3, 12):`
376-
377-
When your stub contains if statements for different Python versions,
378-
always put the code for the most recent Python version first.
379-
380-
## Stub file coding style
381-
382-
### Syntax example
383-
384-
The below is an excerpt from the types for the `datetime` module.
385-
386-
```python
387-
MAXYEAR: int
388-
MINYEAR: int
389-
390-
class date:
391-
def __new__(cls, year: SupportsIndex, month: SupportsIndex, day: SupportsIndex) -> Self: ...
392-
@classmethod
393-
def fromtimestamp(cls, timestamp: float, /) -> Self: ...
394-
@classmethod
395-
def today(cls) -> Self: ...
396-
@classmethod
397-
def fromordinal(cls, n: int, /) -> Self: ...
398-
@property
399-
def year(self) -> int: ...
400-
def replace(self, year: SupportsIndex = ..., month: SupportsIndex = ..., day: SupportsIndex = ...) -> Self: ...
401-
def ctime(self) -> str: ...
402-
def weekday(self) -> int: ...
403-
```
404-
405-
### Conventions
406-
407-
Stub files are *like* Python files and you should generally expect them
408-
to look the same. Your tools should be able to successfully treat them
409-
as regular Python files. However, there are a few important differences
410-
you should know about.
411-
412-
Style conventions for stub files are different from PEP 8. The general
413-
rule is that they should be as concise as possible. Specifically:
414-
* all function bodies should be empty;
415-
* prefer ``...`` over ``pass``;
416-
* prefer ``...`` on the same line as the class/function signature;
417-
* avoid vertical whitespace between consecutive module-level functions,
418-
names, or methods and fields within a single class;
419-
* use a single blank line between top-level class definitions, or none
420-
if the classes are very small;
421-
* do not use docstrings;
422-
* use variable annotations instead of type comments, even for stubs
423-
that target older versions of Python.
424-
425-
The primary users for stub files are type checkers,
426-
so stub files should generally only contain information necessary for the type
427-
checker, and leave out unnecessary detail.
428-
However, stubs also have other use cases:
429-
* stub files are often used as a data source for IDEs,
430-
which will often use the signature in a stub to provide information
431-
on functions or classes in tooltip messages.
432-
* stubs can serve as useful documentation to human readers,
433-
as well as machine-readable sources of data.
434-
435-
As such, we recommend that default values be retained for "simple" default values
436-
(e.g. bools, ints, bytes, strings, and floats are all permitted).
437-
Use `= ...` for more complex default values,
438-
rather than trying to exactly reproduce the default at runtime.
439-
440-
Some further tips for good type hints:
441-
* for arguments that default to `None`, use `Foo | None` explicitly for the type annotation;
442-
* use `float` instead of `int | float` for parameter annotations
443-
(see [PEP 484](https://peps.python.org/pep-0484/#the-numeric-tower) for motivation).
444-
* use built-in generics (`list`, `dict`, `tuple`, `set`), instead
445-
of importing them from `typing`.
446-
* use `X | Y` instead of `Union[X, Y]` and `X | None`, instead of
447-
`Optional[X]`;
448-
* import collections (`Mapping`, `Iterable`, etc.)
449-
from `collections.abc` instead of `typing`;
450-
* avoid invariant collection types (`list`, `dict`) for function
451-
parameters, in favor of covariant types like `Mapping` or `Sequence`;
452-
* avoid union return types: https://github.com/python/mypy/issues/1693;
453-
* use platform checks like `if sys.platform == 'win32'` to denote
454-
platform-dependent APIs;
455-
* use mypy error codes for mypy-specific `# type: ignore` annotations,
456-
e.g. `# type: ignore[override]` for Liskov Substitution Principle violations.
457-
* use pyright error codes for pyright-specific suppressions,
458-
e.g. `# pyright: ignore[reportGeneralTypeIssues]`.
459-
- pyright is configured to discard `# type: ignore` annotations.
460-
If you need both on the same line, mypy's annotation needs to go first,
461-
e.g. `# type: ignore[override] # pyright: ignore[reportGeneralTypeIssues]`.
462-
463-
Imports in stubs are considered private (not part of the exported API)
464-
unless:
465-
* they use the form ``from library import name as name`` (sic, using
466-
explicit ``as`` even if the name stays the same); or
467-
* they use the form ``from library import *`` which means all names
468-
from that library are exported.
469-
470-
Stub files support forward references natively. In other words, the
471-
order of class declarations and type aliases does not matter in
472-
a stub file. You can also use the name of the class within its own
473-
body. Focus on making your stubs clear to the reader. Avoid using
474-
string literals in type annotations.
475-
476-
### Using `Any` and `object`
477-
478-
When adding type hints, avoid using the `Any` type when possible. Reserve
479-
the use of `Any` for when:
480-
* the correct type cannot be expressed in the current type system; and
481-
* to avoid union returns (see above).
482-
483-
Note that `Any` is not the correct type to use if you want to indicate
484-
that some function can accept literally anything: in those cases use
485-
`object` instead.
486-
487-
When using `Any`, document the reason for using it in a comment. Ideally,
488-
document what types could be used. The `_typeshed` module also provides
489-
a few aliases to `Any` — like `Incomplete` and `MaybeNone` (see below) —
490-
that should be used instead of `Any` in appropriate situations and double
491-
as documentation.
492-
493-
### Context managers
494-
495-
When adding type annotations for context manager classes, annotate
496-
the return type of `__exit__` as bool only if the context manager
497-
sometimes suppresses exceptions -- if it sometimes returns `True`
498-
at runtime. If the context manager never suppresses exceptions,
499-
have the return type be either `None` or `bool | None`. If you
500-
are not sure whether exceptions are suppressed or not or if the
501-
context manager is meant to be subclassed, pick `bool | None`.
502-
See https://github.com/python/mypy/issues/7214 for more details.
503-
504-
`__enter__` methods and other methods that return instances of the
505-
current class should be annotated with `typing_extensions.Self`
506-
([example](https://github.com/python/typeshed/blob/3581846/stdlib/contextlib.pyi#L151)).
507-
508-
### Naming
509-
510-
Type variables and aliases you introduce purely for legibility reasons
511-
should be prefixed with an underscore to make it obvious to the reader
512-
they are not part of the stubbed API.
513-
514-
A few guidelines for protocol names below. In cases that don't fall
515-
into any of those categories, use your best judgement.
516-
517-
* Use plain names for protocols that represent a clear concept
518-
(e.g. `Iterator`, `Container`).
519-
* Use `SupportsX` for protocols that provide callable methods (e.g.
520-
`SupportsInt`, `SupportsRead`, `SupportsReadSeek`).
521-
* Use `HasX` for protocols that have readable and/or writable attributes
522-
or getter/setter methods (e.g. `HasItems`, `HasFileno`).
523-
524-
### `@deprecated`
525-
526-
Typeshed uses the `@typing_extensions.deprecated` decorator
527-
(`@warnings.deprecated` since Python 3.13) to mark deprecated
528-
functionality; see [PEP 702](https://peps.python.org/pep-0702/).
529-
530-
A few guidelines for how to use it:
531-
532-
* In the standard library, apply the decorator only in Python versions
533-
where an appropriate replacement for the deprecated functionality
534-
exists. If in doubt, apply the decorator only on versions where the
535-
functionality has been explicitly deprecated, either through runtime
536-
warnings or in the documentation. Use `if sys.version_info` checks to
537-
apply the decorator only to some versions.
538-
* Keep the deprecation message concise, but try to mention the projected
539-
version when the functionality is to be removed, and a suggested
540-
replacement.
541-
542-
### Incomplete annotations
543-
544-
When submitting new stubs, it is not necessary to annotate all arguments,
545-
return types, and fields. Such items should either be left unannotated or
546-
use `_typeshed.Incomplete` if this is not possible:
547-
548-
```python
549-
from _typeshed import Incomplete
550-
551-
field: Incomplete # unannotated
552-
553-
def foo(x): ... # unannotated argument and return type
554-
```
555-
556-
`Incomplete` can also be used for partially known types:
557-
558-
```python
559-
def foo(x: Incomplete | None = None) -> list[Incomplete]: ...
560-
```
561-
562-
### `Any` vs. `Incomplete`
563-
564-
While `Incomplete` is a type alias of `Any`, they serve difference purposes:
565-
`Incomplete` is a placeholder where a proper type might be substituted.
566-
It's a "to do" item and should be replaced if possible. `Any` is used when
567-
it's not possible to accurately type an item using the current type system.
568-
It should be used sparingly.
569-
570-
### "The `Any` trick"
571-
572-
In cases where a function or method can return `None`, but where forcing the
573-
user to explicitly check for `None` can be detrimental, use
574-
`_typeshed.MaybeNone` (an alias to `Any`), instead of `None`.
575-
576-
Consider the following (simplified) signature of `re.Match[str].group`:
577-
578-
```python
579-
class Match:
580-
def group(self, group: str | int, /) -> str | MaybeNone: ...
581-
```
582-
583-
This avoid forcing the user to check for `None`:
584-
585-
```python
586-
match = re.fullmatch(r"\d+_(.*)", some_string)
587-
assert match is not None
588-
name_group = match.group(1) # The user knows that this will never be None
589-
return name_group.uper() # This typo will be flagged by the type checker
590-
```
591-
592-
In this case, the user of `match.group()` must be prepared to handle a `str`,
593-
but type checkers are happy with `if name_group is None` checks, because we're
594-
saying it can also be something else than an `str`.
595-
596-
This is sometimes called "the Any trick".
597-
598367
## Submitting Changes
599368

600369
Even more excellent than a good bug report is a fix for a bug, or the

0 commit comments

Comments
 (0)