mirror of
https://github.com/Textualize/textual.git
synced 2025-10-17 02:38:12 +03:00
added textual.getters
This commit is contained in:
@@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file.
|
||||
The format is based on [Keep a Changelog](http://keepachangelog.com/)
|
||||
and this project adheres to [Semantic Versioning](http://semver.org/).
|
||||
|
||||
## Unreleased
|
||||
|
||||
### Added
|
||||
|
||||
- Added textual.getters
|
||||
|
||||
## [3.6.0] - 2025-07-06
|
||||
|
||||
### Fixed
|
||||
|
||||
5
docs/api/getters.md
Normal file
5
docs/api/getters.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
title: "textual.getters"
|
||||
---
|
||||
|
||||
::: textual.getters
|
||||
@@ -6,7 +6,7 @@ except ImportError:
|
||||
raise ImportError("Please install httpx with 'pip install httpx' ")
|
||||
|
||||
|
||||
from textual import work
|
||||
from textual import getters, work
|
||||
from textual.app import App, ComposeResult
|
||||
from textual.containers import VerticalScroll
|
||||
from textual.widgets import Input, Markdown
|
||||
@@ -17,6 +17,9 @@ class DictionaryApp(App):
|
||||
|
||||
CSS_PATH = "dictionary.tcss"
|
||||
|
||||
results = getters.query_one("#results", Markdown)
|
||||
input = getters.query_one(Input)
|
||||
|
||||
def compose(self) -> ComposeResult:
|
||||
yield Input(placeholder="Search for a word", id="dictionary-search")
|
||||
with VerticalScroll(id="results-container"):
|
||||
@@ -28,7 +31,7 @@ class DictionaryApp(App):
|
||||
self.lookup_word(message.value)
|
||||
else:
|
||||
# Clear the results
|
||||
await self.query_one("#results", Markdown).update("")
|
||||
await self.results.update("")
|
||||
|
||||
@work(exclusive=True)
|
||||
async def lookup_word(self, word: str) -> None:
|
||||
@@ -40,12 +43,12 @@ class DictionaryApp(App):
|
||||
try:
|
||||
results = response.json()
|
||||
except Exception:
|
||||
self.query_one("#results", Markdown).update(response.text)
|
||||
self.results.update(response.text)
|
||||
return
|
||||
|
||||
if word == self.query_one(Input).value:
|
||||
if word == self.input.value:
|
||||
markdown = self.make_word_markdown(results)
|
||||
self.query_one("#results", Markdown).update(markdown)
|
||||
self.results.update(markdown)
|
||||
|
||||
def make_word_markdown(self, results: object) -> str:
|
||||
"""Convert the results into markdown."""
|
||||
|
||||
@@ -202,6 +202,7 @@ nav:
|
||||
- "api/filter.md"
|
||||
- "api/fuzzy_matcher.md"
|
||||
- "api/geometry.md"
|
||||
- "api/getters.md"
|
||||
- "api/layout.md"
|
||||
- "api/lazy.md"
|
||||
- "api/logger.md"
|
||||
|
||||
96
src/textual/getters.py
Normal file
96
src/textual/getters.py
Normal file
@@ -0,0 +1,96 @@
|
||||
"""
|
||||
Descriptors to define properties on your widget, screen, or App.
|
||||
|
||||
"""
|
||||
|
||||
from typing import Generic, overload
|
||||
|
||||
from textual.css.query import QueryType
|
||||
from textual.dom import DOMNode
|
||||
from textual.widget import Widget
|
||||
|
||||
|
||||
class query_one(Generic[QueryType]):
|
||||
"""Create a query one property.
|
||||
|
||||
A query one property calls [query_one][textual.dom.DOMNode.query_one] when accessed, and returns
|
||||
a widget.
|
||||
|
||||
|
||||
Example:
|
||||
```python
|
||||
from textual import getters
|
||||
|
||||
class MyScreen(screen):
|
||||
|
||||
# Note this is at the class level
|
||||
output_log = getters.query_one("#output", RichLog)
|
||||
|
||||
def compose(self) -> ComposeResult:
|
||||
yield RichLog(id="output")
|
||||
|
||||
def on_mount(self) -> None:
|
||||
self.output_log.write("Screen started")
|
||||
# Equivalent to the following line:
|
||||
# self.query_one("#output", RichLog).write("Screen started")
|
||||
```
|
||||
|
||||
|
||||
"""
|
||||
|
||||
selector: str
|
||||
expect_type: type[Widget]
|
||||
|
||||
@overload
|
||||
def __init__(self, selector: str) -> None:
|
||||
self.selector = selector
|
||||
self.expect_type = Widget
|
||||
|
||||
@overload
|
||||
def __init__(self, selector: type[QueryType]) -> None:
|
||||
self.selector = selector.__name__
|
||||
self.expect_type = selector
|
||||
|
||||
@overload
|
||||
def __init__(self, selector: str, expect_type: type[QueryType]) -> None:
|
||||
self.selector = selector
|
||||
self.expect_type = expect_type
|
||||
|
||||
@overload
|
||||
def __init__(self, selector: type[QueryType], expect_type: type[QueryType]) -> None:
|
||||
self.selector = selector.__name__
|
||||
self.expect_type = expect_type
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
selector: str | type[QueryType],
|
||||
expect_type: type[QueryType] | None = None,
|
||||
) -> None:
|
||||
if expect_type is None:
|
||||
self.expect_type = Widget
|
||||
else:
|
||||
self.expect_type = expect_type
|
||||
if isinstance(selector, str):
|
||||
self.selector = selector
|
||||
else:
|
||||
self.selector = selector.__name__
|
||||
self.expect_type = selector
|
||||
|
||||
@overload
|
||||
def __get__(
|
||||
self: "query_one[QueryType]", obj: DOMNode, obj_type: type[DOMNode]
|
||||
) -> QueryType: ...
|
||||
|
||||
@overload
|
||||
def __get__(
|
||||
self: "query_one[QueryType]", obj: None, obj_type: type[DOMNode]
|
||||
) -> "query_one[QueryType]": ...
|
||||
|
||||
def __get__(
|
||||
self: "query_one[QueryType]", obj: DOMNode | None, obj_type: type[DOMNode]
|
||||
) -> QueryType | Widget | "query_one":
|
||||
"""Get the widget matching the selector and/or type."""
|
||||
if obj is None:
|
||||
return self
|
||||
query_node = obj.query_one(self.selector, self.expect_type)
|
||||
return query_node
|
||||
Reference in New Issue
Block a user