Merge pull request #985 from Textualize/query-parse

Add sensible error to query
This commit is contained in:
Will McGugan
2022-10-25 11:28:37 +01:00
committed by GitHub
4 changed files with 42 additions and 6 deletions

View File

@@ -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

View File

@@ -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:

View File

@@ -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:

View File

@@ -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")