18
18
from enum import Enum
19
19
from pathlib import Path
20
20
from textwrap import dedent
21
+ from types import SimpleNamespace
21
22
from typing import (
22
23
TYPE_CHECKING ,
23
24
Any ,
@@ -1155,13 +1156,15 @@ def __call__(self, *, args: list[str] | tuple[str, ...] | bool) -> CliSettingsSo
1155
1156
...
1156
1157
1157
1158
@overload
1158
- def __call__ (self , * , parsed_args : Namespace | dict [str , list [str ] | str ]) -> CliSettingsSource [T ]:
1159
+ def __call__ (
1160
+ self , * , parsed_args : Namespace | SimpleNamespace | dict [str , list [str ] | str ]
1161
+ ) -> CliSettingsSource [T ]:
1159
1162
"""
1160
1163
Loads parsed command line arguments into the CLI settings source.
1161
1164
1162
1165
Note:
1163
- The parsed args must be in `argparse.Namespace` or vars dictionary (e.g., vars(argparse.Namespace))
1164
- format.
1166
+ The parsed args must be in `argparse.Namespace`, `SimpleNamespace`, or vars dictionary
1167
+ (e.g., vars(argparse.Namespace)) format.
1165
1168
1166
1169
Args:
1167
1170
parsed_args: The parsed args to load.
@@ -1175,7 +1178,7 @@ def __call__(
1175
1178
self ,
1176
1179
* ,
1177
1180
args : list [str ] | tuple [str , ...] | bool | None = None ,
1178
- parsed_args : Namespace | dict [str , list [str ] | str ] | None = None ,
1181
+ parsed_args : Namespace | SimpleNamespace | dict [str , list [str ] | str ] | None = None ,
1179
1182
) -> dict [str , Any ] | CliSettingsSource [T ]:
1180
1183
if args is not None and parsed_args is not None :
1181
1184
raise SettingsError ('`args` and `parsed_args` are mutually exclusive' )
@@ -1194,13 +1197,15 @@ def __call__(
1194
1197
def _load_env_vars (self ) -> Mapping [str , str | None ]: ...
1195
1198
1196
1199
@overload
1197
- def _load_env_vars (self , * , parsed_args : Namespace | dict [str , list [str ] | str ]) -> CliSettingsSource [T ]:
1200
+ def _load_env_vars (
1201
+ self , * , parsed_args : Namespace | SimpleNamespace | dict [str , list [str ] | str ]
1202
+ ) -> CliSettingsSource [T ]:
1198
1203
"""
1199
1204
Loads the parsed command line arguments into the CLI environment settings variables.
1200
1205
1201
1206
Note:
1202
- The parsed args must be in `argparse.Namespace` or vars dictionary (e.g., vars(argparse.Namespace))
1203
- format.
1207
+ The parsed args must be in `argparse.Namespace`, `SimpleNamespace`, or vars dictionary
1208
+ (e.g., vars(argparse.Namespace)) format.
1204
1209
1205
1210
Args:
1206
1211
parsed_args: The parsed args to load.
@@ -1211,12 +1216,12 @@ def _load_env_vars(self, *, parsed_args: Namespace | dict[str, list[str] | str])
1211
1216
...
1212
1217
1213
1218
def _load_env_vars (
1214
- self , * , parsed_args : Namespace | dict [str , list [str ] | str ] | None = None
1219
+ self , * , parsed_args : Namespace | SimpleNamespace | dict [str , list [str ] | str ] | None = None
1215
1220
) -> Mapping [str , str | None ] | CliSettingsSource [T ]:
1216
1221
if parsed_args is None :
1217
1222
return {}
1218
1223
1219
- if isinstance (parsed_args , Namespace ):
1224
+ if isinstance (parsed_args , ( Namespace , SimpleNamespace ) ):
1220
1225
parsed_args = vars (parsed_args )
1221
1226
1222
1227
selected_subcommands : list [str ] = []
@@ -1246,26 +1251,35 @@ def _load_env_vars(
1246
1251
1247
1252
return self
1248
1253
1254
+ def _get_merge_parsed_list_types (
1255
+ self , parsed_list : list [str ], field_name : str
1256
+ ) -> tuple [Optional [type ], Optional [type ]]:
1257
+ merge_type = self ._cli_dict_args .get (field_name , list )
1258
+ if (
1259
+ merge_type is list
1260
+ or not origin_is_union (get_origin (merge_type ))
1261
+ or not any (
1262
+ type_
1263
+ for type_ in get_args (merge_type )
1264
+ if type_ is not type (None ) and get_origin (type_ ) not in (dict , Mapping )
1265
+ )
1266
+ ):
1267
+ inferred_type = merge_type
1268
+ else :
1269
+ inferred_type = list if parsed_list and (len (parsed_list ) > 1 or parsed_list [0 ].startswith ('[' )) else str
1270
+
1271
+ return merge_type , inferred_type
1272
+
1249
1273
def _merge_parsed_list (self , parsed_list : list [str ], field_name : str ) -> str :
1250
1274
try :
1251
1275
merged_list : list [str ] = []
1252
1276
is_last_consumed_a_value = False
1253
- merge_type = self ._cli_dict_args .get (field_name , list )
1254
- if (
1255
- merge_type is list
1256
- or not origin_is_union (get_origin (merge_type ))
1257
- or not any (
1258
- type_
1259
- for type_ in get_args (merge_type )
1260
- if type_ is not type (None ) and get_origin (type_ ) not in (dict , Mapping )
1261
- )
1262
- ):
1263
- inferred_type = merge_type
1264
- else :
1265
- inferred_type = (
1266
- list if parsed_list and (len (parsed_list ) > 1 or parsed_list [0 ].startswith ('[' )) else str
1267
- )
1277
+ merge_type , inferred_type = self ._get_merge_parsed_list_types (parsed_list , field_name )
1268
1278
for val in parsed_list :
1279
+ if not isinstance (val , str ):
1280
+ # If val is not a string, it's from an external parser and we can ignore parsing the rest of the
1281
+ # list.
1282
+ break
1269
1283
val = val .strip ()
1270
1284
if val .startswith ('[' ) and val .endswith (']' ):
1271
1285
val = val [1 :- 1 ].strip ()
0 commit comments