11from pathlib import Path
2- from typing import NamedTuple , Optional
2+ from typing import Optional
33
44import yaml
5- from bindr import bind
6- from jsonschema import ValidationError , validate
5+ from pydantic import BaseModel , StrictStr , ValidationError
76
87
9- class LocalOnlineStoreConfig (NamedTuple ):
8+ class FeastBaseModel (BaseModel ):
9+ """ Feast Pydantic Configuration Class """
10+
11+ class Config :
12+ arbitrary_types_allowed = True
13+ extra = "forbid"
14+
15+
16+ class LocalOnlineStoreConfig (FeastBaseModel ):
1017 """ Online store config for local (SQLite-based) online store """
1118
12- path : str
19+ path : StrictStr
1320 """ str: Path to sqlite db """
1421
1522
16- class DatastoreOnlineStoreConfig (NamedTuple ):
23+ class DatastoreOnlineStoreConfig (FeastBaseModel ):
1724 """ Online store config for GCP Datastore """
1825
19- project_id : str
26+ project_id : StrictStr
2027 """ str: GCP Project Id """
2128
2229
23- class OnlineStoreConfig (NamedTuple ):
30+ class OnlineStoreConfig (FeastBaseModel ):
2431 datastore : Optional [DatastoreOnlineStoreConfig ] = None
2532 """ DatastoreOnlineStoreConfig: Optional DatastoreConfig """
33+
2634 local : Optional [LocalOnlineStoreConfig ] = None
2735 """ LocalOnlineStoreConfig: Optional local online store config """
2836
2937
30- class RepoConfig (NamedTuple ):
38+ class RepoConfig (FeastBaseModel ):
3139 """ Repo config. Typically loaded from `feature_store.yaml` """
3240
33- metadata_store : str
41+ metadata_store : StrictStr
3442 """ str: Path to metadata store. Can be a local path, or remote object storage path, e.g. gcs://foo/bar """
35- project : str
43+
44+ project : StrictStr
3645 """ str: Feast project id. This can be any alphanumeric string up to 16 characters.
3746 You can have multiple independent feature repositories deployed to the same cloud
3847 provider account, as long as they have different project ids.
3948 """
40- provider : str
49+
50+ provider : StrictStr
4151 """ str: local or gcp """
52+
4253 online_store : Optional [OnlineStoreConfig ] = None
4354 """ OnlineStoreConfig: Online store configuration (optional depending on provider) """
4455
@@ -79,20 +90,18 @@ class RepoConfig(NamedTuple):
7990
8091
8192class FeastConfigError (Exception ):
82- def __init__ (self , error_message , error_path , config_path ):
93+ def __init__ (self , error_message , config_path ):
8394 self ._error_message = error_message
84- self ._error_path = error_path
8595 self ._config_path = config_path
8696 super ().__init__ (self ._error_message )
8797
8898 def __str__ (self ) -> str :
89- if self ._error_path :
90- return f'{ self ._error_message } under { "->" .join (self ._error_path )} in { self ._config_path } '
91- else :
92- return f"{ self ._error_message } in { self ._config_path } "
99+ return f"{ self ._error_message } \n at { self ._config_path } "
93100
94101 def __repr__ (self ) -> str :
95- return f"FeastConfigError({ repr (self ._error_message )} , { repr (self ._error_path )} , { repr (self ._config_path )} )"
102+ return (
103+ f"FeastConfigError({ repr (self ._error_message )} , { repr (self ._config_path )} )"
104+ )
96105
97106
98107def load_repo_config (repo_path : Path ) -> RepoConfig :
@@ -101,7 +110,6 @@ def load_repo_config(repo_path: Path) -> RepoConfig:
101110 with open (config_path ) as f :
102111 raw_config = yaml .safe_load (f )
103112 try :
104- validate (raw_config , config_schema )
105- return bind (RepoConfig , raw_config )
113+ return RepoConfig (** raw_config )
106114 except ValidationError as e :
107- raise FeastConfigError (e . message , e . absolute_path , config_path )
115+ raise FeastConfigError (e , config_path )
0 commit comments