99from dateutil import parser as dateparser
1010from typeguard import typechecked
1111
12- from dj_toml_settings .value_parsers .dict_value_parsers import (
13- EnvValueParser ,
14- InsertValueParser ,
15- NoneValueParser ,
16- PathValueParser ,
17- TypeValueParser ,
18- ValueValueParser ,
12+ from dj_toml_settings .value_parsers .dict_parsers import (
13+ EnvParser ,
14+ InsertParser ,
15+ NoneParser ,
16+ PathParser ,
17+ TypeParser ,
18+ ValueParser ,
1919)
20+ from dj_toml_settings .value_parsers .str_parsers import VariableParser
2021
2122logger = logging .getLogger (__name__ )
2223
@@ -65,14 +66,14 @@ def parse_file(self):
6566 for key , value in toml_data .items ():
6667 logger .debug (f"tool.django: Update '{ key } ' with '{ value } '" )
6768
68- self .data .update (self .parse_key_value (key , value ))
69+ self .data .update ({ key : self .parse_value (key , value )} )
6970
7071 # Add settings from `tool.django.apps.*`
7172 for apps_name , apps_value in apps_data .items ():
7273 for app_key , app_value in apps_value .items ():
7374 logger .debug (f"tool.django.apps.{ apps_name } : Update '{ app_key } ' with '{ app_value } '" )
7475
75- self .data .update (self .parse_key_value (app_key , app_value ))
76+ self .data .update ({ app_key : self .parse_value (app_key , app_value )} )
7677
7778 # Add settings from `tool.django.envs.*` if it matches the `ENVIRONMENT` env variable
7879 if environment_env_variable := os .getenv ("ENVIRONMENT" ):
@@ -81,7 +82,7 @@ def parse_file(self):
8182 for env_key , env_value in envs_value .items ():
8283 logger .debug (f"tool.django.envs.{ envs_name } : Update '{ env_key } ' with '{ env_value } '" )
8384
84- self .data .update (self .parse_key_value (env_key , env_value ))
85+ self .data .update ({ env_key : self .parse_value (env_key , env_value )} )
8586
8687 return self .data
8788
@@ -101,7 +102,7 @@ def get_data(self) -> dict:
101102 return data .get ("tool" , {}).get ("django" , {}) or {}
102103
103104 @typechecked
104- def parse_key_value (self , key : str , value : Any ) -> dict :
105+ def parse_value (self , key : Any , value : Any ) -> Any :
105106 """Handle special cases for `value`.
106107
107108 Special cases:
@@ -116,13 +117,33 @@ def parse_key_value(self, key: str, value: Any) -> dict:
116117 - `datetime`
117118 """
118119
119- if isinstance (value , dict ):
120- type_parser = TypeValueParser (data = self .data , value = value )
121- env_parser = EnvValueParser (data = self .data , value = value )
122- path_parser = PathValueParser (data = self .data , value = value , path = self .path )
123- value_parser = ValueValueParser (data = self .data , value = value )
124- none_parser = NoneValueParser (data = self .data , value = value )
125- insert_parser = InsertValueParser (data = self .data , value = value , data_key = key )
120+ if isinstance (value , list ):
121+ processed_list = []
122+
123+ for item in value :
124+ processed_item = self .parse_value (key , item )
125+ processed_list .append (processed_item )
126+
127+ value = processed_list
128+ elif isinstance (value , dict ):
129+ # Process nested dictionaries
130+ processed_dict = {}
131+
132+ for k , v in value .items ():
133+ if isinstance (v , dict ):
134+ processed_dict .update ({k : self .parse_value (key , v )})
135+ else :
136+ processed_dict [k ] = v
137+
138+ if processed_dict :
139+ value = processed_dict
140+
141+ type_parser = TypeParser (data = self .data , value = value )
142+ env_parser = EnvParser (data = self .data , value = value )
143+ path_parser = PathParser (data = self .data , value = value , path = self .path )
144+ value_parser = ValueParser (data = self .data , value = value )
145+ none_parser = NoneParser (data = self .data , value = value )
146+ insert_parser = InsertParser (data = self .data , value = value , data_key = key )
126147
127148 # Check for a match for all specials (except $type)
128149 for parser in [env_parser , path_parser , value_parser , insert_parser , none_parser ]:
@@ -134,42 +155,8 @@ def parse_key_value(self, key: str, value: Any) -> dict:
134155 if type_parser .match ():
135156 value = type_parser .parse (value )
136157 elif isinstance (value , str ):
137- # Handle variable substitution
138- for match in re .finditer (r"\$\{\w+\}" , value ):
139- data_key = value [match .start () : match .end ()][2 :- 1 ]
140-
141- if variable := self .data .get (data_key ):
142- if isinstance (variable , Path ):
143- path_str = combine_bookends (value , match , variable )
144-
145- value = Path (path_str )
146- elif callable (variable ):
147- value = variable
148- elif isinstance (variable , int ):
149- value = combine_bookends (value , match , variable )
150-
151- try :
152- value = int (value )
153- except Exception : # noqa: S110
154- pass
155- elif isinstance (variable , float ):
156- value = combine_bookends (value , match , variable )
157-
158- try :
159- value = float (value )
160- except Exception : # noqa: S110
161- pass
162- elif isinstance (variable , list ):
163- value = variable
164- elif isinstance (variable , dict ):
165- value = variable
166- elif isinstance (variable , datetime ):
167- value = dateparser .isoparse (str (variable ))
168- else :
169- value = value .replace (match .string , str (variable ))
170- else :
171- logger .warning (f"Missing variable substitution { value } " )
158+ value = VariableParser (data = self .data , value = value ).parse ()
172159 elif isinstance (value , datetime ):
173160 value = dateparser .isoparse (str (value ))
174161
175- return { key : value }
162+ return value
0 commit comments