mirror of
https://github.com/Textualize/textual.git
synced 2025-10-17 02:38:12 +03:00
Merge pull request #985 from Textualize/query-parse
Add sensible error to query
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/).
|
||||
|
||||
## [0.2.2] - Unreleased
|
||||
|
||||
### Changed
|
||||
|
||||
- DOMQuery now raises InvalidQueryFormat in response to invalid query strings, rather than cryptic CSS error
|
||||
|
||||
## [0.2.1] - 2022-10-23
|
||||
|
||||
### Changed
|
||||
|
||||
@@ -28,7 +28,8 @@ class CalculatorApp(App):
|
||||
"plus_minus_sign": "plus-minus",
|
||||
"percent_sign": "percent",
|
||||
"equals_sign": "equals",
|
||||
"enter": "equals",
|
||||
"minus": "minus",
|
||||
"plus": "plus",
|
||||
}
|
||||
|
||||
def watch_numbers(self, value: str) -> None:
|
||||
@@ -80,7 +81,6 @@ class CalculatorApp(App):
|
||||
self.query_one(f"#{button_id}", Button).press()
|
||||
except NoMatches:
|
||||
pass
|
||||
self.set_focus(None)
|
||||
|
||||
key = event.key
|
||||
if key.isdecimal():
|
||||
@@ -89,6 +89,8 @@ class CalculatorApp(App):
|
||||
press("c")
|
||||
press("ac")
|
||||
else:
|
||||
button_id = self.NAME_MAP.get(key)
|
||||
if button_id is not None:
|
||||
press(self.NAME_MAP.get(key, key))
|
||||
|
||||
def on_button_pressed(self, event: Button.Pressed) -> None:
|
||||
|
||||
@@ -20,7 +20,7 @@ from typing import cast, Generic, TYPE_CHECKING, Iterator, TypeVar, overload
|
||||
|
||||
import rich.repr
|
||||
|
||||
from .errors import DeclarationError
|
||||
from .errors import DeclarationError, TokenError
|
||||
from .match import match
|
||||
from .model import SelectorSet
|
||||
from .parse import parse_declarations, parse_selectors
|
||||
@@ -34,6 +34,10 @@ class QueryError(Exception):
|
||||
"""Base class for a query related error."""
|
||||
|
||||
|
||||
class InvalidQueryFormat(QueryError):
|
||||
"""Query did not parse correctly."""
|
||||
|
||||
|
||||
class NoMatches(QueryError):
|
||||
"""No nodes matched the query."""
|
||||
|
||||
@@ -72,9 +76,17 @@ class DOMQuery(Generic[QueryType]):
|
||||
parent._excludes.copy() if parent else []
|
||||
)
|
||||
if filter is not None:
|
||||
try:
|
||||
self._filters.append(parse_selectors(filter))
|
||||
except TokenError:
|
||||
# TODO: More helpful errors
|
||||
raise InvalidQueryFormat(f"Unable to parse filter {filter!r} as query")
|
||||
|
||||
if exclude is not None:
|
||||
try:
|
||||
self._excludes.append(parse_selectors(exclude))
|
||||
except TokenError:
|
||||
raise InvalidQueryFormat(f"Unable to parse filter {filter!r} as query")
|
||||
|
||||
@property
|
||||
def node(self) -> DOMNode:
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
import pytest
|
||||
|
||||
from textual.widget import Widget
|
||||
from textual.css.query import InvalidQueryFormat
|
||||
|
||||
|
||||
def test_query():
|
||||
@@ -78,3 +81,16 @@ def test_query():
|
||||
assert list(app.query("#widget1, #widget2")) == [widget1, widget2]
|
||||
assert list(app.query("#widget1 , #widget2")) == [widget1, widget2]
|
||||
assert list(app.query("#widget1, #widget2, App")) == [app, widget1, widget2]
|
||||
|
||||
|
||||
def test_invalid_query():
|
||||
class App(Widget):
|
||||
pass
|
||||
|
||||
app = App()
|
||||
|
||||
with pytest.raises(InvalidQueryFormat):
|
||||
app.query("#3")
|
||||
|
||||
with pytest.raises(InvalidQueryFormat):
|
||||
app.query("#foo").exclude("#2")
|
||||
|
||||
Reference in New Issue
Block a user