Skip to content
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

Use tabs for generics docs #18264

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
3 changes: 2 additions & 1 deletion docs/requirements-docs.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
sphinx>=8.1.0
furo>=2022.3.4
myst-parser>=4.0.0
sphinx_inline_tabs>=2023.04.21
# sphinx_inline_tabs>=2023.04.21
git+https://github.com/cdce8p/[email protected]
9 changes: 9 additions & 0 deletions docs/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,15 @@
# man_show_urls = False


# -- sphinx_inline_tabs ---------------------------------------------------

# Disable sync globally
# tabs_default_sync_behavior = "none"

# Disable sync globally for specific labels
tabs_no_sync_labels = {"Python 3.12+", "Legacy"}


# -- Options for Texinfo output -------------------------------------------

# Grouping the document tree into Texinfo files. List of tuples
Expand Down
126 changes: 68 additions & 58 deletions docs/source/generics.rst
Original file line number Diff line number Diff line change
Expand Up @@ -95,31 +95,39 @@ Using ``Stack`` is similar to built-in container types:
stack2: Stack[str] = Stack()
stack2.append('x')

Construction of instances of generic types is type checked (Python 3.12 syntax):
Construction of instances of generic types is type checked:

.. code-block:: python
.. tab:: Python 3.12+

class Box[T]:
def __init__(self, content: T) -> None:
self.content = content
.. code-block:: python

Box(1) # OK, inferred type is Box[int]
Box[int](1) # Also OK
class Box[T]:
def __init__(self, content: T) -> None:
self.content = content

# error: Argument 1 to "Box" has incompatible type "str"; expected "int"
Box[int]('some string')
Box(1) # OK, inferred type is Box[int]
Box[int](1) # Also OK

Here is the definition of ``Box`` using the legacy syntax (Python 3.11 and earlier):
# error: Argument 1 to "Box" has incompatible type "str"; expected "int"
Box[int]('some string')

.. code-block:: python
.. tab:: Legacy

from typing import TypeVar, Generic
.. code-block:: python

T = TypeVar('T')
from typing import TypeVar, Generic

class Box(Generic[T]):
def __init__(self, content: T) -> None:
self.content = content
T = TypeVar('T')

class Box(Generic[T]):
def __init__(self, content: T) -> None:
self.content = content

Box(1) # OK, inferred type is Box[int]
Box[int](1) # Also OK

# error: Argument 1 to "Box" has incompatible type "str"; expected "int"
Box[int]('some string')

.. note::

Expand All @@ -139,66 +147,68 @@ Defining subclasses of generic classes

User-defined generic classes and generic classes defined in :py:mod:`typing`
can be used as a base class for another class (generic or non-generic). For
example (Python 3.12 syntax):
example:

.. code-block:: python
.. tab:: Python 3.12+

from typing import Mapping, Iterator
.. code-block:: python

# This is a generic subclass of Mapping
class MyMap[KT, VT](Mapping[KT, VT]):
def __getitem__(self, k: KT) -> VT: ...
def __iter__(self) -> Iterator[KT]: ...
def __len__(self) -> int: ...
from typing import Mapping, Iterator

items: MyMap[str, int] # OK
# This is a generic subclass of Mapping
class MyMap[KT, VT](Mapping[KT, VT]):
def __getitem__(self, k: KT) -> VT: ...
def __iter__(self) -> Iterator[KT]: ...
def __len__(self) -> int: ...

# This is a non-generic subclass of dict
class StrDict(dict[str, str]):
def __str__(self) -> str:
return f'StrDict({super().__str__()})'
items: MyMap[str, int] # OK

data: StrDict[int, int] # Error! StrDict is not generic
data2: StrDict # OK
# This is a non-generic subclass of dict
class StrDict(dict[str, str]):
def __str__(self) -> str:
return f'StrDict({super().__str__()})'

# This is a user-defined generic class
class Receiver[T]:
def accept(self, value: T) -> None: ...
data: StrDict[int, int] # Error! StrDict is not generic
data2: StrDict # OK

# This is a generic subclass of Receiver
class AdvancedReceiver[T](Receiver[T]): ...
# This is a user-defined generic class
class Receiver[T]:
def accept(self, value: T) -> None: ...

Here is the above example using the legacy syntax (Python 3.11 and earlier):
# This is a generic subclass of Receiver
class AdvancedReceiver[T](Receiver[T]): ...

.. code-block:: python
.. tab:: Legacy

.. code-block:: python

from typing import Generic, TypeVar, Mapping, Iterator
from typing import Generic, TypeVar, Mapping, Iterator

KT = TypeVar('KT')
VT = TypeVar('VT')
KT = TypeVar('KT')
VT = TypeVar('VT')

# This is a generic subclass of Mapping
class MyMap(Mapping[KT, VT]):
def __getitem__(self, k: KT) -> VT: ...
def __iter__(self) -> Iterator[KT]: ...
def __len__(self) -> int: ...
# This is a generic subclass of Mapping
class MyMap(Mapping[KT, VT]):
def __getitem__(self, k: KT) -> VT: ...
def __iter__(self) -> Iterator[KT]: ...
def __len__(self) -> int: ...

items: MyMap[str, int] # OK
items: MyMap[str, int] # OK

# This is a non-generic subclass of dict
class StrDict(dict[str, str]):
def __str__(self) -> str:
return f'StrDict({super().__str__()})'
# This is a non-generic subclass of dict
class StrDict(dict[str, str]):
def __str__(self) -> str:
return f'StrDict({super().__str__()})'

data: StrDict[int, int] # Error! StrDict is not generic
data2: StrDict # OK
data: StrDict[int, int] # Error! StrDict is not generic
data2: StrDict # OK

# This is a user-defined generic class
class Receiver(Generic[T]):
def accept(self, value: T) -> None: ...
# This is a user-defined generic class
class Receiver(Generic[T]):
def accept(self, value: T) -> None: ...

# This is a generic subclass of Receiver
class AdvancedReceiver(Receiver[T]): ...
# This is a generic subclass of Receiver
class AdvancedReceiver(Receiver[T]): ...

.. note::

Expand Down
Loading