11import logging
2+ import re
3+ from dataclasses import field , dataclass
24from typing import Generator , Any , Tuple
35
46from sanic_rest .exceptions import ValidationError
810logger = logging .getLogger ()
911
1012
13+ ALIAS_REGEX = r"\${(?P<alias_to>.*)}"
14+
15+
16+ @dataclass
17+ class ReplacementEngine :
18+ replacements : KeyValue = field (default_factory = dict )
19+
20+ def add (self , items : KeyValue ):
21+ for k , v in items .items ():
22+ if AliasEngine .is_virtual (value = v ):
23+ continue
24+ self .replacements [k ] = v
25+
26+ def get (self , value ):
27+ return self .replacements [value ]
28+
29+ def replace (self , virtual_value ):
30+ alias_to = re .match (ALIAS_REGEX , virtual_value ).group ('alias_to' )
31+
32+ try :
33+ replace_with = self .replacements [alias_to ]
34+ except KeyError as e :
35+ raise ValidationError (f"Could not find the referenced env var for { virtual_value .as_kv } " ) from e
36+
37+ return re .sub (ALIAS_REGEX , replace_with , virtual_value )
38+
39+
1140class AliasEngine :
12- def __init__ (self , items : KeyValue , replacements : KeyValue = None ):
41+ def __init__ (self , items : KeyValue , replacements : ReplacementEngine = None ):
1342 super ().__init__ ()
1443 self ._concrete : KeyValue = dict ()
1544 self ._virtual : KeyValue = dict ()
16- self ._replacements : KeyValue = replacements or items
45+
46+ if not replacements :
47+ replacements = ReplacementEngine ()
48+ replacements .add (items = items )
49+ self ._replacements = replacements
1750
1851 self .extend (items )
1952
20- def is_virtual (self , value ):
21- return False # TODO We need an use case for this, the syntax must not be defined too
53+ @classmethod
54+ def is_virtual (cls , value ):
55+ matches = re .match (ALIAS_REGEX , str (value ))
56+ return bool (matches )
2257
2358 def append (self , key : str , value : Any ) -> None :
2459 container = self ._virtual if self .is_virtual (value ) else self ._concrete
@@ -33,14 +68,4 @@ def extend(self, items: KeyValue) -> None:
3368 def items (self ) -> Generator [Tuple [str , Any ], None , None ]:
3469 yield from self ._concrete .items ()
3570 for key , virtual_value in self ._virtual .items ():
36- yield key , self ._to_concrete (virtual_value = virtual_value )
37-
38- def _to_concrete (self , virtual_value ) -> Any :
39- alias_to = virtual_value [1 :]
40-
41- try :
42- value = self ._replacements [alias_to ]
43- except KeyError as e :
44- raise ValidationError (f"Could not find the referenced env var for { virtual_value .as_kv } " ) from e
45-
46- return value
71+ yield key , self ._replacements .replace (virtual_value = virtual_value )
0 commit comments