Cross-check rule-declared UE enum members against the actual hand enums AND against MuJoCo's mjt* enums.
(
schema: Dict[str, Any],
rules: Dict[str, Any],
mjspec: Optional[Dict[str, Any]],
public_root: str,
)
| 91 | |
| 92 | |
| 93 | def _check_hand_enum_drift( |
| 94 | schema: Dict[str, Any], |
| 95 | rules: Dict[str, Any], |
| 96 | mjspec: Optional[Dict[str, Any]], |
| 97 | public_root: str, |
| 98 | ) -> None: |
| 99 | """Cross-check rule-declared UE enum members against the actual |
| 100 | hand enums AND against MuJoCo's mjt* enums.""" |
| 101 | hand_enums = _hand_enums_from_snapshot(mjspec) |
| 102 | if not hand_enums: |
| 103 | hand_enums = _scan_hand_enums(public_root) |
| 104 | if not hand_enums: |
| 105 | return |
| 106 | |
| 107 | for cat_name, cat_rules in rules.get("categories", {}).items(): |
| 108 | type_enum = cat_rules.get("type_enum_name") |
| 109 | if not type_enum or type_enum not in hand_enums: |
| 110 | continue |
| 111 | members = set(hand_enums[type_enum]) |
| 112 | for sub in cat_rules.get("subtypes", []): |
| 113 | ev = sub.get("enum_value") |
| 114 | if ev and ev not in members: |
| 115 | _diag_add( |
| 116 | f"[diagnostic] category '{cat_name}' subtype '{sub.get('key')}' " |
| 117 | f"references enum_value '{type_enum}::{ev}' that does not " |
| 118 | f"exist in {type_enum} members {sorted(members)}.", |
| 119 | source="hand_enum_drift", |
| 120 | ) |
| 121 | |
| 122 | element_rules = rules.get("element_rules", {}) |
| 123 | mjspec_enums = (mjspec or {}).get("enums", {}) |
| 124 | intentional_skips = rules.get("intentionally_unmapped_mj_enum_values", {}) |
| 125 | for elem, elem_rules in element_rules.items(): |
| 126 | for attr, enum_def in elem_rules.get("xml_enum_attrs", {}).items(): |
| 127 | ue_enum_type = enum_def.get("ue_enum_type") or enum_def.get("ue_enum") |
| 128 | value_map = enum_def.get("value_map", {}) |
| 129 | if not ue_enum_type or ue_enum_type not in hand_enums: |
| 130 | continue |
| 131 | members = set(hand_enums[ue_enum_type]) |
| 132 | for xml_val, mapping in value_map.items(): |
| 133 | pair = _value_map_pair(mapping) |
| 134 | if pair is None: |
| 135 | continue |
| 136 | ue_member, _ = pair |
| 137 | if ue_member not in members: |
| 138 | _diag_add( |
| 139 | f"[diagnostic] element '{elem}' xml_enum '{attr}' " |
| 140 | f"value_map entry '{xml_val}' maps to " |
| 141 | f"'{ue_enum_type}::{ue_member}' that does not exist " |
| 142 | f"in members {sorted(members)}.", |
| 143 | source="hand_enum_drift", |
| 144 | ) |
| 145 | from_mj_enum = enum_def.get("from_mj_enum") |
| 146 | if not from_mj_enum: |
| 147 | mjs_cast = enum_def.get("mjs_cast", "") |
| 148 | if mjs_cast.startswith("mjt"): |
| 149 | from_mj_enum = mjs_cast |
| 150 | if from_mj_enum and from_mj_enum in mjspec_enums: |
no test coverage detected