22
33import inspect
44import re
5- from typing import Any , Callable , Dict , Optional , Tuple , Type
5+ from contextlib import suppress
6+ from typing import Any , Callable , Dict , Optional , Set , Tuple , Type
67
78from ._common import load_value_mode , parent_parser
8- from ._optionals import import_jsonnet , omegaconf_support , pyyaml_available
9+ from ._optionals import import_jsonnet , import_toml_dumps , import_toml_loads , omegaconf_support , pyyaml_available
910from ._type_checking import ArgumentParser
1011
1112__all__ = [
1516]
1617
1718
19+ not_loaded = object ()
1820yaml_default_loader = None
1921
2022
23+ def load_basic (value ):
24+ value = value .strip ()
25+ if value == "true" :
26+ return True
27+ if value == "false" :
28+ return False
29+ if value == "null" :
30+ return None
31+ if value .isdigit () or (value .startswith ("-" ) and value [1 :].isdigit ()):
32+ return int (value )
33+ if value .replace ("." , "" , 1 ).replace ("e" , "" , 1 ).replace ("-" , "" , 2 ).isdigit () and ("e" in value or "." in value ):
34+ return float (value )
35+ return not_loaded
36+
37+
2138def get_yaml_default_loader ():
2239 global yaml_default_loader
2340 if yaml_default_loader :
@@ -57,7 +74,7 @@ def remove_implicit_resolver(cls, tag_to_remove):
5774 )
5875
5976 yaml_default_loader = DefaultLoader
60- return DefaultLoader
77+ return yaml_default_loader
6178
6279
6380def yaml_load (stream ):
@@ -74,13 +91,15 @@ def yaml_load(stream):
7491 return value
7592
7693
77- def json_load (stream ):
94+ def json_load (value ):
7895 import json
7996
80- try :
81- return json .loads (stream )
82- except json .JSONDecodeError :
83- return stream
97+ return json .loads (value )
98+
99+
100+ def toml_load (value ):
101+ toml_loads , _ = import_toml_loads ("toml_load" )
102+ return toml_loads (value )
84103
85104
86105def jsonnet_load (stream , path = "" , ext_vars = None ):
@@ -101,10 +120,15 @@ def jsonnet_load(stream, path="", ext_vars=None):
101120loaders : Dict [str , Callable ] = {
102121 "yaml" : yaml_load ,
103122 "json" : json_load ,
104- "jsonnet " : jsonnet_load ,
123+ "toml " : toml_load ,
105124}
106-
107125loader_exceptions : Dict [str , Tuple [Type [Exception ], ...]] = {}
126+ loader_json_superset : Dict [str , bool ] = {
127+ "yaml" : True ,
128+ "json" : True ,
129+ "toml" : False ,
130+ }
131+ loader_params : Dict [str , Set [str ]] = {}
108132
109133
110134def get_load_value_mode () -> str :
@@ -123,28 +147,56 @@ def get_loader_exceptions(mode: Optional[str] = None) -> Tuple[Type[Exception],
123147 if mode == "yaml" :
124148 loader_exceptions [mode ] = (__import__ ("yaml" ).YAMLError ,)
125149 elif mode == "json" :
126- loader_exceptions [mode ] = tuple ()
150+ loader_exceptions [mode ] = (__import__ ("json" ).JSONDecodeError ,)
151+ elif mode == "toml" :
152+ loader_exceptions [mode ] = (import_toml_loads ("get_loader_exceptions" )[1 ],)
127153 elif mode == "jsonnet" :
128- return get_loader_exceptions ("yaml" if pyyaml_available else "json" )
154+ return get_loader_exceptions ("yaml" if pyyaml_available else "json" ) + ( ValueError ,)
129155 return loader_exceptions [mode ]
130156
131157
132- json_or_yaml_load = yaml_load if pyyaml_available else json_load
158+ def json_or_yaml_load (value ):
159+ if pyyaml_available :
160+ if isinstance (value , str ) and value .strip () == "" :
161+ return value
162+ return yaml_load (value )
163+ return json_load (value )
164+
165+
133166json_or_yaml_loader_exceptions = get_loader_exceptions ("yaml" if pyyaml_available else "json" )
134167
135168
169+ def load_list_or_dict (value : str ):
170+ strip = value .strip ()
171+ if (strip .startswith ("[" ) and strip .endswith ("]" )) or (strip .startswith ("{" ) and strip .endswith ("}" )):
172+ import json
173+
174+ with suppress (json .JSONDecodeError ):
175+ return json .loads (strip )
176+ return not_loaded
177+
178+
136179def load_value (value : str , simple_types : bool = False , ** kwargs ):
137- if not value :
138- return None
139- elif value .strip () == "-" :
180+ if value .strip () == "-" :
140181 return value
141- loader = loaders [get_load_value_mode ()]
142- if kwargs :
143- params = set (list (inspect .signature (loader ).parameters )[1 :])
144- kwargs = {k : v for k , v in kwargs .items () if k in params }
145- loaded_value = loader (value , ** kwargs )
182+
183+ loaded_value = load_basic (value )
184+
185+ mode = get_load_value_mode ()
186+ if loaded_value is not_loaded and not loader_json_superset [mode ]:
187+ loaded_value = load_list_or_dict (value )
188+
189+ if loaded_value is not_loaded :
190+ loader = loaders [mode ]
191+ load_kwargs = {}
192+ if kwargs and mode in loader_params :
193+ params = loader_params [mode ]
194+ load_kwargs = {k : v for k , v in kwargs .items () if k in params }
195+ loaded_value = loader (value , ** load_kwargs )
196+
146197 if not simple_types and isinstance (loaded_value , (int , float , bool , str )):
147198 loaded_value = value
199+
148200 return loaded_value
149201
150202
@@ -172,7 +224,7 @@ def yaml_comments_dump(data, parser):
172224 return formatter .add_yaml_comments (dump )
173225
174226
175- def json_dump (data ):
227+ def json_compact_dump (data ):
176228 import json
177229
178230 return json .dumps (data , separators = ("," , ":" ), ** dump_json_kwargs )
@@ -184,18 +236,26 @@ def json_indented_dump(data):
184236 return json .dumps (data , indent = 2 , ** dump_json_kwargs ) + "\n "
185237
186238
239+ def toml_dump (data ):
240+ toml_dumps = import_toml_dumps ("toml_dump" )
241+ return toml_dumps (data )
242+
243+
187244dumpers : Dict [str , Callable ] = {
188245 "yaml" : yaml_dump ,
189246 "yaml_comments" : yaml_comments_dump ,
190- "json" : json_dump ,
247+ "json" : json_compact_dump ,
248+ "json_compact" : json_compact_dump ,
191249 "json_indented" : json_indented_dump ,
250+ "toml" : toml_dump ,
192251 "jsonnet" : json_indented_dump ,
193252}
194253
195254comment_prefix : Dict [str , str ] = {
196255 "yaml" : "# " ,
197256 "yaml_comments" : "# " ,
198257 "jsonnet" : "// " ,
258+ "toml" : "# " ,
199259}
200260
201261
@@ -220,6 +280,7 @@ def set_loader(
220280 mode : str ,
221281 loader_fn : Callable [[str ], Any ],
222282 exceptions : Tuple [Type [Exception ], ...] = tuple (),
283+ json_superset : bool = True ,
223284):
224285 """Sets the value loader function to be used when parsing with a certain mode.
225286
@@ -234,9 +295,14 @@ def set_loader(
234295 loader_fn: The loader function to set. Example: ``yaml.safe_load``.
235296 exceptions: Exceptions that the loader can raise when load fails.
236297 Example: (yaml.YAMLError,).
298+ json_superset: Whether the loader can load JSON data.
237299 """
238300 loaders [mode ] = loader_fn
239301 loader_exceptions [mode ] = exceptions
302+ loader_json_superset [mode ] = json_superset
303+ params = set (list (inspect .signature (loader_fn ).parameters )[1 :])
304+ if params :
305+ loader_params [mode ] = params
240306
241307
242308def get_loader (mode : str ):
@@ -259,3 +325,6 @@ def set_omegaconf_loader():
259325 from ._optionals import get_omegaconf_loader
260326
261327 set_loader ("omegaconf" , get_omegaconf_loader ())
328+
329+
330+ set_loader ("jsonnet" , jsonnet_load , get_loader_exceptions ("jsonnet" ))
0 commit comments