From cc02730f206e96dcf827819af614b8b4e3b87bdc Mon Sep 17 00:00:00 2001 From: Ollie Copping Date: Tue, 5 May 2026 09:33:53 +0000 Subject: [PATCH 1/2] Add docstrings and annotations to models --- src/techui_builder/models.py | 71 +++++++++++++++++++++++++++--------- 1 file changed, 54 insertions(+), 17 deletions(-) diff --git a/src/techui_builder/models.py b/src/techui_builder/models.py index ca97abc..a3739f5 100644 --- a/src/techui_builder/models.py +++ b/src/techui_builder/models.py @@ -56,11 +56,13 @@ class Beamline(BaseModel): - location: str = Field(description="Short BL location e.g. b23, ixx-1") - domain: str = Field(description="Full BL domain e.g. bl23b") - desc: str = Field(description="Description") + """Global Beamline values read from `beamline:` table in techui.yaml""" + + location: Annotated[str, Field(description="Short BL location e.g. b23, ixx-1")] + domain: Annotated[str, Field(description="Full BL domain e.g. bl23b")] + desc: Annotated[str, Field(description="Description")] + url: Annotated[str, Field(description="URL of ixx-opis")] model_config = ConfigDict(extra="forbid") - url: str = Field(description="URL of ixx-opis") @field_validator("location") @classmethod @@ -101,12 +103,30 @@ def check_url(cls, url: str) -> str: class Component(BaseModel): - prefix: str - desc: str | None = None - extras: list[str] | None = None - file: str | None = None - macros: dict[str, str | int | float] | None = None - status: list[str] | None = None + """One UI Component from techui.yaml `components:` dictionary""" + + prefix: Annotated[str, Field(description="Component PV Prefix")] + desc: Annotated[str | None, Field(None, description="Component description")] + extras: Annotated[ + list[str] | None, + Field( + None, + description="Extra PV Prefixes to include in the generation of " + "UI components", + ), + ] + file: Annotated[ + str | None, + Field(None, description="File path for custom screen (bypasses generation)"), + ] + macros: Annotated[ + dict[str, str | int | float] | None, + Field(None, description="Macro dictionary to pass to the custom screen"), + ] + status: Annotated[ + list[str] | None, + Field(None, description="PVs to add to the component status PV"), + ] model_config = ConfigDict( # Makes sure that 'macros' is only allowed if 'file' is present # (this is required for VSCode checks) @@ -196,8 +216,13 @@ def attribute(self) -> str | None: class TechUi(BaseModel): - beamline: Beamline - components: dict[str, Component] + """Beamline values and Component objects read from techui.yaml""" + + beamline: Annotated[Beamline, Field(description="Beamline table from techui.yaml")] + components: Annotated[ + dict[str, Component], + Field(description="Components dictionary from techui.yaml"), + ] model_config = ConfigDict( extra="forbid", hide_input_in_errors=True, @@ -235,8 +260,20 @@ class GuiComponents(RootModel[dict[str, GuiComponentUnion]]): class Entity(BaseModel): - type: str - P: str - desc: str | None = None - M: str | None - R: str | None + """One table of IOC variables extracted from an ioc.yaml file""" + + type: Annotated[ + str, + Field( + description="IOC module entity table in ioc.yaml, e.g. " + "ADAravis.aravisCamera" + ), + ] + P: Annotated[str, Field(description="PV Prefix for module entity")] + desc: Annotated[ + str | None, Field(None, description="Optional description of module entity") + ] + M: Annotated[str | None, Field(description="Optional PV suffix for a motor")] + R: Annotated[ + str | None, Field(description="Optional PV suffix for an ADAravis plugin") + ] From e68829387797ff506729eb5c4d7812bdaeb16763 Mon Sep 17 00:00:00 2001 From: Ollie Copping Date: Tue, 5 May 2026 09:42:01 +0000 Subject: [PATCH 2/2] Fix default values --- src/techui_builder/models.py | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/src/techui_builder/models.py b/src/techui_builder/models.py index a3739f5..4ee1a20 100644 --- a/src/techui_builder/models.py +++ b/src/techui_builder/models.py @@ -106,27 +106,26 @@ class Component(BaseModel): """One UI Component from techui.yaml `components:` dictionary""" prefix: Annotated[str, Field(description="Component PV Prefix")] - desc: Annotated[str | None, Field(None, description="Component description")] + desc: Annotated[str | None, Field(description="Component description")] = None extras: Annotated[ list[str] | None, Field( - None, description="Extra PV Prefixes to include in the generation of " "UI components", ), - ] + ] = None file: Annotated[ str | None, - Field(None, description="File path for custom screen (bypasses generation)"), - ] + Field(description="File path for custom screen (bypasses generation)"), + ] = None macros: Annotated[ dict[str, str | int | float] | None, - Field(None, description="Macro dictionary to pass to the custom screen"), - ] + Field(description="Macro dictionary to pass to the custom screen"), + ] = None status: Annotated[ list[str] | None, - Field(None, description="PVs to add to the component status PV"), - ] + Field(description="PVs to add to the component status PV"), + ] = None model_config = ConfigDict( # Makes sure that 'macros' is only allowed if 'file' is present # (this is required for VSCode checks) @@ -271,8 +270,8 @@ class Entity(BaseModel): ] P: Annotated[str, Field(description="PV Prefix for module entity")] desc: Annotated[ - str | None, Field(None, description="Optional description of module entity") - ] + str | None, Field(description="Optional description of module entity") + ] = None M: Annotated[str | None, Field(description="Optional PV suffix for a motor")] R: Annotated[ str | None, Field(description="Optional PV suffix for an ADAravis plugin")