diff --git a/linkml_runtime/utils/schema_builder.py b/linkml_runtime/utils/schema_builder.py index b7d6024b..9544a09f 100644 --- a/linkml_runtime/utils/schema_builder.py +++ b/linkml_runtime/utils/schema_builder.py @@ -179,6 +179,12 @@ def add_enum( if permissible_values is None: permissible_values = [] + # Validate kwargs - all keys must be valid EnumDefinition fields + valid_fields = {f.name for f in fields(EnumDefinition)} + invalid_kwargs = set(kwargs.keys()) - valid_fields + if invalid_kwargs: + raise ValueError(f"Invalid kwargs for EnumDefinition: {', '.join(invalid_kwargs)}") + if isinstance(enum_def, str): enum_def = EnumDefinition(enum_def, **kwargs) elif isinstance(enum_def, dict): @@ -191,6 +197,8 @@ def add_enum( f"not {type(enum_def)!r}" ) raise TypeError(msg) + + # No need to apply kwargs to existing EnumDefinition object if enum_def.name in self.schema.enums and not replace_if_present: raise ValueError(f"Enum {enum_def.name} already exists") diff --git a/linkml_runtime/utils/schemaview.py b/linkml_runtime/utils/schemaview.py index bc76bcaa..8d011084 100644 --- a/linkml_runtime/utils/schemaview.py +++ b/linkml_runtime/utils/schemaview.py @@ -15,7 +15,7 @@ from linkml_runtime.utils.namespaces import Namespaces from deprecated.classic import deprecated from linkml_runtime.utils.context_utils import parse_import_map, map_import -from linkml_runtime.utils.formatutils import is_empty, underscore, camelcase +from linkml_runtime.utils.formatutils import camelcase, is_empty, sfx, underscore from linkml_runtime.utils.pattern import PatternResolver from linkml_runtime.linkml_model.meta import * from linkml_runtime.exceptions import OrderingError @@ -1121,13 +1121,18 @@ def get_uri(self, element: Union[ElementName, Element], imports=True, expand=Fal raise ValueError(f'Cannot find {e.from_schema} in schema_map') else: schema = self.schema_map[self.in_schema(e.name)] - pfx = schema.default_prefix if use_element_type: e_type = e.class_name.split("_",1)[0] # for example "class_definition" e_type_path = f"{e_type}/" else: e_type_path = "" - uri = f'{pfx}:{e_type_path}{e_name}' + pfx = schema.default_prefix + # To construct the uri we have to find out if the schema has a default_prefix + # or if a pseudo "prefix" was derived from the schema id. + if pfx == sfx(str(schema.id)): # no prefix defined in schema + uri = f'{pfx}{e_type_path}{e_name}' + else: + uri = f'{pfx}:{e_type_path}{e_name}' if expand: return self.expand_curie(uri) else: diff --git a/tests/test_utils/test_schema_builder.py b/tests/test_utils/test_schema_builder.py index 707d75ef..643f9b7f 100644 --- a/tests/test_utils/test_schema_builder.py +++ b/tests/test_utils/test_schema_builder.py @@ -185,7 +185,7 @@ def test_add_class_with_extra_kwargs( ) def test_add_enum_with_extra_permissible_values( enum_def: EnumDefinition, - permissible_values: List[Union[str, PermissibleValue]], + permissible_values: list[Union[str, PermissibleValue]], expected_added_enum: Optional[EnumDefinition], ): """ @@ -231,7 +231,7 @@ def test_add_enum_with_extra_permissible_values( ) def test_add_enum_with_extra_kwargs( enum_def: Union[EnumDefinition, dict, str], - extra_kwargs: Dict[str, Any], + extra_kwargs: dict[str, Any], expected_added_enum: Optional[EnumDefinition], ): """ diff --git a/tests/test_utils/test_schemaview.py b/tests/test_utils/test_schemaview.py index 2cca0cfa..2b1ce32a 100644 --- a/tests/test_utils/test_schemaview.py +++ b/tests/test_utils/test_schemaview.py @@ -488,7 +488,6 @@ def test_imports(view): height = view.get_slot('height_in_m') assert height.unit.ucum_code == "m" - def test_imports_from_schemaview(view): """view should by default dynamically include imports chain""" view2 = SchemaView(view.schema) @@ -923,3 +922,17 @@ def test_type_and_slot_with_same_name(): view.add_type(TypeDefinition(name="test", from_schema="https://example.org/imported#")) assert view.get_uri("test", imports=True) == "ex:test" + + +def test_uris_without_default_prefix(): + """ + Test if uri is correct if no default_prefix is defined for the schema. Issue: linkml/linkml#2578 + """ + schema_definition = SchemaDefinition(id="https://example.org/test#", name="test_schema") + + view = SchemaView(schema_definition) + view.add_class(ClassDefinition(name="TestClass", from_schema="https://example.org/another#")) + view.add_slot(SlotDefinition(name="test_slot", from_schema="https://example.org/another#")) + + assert view.get_uri("TestClass", imports=True) == "https://example.org/test#TestClass" + assert view.get_uri("test_slot", imports=True) == "https://example.org/test#test_slot"