From 17cf92d97960e182a8419bbb6e68a750cfa07626 Mon Sep 17 00:00:00 2001 From: Christian Sandberg Date: Fri, 25 Oct 2024 15:06:40 +0200 Subject: [PATCH] Improved type checking support --- onedm/py.typed | 0 onedm/sdf/common.py | 5 +- onedm/sdf/data.py | 16 +----- onedm/sdf/definitions.py | 103 ++++++++++++++++++++------------------- onedm/sdf/document.py | 60 ++++++++++++++--------- 5 files changed, 94 insertions(+), 90 deletions(-) create mode 100644 onedm/py.typed diff --git a/onedm/py.typed b/onedm/py.typed new file mode 100644 index 0000000..e69de29 diff --git a/onedm/sdf/common.py b/onedm/sdf/common.py index a2771c3..d3d4448 100644 --- a/onedm/sdf/common.py +++ b/onedm/sdf/common.py @@ -1,3 +1,4 @@ +from typing import Annotated from pydantic import BaseModel, ConfigDict, Field from pydantic.alias_generators import to_camel @@ -7,6 +8,6 @@ class CommonQualities(BaseModel): extra="allow", alias_generator=to_camel, populate_by_name=True ) - label: str | None = Field(None, validation_alias="title") + label: Annotated[str | None, Field(validation_alias="title")] = None description: str | None = None - ref: str | None = Field(None, alias="sdfRef", validation_alias="$ref") + ref: Annotated[str | None, Field(alias="sdfRef", validation_alias="$ref")] = None diff --git a/onedm/sdf/data.py b/onedm/sdf/data.py index e2d15d6..4dcbfd3 100644 --- a/onedm/sdf/data.py +++ b/onedm/sdf/data.py @@ -25,6 +25,7 @@ class DataQualities(CommonQualities, ABC): None ) sdf_type: Annotated[str, Field(pattern=r"^[a-z][\-a-z0-9]*$")] | None = None + unit: str | None = None nullable: bool = True const: Any | None = None default: Any | None = None @@ -66,7 +67,6 @@ def validate_input(self, input: Any) -> Any: class NumberData(DataQualities): type: Literal["number"] = "number" - unit: str | None = None minimum: float | None = None maximum: float | None = None exclusive_minimum: float | None = None @@ -115,7 +115,6 @@ def _get_base_schema(self) -> core_schema.CoreSchema: class IntegerData(DataQualities): type: Literal["integer"] = "integer" - unit: str | None = None minimum: int | None = None maximum: int | None = None exclusive_minimum: int | None = None @@ -296,19 +295,6 @@ def _get_base_schema(self) -> core_schema.AnySchema: ] -DataDefinitions = Annotated[ - dict[str, Data], - Field( - default_factory=dict, - alias="sdfData", - description=( - "Common modeling patterns, data constraints, " - "and semantic anchor concepts" - ), - ), -] - - ObjectData.model_rebuild() ArrayData.model_rebuild() DataQualities.model_rebuild() diff --git a/onedm/sdf/definitions.py b/onedm/sdf/definitions.py index ff5f2c7..dd579fa 100644 --- a/onedm/sdf/definitions.py +++ b/onedm/sdf/definitions.py @@ -10,7 +10,6 @@ ArrayData, BooleanData, Data, - DataDefinitions, IntegerData, NumberData, ObjectData, @@ -74,79 +73,81 @@ def property_from_data(data: Data) -> Property: return PropertyAdapter.validate_python(data.model_dump()) -Properties = Annotated[ - dict[str, Property], - Field( - default_factory=dict, - alias="sdfProperty", - description="Elements of state within Things", - ), -] - - class Action(CommonQualities): - input_data: Data | None = Field(None, alias="sdfInputData") - output_data: Data | None = Field(None, alias="sdfOutputData") + input_data: Annotated[Data | None, Field(alias="sdfInputData")] = None + output_data: Annotated[Data | None, Field(None, alias="sdfOutputData")] = None sdf_required: Tuple[Literal[True]] | None = None -Actions = Annotated[ - dict[str, Action], - Field( - default_factory=dict, - alias="sdfAction", - description="Commands and methods which are invoked", - ), -] - - class Event(CommonQualities): - output_data: Data | None = Field(None, alias="sdfOutputData") + output_data: Annotated[Data | None, Field(None, alias="sdfOutputData")] = None sdf_required: Tuple[Literal[True]] | None = None -Events = Annotated[ - dict[str, Event], - Field( +class Object(CommonQualities): + properties: dict[str, Property] = Field( + default_factory=dict, + alias="sdfProperty", + description="Elements of state within Things", + ) + actions: dict[str, Action] = Field( + default_factory=dict, + alias="sdfAction", + description="Commands and methods which are invoked", + ) + events: dict[str, Event] = Field( default_factory=dict, alias="sdfEvent", description='"Happenings" associated with a Thing', - ), -] - - -class Object(CommonQualities): - properties: Properties - actions: Actions - events: Events - data: DataDefinitions + ) + data: dict[str, Data] = Field( + default_factory=dict, + alias="sdfData", + description=( + "Common modeling patterns, data constraints, " + "and semantic anchor concepts" + ), + ) sdf_required: list[str | Literal[True]] = Field(default_factory=list) # If array of objects min_items: NonNegativeInt | None = None max_items: NonNegativeInt | None = None -Objects = Annotated[ - dict[str, Object], - Field( - default_factory=dict, - alias="sdfObject", - description='Main "atom" of reusable semantics for model construction', - ), -] - - class Thing(CommonQualities): things: dict[str, Thing] = Field( default_factory=dict, alias="sdfThing", description="Definition of models for complex devices", ) - objects: Objects - properties: Properties - actions: Actions - events: Events - data: DataDefinitions + objects: dict[str, Object] = Field( + default_factory=dict, + alias="sdfObject", + description='Main "atom" of reusable semantics for model construction', + ) + properties: dict[str, Property] = Field( + default_factory=dict, + alias="sdfProperty", + description="Elements of state within Things", + ) + actions: dict[str, Action] = Field( + default_factory=dict, + alias="sdfAction", + description="Commands and methods which are invoked", + ) + events: dict[str, Event] = Field( + default_factory=dict, + alias="sdfEvent", + description='"Happenings" associated with a Thing', + ) + data: dict[str, Data] = Field( + default_factory=dict, + alias="sdfData", + description=( + "Common modeling patterns, data constraints, " + "and semantic anchor concepts" + ), + ) sdf_required: list[str | Literal[True]] = Field(default_factory=list) # If array of things min_items: NonNegativeInt | None = None diff --git a/onedm/sdf/document.py b/onedm/sdf/document.py index ac00588..faba88c 100644 --- a/onedm/sdf/document.py +++ b/onedm/sdf/document.py @@ -40,10 +40,9 @@ class Information(BaseModel): str | None, Field(description="Link to text or embedded text containing license terms"), ] = None - features: Annotated[ - list[str], - Field(default_factory=list, description="List of extension features used"), - ] + features: list[str] = Field( + default_factory=list, description="List of extension features used" + ) class Document(BaseModel): @@ -51,20 +50,14 @@ class Document(BaseModel): extra="allow", alias_generator=to_camel, populate_by_name=True ) - info: Annotated[ - Information, - Field(default_factory=Information), - ] - namespace: Annotated[ - dict[str, str], - Field( - default_factory=dict, - description=( - "Defines short names mapped to namespace URIs, " - "to be used as identifier prefixes" - ), + info: Information = Field(default_factory=lambda: Information()) + namespace: dict[str, str] = Field( + default_factory=dict, + description=( + "Defines short names mapped to namespace URIs, " + "to be used as identifier prefixes" ), - ] + ) default_namespace: Annotated[ str | None, Field( @@ -79,11 +72,34 @@ class Document(BaseModel): alias="sdfThing", description="Definition of models for complex devices", ) - objects: definitions.Objects - properties: definitions.Properties - actions: definitions.Actions - events: definitions.Events - data: definitions.DataDefinitions + objects: dict[str, definitions.Object] = Field( + default_factory=dict, + alias="sdfObject", + description='Main "atom" of reusable semantics for model construction', + ) + properties: dict[str, definitions.Property] = Field( + default_factory=dict, + alias="sdfProperty", + description="Elements of state within Things", + ) + actions: dict[str, definitions.Action] = Field( + default_factory=dict, + alias="sdfAction", + description="Commands and methods which are invoked", + ) + events: dict[str, definitions.Event] = Field( + default_factory=dict, + alias="sdfEvent", + description='"Happenings" associated with a Thing', + ) + data: dict[str, definitions.Data] = Field( + default_factory=dict, + alias="sdfData", + description=( + "Common modeling patterns, data constraints, " + "and semantic anchor concepts" + ), + ) def to_json(self) -> str: return self.model_dump_json(indent=2, exclude_defaults=True, by_alias=True)