Field Annotations¶
The annotations control how a field is loaded, generated or derived from external data. They are expressed directly on the dataclass / pydantic model attributes.
Overview¶
In FLYNC a field can stray away from standard yaml serializiation by being:
External - the value is read from or written to a separate file / folder.
Implied - the value is not stored but calculated on the fly using a defined strategy.
Both concepts are implemented by the External and Implied dataclasses. The behaviour of
these dataclasses is further refined by three IntEnum strategy classes:
NamingStrategy- how the external file / folder is named.OutputStrategy- how the external representation is organised (single file vs folder).ImpliedStrategy- how an implied field is calculated.
Using External in a model¶
from flync.core.base_models import External, NamingStrategy, OutputStrategy
from flync.model.base_model import FLYNCBaseModel
class FLYNCGeneralConfig(FLYNCBaseModel):
someip_config: Annotated[
Optional[SOMEIPConfig],
External(
output_structure=OutputStrategy.FOLDER,
naming_strategy=NamingStrategy.FIXED_PATH,
path="someip",
),
] = Field(
default=None,
description="contains the SOME/IP config for the entire system.",
)
path- location of the external resource relative to the current component, if left empty, this will be calculated from the naming_strategy attribute.output_structure-SINGLE_FILEcreates one file,FOLDERcreates a directory containing multiple files.naming_strategy-FIXED_PATHuses the explicitpath;AUTOwould derive the name from the field name.
Using Implied in a model¶
from flync.core.base_models import Implied, ImpliedStrategy
from flync.model.base_model import BaseModel
class ECU(FLYNCBaseModel, UniqueName):
name: Annotated[
str,
Implied(strategy=ImpliedStrategy.FOLDER_NAME)
] = pydantic.Field()
When the model is instantiated, flync will compute name based on the folder name
that contains the ECU definition.
Combining both annotations¶
A field can be declared as either External or Implied - they are mutually exclusive.
If both are needed, split the logic into separate helper properties.
Example model¶
from pathlib import Path
from flync.core.base_models import External, Implied, NamingStrategy, OutputStrategy, ImpliedStrategy
from flync.model.base_model import BaseModel
class ECU(FLYNCBaseModel, UniqueName):
name: Annotated[str, Implied(ImpliedStrategy.FOLDER_NAME)]
ports: Annotated[List["ECUPort"], External()] = pydantic.Field(min_length=1)
controllers: Annotated[List["Controller"], External()] = pydantic.Field()
switches: Annotated[Optional[List["Switch"]], External()] = pydantic.Field(
default=[]
)
topology: Annotated[
"InternalTopology",
External(),
] = pydantic.Field()
info: Annotated[
"MetadataECU",
External(
output_structure=OutputStrategy.SINGLE_FILE,
),
] = pydantic.Field()
Key points¶
Choose the appropriate
NamingStrategyto control file naming.Use
OutputStrategy.FOLDERwhen a field naturally maps to multiple files (e.g. controllers).ImpliedStrategy.FOLDER_NAMEis handy for identifiers that follow the directory layout.All strategy classes are defined in
src/flync/helper_models.py- keep them imported from that module to avoid circular imports.