Exercise 2: display:none on the Root Node Itself — Possible Solution ==================================================================== THE TEST ------------------------------ root_hidden = Element('div', {'id': 'roothidden'}) root_hidden.children = [Element('p', {})] assign_parents(root_hidden) rule = Rule(['#roothidden'], [Declaration('display', 'none')]) sheet = Stylesheet([rule]) build_style_tree(root_hidden, sheet) # called DIRECTLY, not as a child RESULT ------------------------------ None WHY THIS IS THE CORRECT RESULT ------------------------------ build_style_tree computes root_hidden's own style via compute_style(), which resolves display to 'none' (the rule matches directly). The very next line is: if style.get('display') == 'none': return None This check runs unconditionally, every single time build_style_tree processes an element -- it has no way to know or care whether it's being called as the top-level entry point of the whole walk or as a recursive call from inside some parent's own loop over its children. The function's own signature and body are identical in both situations; there is no separate "am I the root" parameter anywhere. WHY THIS HAS TO BE THE SAME RESULT EITHER WAY ------------------------------ If display:none were only ever checked from INSIDE a parent's loop -- i.e., if the check lived in the calling code ("skip this child if its own style says display:none") rather than inside build_style_tree itself -- then calling build_style_tree directly on a hidden element would skip that check entirely, since there'd be no parent loop around it to enforce the rule. That would make the function's behavior depend on HOW it's invoked rather than on the actual computed style of the node it was given -- a hidden element would only stay hidden if you happened to reach it "the normal way," through its own parent, but calling build_style_tree on it directly (exactly as this exercise does) would produce a different, wrong answer: a real StyledNode, complete with a
child, for an element that's supposed to produce no box at all. WHY THIS WORKS AS AN ANSWER ------------------------------ Putting the display:none check INSIDE build_style_tree itself, right after computing that node's own style, guarantees the function gives the same answer for the same input regardless of who's calling it or from where -- a genuinely important property for a function that's called recursively on itself. The chapter's own Test 4 (a div containing a visible and a hidden sibling) exercises this same check from inside a parent's loop; this exercise exercises the identical check from the top level, and because the check lives in the callee rather than the caller, both paths are guaranteed to agree.