11"""Schemas relating to VLM API."""
22
3- from collections . abc import Callable
4- from typing import Any , ClassVar , Literal , Self
3+ import os
4+ from typing import ClassVar , Literal , Self
55
6- from pydantic import BaseModel , ConfigDict , Field , field_validator , model_validator
7- from pydantic_settings import BaseSettings , SettingsConfigDict
6+ from pydantic import BaseModel , ConfigDict , Field , model_validator
87
98from anyvlm .utils .types import Zygosity
109
1312RESULT_ENTITY_TYPE = "genomicVariant"
1413
1514
16- def forbid_env_override (field_name : str ) -> Callable [..., Any ]:
17- """Returns a Pydantic field validator that forbids explicitly
18- passing a value for `field_name`. The value must come from env.
19- """
15+ class MissingEnvironmentVariableError (Exception ):
16+ """Raised when a required environment variable is not set."""
2017
21- @field_validator (field_name , mode = "before" )
22- @classmethod
23- def _forbid_override (cls , value : Any ) -> Any : # noqa: ARG001, ANN401, ANN001
24- if value is not None :
25- raise TypeError (f"{ field_name } must be set via environment variable only" )
26- return value
2718
28- return _forbid_override
19+ def _get_environment_var (key : str ) -> str :
20+ value : str | None = os .environ .get (key )
21+ if not value :
22+ message = f"Missing required environment variable: { key } "
23+ raise MissingEnvironmentVariableError (message )
24+ return value
2925
3026
31- class HandoverType (BaseSettings ):
27+ class HandoverType (BaseModel ):
3228 """The type of handover the parent `BeaconHandover` represents."""
3329
34- id : str = Field (..., description = "Node-specific identifier" )
35- label : str = Field (..., description = "Node-specific label" )
36-
37- model_config = SettingsConfigDict (env_prefix = "HANDOVER_TYPE_" , extra = "forbid" )
38-
39- # These validators prevent instantiation of this class with values that would override `id` or `label`
40- _forbid_id_override = forbid_env_override ("id" )
41- _forbid_label_override = forbid_env_override ("label" )
30+ id : str = Field (
31+ _get_environment_var ("HANDOVER_TYPE_ID" ), description = "Node-specific identifier"
32+ )
33+ label : str = Field (
34+ _get_environment_var ("HANDOVER_TYPE_LABEL" ), description = "Node-specific label"
35+ )
4236
43- # Allows `HandoverType` to be instantiated without providing values for the
44- # any required fields, since both are pulled from environment variables instead
37+ # override __init__ to prevent the ability to override attributes that are set via environment variables
4538 def __init__ (self ) -> None :
4639 super ().__init__ ()
4740
4841
49- class BeaconHandover (BaseSettings ):
42+ class BeaconHandover (BaseModel ):
5043 """Describes how users can get more information about the results provided in the parent `VlmResponse`"""
5144
5245 handoverType : HandoverType = Field (default = HandoverType ())
5346 url : str = Field (
54- ... ,
47+ _get_environment_var ( "BEACON_HANDOVER_URL" ) ,
5548 description = """
5649 A url which directs users to more detailed information about the results tabulated by the API. Must be human-readable.
5750 Ideally links directly to the variant specified in the query, but can be a generic search page if necessary.
5851 """ ,
5952 )
6053
61- model_config = SettingsConfigDict (env_prefix = "BEACON_HANDOVER_" , extra = "forbid" )
62-
63- # These validators prevent instantiation of this class with values that would override `handoverType` or `url`
64- _forbid_handoverType_override = forbid_env_override ("handoverType" )
65- _forbid_url_override = forbid_env_override ("url" )
66-
67- # Allows `BeaconHandover` to be instantiated without providing values
68- # for any required fields, since both are generated statically
54+ # override __init__ to prevent the ability to override attributes that are set via environment variables
6955 def __init__ (self ) -> None :
7056 super ().__init__ ()
7157
@@ -87,16 +73,15 @@ class ReturnedSchema(BaseModel):
8773 model_config = ConfigDict (populate_by_name = True )
8874
8975
90- class Meta (BaseSettings ):
76+ class Meta (BaseModel ):
9177 """Relevant metadata about the results provided in the parent `VlmResponse`"""
9278
9379 apiVersion : str = Field (
9480 default = "v1.0" ,
9581 description = "The version of the VLM API that this response conforms to" ,
9682 )
9783 beaconId : str = Field (
98- ...,
99- alias = "BEACON_NODE_ID" ,
84+ _get_environment_var ("BEACON_NODE_ID" ),
10085 description = """
10186 The Id of a Beacon. Usually a reversed domain string, but any URI is acceptable. The purpose of this attribute is,
10287 in the context of a Beacon network, to disambiguate responses coming from different Beacons. See the beacon documentation
@@ -105,15 +90,7 @@ class Meta(BaseSettings):
10590 )
10691 returnedSchemas : list [ReturnedSchema ] = [ReturnedSchema ()]
10792
108- model_config = SettingsConfigDict (
109- env_prefix = "" , populate_by_name = False , extra = "forbid"
110- )
111-
112- # This validator prevents instantiation of this class with values that would override `handoverType` or `url`
113- _forbid_beaconId_override = forbid_env_override ("beaconId" )
114-
115- # Allows `Meta` to be instantiated without providing values
116- # for any required fields, since all are generated statically
93+ # override __init__ to prevent the ability to override attributes that are set via environment variables
11794 def __init__ (self ) -> None :
11895 super ().__init__ ()
11996
0 commit comments