From 56c678a55ba57cb4cc0f7718d7523a0f798a5b33 Mon Sep 17 00:00:00 2001 From: eeshsaxena Date: Sat, 15 Aug 2026 13:11:48 +0530 Subject: [PATCH] Default _parse's 'new' to a dict to avoid TypeError on stray at-keywords The default productions record the wellformed state via new['wellformed'], but _parse's 'new' argument is optional and defaults to None. Parsing a bare property name (which passes new=None) that contains an '@' reached the ATKEYWORD production and raised 'NoneType' object does not support item assignment. Give _parse a throwaway dict when new is None so the input is reported as a normal CSS error instead. --- cssutils/util.py | 7 +++++++ tests/test_cssstyledeclaration.py | 13 +++++++++++++ 2 files changed, 20 insertions(+) diff --git a/cssutils/util.py b/cssutils/util.py index c2e6db78..799a2e22 100644 --- a/cssutils/util.py +++ b/cssutils/util.py @@ -468,6 +468,13 @@ def _parse( """ wellformed = True + if new is None: + # ``new`` is optional, but the default productions record the + # wellformed state into it (new['wellformed'] = False). Give them a + # throwaway dict when a caller that does not track it (e.g. parsing + # a bare property name) passes None, to avoid a TypeError. + new = {} + if initialtoken: # add initialtoken to tokenizer def tokens(): diff --git a/tests/test_cssstyledeclaration.py b/tests/test_cssstyledeclaration.py index 69f54fac..71735089 100644 --- a/tests/test_cssstyledeclaration.py +++ b/tests/test_cssstyledeclaration.py @@ -33,6 +33,19 @@ def test_init(self): assert 'top: 0' == s.cssText assert sheet == s.parentRule + def test_at_in_property_name(self): + "CSSStyleDeclaration with an '@' in a property name" + # A property name containing '@' reached the default productions with + # new=None and used to raise TypeError ('NoneType' object does not + # support item assignment). It should be reported as a normal CSS + # error instead: parsing a whole sheet drops the bad property and keeps + # the rest, and building a declaration directly raises SyntaxErr. + sheet = cssutils.parseString('a { col@or: red; width: 1px }') + assert '1px' == sheet.cssRules[0].style.getPropertyValue('width') + + with pytest.raises(xml.dom.SyntaxErr): + cssutils.css.CSSStyleDeclaration(cssText='col@or: red') + def test_items(self): "CSSStyleDeclaration[CSSName]" s = cssutils.css.CSSStyleDeclaration()