Source code for lodstorage.linkml

"""
Created on 2024-01-28

@author: wf
"""
from dataclasses import field
from typing import Dict, List, Optional, Type

from rdflib.namespace import XSD

from lodstorage.yamlable import lod_storable


@lod_storable
class Slot:
    """
    Represents a slot in the LinkML schema, equivalent to a field or property.
    """

    description: str
    range: str = "string"
    multivalued: bool = False
    identifier: bool = False 


@lod_storable
class Class:
    """
    Represents a class in the LinkML schema.
    """
    description: str
    slots: List[Slot]
    
@lod_storable
class Type:
    """
    Represents a type in the LinkML schema.
    """
    uri: str
    base: str
    description: Optional[str]
    notes: Optional[str]
    exact_mappings: Optional[List[str]] = field(default_factory=list)
    close_mappings: Optional[List[str]] = field(default_factory=list)
    broad_mappings: Optional[List[str]] = field(default_factory=list)
    mappings: Optional[str] = field(init=False, default=None, repr=False)
    
    def __post_init__(self):
        # Take the first item from exact_mappings, close_mappings, or broad_mappings, in that order
        if self.exact_mappings:
            self.mappings = self.exact_mappings[0]
        elif self.close_mappings:
            self.mappings = self.close_mappings[0]
        elif self.broad_mappings:
            self.mappings = self.broad_mappings[0]


@lod_storable
class Schema:
    """
    Represents the entire LinkML schema.
    """
    name: str
    id: str
    description: str
    title: Optional[str] = None
    version: Optional[str] = None
    license: Optional[str] = None
    
    default_prefix: Optional[str] = None
    
    prefixes: Dict[str, str] = field(default_factory=dict)
    imports: List[str] = field(default_factory=list)
    default_range: str = "string"
    classes: Dict[str, Class] = field(default_factory=dict)
    slots: Dict[str, Slot] = field(default_factory=dict)
    types: Dict[str, Type] = field(default_factory=dict)

    def __post_init__(self):
        if not self.title:
            self.title = self.name

[docs] class PythonTypes: """ python type handling """ # Define a mapping from Python types to LinkML ranges to_linkml_ranges = { str: "string", int: "integer", float: "float", bool: "boolean", list: "list", dict: "dictionary", } # Mapping from Python types to RDF (XSD) datatypes to_rdf_datatypes = { str: XSD.string, int: XSD.integer, float: XSD.float, bool: XSD.boolean, # Add more mappings if needed }
[docs] @classmethod def get_linkml_range(cls, ptype: Type) -> str: """ Determines the LinkML range for a given Python type. Args: ptype (Type): The Python type for which the LinkML range is required. Returns: str: The corresponding LinkML range as a string. Defaults to "string" if the type is not found. """ return cls.to_linkml_ranges.get(ptype, "string")
[docs] @classmethod def get_rdf_datatype(cls, ptype: Type) -> Optional[XSD]: """ Determines the RDF (XSD) datatype for a given Python type. Args: ptype (Type): The Python type for which the RDF (XSD) datatype is required. Returns: XSD: The corresponding RDF (XSD) datatype. Returns None if the type is not found. """ return cls.to_rdf_datatypes.get(ptype)