diff --git a/AGENTS.md b/AGENTS.md index d67458f..24b94c3 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -11,7 +11,7 @@ ## Build, Test, and Development Commands - Build workspace: `cargo build --workspace` - Run all tests: `cargo test --workspace` -- Format (check): `cargo fmt --all -- --check` | Fix: `cargo fmt --all` +- Format (check): `cargo +stable fmt --all -- --check` | Fix: `cargo +stable fmt --all` - Lint: `cargo clippy -p schemaview -p linkml_runtime -p linkml_tools -p linkml_runtime_python -p linkml_wasm --all-targets --all-features -- -D warnings --no-deps` (excludes autogenerated `linkml_meta`) - Run a CLI (example): - Validate: `cargo run -p linkml_tools --bin linkml-validate -- src/runtime/tests/data/schema.yaml Person src/runtime/tests/data/person_valid.yaml` diff --git a/src/metamodel/src/lib.rs b/src/metamodel/src/lib.rs index 25755e7..1a1e1d8 100644 --- a/src/metamodel/src/lib.rs +++ b/src/metamodel/src/lib.rs @@ -8200,176 +8200,176 @@ impl<'py> FromPyObject<'py> for Box { #[cfg_attr(feature = "pyo3", pyclass(subclass, get_all, set_all))] #[derive(Merge)] pub struct SlotDefinition { - #[merge(strategy = merge::option::overwrite_none)] + #[merge(strategy = overwrite_except_none)] #[cfg_attr(feature = "serde", serde(default))] pub singular_name: Option, - #[merge(strategy = merge::option::overwrite_none)] + #[merge(strategy = overwrite_except_none)] #[cfg_attr(feature = "serde", serde(default))] pub domain: Option, - #[merge(strategy = merge::option::overwrite_none)] + #[merge(strategy = overwrite_except_none)] #[cfg_attr(feature = "serde", serde(default))] pub slot_uri: Option, - #[merge(strategy = merge::option::overwrite_none)] + #[merge(strategy = overwrite_except_none)] #[cfg_attr(feature = "serde", serde(default))] pub array: Option, - #[merge(strategy = merge::option::overwrite_none)] + #[merge(strategy = overwrite_except_none)] #[cfg_attr(feature = "serde", serde(default))] pub inherited: Option, - #[merge(strategy = merge::option::overwrite_none)] + #[merge(strategy = overwrite_except_none)] #[cfg_attr(feature = "serde", serde(default))] pub readonly: Option, - #[merge(strategy = merge::option::overwrite_none)] + #[merge(strategy = overwrite_except_none)] #[cfg_attr(feature = "serde", serde(default))] pub ifabsent: Option, - #[merge(strategy = merge::option::overwrite_none)] + #[merge(strategy = overwrite_except_none)] #[cfg_attr(feature = "serde", serde(default))] pub list_elements_unique: Option, - #[merge(strategy = merge::option::overwrite_none)] + #[merge(strategy = overwrite_except_none)] #[cfg_attr(feature = "serde", serde(default))] pub list_elements_ordered: Option, - #[merge(strategy = merge::option::overwrite_none)] + #[merge(strategy = overwrite_except_none)] #[cfg_attr(feature = "serde", serde(default))] pub shared: Option, - #[merge(strategy = merge::option::overwrite_none)] + #[merge(strategy = overwrite_except_none)] #[cfg_attr(feature = "serde", serde(default))] pub key: Option, - #[merge(strategy = merge::option::overwrite_none)] + #[merge(strategy = overwrite_except_none)] #[cfg_attr(feature = "serde", serde(default))] pub identifier: Option, - #[merge(strategy = merge::option::overwrite_none)] + #[merge(strategy = overwrite_except_none)] #[cfg_attr(feature = "serde", serde(default))] pub designates_type: Option, - #[merge(strategy = merge::option::overwrite_none)] + #[merge(strategy = overwrite_except_none)] #[cfg_attr(feature = "serde", serde(default))] pub alias: Option, - #[merge(strategy = merge::option::overwrite_none)] + #[merge(strategy = overwrite_except_none)] #[cfg_attr(feature = "serde", serde(default))] pub owner: Option, - #[merge(strategy = merge::option::overwrite_none)] + #[merge(strategy = overwrite_except_none)] #[cfg_attr(feature = "serde", serde(default))] pub domain_of: Option>, - #[merge(strategy = merge::option::overwrite_none)] + #[merge(strategy = overwrite_except_none)] #[cfg_attr(feature = "serde", serde(default))] pub subproperty_of: Option, - #[merge(strategy = merge::option::overwrite_none)] + #[merge(strategy = overwrite_except_none)] #[cfg_attr(feature = "serde", serde(default))] pub symmetric: Option, - #[merge(strategy = merge::option::overwrite_none)] + #[merge(strategy = overwrite_except_none)] #[cfg_attr(feature = "serde", serde(default))] pub reflexive: Option, - #[merge(strategy = merge::option::overwrite_none)] + #[merge(strategy = overwrite_except_none)] #[cfg_attr(feature = "serde", serde(default))] pub locally_reflexive: Option, - #[merge(strategy = merge::option::overwrite_none)] + #[merge(strategy = overwrite_except_none)] #[cfg_attr(feature = "serde", serde(default))] pub irreflexive: Option, - #[merge(strategy = merge::option::overwrite_none)] + #[merge(strategy = overwrite_except_none)] #[cfg_attr(feature = "serde", serde(default))] pub asymmetric: Option, - #[merge(strategy = merge::option::overwrite_none)] + #[merge(strategy = overwrite_except_none)] #[cfg_attr(feature = "serde", serde(default))] pub transitive: Option, - #[merge(strategy = merge::option::overwrite_none)] + #[merge(strategy = overwrite_except_none)] #[cfg_attr(feature = "serde", serde(default))] pub inverse: Option, - #[merge(strategy = merge::option::overwrite_none)] + #[merge(strategy = overwrite_except_none)] #[cfg_attr(feature = "serde", serde(default))] pub is_class_field: Option, - #[merge(strategy = merge::option::overwrite_none)] + #[merge(strategy = overwrite_except_none)] #[cfg_attr(feature = "serde", serde(default))] pub transitive_form_of: Option, - #[merge(strategy = merge::option::overwrite_none)] + #[merge(strategy = overwrite_except_none)] #[cfg_attr(feature = "serde", serde(default))] pub reflexive_transitive_form_of: Option, - #[merge(strategy = merge::option::overwrite_none)] + #[merge(strategy = overwrite_except_none)] #[cfg_attr(feature = "serde", serde(default))] pub role: Option, - #[merge(strategy = merge::option::overwrite_none)] + #[merge(strategy = overwrite_except_none)] #[cfg_attr(feature = "serde", serde(default))] pub is_usage_slot: Option, - #[merge(strategy = merge::option::overwrite_none)] + #[merge(strategy = overwrite_except_none)] #[cfg_attr(feature = "serde", serde(default))] pub usage_slot_name: Option, - #[merge(strategy = merge::option::overwrite_none)] + #[merge(strategy = overwrite_except_none)] #[cfg_attr(feature = "serde", serde(default))] pub relational_role: Option, - #[merge(strategy = merge::option::overwrite_none)] + #[merge(strategy = overwrite_except_none)] #[cfg_attr(feature = "serde", serde(default))] pub slot_group: Option, - #[merge(strategy = merge::option::overwrite_none)] + #[merge(strategy = overwrite_except_none)] #[cfg_attr(feature = "serde", serde(default))] pub is_grouping_slot: Option, - #[merge(strategy = merge::option::overwrite_none)] + #[merge(strategy = overwrite_except_none)] #[cfg_attr(feature = "serde", serde(default))] pub path_rule: Option>, - #[merge(strategy = merge::option::overwrite_none)] + #[merge(strategy = overwrite_except_none)] #[cfg_attr(feature = "serde", serde(default))] pub disjoint_with: Option>, - #[merge(strategy = merge::option::overwrite_none)] + #[merge(strategy = overwrite_except_none)] #[cfg_attr(feature = "serde", serde(default))] pub children_are_mutually_disjoint: Option, - #[merge(strategy = merge::option::overwrite_none)] + #[merge(strategy = overwrite_except_none)] #[cfg_attr(feature = "serde", serde(default))] pub union_of: Option>, - #[merge(strategy = merge::option::overwrite_none)] + #[merge(strategy = overwrite_except_none)] #[cfg_attr( feature = "serde", serde(deserialize_with = "serde_utils::deserialize_inlined_dict_map_optional") )] #[cfg_attr(feature = "serde", serde(default))] pub type_mappings: Option>, - #[merge(strategy = merge::option::overwrite_none)] + #[merge(strategy = overwrite_except_none)] #[cfg_attr(feature = "serde", serde(default))] pub range: Option, - #[merge(strategy = merge::option::overwrite_none)] + #[merge(strategy = overwrite_except_none)] #[cfg_attr(feature = "serde", serde(default))] pub range_expression: Option>, - #[merge(strategy = merge::option::overwrite_none)] + #[merge(strategy = overwrite_except_none)] #[cfg_attr(feature = "serde", serde(default))] pub enum_range: Option, - #[merge(strategy = merge::option::overwrite_none)] + #[merge(strategy = overwrite_except_none)] #[cfg_attr(feature = "serde", serde(default))] pub bindings: Option>, - #[merge(strategy = merge::option::overwrite_none)] + #[merge(strategy = overwrite_except_none)] #[cfg_attr(feature = "serde", serde(default))] pub required: Option, - #[merge(strategy = merge::option::overwrite_none)] + #[merge(strategy = overwrite_except_none)] #[cfg_attr(feature = "serde", serde(default))] pub recommended: Option, - #[merge(strategy = merge::option::overwrite_none)] + #[merge(strategy = overwrite_except_none)] #[cfg_attr(feature = "serde", serde(default))] pub multivalued: Option, - #[merge(strategy = merge::option::overwrite_none)] + #[merge(strategy = overwrite_except_none)] #[cfg_attr(feature = "serde", serde(default))] pub inlined: Option, - #[merge(strategy = merge::option::overwrite_none)] + #[merge(strategy = overwrite_except_none)] #[cfg_attr(feature = "serde", serde(default))] pub inlined_as_list: Option, - #[merge(strategy = merge::option::overwrite_none)] + #[merge(strategy = overwrite_except_none)] #[cfg_attr(feature = "serde", serde(default))] pub minimum_value: Option, - #[merge(strategy = merge::option::overwrite_none)] + #[merge(strategy = overwrite_except_none)] #[cfg_attr(feature = "serde", serde(default))] pub maximum_value: Option, - #[merge(strategy = merge::option::overwrite_none)] + #[merge(strategy = overwrite_except_none)] #[cfg_attr(feature = "serde", serde(default))] pub pattern: Option, - #[merge(strategy = merge::option::overwrite_none)] + #[merge(strategy = overwrite_except_none)] #[cfg_attr(feature = "serde", serde(default))] pub structured_pattern: Option, - #[merge(strategy = merge::option::overwrite_none)] + #[merge(strategy = overwrite_except_none)] #[cfg_attr(feature = "serde", serde(default))] pub unit: Option, - #[merge(strategy = merge::option::overwrite_none)] + #[merge(strategy = overwrite_except_none)] #[cfg_attr(feature = "serde", serde(default))] pub implicit_prefix: Option, - #[merge(strategy = merge::option::overwrite_none)] + #[merge(strategy = overwrite_except_none)] #[cfg_attr(feature = "serde", serde(default))] pub value_presence: Option, - #[merge(strategy = merge::option::overwrite_none)] + #[merge(strategy = overwrite_except_none)] #[cfg_attr(feature = "serde", serde(default))] pub equals_string: Option, - #[merge(strategy = merge::option::overwrite_none)] + #[merge(strategy = overwrite_except_none)] #[cfg_attr( feature = "serde", serde( @@ -8378,56 +8378,56 @@ pub struct SlotDefinition { )] #[cfg_attr(feature = "serde", serde(default))] pub equals_string_in: Option>, - #[merge(strategy = merge::option::overwrite_none)] + #[merge(strategy = overwrite_except_none)] #[cfg_attr(feature = "serde", serde(default))] pub equals_number: Option, - #[merge(strategy = merge::option::overwrite_none)] + #[merge(strategy = overwrite_except_none)] #[cfg_attr(feature = "serde", serde(default))] pub equals_expression: Option, - #[merge(strategy = merge::option::overwrite_none)] + #[merge(strategy = overwrite_except_none)] #[cfg_attr(feature = "serde", serde(default))] pub exact_cardinality: Option, - #[merge(strategy = merge::option::overwrite_none)] + #[merge(strategy = overwrite_except_none)] #[cfg_attr(feature = "serde", serde(default))] pub minimum_cardinality: Option, - #[merge(strategy = merge::option::overwrite_none)] + #[merge(strategy = overwrite_except_none)] #[cfg_attr(feature = "serde", serde(default))] pub maximum_cardinality: Option, - #[merge(strategy = merge::option::overwrite_none)] + #[merge(strategy = overwrite_except_none)] #[cfg_attr(feature = "serde", serde(default))] pub has_member: Option>, - #[merge(strategy = merge::option::overwrite_none)] + #[merge(strategy = overwrite_except_none)] #[cfg_attr(feature = "serde", serde(default))] pub all_members: Option>, - #[merge(strategy = merge::option::overwrite_none)] + #[merge(strategy = overwrite_except_none)] #[cfg_attr(feature = "serde", serde(default))] pub none_of: Option>>, - #[merge(strategy = merge::option::overwrite_none)] + #[merge(strategy = overwrite_except_none)] #[cfg_attr(feature = "serde", serde(default))] pub exactly_one_of: Option>>, - #[merge(strategy = merge::option::overwrite_none)] + #[merge(strategy = overwrite_except_none)] #[cfg_attr(feature = "serde", serde(default))] pub any_of: Option>>, - #[merge(strategy = merge::option::overwrite_none)] + #[merge(strategy = overwrite_except_none)] #[cfg_attr(feature = "serde", serde(default))] pub all_of: Option>>, - #[merge(strategy = merge::option::overwrite_none)] + #[merge(strategy = overwrite_except_none)] #[cfg_attr(feature = "serde", serde(default))] pub is_a: Option, - #[merge(strategy = merge::option::overwrite_none)] + #[merge(strategy = overwrite_except_none)] #[cfg_attr(feature = "serde", serde(default))] #[cfg_attr(feature = "serde", serde(alias = "abstract"))] pub abstract_: Option, - #[merge(strategy = merge::option::overwrite_none)] + #[merge(strategy = overwrite_except_none)] #[cfg_attr(feature = "serde", serde(default))] pub mixin: Option, - #[merge(strategy = merge::option::overwrite_none)] + #[merge(strategy = overwrite_except_none)] #[cfg_attr(feature = "serde", serde(default))] pub mixins: Option>, - #[merge(strategy = merge::option::overwrite_none)] + #[merge(strategy = overwrite_except_none)] #[cfg_attr(feature = "serde", serde(default))] pub apply_to: Option>, - #[merge(strategy = merge::option::overwrite_none)] + #[merge(strategy = overwrite_except_none)] #[cfg_attr( feature = "serde", serde( @@ -8436,12 +8436,12 @@ pub struct SlotDefinition { )] #[cfg_attr(feature = "serde", serde(default))] pub values_from: Option>, - #[merge(strategy = merge::option::overwrite_none)] + #[merge(strategy = overwrite_except_none)] #[cfg_attr(feature = "serde", serde(default))] pub string_serialization: Option, #[merge(skip)] pub name: String, - #[merge(strategy = merge::option::overwrite_none)] + #[merge(strategy = overwrite_except_none)] #[cfg_attr( feature = "serde", serde( @@ -8450,23 +8450,23 @@ pub struct SlotDefinition { )] #[cfg_attr(feature = "serde", serde(default))] pub id_prefixes: Option>, - #[merge(strategy = merge::option::overwrite_none)] + #[merge(strategy = overwrite_except_none)] #[cfg_attr(feature = "serde", serde(default))] pub id_prefixes_are_closed: Option, - #[merge(strategy = merge::option::overwrite_none)] + #[merge(strategy = overwrite_except_none)] #[cfg_attr(feature = "serde", serde(default))] pub definition_uri: Option, - #[merge(strategy = merge::option::overwrite_none)] + #[merge(strategy = overwrite_except_none)] #[cfg_attr( feature = "serde", serde(deserialize_with = "serde_utils::deserialize_inlined_dict_map_optional") )] #[cfg_attr(feature = "serde", serde(default))] pub local_names: Option>, - #[merge(strategy = merge::option::overwrite_none)] + #[merge(strategy = overwrite_except_none)] #[cfg_attr(feature = "serde", serde(default))] pub conforms_to: Option, - #[merge(strategy = merge::option::overwrite_none)] + #[merge(strategy = overwrite_except_none)] #[cfg_attr( feature = "serde", serde( @@ -8475,7 +8475,7 @@ pub struct SlotDefinition { )] #[cfg_attr(feature = "serde", serde(default))] pub implements: Option>, - #[merge(strategy = merge::option::overwrite_none)] + #[merge(strategy = overwrite_except_none)] #[cfg_attr( feature = "serde", serde( @@ -8484,37 +8484,37 @@ pub struct SlotDefinition { )] #[cfg_attr(feature = "serde", serde(default))] pub instantiates: Option>, - #[merge(strategy = merge::option::overwrite_none)] + #[merge(strategy = overwrite_except_none)] #[cfg_attr( feature = "serde", serde(deserialize_with = "serde_utils::deserialize_inlined_dict_map_optional") )] #[cfg_attr(feature = "serde", serde(default))] pub extensions: Option>, - #[merge(strategy = merge::option::overwrite_none)] + #[merge(strategy = overwrite_except_none)] #[cfg_attr( feature = "serde", serde(deserialize_with = "serde_utils::deserialize_inlined_dict_map_optional") )] #[cfg_attr(feature = "serde", serde(default))] pub annotations: Option>, - #[merge(strategy = merge::option::overwrite_none)] + #[merge(strategy = overwrite_except_none)] #[cfg_attr(feature = "serde", serde(default))] pub description: Option, - #[merge(strategy = merge::option::overwrite_none)] + #[merge(strategy = overwrite_except_none)] #[cfg_attr( feature = "serde", serde(deserialize_with = "serde_utils::deserialize_inlined_dict_map_optional") )] #[cfg_attr(feature = "serde", serde(default))] pub alt_descriptions: Option>, - #[merge(strategy = merge::option::overwrite_none)] + #[merge(strategy = overwrite_except_none)] #[cfg_attr(feature = "serde", serde(default))] pub title: Option, - #[merge(strategy = merge::option::overwrite_none)] + #[merge(strategy = overwrite_except_none)] #[cfg_attr(feature = "serde", serde(default))] pub deprecated: Option, - #[merge(strategy = merge::option::overwrite_none)] + #[merge(strategy = overwrite_except_none)] #[cfg_attr( feature = "serde", serde( @@ -8523,7 +8523,7 @@ pub struct SlotDefinition { )] #[cfg_attr(feature = "serde", serde(default))] pub todos: Option>, - #[merge(strategy = merge::option::overwrite_none)] + #[merge(strategy = overwrite_except_none)] #[cfg_attr( feature = "serde", serde( @@ -8532,7 +8532,7 @@ pub struct SlotDefinition { )] #[cfg_attr(feature = "serde", serde(default))] pub notes: Option>, - #[merge(strategy = merge::option::overwrite_none)] + #[merge(strategy = overwrite_except_none)] #[cfg_attr( feature = "serde", serde( @@ -8541,25 +8541,25 @@ pub struct SlotDefinition { )] #[cfg_attr(feature = "serde", serde(default))] pub comments: Option>, - #[merge(strategy = merge::option::overwrite_none)] + #[merge(strategy = overwrite_except_none)] #[cfg_attr(feature = "serde", serde(default))] pub examples: Option>, - #[merge(strategy = merge::option::overwrite_none)] + #[merge(strategy = overwrite_except_none)] #[cfg_attr(feature = "serde", serde(default))] pub in_subset: Option>, - #[merge(strategy = merge::option::overwrite_none)] + #[merge(strategy = overwrite_except_none)] #[cfg_attr(feature = "serde", serde(default))] pub from_schema: Option, - #[merge(strategy = merge::option::overwrite_none)] + #[merge(strategy = overwrite_except_none)] #[cfg_attr(feature = "serde", serde(default))] pub imported_from: Option, - #[merge(strategy = merge::option::overwrite_none)] + #[merge(strategy = overwrite_except_none)] #[cfg_attr(feature = "serde", serde(default))] pub source: Option, - #[merge(strategy = merge::option::overwrite_none)] + #[merge(strategy = overwrite_except_none)] #[cfg_attr(feature = "serde", serde(default))] pub in_language: Option, - #[merge(strategy = merge::option::overwrite_none)] + #[merge(strategy = overwrite_except_none)] #[cfg_attr( feature = "serde", serde( @@ -8568,13 +8568,13 @@ pub struct SlotDefinition { )] #[cfg_attr(feature = "serde", serde(default))] pub see_also: Option>, - #[merge(strategy = merge::option::overwrite_none)] + #[merge(strategy = overwrite_except_none)] #[cfg_attr(feature = "serde", serde(default))] pub deprecated_element_has_exact_replacement: Option, - #[merge(strategy = merge::option::overwrite_none)] + #[merge(strategy = overwrite_except_none)] #[cfg_attr(feature = "serde", serde(default))] pub deprecated_element_has_possible_replacement: Option, - #[merge(strategy = merge::option::overwrite_none)] + #[merge(strategy = overwrite_except_none)] #[cfg_attr( feature = "serde", serde( @@ -8583,10 +8583,10 @@ pub struct SlotDefinition { )] #[cfg_attr(feature = "serde", serde(default))] pub aliases: Option>, - #[merge(strategy = merge::option::overwrite_none)] + #[merge(strategy = overwrite_except_none)] #[cfg_attr(feature = "serde", serde(default))] pub structured_aliases: Option>, - #[merge(strategy = merge::option::overwrite_none)] + #[merge(strategy = overwrite_except_none)] #[cfg_attr( feature = "serde", serde( @@ -8595,7 +8595,7 @@ pub struct SlotDefinition { )] #[cfg_attr(feature = "serde", serde(default))] pub mappings: Option>, - #[merge(strategy = merge::option::overwrite_none)] + #[merge(strategy = overwrite_except_none)] #[cfg_attr( feature = "serde", serde( @@ -8604,7 +8604,7 @@ pub struct SlotDefinition { )] #[cfg_attr(feature = "serde", serde(default))] pub exact_mappings: Option>, - #[merge(strategy = merge::option::overwrite_none)] + #[merge(strategy = overwrite_except_none)] #[cfg_attr( feature = "serde", serde( @@ -8613,7 +8613,7 @@ pub struct SlotDefinition { )] #[cfg_attr(feature = "serde", serde(default))] pub close_mappings: Option>, - #[merge(strategy = merge::option::overwrite_none)] + #[merge(strategy = overwrite_except_none)] #[cfg_attr( feature = "serde", serde( @@ -8622,7 +8622,7 @@ pub struct SlotDefinition { )] #[cfg_attr(feature = "serde", serde(default))] pub related_mappings: Option>, - #[merge(strategy = merge::option::overwrite_none)] + #[merge(strategy = overwrite_except_none)] #[cfg_attr( feature = "serde", serde( @@ -8631,7 +8631,7 @@ pub struct SlotDefinition { )] #[cfg_attr(feature = "serde", serde(default))] pub narrow_mappings: Option>, - #[merge(strategy = merge::option::overwrite_none)] + #[merge(strategy = overwrite_except_none)] #[cfg_attr( feature = "serde", serde( @@ -8640,10 +8640,10 @@ pub struct SlotDefinition { )] #[cfg_attr(feature = "serde", serde(default))] pub broad_mappings: Option>, - #[merge(strategy = merge::option::overwrite_none)] + #[merge(strategy = overwrite_except_none)] #[cfg_attr(feature = "serde", serde(default))] pub created_by: Option, - #[merge(strategy = merge::option::overwrite_none)] + #[merge(strategy = overwrite_except_none)] #[cfg_attr( feature = "serde", serde( @@ -8652,22 +8652,22 @@ pub struct SlotDefinition { )] #[cfg_attr(feature = "serde", serde(default))] pub contributors: Option>, - #[merge(strategy = merge::option::overwrite_none)] + #[merge(strategy = overwrite_except_none)] #[cfg_attr(feature = "serde", serde(default))] pub created_on: Option, - #[merge(strategy = merge::option::overwrite_none)] + #[merge(strategy = overwrite_except_none)] #[cfg_attr(feature = "serde", serde(default))] pub last_updated_on: Option, - #[merge(strategy = merge::option::overwrite_none)] + #[merge(strategy = overwrite_except_none)] #[cfg_attr(feature = "serde", serde(default))] pub modified_by: Option, - #[merge(strategy = merge::option::overwrite_none)] + #[merge(strategy = overwrite_except_none)] #[cfg_attr(feature = "serde", serde(default))] pub status: Option, - #[merge(strategy = merge::option::overwrite_none)] + #[merge(strategy = overwrite_except_none)] #[cfg_attr(feature = "serde", serde(default))] pub rank: Option, - #[merge(strategy = merge::option::overwrite_none)] + #[merge(strategy = overwrite_except_none)] #[cfg_attr( feature = "serde", serde( @@ -8676,7 +8676,7 @@ pub struct SlotDefinition { )] #[cfg_attr(feature = "serde", serde(default))] pub categories: Option>, - #[merge(strategy = merge::option::overwrite_none)] + #[merge(strategy = overwrite_except_none)] #[cfg_attr( feature = "serde", serde( @@ -12869,3 +12869,10 @@ impl serde_utils::InlinedPair for TypeMapping { } } } + +/// Overwrite `left` with `right` unless `right` is `None`. +fn overwrite_except_none(left: &mut Option, right: Option) { + if right.is_some() { + *left = right; + } +} diff --git a/src/schemaview/src/schemaview.rs b/src/schemaview/src/schemaview.rs index 4a59bfe..0728bbc 100644 --- a/src/schemaview/src/schemaview.rs +++ b/src/schemaview/src/schemaview.rs @@ -228,6 +228,12 @@ impl SchemaView { self.data.schema_definitions.iter() } + /// Returns a converter built from every schema loaded into this view. + /// + /// Note that prefix collisions across schemas will resolve to whichever + /// expansion appears last; avoid this helper if you expect conflicting + /// CURIE mappings and instead use `converter_for_schema` with a specific + /// schema URI. pub fn converter(&self) -> Converter { converter_from_schemas(self.data.schema_definitions.values()) } diff --git a/src/schemaview/src/slotview.rs b/src/schemaview/src/slotview.rs index d432a38..1d1c372 100644 --- a/src/schemaview/src/slotview.rs +++ b/src/schemaview/src/slotview.rs @@ -53,22 +53,32 @@ impl RangeInfo { e: &SlotExpressionOrSubtype, slotview: &SlotView, ) -> Option { - let conv = slotview.sv.converter_for_schema(&slotview.schema_uri)?; e.range().and_then(|r| { + if let Some(conv) = slotview.sv.converter_for_schema(&slotview.schema_uri) { + if let Ok(Some(cv)) = slotview.sv.get_class(&Identifier::new(r), conv) { + return Some(cv); + } + } + let conv = slotview.sv.converter(); slotview .sv - .get_class(&Identifier::new(r), conv) + .get_class(&Identifier::new(r), &conv) .ok() .flatten() }) } fn determine_range_enum(e: &SlotExpressionOrSubtype, slotview: &SlotView) -> Option { - let conv = slotview.sv.converter_for_schema(&slotview.schema_uri)?; e.range().and_then(|r| { + if let Some(conv) = slotview.sv.converter_for_schema(&slotview.schema_uri) { + if let Ok(Some(ev)) = slotview.sv.get_enum(&Identifier::new(r), conv) { + return Some(ev); + } + } + let conv = slotview.sv.converter(); slotview .sv - .get_enum(&Identifier::new(r), conv) + .get_enum(&Identifier::new(r), &conv) .ok() .flatten() }) diff --git a/src/schemaview/tests/data/slot_usage_base.yaml b/src/schemaview/tests/data/slot_usage_base.yaml new file mode 100644 index 0000000..3e71135 --- /dev/null +++ b/src/schemaview/tests/data/slot_usage_base.yaml @@ -0,0 +1,15 @@ +id: http://example.org/base +name: base +prefixes: + base: http://example.org/base/ +default_prefix: base +default_range: string + +classes: + BaseThing: + slots: + - shared_slot + +slots: + shared_slot: + range: string diff --git a/src/schemaview/tests/data/slot_usage_specialized.yaml b/src/schemaview/tests/data/slot_usage_specialized.yaml new file mode 100644 index 0000000..8d07a5c --- /dev/null +++ b/src/schemaview/tests/data/slot_usage_specialized.yaml @@ -0,0 +1,26 @@ +id: http://example.org/specialized +name: specialized +prefixes: + specialized: http://example.org/specialized/ + base: http://example.org/base/ +default_prefix: specialized +default_range: string +imports: + - http://example.org/base + +classes: + TargetClass: + slots: + - target_slot + + SpecializedThing: + is_a: base:BaseThing + slots: + - shared_slot + slot_usage: + shared_slot: + range: specialized:TargetClass + +slots: + target_slot: + range: string diff --git a/src/schemaview/tests/slot_view.rs b/src/schemaview/tests/slot_view.rs index 084f7be..de2c3f8 100644 --- a/src/schemaview/tests/slot_view.rs +++ b/src/schemaview/tests/slot_view.rs @@ -41,3 +41,47 @@ fn slot_lookup_and_class_slots() { assert_eq!(map.get("symbol"), Some(&1usize)); assert_eq!(map.get("exact mappings"), Some(&2usize)); } + +#[test] +fn slot_usage_overrides_range_across_schemas() { + let base_schema = from_yaml(Path::new(&data_path("slot_usage_base.yaml"))).unwrap(); + let specialized_schema = + from_yaml(Path::new(&data_path("slot_usage_specialized.yaml"))).unwrap(); + + let mut sv = SchemaView::new(); + sv.add_schema(base_schema.clone()).unwrap(); + sv.add_schema(specialized_schema.clone()).unwrap(); + + let conv = converter_from_schemas([&base_schema, &specialized_schema]); + + let base_class = sv + .get_class(&Identifier::new("base:BaseThing"), &conv) + .unwrap() + .unwrap(); + let base_slot = base_class + .slots() + .iter() + .find(|s| s.name == "shared_slot") + .expect("shared_slot not found"); + + assert_eq!(base_slot.definition().range.as_deref(), Some("string")); + + let class = sv + .get_class(&Identifier::new("specialized:SpecializedThing"), &conv) + .unwrap() + .unwrap(); + let slot = class + .slots() + .iter() + .find(|s| s.name == "shared_slot") + .expect("shared_slot not found"); + + assert_eq!( + slot.definition().range.as_deref(), + Some("specialized:TargetClass") + ); + assert_eq!( + slot.get_range_class().map(|cv| cv.name().to_string()), + Some("TargetClass".to_string()) + ); +}