lazy parse_rules

This commit is contained in:
Will McGugan
2022-04-29 10:34:35 +01:00
parent 233c2c4075
commit 8e821d4113
3 changed files with 17 additions and 7 deletions

View File

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

View File

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

View File

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