Skip to content

Commit

Permalink
Merge pull request #3730 from Textualize/docs-improvements
Browse files Browse the repository at this point in the history
Improve documentation.
  • Loading branch information
rodrigogiraoserrao authored Nov 23, 2023
2 parents a64a0d2 + 92f5c42 commit 07bfcf2
Show file tree
Hide file tree
Showing 21 changed files with 102 additions and 45 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
- Rich markup in markdown headings is now escaped when building the TOC https://github.com/Textualize/textual/issues/3689
- Mechanics behind mouse clicks. See [this](https://github.com/Textualize/textual/pull/3495#issue-1934915047) for more details. https://github.com/Textualize/textual/pull/3495
- Breaking change: max/min-width/height now includes padding and border. https://github.com/Textualize/textual/pull/3712
- Method `MarkdownTableOfContents.set_table_of_contents` renamed to `MarkdownTableOfContents.rebuild_table_of_contents` https://github.com/Textualize/textual/pull/3730
- Exception `Tree.UnknownNodeID` moved out of `Tree`, import from `textual.widgets.tree` https://github.com/Textualize/textual/pull/3730
- Exception `TreeNode.RemoveRootError` moved out of `TreeNode`, import from `textual.widgets.tree` https://github.com/Textualize/textual/pull/3730


## [0.41.0] - 2023-10-31
Expand Down
1 change: 1 addition & 0 deletions docs/api/await_complete.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
::: textual.await_complete
6 changes: 6 additions & 0 deletions docs/widgets/markdown_viewer.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,3 +57,9 @@ This widget has no component classes.
::: textual.widgets.MarkdownViewer
options:
heading_level: 2


::: textual.widgets.markdown
options:
show_root_heading: true
show_root_toc_entry: true
2 changes: 1 addition & 1 deletion docs/widgets/tree.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,6 @@ The tree widget provides the following component classes:

---

::: textual.widgets.tree.TreeNode
::: textual.widgets.tree
options:
heading_level: 2
1 change: 1 addition & 0 deletions mkdocs-nav.yml
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,7 @@ nav:
- API:
- "api/index.md"
- "api/app.md"
- "api/await_complete.md"
- "api/await_remove.md"
- "api/binding.md"
- "api/color.md"
Expand Down
4 changes: 2 additions & 2 deletions src/textual/_text_area_theme.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ def __post_init__(self) -> None:
)

@classmethod
def get_builtin_theme(cls, theme_name: str) -> "TextAreaTheme" | None:
def get_builtin_theme(cls, theme_name: str) -> TextAreaTheme | None:
"""Get a `TextAreaTheme` by name.
Given a `theme_name`, return the corresponding `TextAreaTheme` object.
Expand All @@ -120,7 +120,7 @@ def get_builtin_theme(cls, theme_name: str) -> "TextAreaTheme" | None:
Returns:
The `TextAreaTheme` corresponding to the name or `None` if the theme isn't
found.
found.
"""
return _BUILTIN_THEMES.get(theme_name)

Expand Down
1 change: 0 additions & 1 deletion src/textual/await_remove.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
"""
An *optionally* awaitable object returned by methods that remove widgets.
"""

Expand Down
6 changes: 3 additions & 3 deletions src/textual/document/_document.py
Original file line number Diff line number Diff line change
Expand Up @@ -133,10 +133,10 @@ def get_size(self, indent_width: int) -> Size:

def query_syntax_tree(
self,
query: "Query",
query: Query,
start_point: tuple[int, int] | None = None,
end_point: tuple[int, int] | None = None,
) -> list[tuple["Node", str]]:
) -> list[tuple[Node, str]]:
"""Query the tree-sitter syntax tree.
The default implementation always returns an empty list.
Expand All @@ -153,7 +153,7 @@ def query_syntax_tree(
"""
return []

def prepare_query(self, query: str) -> "Query" | None:
def prepare_query(self, query: str) -> Query | None:
return None

@property
Expand Down
16 changes: 14 additions & 2 deletions src/textual/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,15 @@
)
from .actions import ActionParseResult
from .css.styles import RenderStyles
from .widgets._data_table import CursorType
from .widgets._directory_tree import DirEntry
from .widgets._input import InputValidationOn
from .widgets._option_list import (
DuplicateID,
NewOptionListContent,
OptionDoesNotExist,
OptionListContent,
)
from .widgets._placeholder import PlaceholderVariant
from .widgets._select import NoSelection, SelectType

__all__ = [
Expand All @@ -24,13 +31,18 @@
"CallbackType",
"CSSPathError",
"CSSPathType",
"CursorType",
"DirEntry",
"DuplicateID",
"EasingFunction",
"IgnoreReturnCallbackType",
"InputValidationOn",
"MessageTarget",
"NewOptionListContent",
"NoActiveAppError",
"NoSelection",
"OptionDoesNotExist",
"OptionListContent",
"PlaceholderVariant",
"RenderStyles",
"SelectType",
"UnusedParameter",
Expand Down
1 change: 1 addition & 0 deletions src/textual/widgets/_data_table.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
CursorType = Literal["cell", "row", "column", "none"]
"""The valid types of cursors for [`DataTable.cursor_type`][textual.widgets.DataTable.cursor_type]."""
CellType = TypeVar("CellType")
"""Type used for cells in the DataTable."""

_DEFAULT_CELL_X_PADDING = 1
"""Default padding to use on each side of a column in the data table."""
Expand Down
2 changes: 1 addition & 1 deletion src/textual/widgets/_directory_tree.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@

@dataclass
class DirEntry:
"""Attaches directory information to a node."""
"""Attaches directory information to a [`DirectoryTree`][textual.widgets.DirectoryTree] node."""

path: Path
"""The path of the directory entry."""
Expand Down
2 changes: 1 addition & 1 deletion src/textual/widgets/_loading_indicator.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ def apply(self, widget: Widget) -> AwaitMount:
widget: A widget.
Returns:
AwaitMount: An awaitable for mounting the indicator.
An awaitable for mounting the indicator.
"""
self.add_class("-overlay")
await_mount = widget.mount(self)
Expand Down
25 changes: 16 additions & 9 deletions src/textual/widgets/_markdown.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from __future__ import annotations

from pathlib import Path, PurePath
from typing import Callable, Iterable
from typing import Callable, Iterable, Optional

from markdown_it import MarkdownIt
from markdown_it.token import Token
Expand All @@ -22,6 +22,10 @@
from ..widgets import Static, Tree

TableOfContentsType: TypeAlias = "list[tuple[int, str, str | None]]"
"""Information about the table of contents of a markdown document.
The triples encode the level, the label, and the optional block id of each heading.
"""


class Navigator:
Expand Down Expand Up @@ -709,7 +713,7 @@ def unhandled_token(self, token: Token) -> MarkdownBlock | None:
"""Process an unhandled token.
Args:
token: The token to handle.
token: The MarkdownIt token to handle.
Returns:
Either a widget to be added to the output, or `None`.
Expand Down Expand Up @@ -872,6 +876,8 @@ def update(self, markdown: str) -> AwaitMount:


class MarkdownTableOfContents(Widget, can_focus_children=True):
"""Displays a table of contents for a markdown document."""

DEFAULT_CSS = """
MarkdownTableOfContents {
width: auto;
Expand All @@ -884,7 +890,8 @@ class MarkdownTableOfContents(Widget, can_focus_children=True):
}
"""

table_of_contents = reactive["TableOfContentsType | None"](None, init=False)
table_of_contents = reactive[Optional[TableOfContentsType]](None, init=False)
"""Underlying data to populate the table of contents widget."""

def __init__(
self,
Expand All @@ -903,7 +910,7 @@ def __init__(
classes: The CSS classes for the widget.
disabled: Whether the widget is disabled or not.
"""
self.markdown = markdown
self.markdown: Markdown = markdown
"""The Markdown document associated with this table of contents."""
super().__init__(name=name, id=id, classes=classes, disabled=disabled)

Expand All @@ -917,10 +924,10 @@ def compose(self) -> ComposeResult:

def watch_table_of_contents(self, table_of_contents: TableOfContentsType) -> None:
"""Triggered when the table of contents changes."""
self.set_table_of_contents(table_of_contents)
self.rebuild_table_of_contents(table_of_contents)

def set_table_of_contents(self, table_of_contents: TableOfContentsType) -> None:
"""Set the table of contents.
def rebuild_table_of_contents(self, table_of_contents: TableOfContentsType) -> None:
"""Rebuilds the tree representation of the table of contents data.
Args:
table_of_contents: Table of contents.
Expand Down Expand Up @@ -1005,12 +1012,12 @@ def __init__(

@property
def document(self) -> Markdown:
"""The Markdown document object."""
"""The [`Markdown`][textual.widgets.Markdown] document widget."""
return self.query_one(Markdown)

@property
def table_of_contents(self) -> MarkdownTableOfContents:
"""The table of contents widget"""
"""The [table of contents][textual.widgets.markdown.MarkdownTableOfContents] widget."""
return self.query_one(MarkdownTableOfContents)

def _on_mount(self, _: Mount) -> None:
Expand Down
6 changes: 3 additions & 3 deletions src/textual/widgets/_option_list.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,11 @@


class DuplicateID(Exception):
"""Exception raised if a duplicate ID is used."""
"""Raised if a duplicate ID is used when adding options to an option list."""


class OptionDoesNotExist(Exception):
"""Exception raised when a request has been made for an option that doesn't exist."""
"""Raised when a request has been made for an option that doesn't exist."""


class Option:
Expand Down Expand Up @@ -126,7 +126,7 @@ def __contains__(self, line: object) -> bool:
"""The type of a new item of option list content to be added to an option list.
This type represents all of the types that will be accepted when adding new
content to the option list. This is a superset of `OptionListContent`.
content to the option list. This is a superset of [`OptionListContent`][textual.types.OptionListContent].
"""


Expand Down
7 changes: 4 additions & 3 deletions src/textual/widgets/_placeholder.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,20 @@
from __future__ import annotations

from itertools import cycle
from typing import Iterator
from typing import TYPE_CHECKING, Iterator
from weakref import WeakKeyDictionary

from rich.console import RenderableType
from typing_extensions import Literal, Self

from textual.app import App

from .. import events
from ..css._error_tools import friendly_list
from ..reactive import Reactive, reactive
from ..widget import Widget

if TYPE_CHECKING:
from textual.app import App

PlaceholderVariant = Literal["default", "size", "text"]
"""The different variants of placeholder."""

Expand Down
2 changes: 1 addition & 1 deletion src/textual/widgets/_tabbed_content.py
Original file line number Diff line number Diff line change
Expand Up @@ -306,7 +306,7 @@ def add_pane(
Note:
Only one of `before` or `after` can be provided. If both are
provided a `Tabs.TabError` will be raised.
provided an exception is raised.
"""
if isinstance(before, TabPane):
before = before.id
Expand Down
22 changes: 12 additions & 10 deletions src/textual/widgets/_tree.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,14 @@
TOGGLE_STYLE = Style.from_meta({"toggle": True})


class RemoveRootError(Exception):
"""Exception raised when trying to remove the root of a [`TreeNode`][textual.widgets.tree.TreeNode]."""


class UnknownNodeID(Exception):
"""Exception raised when referring to an unknown [`TreeNode`][textual.widgets.tree.TreeNode] ID."""


@dataclass
class _TreeLine(Generic[TreeDataType]):
path: list[TreeNode[TreeDataType]]
Expand Down Expand Up @@ -352,9 +360,6 @@ def add_leaf(
node = self.add(label, data, expand=False, allow_expand=False)
return node

class RemoveRootError(Exception):
"""Exception raised when trying to remove a tree's root node."""

def _remove_children(self) -> None:
"""Remove child nodes of this node.
Expand All @@ -381,10 +386,10 @@ def remove(self) -> None:
"""Remove this node from the tree.
Raises:
TreeNode.RemoveRootError: If there is an attempt to remove the root.
RemoveRootError: If there is an attempt to remove the root.
"""
if self.is_root:
raise self.RemoveRootError("Attempt to remove the root node of a Tree.")
raise RemoveRootError("Attempt to remove the root node of a Tree.")
self._remove()
self._tree._invalidate()

Expand Down Expand Up @@ -758,9 +763,6 @@ def get_node_at_line(self, line_no: int) -> TreeNode[TreeDataType] | None:
else:
return line.node

class UnknownNodeID(Exception):
"""Exception raised when referring to an unknown `TreeNode` ID."""

def get_node_by_id(self, node_id: NodeID) -> TreeNode[TreeDataType]:
"""Get a tree node by its ID.
Expand All @@ -771,12 +773,12 @@ def get_node_by_id(self, node_id: NodeID) -> TreeNode[TreeDataType]:
The node associated with that ID.
Raises:
Tree.UnknownID: Raised if the `TreeNode` ID is unknown.
UnknownNodeID: Raised if the `TreeNode` ID is unknown.
"""
try:
return self._tree_nodes[node_id]
except KeyError:
raise self.UnknownNodeID(f"Unknown NodeID ({node_id}) in tree") from None
raise UnknownNodeID(f"Unknown NodeID ({node_id}) in tree") from None

def validate_cursor_line(self, value: int) -> int:
"""Prevent cursor line from going outside of range.
Expand Down
14 changes: 12 additions & 2 deletions src/textual/widgets/markdown.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
from ._markdown import Markdown, MarkdownBlock, MarkdownTableOfContents
from ._markdown import (
Markdown,
MarkdownBlock,
MarkdownTableOfContents,
TableOfContentsType,
)

__all__ = ["MarkdownTableOfContents", "Markdown", "MarkdownBlock"]
__all__ = [
"MarkdownTableOfContents",
"Markdown",
"MarkdownBlock",
"TableOfContentsType",
]
18 changes: 16 additions & 2 deletions src/textual/widgets/tree.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,19 @@
"""Make non-widget Tree support classes available."""

from ._tree import TreeNode
from ._tree import (
EventTreeDataType,
NodeID,
RemoveRootError,
TreeDataType,
TreeNode,
UnknownNodeID,
)

__all__ = ["TreeNode"]
__all__ = [
"EventTreeDataType",
"NodeID",
"RemoveRootError",
"TreeDataType",
"TreeNode",
"UnknownNodeID",
]
Loading

0 comments on commit 07bfcf2

Please sign in to comment.