Skip to content

[docutils] Add remaining node classes and functions #11255

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

Merged
merged 18 commits into from
Jan 31, 2024
Merged
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: 1 addition & 2 deletions stubs/docutils/@tests/stubtest_allowlist.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,8 @@ docutils.io.FileOutput.__init__
docutils.io.Input.__init__
docutils.languages.LanguageImporter.__getattr__
docutils.nodes.Element.__getattr__
docutils.nodes.NodeVisitor.__getattr__
docutils.nodes.GenericNodeVisitor.__getattr__
docutils.nodes.document.__getattr__
docutils.nodes.document.__init__
docutils.nodes.Element.__iter__ # doesn't exist at runtime, but the class is iterable due to __getitem__
docutils.parsers.rst.Directive.__getattr__
docutils.transforms.Transform.__getattr__
Expand Down
264 changes: 233 additions & 31 deletions stubs/docutils/docutils/nodes.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,27 @@ import sys
import xml.dom.minidom
from _typeshed import Incomplete
from abc import abstractmethod
from collections.abc import Callable, Generator, Iterable, Iterator, Sequence
from collections.abc import Callable, Generator, Iterable, Iterator, Mapping, Sequence
from typing import Any, ClassVar, Literal, Protocol, SupportsIndex, TypeVar, overload
from typing_extensions import Self
from typing_extensions import Self, TypeAlias

from docutils.transforms import Transformer
from docutils.transforms import Transform, Transformer
from docutils.utils import Reporter

_N = TypeVar("_N", bound=Node)

class _DomModule(Protocol):
Document: type[xml.dom.minidom.Document]

# Functional Node Base Classes

class Node:
# children is initialized by the subclasses
children: Sequence[Node]
parent: Node | None
# TODO: `parent` is actually `Element | None``, but `None`` only happens rarely,
# i.e. for synthetic nodes (or `document`, where it is overridden).
# See https://github.com/python/typeshed/blob/main/CONTRIBUTING.md#the-any-trick
parent: Element | Any
source: str | None
line: int | None
document: document | None
Expand Down Expand Up @@ -77,6 +83,25 @@ class Node:
ascend: bool = False,
) -> Node: ...

# Left out
# - def ensure_str (deprecated)
# - def unescape (canonical import from docutils.utils)
Comment on lines +86 to +88
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Self-explanatory

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's a history of leaving out deprecated symbols for third-party stubs, I'd say it's fine.
But if you want, you could use the typing_extensions.deprecated decorator.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think in these two cases, it’s not necessary. One is for Python 2 only and therefore completely unnecessary, the other should just be imported from somewhere else, which is a single line change.


class Text(Node, str):
Copy link
Contributor Author

@flying-sheep flying-sheep Jan 7, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved this up so the module layout matches the source file.

This makes it easier to compare stubs and module code

tagname: ClassVar[str]
children: tuple[()]

# we omit the rawsource parameter because it has been deprecated and is ignored
def __new__(cls, data: str) -> Self: ...
def __init__(self, data: str) -> None: ...
def shortrepr(self, maxlen: int = 18) -> str: ...
def copy(self) -> Self: ...
def deepcopy(self) -> Self: ...
def pformat(self, indent: str = " ", level: int = 0) -> str: ...
def astext(self) -> str: ...
def rstrip(self, chars: str | None = None) -> str: ...
def lstrip(self, chars: str | None = None) -> str: ...

class Element(Node):
children: list[Node]
rawsource: str
Expand Down Expand Up @@ -113,58 +138,235 @@ class Element(Node):
def __getattr__(self, __name: str) -> Incomplete: ...

class TextElement(Element):
# A few classes not subclassing TextElement have this, too
child_text_separator: ClassVar[str]
def __init__(self, rawsource: str = "", text: str = "", *children: Node, **attributes) -> None: ...

class FixedTextElement(TextElement):
def __init__(self, rawsource: str = "", text: str = "", *children: Node, **attributes) -> None: ...
class FixedTextElement(TextElement): ...

# Mixins

class Resolvable:
resolved: int

class BackLinkable:
def add_backref(self, refid: str) -> None: ...

class Text(Node, str):
tagname: ClassVar[str]
children: tuple[()]

# we omit the rawsource parameter because it has been deprecated and is ignored
def __new__(cls, data: str) -> Self: ...
def __init__(self, data: str) -> None: ...
def shortrepr(self, maxlen: int = 18) -> str: ...
def copy(self) -> Self: ...
def deepcopy(self) -> Self: ...
def pformat(self, indent: str = " ", level: int = 0) -> str: ...
def astext(self) -> str: ...
def rstrip(self, chars: str | None = None) -> str: ...
def lstrip(self, chars: str | None = None) -> str: ...
# Element Categories

class Root: ...
class Titular: ...
class PreBibliographic: ...
class Bibliographic: ...
class Decorative(PreBibliographic): ...
class Structural: ...
class Body: ...
class General(Body): ...
class Root: ...
class PreBibliographic: ...
class Sequential(Body): ...
class Admonition(Body): ...
class Special(Body): ...
class Invisible(PreBibliographic): ...
class Part: ...
class Inline: ...
class Referential(Resolvable): ...

class Targetable(Resolvable):
referenced: int
indirect_reference_name: str | None

class Labeled: ...

# Root Element

class document(Root, Structural, Element):
parent: None
transformer: Transformer
substitution_defs: dict[str, substitution_definition]
def copy(self) -> Self: ...
def deepcopy(self) -> Self: ...
def pformat(self, indent: str = " ", level: int = 0) -> str: ...
def astext(self) -> str: ...
Comment on lines -151 to -154
Copy link
Contributor Author

@flying-sheep flying-sheep Jan 7, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As document inherits these from Element, duplicating these is not necessary.

def __init__(self, settings, reporter: Reporter, rawsource: str = "", *children: Node, **attributes) -> None: ...
def __getattr__(self, __name: str) -> Incomplete: ...

# Title Elements

class title(Titular, PreBibliographic, TextElement): ...
class subtitle(Titular, PreBibliographic, TextElement): ...
class rubric(Titular, TextElement): ...

# Meta-Data Element

class meta(PreBibliographic, Element): ...

# Bibliographic Elements

class docinfo(Bibliographic, Element): ...
class author(Bibliographic, TextElement): ...
class authors(Bibliographic, Element): ...
class organization(Bibliographic, TextElement): ...
class address(Bibliographic, FixedTextElement): ...
class contact(Bibliographic, TextElement): ...
class version(Bibliographic, TextElement): ...
class revision(Bibliographic, TextElement): ...
class status(Bibliographic, TextElement): ...
class date(Bibliographic, TextElement): ...
class copyright(Bibliographic, TextElement): ...

# Decorative Elements

class decoration(Decorative, Element):
def get_header(self) -> header: ...
def get_footer(self) -> footer: ...

class header(Decorative, Element): ...
class footer(Decorative, Element): ...

# Structural Elements

class section(Structural, Element): ...
class topic(Structural, Element): ...
class sidebar(Structural, Element): ...
class transition(Structural, Element): ...

# Body Elements
# ===============

class paragraph(General, TextElement): ...
class compound(General, Element): ...
class container(General, Element): ...
class bullet_list(Sequential, Element): ...
class enumerated_list(Sequential, Element): ...
class list_item(Part, Element): ...
class definition_list(Sequential, Element): ...
class definition_list_item(Part, Element): ...
class term(Part, TextElement): ...
class classifier(Part, TextElement): ...
class definition(Part, Element): ...
class field_list(Sequential, Element): ...
class field(Part, Element): ...
class field_name(Part, TextElement): ...
class field_body(Part, Element): ...

# child_text_separator in some option* classes mirrors TextElement,
# but these classes do not subclass TextElement
class option(Part, Element):
child_text_separator: str

class option_argument(Part, TextElement): ...

class option_group(Part, Element):
child_text_separator: str # see above

class option_list(Sequential, Element): ...

class option_list_item(Part, Element):
child_text_separator: str # see above

class option_string(Part, TextElement): ...
class description(Part, Element): ...
class literal_block(General, FixedTextElement): ...
class doctest_block(General, FixedTextElement): ...
class math_block(General, FixedTextElement): ...
class line_block(General, Element): ...

class line(Part, TextElement):
indent: str | None

class block_quote(General, Element): ...
class attribution(Part, TextElement): ...
class attention(Admonition, Element): ...
class caution(Admonition, Element): ...
class danger(Admonition, Element): ...
class error(Admonition, Element): ...
class important(Admonition, Element): ...
class note(Admonition, Element): ...
class tip(Admonition, Element): ...
class hint(Admonition, Element): ...
class warning(Admonition, Element): ...
class admonition(Admonition, Element): ...
class comment(Special, Invisible, FixedTextElement): ...
class substitution_definition(Special, Invisible, TextElement): ...
class raw(Special, Inline, PreBibliographic, FixedTextElement): ...
class target(Special, Invisible, Inline, TextElement, Targetable): ...
class footnote(General, BackLinkable, Element, Labeled, Targetable): ...
class citation(General, BackLinkable, Element, Labeled, Targetable): ...
class label(Part, TextElement): ...
class figure(General, Element): ...
class caption(Part, TextElement): ...
class legend(Part, Element): ...
class table(General, Element): ...
class tgroup(Part, Element): ...
class colspec(Part, Element): ...
class thead(Part, Element): ...
class tbody(Part, Element): ...
class row(Part, Element): ...
class entry(Part, Element): ...

class system_message(Special, BackLinkable, PreBibliographic, Element):
def __init__(self, message: str | None = None, *children: Node, **attributes) -> None: ...
def astext(self) -> str: ...

class pending(Special, Invisible, Element):
transform: Transform
details: Mapping[str, Any]
def __init__(
self, transform: Transform, details: Mapping[str, Any] | None = None, rawsource: str = "", *children: Node, **attributes
) -> None: ...

class raw(Special, Inline, PreBibliographic, FixedTextElement): ...

# Inline Elements

class emphasis(Inline, TextElement): ...
class strong(Inline, TextElement): ...
class literal(Inline, TextElement): ...
class reference(General, Inline, Referential, TextElement): ...
class footnote_reference(Inline, Referential, TextElement): ...
class citation_reference(Inline, Referential, TextElement): ...
class substitution_reference(Inline, TextElement): ...
class title_reference(Inline, TextElement): ...
class abbreviation(Inline, TextElement): ...
class acronym(Inline, TextElement): ...
class superscript(Inline, TextElement): ...
class subscript(Inline, TextElement): ...
class math(Inline, TextElement): ...
class image(General, Inline, Element): ...
class inline(Inline, TextElement): ...
class problematic(Inline, TextElement): ...
class generated(Inline, TextElement): ...

# Auxiliary Classes, Functions, and Data

node_class_names: list[str]

# necessary to disambiguate type and field in NodeVisitor
_Document: TypeAlias = document

class NodeVisitor:
def __init__(self, document: document): ...
optional: ClassVar[tuple[str, ...]]
document: _Document
def __init__(self, document: _Document) -> None: ...
def dispatch_visit(self, node: Node) -> Any: ...
def dispatch_departure(self, node: Node) -> Any: ...
def unknown_visit(self, node: Node) -> Any: ...
def unknown_departure(self, node: Node) -> Any: ...

class SparseNodeVisitor(NodeVisitor): ...

class GenericNodeVisitor(NodeVisitor):
# all the visit_<node_class_name> methods
def __getattr__(self, __name: str) -> Incomplete: ...

def __getattr__(name: str) -> Incomplete: ...
class TreeCopyVisitor(GenericNodeVisitor):
parent_stack: list[Node]
parent: list[Node]
def get_tree_copy(self) -> Node: ...

class TreePruningException(Exception): ...
class SkipChildren(TreePruningException): ...
class SkipSiblings(TreePruningException): ...
class SkipNode(TreePruningException): ...
class SkipDeparture(TreePruningException): ...
class NodeFound(TreePruningException): ...
class StopTraversal(TreePruningException): ...

def make_id(string: str) -> str: ...
def dupname(node: Node, name: str) -> None: ...
def fully_normalize_name(name: str) -> str: ...
def whitespace_normalize_name(name: str) -> str: ...
def serial_escape(value: str) -> str: ...
def pseudo_quoteattr(value: str) -> str: ...