From e0d4979d12e9a8451735f0044ac691c9fb35093c Mon Sep 17 00:00:00 2001 From: Isaac Muse Date: Wed, 10 Jul 2024 07:20:01 -0600 Subject: [PATCH] Improve pseudo-class error message (#270) * Improve pseudo-class error message When encountering a pseudo-class that is unrecognized, we should not state it is "unsupported" a it may be entirely invalid. While there are some pseudo-classes that are valid but not supported, the status of such things can change all the time and our internal list may become outdated. Additionally, sometimes users trying to incorrectly specify tags with namespaces can trigger this message as they may assume that because a namespace is declared in their document as `ns:element` that they can do this in CSS as well. This specific case is not easily detectable for us as we generically parse the syntax, not the intent of the syntax. To clear up confusion, be more specific and simply state that anytime a pseudo-class is not recognized by soupsieve that it is either invalid or not recognizable by soupsieve. By stating both possibilities, this points out that pseudo-class syntax was noted and that it is unrecognized by soupsieve, regardless of status, and may be entirely invalid. Additionally, note that if it being recognized as a pseudo-class is a surprise that the colon can be escaped to avoid the recognition as such. * Update test to accommodate change in error and use SelectorSyntaxError --- docs/src/markdown/about/changelog.md | 3 ++- soupsieve/css_parser.py | 7 +++++-- tests/test_level1/test_pseudo_class.py | 5 +++-- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/docs/src/markdown/about/changelog.md b/docs/src/markdown/about/changelog.md index 8dd142cd..c12ed3ae 100644 --- a/docs/src/markdown/about/changelog.md +++ b/docs/src/markdown/about/changelog.md @@ -2,8 +2,9 @@ ## 2.6 -- **NEW** Add support for `&` as scoping root per the CSS Nesting Module, Level 1. When `&` is used outside the +- **NEW**: Add support for `&` as scoping root per the CSS Nesting Module, Level 1. When `&` is used outside the context of nesting, it is treated as the scoping root (equivalent to `:scope`). +- **FIX**: Improve error message when an unrecognized pseudo-class is used. ## 2.5 diff --git a/soupsieve/css_parser.py b/soupsieve/css_parser.py index 85854b3d..bedae694 100644 --- a/soupsieve/css_parser.py +++ b/soupsieve/css_parser.py @@ -655,8 +655,11 @@ def parse_pseudo_class( m.start(0) ) else: - raise NotImplementedError( - f"'{pseudo}' pseudo-class is not implemented at this time" + raise SelectorSyntaxError( + f"'{pseudo}' was detected as a pseudo-class and is either unsupported or invalid. " + "If the syntax was not intended to be recognized as a pseudo-class, please escape the colon.", + self.pattern, + m.start(0) ) return has_selector, is_html diff --git a/tests/test_level1/test_pseudo_class.py b/tests/test_level1/test_pseudo_class.py index 63fbf717..661e6e6a 100644 --- a/tests/test_level1/test_pseudo_class.py +++ b/tests/test_level1/test_pseudo_class.py @@ -1,5 +1,6 @@ """Test general pseudo-class cases.""" from .. import util +from soupsieve import SelectorSyntaxError class TestPseudoClass(util.TestCase): @@ -8,9 +9,9 @@ class TestPseudoClass(util.TestCase): def test_pseudo_class_not_implemented(self): """Test pseudo-class that is not implemented.""" - self.assert_raises(':not-implemented', NotImplementedError) + self.assert_raises(':not-implemented', SelectorSyntaxError) def test_unrecognized_pseudo(self): """Test unrecognized pseudo class.""" - self.assert_raises(':before', NotImplementedError) + self.assert_raises(':before', SelectorSyntaxError)