Exercise 3: A Full Compound Selector, Tag Mismatch Only — Possible Solution ==================================================================== THE TEST ------------------------------ target =
target2 = (identical id/class, wrong tag)
sel = parse_selector("p#main.highlight")
matches_selector(target, sel)
matches_selector(target2, sel)
RESULT
------------------------------
target -> True
target2 -> False
WHICH CHECK IS RESPONSIBLE
------------------------------
parse_selector("p#main.highlight") produces a SINGLE SimpleSelector
(no spaces in the string, so it's a one-part Selector) with all three
fields set at once: tag='p', id='main', classes={'highlight'}.
matches_simple runs its three checks in order:
if simple.tag is not None and element.tag != simple.tag:
return False
if simple.id is not None:
if element.attrs.get('id') != simple.id:
return False
if simple.classes:
elem_classes = set(element.attrs.get('class', '').split())
if not simple.classes.issubset(elem_classes):
return False
return True
For target (a ), the tag check passes (element.tag == 'p' ==
simple.tag), the id check passes ('main' == 'main'), and the class
check passes ('highlight' is a subset of {'highlight'}) -- all three
survive, so the function falls through to `return True`.
For target2 (a ), the VERY FIRST check is what fails:
element.tag is 'span', simple.tag is 'p', they don't match, and the
function returns False immediately -- via `return False` on line one
of the function body. The id and class checks are never even reached;
Python's short-circuiting `if` never gets past the first failing
condition to evaluate the rest.
WHY THIS WORKS AS AN ANSWER
------------------------------
Because all three checks in matches_simple are independent early-exit
guards (each one only ever returns False and moves on, never True),
a compound selector effectively behaves like a logical AND across all
of its parts -- EVERY check has to pass for the function to reach its
final `return True` at the bottom. Here, target2 fails at the very
first guard (the tag check) despite satisfying both of the other two
-- proving that a compound selector isn't "mostly satisfied" by
matching two out of three attributes; a single mismatched part is
enough to reject the whole selector, exactly like a real CSS compound
selector such as `p#main.highlight` requires every one of its parts
to hold on the same element at once.