|
39 | 39 | from pyld import jsonld |
40 | 40 |
|
41 | 41 | import osw.model.entity as model |
| 42 | + |
| 43 | +try: |
| 44 | + # Characteristics of the released opensemantic packages derive from this |
| 45 | + # class, not from the one in osw.model.entity. |
| 46 | + from opensemantic.core.v1 import ( |
| 47 | + CharacteristicType as _OpensemanticCharacteristicType, |
| 48 | + ) |
| 49 | +except ImportError: # pragma: no cover - optional dependency |
| 50 | + _OpensemanticCharacteristicType = None |
42 | 51 | from osw.defaults import params as default_params |
43 | 52 | from osw.utils.code_postprocessing import ( |
44 | 53 | remove_constraints_from_forward_refs, |
@@ -476,7 +485,29 @@ def register_schema(self, schema_registration: SchemaRegistration): |
476 | 485 | else: |
477 | 486 | result_array.append(subschema) |
478 | 487 | match.full_path.update_or_create(schema, result_array) |
479 | | - if "definitions" in schema: |
| 488 | + |
| 489 | + all_refs_resolved = True |
| 490 | + bare_ref_jsonpath_expr = parse("$..dollarref") |
| 491 | + # pydantic only wraps a $ref in allOf when the field carries extra |
| 492 | + # metadata (e.g. Field(description=...)). A plain nested-model |
| 493 | + # field produces a bare {"$ref": ...} that is not reachable via |
| 494 | + # the "$..allOf" jsonpath above, so replace those local |
| 495 | + # definitions (#/definitions/...) with embedded definitions too, |
| 496 | + # to prevent a dangling ref once "definitions" is removed below |
| 497 | + for match in bare_ref_jsonpath_expr.find(schema): |
| 498 | + value = match.value |
| 499 | + if value.startswith("#"): |
| 500 | + definition_jsonpath_expr = parse( |
| 501 | + value.replace("#", "$").replace("/", ".") |
| 502 | + ) |
| 503 | + def_matches = definition_jsonpath_expr.find(schema) |
| 504 | + for def_match in def_matches: |
| 505 | + match.context.full_path.update_or_create( |
| 506 | + schema, def_match.value |
| 507 | + ) |
| 508 | + if not def_matches: |
| 509 | + all_refs_resolved = False |
| 510 | + if "definitions" in schema and all_refs_resolved: |
480 | 511 | del schema["definitions"] |
481 | 512 |
|
482 | 513 | if "allOf" not in schema: |
@@ -1788,12 +1819,15 @@ def __init__(self, **data): |
1788 | 1819 | if self.change_id is None: |
1789 | 1820 | self.change_id = str(uuid4()) |
1790 | 1821 | for entity in self.entities: |
1791 | | - if getattr(entity, "meta", None) is None: |
1792 | | - entity.meta = model.Meta() |
1793 | | - if entity.meta.change_id is None: |
1794 | | - entity.meta.change_id = [] |
1795 | | - if self.change_id not in entity.meta.change_id: |
1796 | | - entity.meta.change_id.append(self.change_id) |
| 1822 | + try: |
| 1823 | + if getattr(entity, "meta", None) is None: |
| 1824 | + entity.meta = model.Meta() |
| 1825 | + if entity.meta.change_id is None: |
| 1826 | + entity.meta.change_id = [] |
| 1827 | + if self.change_id not in entity.meta.change_id: |
| 1828 | + entity.meta.change_id.append(self.change_id) |
| 1829 | + except (ValueError, AttributeError): |
| 1830 | + pass # entity model doesn't have meta field |
1797 | 1831 | if len(self.entities) > 5 and self.parallel is None: |
1798 | 1832 | self.parallel = True |
1799 | 1833 | if self.parallel is None: |
@@ -2058,10 +2092,18 @@ def store_entity_( |
2058 | 2092 |
|
2059 | 2093 | mode = AggregateGeneratedSchemasParamMode.ROOT_LEVEL |
2060 | 2094 | # Put generated schema in definitions section, |
2061 | | - # currently only enabled for Characteristics |
2062 | | - if hasattr(model, "CharacteristicType") and isinstance( |
2063 | | - entity_, model.CharacteristicType |
2064 | | - ): |
| 2095 | + # currently only enabled for Characteristics. The class is |
| 2096 | + # either the locally generated one or the one shipped by the |
| 2097 | + # opensemantic packages, depending on where the model is from. |
| 2098 | + characteristic_types = tuple( |
| 2099 | + t |
| 2100 | + for t in ( |
| 2101 | + getattr(model, "CharacteristicType", None), |
| 2102 | + _OpensemanticCharacteristicType, |
| 2103 | + ) |
| 2104 | + if t is not None |
| 2105 | + ) |
| 2106 | + if characteristic_types and isinstance(entity_, characteristic_types): |
2065 | 2107 | mode = AggregateGeneratedSchemasParamMode.DEFINITIONS_SECTION |
2066 | 2108 |
|
2067 | 2109 | new_schema = aggregate_generated_schemas( |
|
0 commit comments