Skip to content

Commit 21843dd

Browse files
committed
fix: resolve bare OSW ID type hints in generated Python code
When child schemas override inherited properties with only options (e.g. {"options": {"hidden": true}}), datamodel-code-generator uses the JSON schema file stem (OSW ID) instead of the schema title as the type name. This adds a post-processing step that builds a UUID-to-class mapping from generated class definitions and replaces bare OSW IDs.
1 parent 60fb976 commit 21843dd

2 files changed

Lines changed: 67 additions & 1 deletion

File tree

src/osw/core.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,10 @@
3939

4040
import osw.model.entity as model
4141
from osw.defaults import params as default_params
42-
from osw.utils.code_postprocessing import remove_constraints_from_forward_refs
42+
from osw.utils.code_postprocessing import (
43+
remove_constraints_from_forward_refs,
44+
resolve_osw_id_type_hints,
45+
)
4346
from osw.utils.oold import (
4447
AggregateGeneratedSchemasParam,
4548
AggregateGeneratedSchemasParamMode,
@@ -908,6 +911,11 @@ def _fetch_schema(
908911
content = all_content
909912

910913
if fetchSchemaParam.final:
914+
# Resolve bare OSW ID type hints (e.g. OSW3886...)
915+
# with actual class names (e.g. RiskAssessmentProcess)
916+
# using UUID annotations from generated class definitions
917+
content = resolve_osw_id_type_hints(content)
918+
911919
# Cleanup the combined content
912920
# find all "<cls>.update_forward_refs()" lines,
913921
# remove duplicates and put them to EOF

src/osw/utils/code_postprocessing.py

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,3 +44,61 @@ def replace_field(match):
4444
return match.group(0)
4545

4646
return re.sub(pattern, replace_field, src_code)
47+
48+
49+
def resolve_osw_id_type_hints(content: str) -> str:
50+
"""Replace bare OSW ID type hints with their actual class names.
51+
52+
When datamodel-code-generator processes child schemas that override inherited
53+
properties with only options (e.g. {"options": {"hidden": true}}), it may use
54+
the JSON schema file stem (an OSW ID like OSW3886740859ae459588fee73d3bb3c83e)
55+
instead of the schema title (e.g. RiskAssessmentProcess) as the type name.
56+
57+
This function builds a mapping from OSW IDs to class names by extracting UUIDs
58+
from class Config.schema_extra annotations in the generated code, then replaces
59+
any bare OSW ID references with the resolved class name.
60+
61+
Parameters
62+
----------
63+
content : str
64+
The generated Python source code (may contain multiple classes).
65+
66+
Returns
67+
-------
68+
str
69+
The source code with bare OSW ID type hints replaced by class names.
70+
"""
71+
# Build mapping: OSW ID -> class name from schema_extra uuid annotations
72+
# Each generated class has: class Foo(...): class Config: schema_extra = {"uuid": "..."}
73+
class_starts = list(re.finditer(r"^class\s+(\w+)\s*\(", content, re.MULTILINE))
74+
osw_id_to_class = {}
75+
for i, match in enumerate(class_starts):
76+
class_name = match.group(1)
77+
start = match.start()
78+
end = class_starts[i + 1].start() if i + 1 < len(class_starts) else len(content)
79+
class_block = content[start:end]
80+
uuid_match = re.search(
81+
r'"uuid":\s*"([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}'
82+
r"-[0-9a-f]{4}-[0-9a-f]{12})" + '"',
83+
class_block,
84+
)
85+
if uuid_match:
86+
osw_id = "OSW" + uuid_match.group(1).replace("-", "")
87+
osw_id_to_class[osw_id] = class_name
88+
89+
if not osw_id_to_class:
90+
return content
91+
92+
# Find bare OSW IDs used as identifiers (not inside "Category:OSW..." strings)
93+
bare_osw_pattern = re.compile(r"(?<![:\w])OSW[0-9a-f]{32}(?!\w)")
94+
unresolved = set(bare_osw_pattern.findall(content))
95+
96+
for osw_id in unresolved:
97+
if osw_id in osw_id_to_class:
98+
content = re.sub(
99+
r"(?<![:\w])" + re.escape(osw_id) + r"(?!\w)",
100+
osw_id_to_class[osw_id],
101+
content,
102+
)
103+
104+
return content

0 commit comments

Comments
 (0)