Conversion: CSS selectors with unknown pseudo-elements should not match any tags. See #1827700 (Private bug)

This commit is contained in:
Kovid Goyal 2019-11-07 14:15:46 +05:30
parent f6087f7929
commit fe066ce2d6
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C

View File

@ -13,7 +13,7 @@ from itertools import chain
from lxml import etree from lxml import etree
from css_selectors.errors import ExpressionError from css_selectors.errors import ExpressionError
from css_selectors.parser import parse, ascii_lower, Element from css_selectors.parser import parse, ascii_lower, Element, FunctionalPseudoElement
from css_selectors.ordered_set import OrderedSet from css_selectors.ordered_set import OrderedSet
from polyglot.builtins import iteritems, itervalues from polyglot.builtins import iteritems, itervalues
@ -182,8 +182,7 @@ class Select(object):
seen = set() seen = set()
if root is not None: if root is not None:
root = frozenset(self.itertag(root)) root = frozenset(self.itertag(root))
for selector in get_parsed_selector(selector): for parsed_selector in get_parsed_selector(selector):
parsed_selector = selector.parsed_tree
for item in self.iterparsedselector(parsed_selector): for item in self.iterparsedselector(parsed_selector):
if item not in seen and (root is None or item in root): if item not in seen and (root is None or item in root):
yield item yield item
@ -581,31 +580,54 @@ def allow_all(cache, item):
return True return True
def select_pseudo(cache, pseudo): def get_func_for_pseudo(cache, ident):
try: try:
func = cache.dispatch_map[pseudo.ident.replace('-', '_')] func = cache.dispatch_map[ident.replace('-', '_')]
except KeyError: except KeyError:
if pseudo.ident == 'root': if ident in cache.ignore_inappropriate_pseudo_classes:
yield cache.root
return
if pseudo.ident in cache.ignore_inappropriate_pseudo_classes:
func = allow_all func = allow_all
else: else:
raise ExpressionError( raise ExpressionError(
"The pseudo-class :%s is not supported" % pseudo.ident) "The pseudo-class :%s is not supported" % ident)
try: try:
func.is_pseudo func.is_pseudo
except AttributeError: except AttributeError:
raise ExpressionError( raise ExpressionError(
"The pseudo-class :%s is invalid" % pseudo.ident) "The pseudo-class :%s is invalid" % ident)
return func
def select_selector(cache, selector):
if selector.pseudo_element is None:
for item in cache.iterparsedselector(selector.parsed_tree):
yield item
return
if isinstance(selector.pseudo_element, FunctionalPseudoElement):
raise ExpressionError(
"The pseudo-element ::%s is not supported" % selector.pseudo_element.name)
func = get_func_for_pseudo(cache, selector.pseudo_element)
for item in cache.iterparsedselector(selector.parsed_tree):
if func(cache, item):
yield item
def select_pseudo(cache, pseudo):
func = get_func_for_pseudo(cache, pseudo.ident)
if func is select_root:
yield cache.root
return
for item in cache.iterparsedselector(pseudo.selector): for item in cache.iterparsedselector(pseudo.selector):
if func(cache, item): if func(cache, item):
yield item yield item
@pseudo_func
def select_root(cache, elem):
return elem is cache.root
@pseudo_func @pseudo_func
def select_first_child(cache, elem): def select_first_child(cache, elem):
try: try: