Exercise 2: Two Different Inherited Properties From Two Different Ancestors — Possible Solution ==================================================================== THE TEST ------------------------------ gp (id="gp") -> mid (id="mid") -> leaf (no rule) rule_gp = Rule(['#gp'], [Declaration('color', 'red')]) rule_mid = Rule(['#mid'], [Declaration('font-weight', 'bold')]) sheet = Stylesheet([rule_gp, rule_mid]) compute_style_tree(gp, sheet) leaf.computed_style['color'] leaf.computed_style['font-weight'] RESULT ------------------------------ leaf.computed_style['color'] -> 'red' leaf.computed_style['font-weight'] -> 'bold' Both inherited values reach the leaf correctly, despite being set on two entirely different ancestors, two levels apart from each other. WHY BOTH VALUES ARRIVE CORRECTLY, INDEPENDENTLY ------------------------------ compute_style_tree walks top-down, and at every level it builds that element's OWN full computed_style by merging the parent's already- computed style with its own cascade() result: gp: own cascade = {'color': 'red'} parent_computed = None -> gp.computed_style = INITIAL_VALUES + {'color': 'red'} (font-weight stays at the initial 'normal' here) mid: own cascade = {'font-weight': 'bold'} parent_computed = gp.computed_style (has color='red') -> mid.computed_style starts from INITIAL_VALUES, inherits color='red' from gp's computed style (color IS inheritable), then own.update() applies font-weight='bold' from mid's OWN rule -> mid ends up with BOTH color='red' (inherited) AND font-weight='bold' (its own rule) -- two properties, two different sources, merged into one dict leaf: own cascade = {} (no rule matches leaf at all) parent_computed = mid.computed_style (has BOTH color='red' AND font-weight='bold' already merged in) -> leaf inherits every inheritable property present in mid.computed_style, which by this point already includes mid's own inherited color as well as mid's own directly-set font-weight Because each level's computed_style is a SINGLE merged dict handed down as one unit -- not two separate "color chain" and "font-weight chain" trackers -- inheritance for every property rides along together in the same downward pass, regardless of which specific ancestor originally introduced which specific property. WHY THIS WORKS AS AN ANSWER ------------------------------ This confirms compute_style_tree's own top-down design handles the general case, not just the single-property case shown in the chapter body. Nothing about the algorithm has to know in advance which properties will be set where -- every inheritable property that ends up in ANY ancestor's computed_style, however it got there, is automatically available to every descendant below it, because each step only ever needs its own immediate parent's already-complete computed_style, never the whole ancestor chain re-walked from scratch.