1
1
from __future__ import annotations
2
2
3
- from pydantic import field_validator , ValidationInfo , model_validator , FilePath , model_serializer , Field , NonNegativeInt , computed_field
3
+ from pydantic import field_validator , ValidationInfo , model_validator , FilePath , model_serializer , Field , NonNegativeInt , computed_field , TypeAdapter
4
4
from enum import StrEnum , auto
5
5
from typing import TYPE_CHECKING , Optional , Any , Union , Literal , Annotated , Self
6
6
import re
@@ -45,6 +45,7 @@ class Lookup(SecurityContentObject, abc.ABC):
45
45
min_matches : None | NonNegativeInt = Field (default = None )
46
46
max_matches : None | Annotated [NonNegativeInt , Field (ge = 1 , le = 1000 )] = Field (default = None )
47
47
case_sensitive_match : None | bool = Field (default = None )
48
+
48
49
49
50
50
51
@@ -108,11 +109,10 @@ def get_lookups(text_field: str, director:DirectorOutputDto, ignore_lookups:set[
108
109
109
110
110
111
111
-
112
-
113
- class CSVLookup (Lookup ):
114
- lookup_type : Literal [Lookup_Type .csv ]
115
-
112
+ class FileBackedLookup (Lookup , abc .ABC ):
113
+ # For purposes of the disciminated union, the child classes which
114
+ # inherit from this class must declare the typing of lookup_type
115
+ # themselves, hence it is not defined in the Lookup class
116
116
117
117
@model_validator (mode = "after" )
118
118
def ensure_lookup_file_exists (self )-> Self :
@@ -124,9 +124,9 @@ def ensure_lookup_file_exists(self)->Self:
124
124
@cached_property
125
125
def filename (self )-> FilePath :
126
126
if self .file_path is None :
127
- raise ValueError ("Cannot get the filename of the lookup CSV because the YML file_path attribute is None" )
127
+ raise ValueError (f "Cannot get the filename of the lookup { self . lookup_type } because the YML file_path attribute is None" ) #type: ignore
128
128
129
- csv_file = self .file_path .parent / f"{ self .file_path .stem } .csv"
129
+ csv_file = self .file_path .parent / f"{ self .file_path .stem } .{ self . lookup_type } " #type: ignore
130
130
return csv_file
131
131
132
132
@computed_field
@@ -138,10 +138,11 @@ def app_filename(self)->FilePath:
138
138
2. Only apply the datetime stamp if it is version > 1. This makes the code a small fraction
139
139
more complicated, but preserves longstanding CSV that have not been modified in a long time
140
140
'''
141
- return pathlib .Path (f"{ self .filename .stem } _{ self .date .year } { self .date .month :02} { self .date .day :02} .csv" )
142
-
143
-
141
+ return pathlib .Path (f"{ self .filename .stem } _{ self .date .year } { self .date .month :02} { self .date .day :02} .{ self .lookup_type } " ) #type: ignore
144
142
143
+ class CSVLookup (FileBackedLookup ):
144
+ lookup_type :Literal [Lookup_Type .csv ]
145
+
145
146
@model_serializer
146
147
def serialize_model (self ):
147
148
#Call parent serializer
@@ -158,13 +159,6 @@ def serialize_model(self):
158
159
159
160
@model_validator (mode = "after" )
160
161
def ensure_correct_csv_structure (self )-> Self :
161
-
162
-
163
- if self .filename .suffix != ".csv" :
164
- raise ValueError (f"All Lookup files must be CSV files and end in .csv. The following file does not: '{ self .filename } '" )
165
-
166
-
167
-
168
162
# https://docs.python.org/3/library/csv.html#csv.DictReader
169
163
# Column Names (fieldnames) determine by the number of columns in the first row.
170
164
# If a row has MORE fields than fieldnames, they will be dumped in a list under the key 'restkey' - this should throw an Exception
@@ -200,7 +194,7 @@ def ensure_correct_csv_structure(self)->Self:
200
194
201
195
class KVStoreLookup (Lookup ):
202
196
lookup_type : Literal [Lookup_Type .kvstore ]
203
- collection : str = Field (description = "Name of the KVStore Collection. Note that collection MUST equal the name." )
197
+ collection : str = Field (description = "Name of the KVStore Collection. Note that collection MUST equal the name. This is a duplicate field, so it will be removed eventually. " )
204
198
fields : list [str ] = Field (description = "The names of the fields/headings for the KVStore." , min_length = 1 )
205
199
206
200
@@ -225,9 +219,9 @@ def serialize_model(self):
225
219
model .update (super_fields )
226
220
return model
227
221
228
- class MlModel (Lookup ):
222
+ class MlModel (FileBackedLookup ):
229
223
lookup_type : Literal [Lookup_Type .mlmodel ]
230
224
231
225
232
-
226
+ LookupAdapter = TypeAdapter ( Annotated [ CSVLookup | KVStoreLookup | MlModel , Field ( discriminator = "lookup_type" )])
233
227
0 commit comments