@@ -1545,14 +1545,58 @@ def expose_account_reference_union_fields() -> None:
15451545 request, nested-input, response, and canonical-clone paths all expose the
15461546 same concrete arm types without import-time Pydantic patching.
15471547 """
1548- pattern = re .compile (r"\b(account_ref(?:_\d+)?)\.AccountReference\b(?![12])" )
1548+ account_ref_source = OUTPUT_DIR / "core" / "account_ref.py"
1549+ if not account_ref_source .exists ():
1550+ print (" account reference model not found (skipping union-field fix)" )
1551+ return
1552+
1553+ tree = ast .parse (account_ref_source .read_text ())
1554+ wrapper = next (
1555+ (
1556+ node
1557+ for node in tree .body
1558+ if isinstance (node , ast .ClassDef ) and node .name == "AccountReference"
1559+ ),
1560+ None ,
1561+ )
1562+ if wrapper is None :
1563+ raise RuntimeError ("generated account_ref.py has no AccountReference wrapper" )
1564+
1565+ root_base = next (
1566+ (
1567+ base
1568+ for base in wrapper .bases
1569+ if isinstance (base , ast .Subscript )
1570+ and isinstance (base .value , ast .Name )
1571+ and base .value .id == "RootModel"
1572+ ),
1573+ None ,
1574+ )
1575+ if root_base is None :
1576+ raise RuntimeError ("generated AccountReference has no RootModel union base" )
1577+
1578+ def union_arm_names (node : ast .expr ) -> list [str ]:
1579+ if isinstance (node , ast .BinOp ) and isinstance (node .op , ast .BitOr ):
1580+ return [* union_arm_names (node .left ), * union_arm_names (node .right )]
1581+ if isinstance (node , ast .Name ):
1582+ return [node .id ]
1583+ raise RuntimeError (
1584+ "generated AccountReference has an unsupported union expression: "
1585+ f"{ ast .unparse (node )} "
1586+ )
1587+
1588+ arm_names = union_arm_names (root_base .slice )
1589+ if len (arm_names ) < 2 or len (set (arm_names )) != len (arm_names ):
1590+ raise RuntimeError (f"generated AccountReference has invalid union arms: { arm_names !r} " )
1591+
1592+ pattern = re .compile (r"\b(account_ref(?:_\d+)?)\.AccountReference\b(?!\d)" )
15491593 total_files = 0
15501594 total_fields = 0
15511595
15521596 for py_file in sorted (OUTPUT_DIR .rglob ("*.py" )):
15531597 source = py_file .read_text ()
15541598 fixed , replacements = pattern .subn (
1555- r"\1.AccountReference1 | \1.AccountReference2" ,
1599+ lambda match : " | " . join ( f" { match . group ( 1 ) } . { arm_name } " for arm_name in arm_names ) ,
15561600 source ,
15571601 )
15581602 if not replacements :
0 commit comments