def extend_and_specialize(items, loader):<EOL>
items = deepcopy_strip(items)<EOL>types = {i["<STR_LIT:name>"]: i for i in items}  <EOL>results = []<EOL>for stype in items:<EOL><INDENT>if "<STR_LIT>" in stype:<EOL><INDENT>specs = {}  <EOL>if "<STR_LIT>" in stype:<EOL><INDENT>for spec in aslist(stype["<STR_LIT>"]):<EOL><INDENT>specs[spec["<STR_LIT>"]] = spec["<STR_LIT>"]<EOL><DEDENT><DEDENT>exfields = []  <EOL>exsym = []  <EOL>for ex in aslist(stype["<STR_LIT>"]):<EOL><INDENT>if ex not in types:<EOL><INDENT>raise Exception(<EOL>"<STR_LIT>".format(<EOL>stype["<STR_LIT>"], stype["<STR_LIT:name>"]))<EOL><DEDENT>basetype = copy.copy(types[ex])<EOL>if stype["<STR_LIT:type>"] == "<STR_LIT>":<EOL><INDENT>if specs:<EOL><INDENT>basetype["<STR_LIT>"] = replace_type(<EOL>basetype.get("<STR_LIT>", []), specs, loader, set())<EOL><DEDENT>for field in basetype.get("<STR_LIT>", []):<EOL><INDENT>if "<STR_LIT>" not in field:<EOL><INDENT>field["<STR_LIT>"] = ex<EOL><DEDENT><DEDENT>exfields.extend(basetype.get("<STR_LIT>", []))<EOL><DEDENT>elif stype["<STR_LIT:type>"] == "<STR_LIT>":<EOL><INDENT>exsym.extend(basetype.get("<STR_LIT>", []))<EOL><DEDENT><DEDENT>if stype["<STR_LIT:type>"] == "<STR_LIT>":<EOL><INDENT>stype = copy.copy(stype)<EOL>exfields.extend(stype.get("<STR_LIT>", []))<EOL>stype["<STR_LIT>"] = exfields<EOL>fieldnames = set()  <EOL>for field in stype["<STR_LIT>"]:<EOL><INDENT>if field["<STR_LIT:name>"] in fieldnames:<EOL><INDENT>raise validate.ValidationException(<EOL>"<STR_LIT>".format(<EOL>field["<STR_LIT:name>"], stype["<STR_LIT:name>"]))<EOL><DEDENT>else:<EOL><INDENT>fieldnames.add(field["<STR_LIT:name>"])<EOL><DEDENT><DEDENT><DEDENT>elif stype["<STR_LIT:type>"] == "<STR_LIT>":<EOL><INDENT>stype = copy.copy(stype)<EOL>exsym.extend(stype.get("<STR_LIT>", []))<EOL>stype["<STR_LIT>"] = exsym<EOL><DEDENT>types[stype["<STR_LIT:name>"]] = stype<EOL><DEDENT>results.append(stype)<EOL><DEDENT>ex_types = {}<EOL>for result in results:<EOL><INDENT>ex_types[result["<STR_LIT:name>"]] = result<EOL><DEDENT>extended_by = {}  <EOL>for result in results:<EOL><INDENT>if "<STR_LIT>" in result:<EOL><INDENT>for ex in aslist(result["<STR_LIT>"]):<EOL><INDENT>if ex_types[ex].get("<STR_LIT>"):<EOL><INDENT>add_dictlist(extended_by, ex, ex_types[result["<STR_LIT:name>"]])<EOL>add_dictlist(extended_by, avro_name(ex), ex_types[ex])<EOL><DEDENT><DEDENT><DEDENT><DEDENT>for result in results:<EOL><INDENT>if result.get("<STR_LIT>") and result["<STR_LIT:name>"] not in extended_by:<EOL><INDENT>raise validate.ValidationException(<EOL>"<STR_LIT>".format(<EOL>result["<STR_LIT:name>"]))<EOL><DEDENT><DEDENT>for result in results:<EOL><INDENT>if "<STR_LIT>" in result:<EOL><INDENT>result["<STR_LIT>"] = replace_type(<EOL>result["<STR_LIT>"], extended_by, loader, set())<EOL><DEDENT><DEDENT>return results<EOL>
Apply 'extend' and 'specialize' to fully materialize derived record types.