From 41fa15163174fadc0c3a33762b13e27851047a0c Mon Sep 17 00:00:00 2001 From: BipedalBit Date: Sat, 7 Jun 2025 01:18:47 +0800 Subject: [PATCH] fix: return to break loop of $ref in schema, avoid some case of Custom-field-not-found exception. --- src/mcpo/tests/__init__.py | 0 src/mcpo/tests/test_main.py | 15 +++++++++++++++ src/mcpo/utils/main.py | 13 +++++++++++++ 3 files changed, 28 insertions(+) create mode 100644 src/mcpo/tests/__init__.py diff --git a/src/mcpo/tests/__init__.py b/src/mcpo/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/mcpo/tests/test_main.py b/src/mcpo/tests/test_main.py index a7cfe5f..9f46ab6 100644 --- a/src/mcpo/tests/test_main.py +++ b/src/mcpo/tests/test_main.py @@ -310,3 +310,18 @@ def test_multi_type_property_with_any_of(): # assert result_field parameter config assert result_field.description == "A property with multiple types" + + +def test_ref_to_parent_node(): + schema = {'$ref': '#/properties/data/properties/children/items'} + result_type, result_field = _process_schema_property( + _model_cache, + schema, + "generate_fishbone_diagram_form_model_data_model_children_item_model_children", + "item", + False, + {} + ) + + assert result_type == Any + assert result_field.description == "" \ No newline at end of file diff --git a/src/mcpo/utils/main.py b/src/mcpo/utils/main.py index 49fc257..8799c5c 100644 --- a/src/mcpo/utils/main.py +++ b/src/mcpo/utils/main.py @@ -93,6 +93,19 @@ def _process_schema_property( """ if "$ref" in prop_schema: ref = prop_schema["$ref"] + if ref.startswith("#/properties/"): + # Remove common prefix in pathes. + prefix_path = model_name_prefix.split("_form_model_")[-1] + ref_path = ref.split("#/properties/")[-1] + # Translate $ref path to model_name_prefix style. + ref_path = ref_path.replace("/properties/", "_model_") + ref_path = ref_path.replace("/items", "_item") + # If $ref path is a prefix substring of model_name_prefix path, + # there exists a circular reference. + # The loop should be broke with a return to avoid exception. + if prefix_path.startswith(ref_path): + # TODO: Find the exact type hint for the $ref. + return Any, Field(default=None, description="") ref = ref.split("/")[-1] assert ref in schema_defs, "Custom field not found" prop_schema = schema_defs[ref]