mirror of
https://github.com/Textualize/textual.git
synced 2025-10-17 02:38:12 +03:00
lazy parse_rules
This commit is contained in:
@@ -101,17 +101,19 @@ class StylesheetErrors:
|
|||||||
@rich.repr.auto
|
@rich.repr.auto
|
||||||
class Stylesheet:
|
class Stylesheet:
|
||||||
def __init__(self, *, variables: dict[str, str] | None = None) -> None:
|
def __init__(self, *, variables: dict[str, str] | None = None) -> None:
|
||||||
self._rules: list[RuleSet] | None = None
|
self._rules: list[RuleSet] = []
|
||||||
self.variables = variables or {}
|
self.variables = variables or {}
|
||||||
self.source: dict[str, str] = {}
|
self.source: dict[str, str] = {}
|
||||||
|
self._require_parse = False
|
||||||
|
|
||||||
def __rich_repr__(self) -> rich.repr.Result:
|
def __rich_repr__(self) -> rich.repr.Result:
|
||||||
yield self.rules
|
yield self.rules
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def rules(self) -> list[RuleSet]:
|
def rules(self) -> list[RuleSet]:
|
||||||
if self._rules is None:
|
if self._require_parse:
|
||||||
self.parse()
|
self.parse()
|
||||||
|
self._require_parse = False
|
||||||
assert self._rules is not None
|
assert self._rules is not None
|
||||||
return self._rules
|
return self._rules
|
||||||
|
|
||||||
@@ -171,7 +173,7 @@ class Stylesheet:
|
|||||||
except Exception as error:
|
except Exception as error:
|
||||||
raise StylesheetError(f"unable to read {filename!r}; {error}")
|
raise StylesheetError(f"unable to read {filename!r}; {error}")
|
||||||
self.source[path] = css
|
self.source[path] = css
|
||||||
self._rules = None
|
self._require_parse = True
|
||||||
|
|
||||||
def add_source(self, css: str, path: str | None = None) -> None:
|
def add_source(self, css: str, path: str | None = None) -> None:
|
||||||
"""Parse CSS from a string.
|
"""Parse CSS from a string.
|
||||||
@@ -192,7 +194,7 @@ class Stylesheet:
|
|||||||
return
|
return
|
||||||
|
|
||||||
self.source[path] = css
|
self.source[path] = css
|
||||||
self._rules = None
|
self._require_parse = True
|
||||||
|
|
||||||
def parse(self) -> None:
|
def parse(self) -> None:
|
||||||
"""Parse the source in the stylesheet.
|
"""Parse the source in the stylesheet.
|
||||||
@@ -208,6 +210,7 @@ class Stylesheet:
|
|||||||
raise StylesheetParseError(self.error_renderable)
|
raise StylesheetParseError(self.error_renderable)
|
||||||
add_rules(css_rules)
|
add_rules(css_rules)
|
||||||
self._rules = rules
|
self._rules = rules
|
||||||
|
self._require_parse = False
|
||||||
|
|
||||||
def reparse(self) -> None:
|
def reparse(self) -> None:
|
||||||
"""Re-parse source, applying new variables.
|
"""Re-parse source, applying new variables.
|
||||||
@@ -221,7 +224,8 @@ class Stylesheet:
|
|||||||
stylesheet = Stylesheet(variables=self.variables)
|
stylesheet = Stylesheet(variables=self.variables)
|
||||||
for path, css in self.source.items():
|
for path, css in self.source.items():
|
||||||
stylesheet.add_source(css, path)
|
stylesheet.add_source(css, path)
|
||||||
self._rules = None
|
stylesheet.parse()
|
||||||
|
self.rules = stylesheet.rules
|
||||||
self.source = stylesheet.source
|
self.source = stylesheet.source
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
|||||||
@@ -875,6 +875,7 @@ class TestParseLayout:
|
|||||||
stylesheet = Stylesheet()
|
stylesheet = Stylesheet()
|
||||||
with pytest.raises(StylesheetParseError) as ex:
|
with pytest.raises(StylesheetParseError) as ex:
|
||||||
stylesheet.add_source(css)
|
stylesheet.add_source(css)
|
||||||
|
stylesheet.parse()
|
||||||
|
|
||||||
assert ex.value.errors is not None
|
assert ex.value.errors is not None
|
||||||
|
|
||||||
@@ -1033,8 +1034,10 @@ class TestParseTransition:
|
|||||||
stylesheet = Stylesheet()
|
stylesheet = Stylesheet()
|
||||||
with pytest.raises(StylesheetParseError) as ex:
|
with pytest.raises(StylesheetParseError) as ex:
|
||||||
stylesheet.add_source(css)
|
stylesheet.add_source(css)
|
||||||
|
stylesheet.parse()
|
||||||
|
|
||||||
stylesheet_errors = stylesheet.rules[0].errors
|
rules = stylesheet._parse_rules(css, "foo")
|
||||||
|
stylesheet_errors = rules[0].errors
|
||||||
|
|
||||||
assert len(stylesheet_errors) == 1
|
assert len(stylesheet_errors) == 1
|
||||||
assert stylesheet_errors[0][0].value == invalid_func_name
|
assert stylesheet_errors[0][0].value == invalid_func_name
|
||||||
@@ -1067,7 +1070,9 @@ class TestParseOpacity:
|
|||||||
|
|
||||||
with pytest.raises(StylesheetParseError):
|
with pytest.raises(StylesheetParseError):
|
||||||
stylesheet.add_source(css)
|
stylesheet.add_source(css)
|
||||||
assert stylesheet.rules[0].errors
|
stylesheet.parse()
|
||||||
|
rules = stylesheet._parse_rules(css, "foo")
|
||||||
|
assert rules[0].errors
|
||||||
|
|
||||||
|
|
||||||
class TestParseMargin:
|
class TestParseMargin:
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ def test_color_property_parsing(css_value, expectation, expected_color):
|
|||||||
|
|
||||||
with expectation:
|
with expectation:
|
||||||
stylesheet.add_source(css)
|
stylesheet.add_source(css)
|
||||||
|
stylesheet.parse()
|
||||||
|
|
||||||
if expected_color:
|
if expected_color:
|
||||||
css_rule = stylesheet.rules[0]
|
css_rule = stylesheet.rules[0]
|
||||||
|
|||||||
Reference in New Issue
Block a user