Skip to content

Commit

Permalink
improve type annotations in 'docutils.statemachine' (#11469)
Browse files Browse the repository at this point in the history
  • Loading branch information
danieleades authored Mar 13, 2024
1 parent 64f0091 commit a1bfd65
Show file tree
Hide file tree
Showing 3 changed files with 207 additions and 8 deletions.
3 changes: 3 additions & 0 deletions stubs/docutils/@tests/stubtest_allowlist.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ docutils.nodes.GenericNodeVisitor.__getattr__
docutils.nodes.Text.__new__
docutils.parsers.recommonmark_wrapper
docutils.parsers.rst.directives.misc.MetaBody.__getattr__
docutils.statemachine.State.nested_sm # is initialised in __init__
docutils.statemachine.State.nested_sm_kwargs # is initialised in __init__
docutils.statemachine.ViewList.__iter__ # doesn't exist at runtime, but the class is iterable due to __getitem__
docutils.transforms.Transform.__getattr__
docutils.transforms.Transformer.__getattr__
docutils.TransformSpec.unknown_reference_resolvers
12 changes: 6 additions & 6 deletions stubs/docutils/docutils/parsers/rst/tableparser.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ from typing import ClassVar
from typing_extensions import TypeAlias

from docutils import DataError
from docutils.statemachine import Stringlist
from docutils.statemachine import StringList

_Cell: TypeAlias = tuple[int, int, int, list[str]]
_Row: TypeAlias = list[_Cell | None]
Expand All @@ -18,20 +18,20 @@ class TableMarkupError(DataError):
class TableParser:
head_body_separator_pat: ClassVar[Pattern[str] | None]
double_width_pad_char: ClassVar[str]
def parse(self, block: Stringlist) -> tuple[_Colspecs, list[_Row], list[_Row]]: ...
def parse(self, block: StringList) -> tuple[_Colspecs, list[_Row], list[_Row]]: ...
def find_head_body_sep(self) -> None: ...

class GridTableParser(TableParser):
head_body_separator_pat: ClassVar[Pattern[str]]
block: Stringlist
block: StringList
bottom: int
right: int
head_body_sep: int
done: list[int]
cells: list[_Cell]
rowseps: dict[int, list[int]]
colseps: dict[int, list[int]]
def setup(self, block: Stringlist) -> None: ...
def setup(self, block: StringList) -> None: ...
def parse_table(self) -> None: ...
def mark_done(self, top: int, left: int, bottom: int, right: int) -> None: ...
def check_parse_complete(self) -> bool: ...
Expand All @@ -45,15 +45,15 @@ class GridTableParser(TableParser):
class SimpleTableParser(TableParser):
head_body_separator_pat: ClassVar[Pattern[str]]
span_pat: ClassVar[Pattern[str]]
block: Stringlist
block: StringList
head_body_sep: int
columns: list[tuple[int, int]]
border_end: int
table: tuple[list[int], list[_Row], list[_Row]]
done: list[int]
rowseps: dict[int, tuple[int]]
colseps: dict[int, tuple[int]]
def setup(self, block: Stringlist) -> None: ...
def setup(self, block: StringList) -> None: ...
def parse_table(self) -> None: ...
def parse_columns(self, line: str, offset: int) -> list[tuple[int, int]]: ...
def init_row(self, colspec: list[tuple[int, int]], offset: int) -> list[_Cell]: ...
Expand Down
200 changes: 198 additions & 2 deletions stubs/docutils/docutils/statemachine.pyi
Original file line number Diff line number Diff line change
@@ -1,3 +1,199 @@
from _typeshed import Incomplete
from collections.abc import Callable, Generator, Iterable, Iterator, Sequence
from re import Match, Pattern
from typing import Any, ClassVar, Generic, SupportsIndex, TypeVar, overload
from typing_extensions import Self, TypeAlias

def __getattr__(name: str) -> Incomplete: ...
_T = TypeVar("_T")
_Context = TypeVar("_Context")
_TransitionResult: TypeAlias = tuple[_Context, str | None, list[str]]
_TransitionMethod: TypeAlias = Callable[[Match[str], _Context, str], _TransitionResult[_Context]]
_Observer: TypeAlias = Callable[[StateMachine[_Context]], None]

class StateMachine(Generic[_Context]):
input_lines: StringList | None
input_offset: int
line: str | None
line_offset: int
debug: bool
initial_state: str
current_state: str
states: dict[str, State[_Context]]
observers: list[_Observer[_Context]]
def __init__(self, state_classes: Iterable[type[State[_Context]]], initial_state: str, debug: bool = False) -> None: ...
def unlink(self) -> None: ...
def run(
self,
input_lines: Sequence[str] | StringList,
input_offset: int = 0,
context: _Context | None = None,
input_source: str | None = None,
initial_state: str | None = None,
) -> list[str]: ...
def get_state(self, next_state: str | None = None) -> State[_Context]: ...
def next_line(self, n: int = 1) -> str: ...
def is_next_line_blank(self) -> bool: ...
def at_eof(self) -> bool: ...
def at_bof(self) -> bool: ...
def previous_line(self, n: int = 1) -> str | None: ...
def goto_line(self, line_offset: int) -> str | None: ...
def get_source(self, line_offset: int) -> str: ...
def abs_line_offset(self) -> int: ...
def abs_line_number(self) -> int: ...
def get_source_and_line(self, lineno: int | None = None) -> tuple[str, int] | tuple[None, None]: ...
def insert_input(self, input_lines: list[str] | StringList, source: str) -> None: ...
def get_text_block(self, flush_left: bool = False) -> StringList: ...
def check_line(
self, context: _Context, state: State[_Context], transitions: list[str] | None = ...
) -> _TransitionResult[_Context]: ...
def add_state(self, state_class: type[State[_Context]]) -> None: ...
def add_states(self, state_classes: Iterable[type[State[_Context]]]) -> None: ...
def runtime_init(self) -> None: ...
def error(self) -> None: ...
def attach_observer(self, observer: _Observer[_Context]) -> None: ...
def detach_observer(self, observer: _Observer[_Context]) -> None: ...
def notify_observers(self) -> None: ...

class State(Generic[_Context]):
patterns: ClassVar[dict[str, str | Pattern[str]] | None]
initial_transitions: ClassVar[Sequence[str] | Sequence[tuple[str, str]] | None]
nested_sm: type[StateMachine[_Context]]
nested_sm_kwargs: dict[str, Any]
transition_order: list[str]
transitions: dict[str, tuple[Pattern[str], Callable[[], None], str]]
state_machine: StateMachine[_Context]
debug: bool
def __init__(self, state_machine: StateMachine[_Context], debug: bool = False) -> None: ...
def runtime_init(self) -> None: ...
def unlink(self) -> None: ...
def add_initial_transitions(self) -> None: ...
def add_transitions(self, names: Iterable[str], transitions) -> None: ...
def add_transition(self, name: str, transition: tuple[Pattern[str], str, str]) -> None: ...
def remove_transition(self, name: str) -> None: ...
def make_transition(
self, name: str, next_state: str | None = None
) -> tuple[Pattern[str], _TransitionMethod[_Context], str]: ...
def make_transitions(
self, name_list: list[str | tuple[str] | tuple[str, str]]
) -> tuple[list[str], dict[str, tuple[Pattern[str], _TransitionMethod[_Context], str]]]: ...
def no_match(
self, context: _Context, transitions: tuple[list[str], dict[str, tuple[Pattern[str], _TransitionMethod[_Context], str]]]
) -> _TransitionResult[_Context]: ...
def bof(self, context: _Context) -> tuple[list[str], list[str]]: ...
def eof(self, context: _Context) -> list[str]: ...
def nop(self, match: Match[str], context: _Context, next_state: str) -> _TransitionResult[_Context]: ...

class StateMachineWS(StateMachine[_Context]):
def get_indented(self, until_blank: bool = False, strip_indent: bool = True) -> tuple[StringList, int, int, bool]: ...
def get_known_indented(
self, indent: int, until_blank: bool = False, strip_indent: bool = True
) -> tuple[list[str], int, bool]: ...
def get_first_known_indented(
self, indent: int, until_blank: bool = False, strip_indent: bool = True, strip_top: bool = True
) -> tuple[list[str], int, int, bool]: ...

class StateWS(State[_Context]):
indent_sm: type[StateMachine[_Context]] | None
indent_sm_kwargs: dict[str, Any] | None
known_indent_sm: type[StateMachine[_Context]] | None
known_indent_sm_kwargs: dict[str, Any] | None
ws_patterns: dict[str, Pattern[str]]
ws_initial_transitions: Sequence[str]
def __init__(self, state_machine: StateMachine[_Context], debug: bool = False) -> None: ...
def add_initial_transitions(self) -> None: ...
def blank(self, match: Match[str], context: _Context, next_state: str) -> _TransitionResult[_Context]: ...
def indent(self, match: Match[str], context: _Context, next_state: str) -> _TransitionResult[_Context]: ...
def known_indent(self, match: Match[str], context: _Context, next_state: str) -> _TransitionResult[_Context]: ...
def first_known_indent(self, match: Match[str], context: _Context, next_state: str) -> _TransitionResult[_Context]: ...

class _SearchOverride:
def match(self, pattern: Pattern[str]) -> Match[str]: ...

class SearchStateMachine(_SearchOverride, StateMachine[_Context]): ...
class SearchStateMachineWS(_SearchOverride, StateMachineWS[_Context]): ...

class ViewList(Generic[_T]):
data: list[_T]
items: list[tuple[str, int]]
parent: Self
parent_offset: int
def __init__(
self,
initlist: Self | Sequence[_T] | None = None,
source: str | None = None,
items: list[tuple[str, int]] | None = None,
parent: Self | None = None,
parent_offset: int | None = None,
) -> None: ...
def __lt__(self, other: Any) -> bool: ...
def __le__(self, other: Any) -> bool: ...
def __eq__(self, other: object) -> bool: ...
def __ne__(self, other: object) -> bool: ...
def __gt__(self, other: Any) -> bool: ...
def __ge__(self, other: Any) -> bool: ...
def __contains__(self, item: _T) -> bool: ...
def __len__(self) -> int: ...
@overload
def __getitem__(self, i: slice) -> Self: ...
@overload
def __getitem__(self, i: SupportsIndex) -> _T: ...
@overload
def __setitem__(self, i: slice, item: Self) -> None: ...
@overload
def __setitem__(self, i: SupportsIndex, item: _T) -> None: ...
def __delitem__(self, i: SupportsIndex) -> None: ...
def __add__(self, other: Self) -> Self: ...
def __radd__(self, other: Self) -> Self: ...
def __iadd__(self, other: Self) -> Self: ...
def __mul__(self, n: int) -> Self: ...
__rmul__ = __mul__
def __imul__(self, n: int) -> Self: ...
def extend(self, other: Self) -> None: ...
def append(self, item: _T, source: str | None = None, offset: int = 0) -> None: ...
def insert(self, i: int, item: _T, source: str | None = None, offset: int = 0) -> None: ...
def pop(self, i: int = -1) -> _T: ...
def trim_start(self, n: int = 1) -> None: ...
def trim_end(self, n: int = 1) -> None: ...
def remove(self, item: _T) -> None: ...
def count(self, item: _T) -> int: ...
def index(self, item: _T) -> int: ...
def reverse(self) -> None: ...
def sort(self, *args: tuple[_T, tuple[str, int]]) -> None: ...
def info(self, i: int) -> tuple[str, int | None]: ...
def source(self, i: int) -> str: ...
def offset(self, i: int) -> int: ...
def disconnect(self) -> None: ...
def xitems(self) -> Generator[tuple[str, int, str], None, None]: ...
def pprint(self) -> None: ...

# dummy atribute to indicate to mypy that ViewList is Iterable[str]
def __iter__(self) -> Iterator[str]: ...

class StringList(ViewList[str]):
def trim_left(self, length: int, start: int = 0, end: int = ...) -> None: ...
def get_text_block(self, start: int, flush_left: bool = False) -> StringList: ...
def get_indented(
self,
start: int = 0,
until_blank: bool = False,
strip_indent: bool = True,
block_indent: int | None = None,
first_indent: int | None = None,
) -> tuple[StringList, int, bool]: ...
def get_2D_block(self, top: int, left: int, bottom: int, right: int, strip_indent: bool = True) -> StringList: ...
def pad_double_width(self, pad_char: str) -> None: ...
def replace(self, old: str, new: str) -> None: ...

class StateMachineError(Exception): ...
class UnknownStateError(StateMachineError): ...
class DuplicateStateError(StateMachineError): ...
class UnknownTransitionError(StateMachineError): ...
class DuplicateTransitionError(StateMachineError): ...
class TransitionPatternNotFound(StateMachineError): ...
class TransitionMethodNotFound(StateMachineError): ...
class UnexpectedIndentationError(StateMachineError): ...
class TransitionCorrection(Exception): ...
class StateCorrection(Exception): ...

def string2lines(
astring: str, tab_width: int = 8, convert_whitespace: bool = False, whitespace: Pattern[str] = ...
) -> list[str]: ...

0 comments on commit a1bfd65

Please sign in to comment.