19
19
from __future__ import annotations
20
20
21
21
import binascii
22
+ import enum
22
23
import errno
23
24
import json
25
+ import sys
24
26
import typing
25
27
26
28
_VALID_VERSIONS = ["v0" ]
48
50
_JSON_SCHEMA : dict [str , typing .Any ] = {}
49
51
50
52
53
+ class ConfigFormat (enum .Enum ):
54
+ JSON = "json"
55
+ TOML = "toml"
56
+
57
+
51
58
class ValidationUnsupported (Exception ):
52
59
pass
53
60
@@ -56,6 +63,31 @@ class _FakeRefResolutionError(Exception):
56
63
pass
57
64
58
65
66
+ class ConfigFormatUnsupported (Exception ):
67
+ pass
68
+
69
+
70
+ if sys .version_info >= (3 , 11 ):
71
+
72
+ def _load_toml (source : typing .IO ) -> JSONData :
73
+ try :
74
+ import tomllib
75
+ except ImportError :
76
+ raise ConfigFormatUnsupported (ConfigFormat .TOML )
77
+ return tomllib .load (source )
78
+
79
+ else :
80
+
81
+ def _load_toml (source : typing .IO ) -> JSONData :
82
+ raise ConfigFormatUnsupported (ConfigFormat .TOML )
83
+
84
+
85
+ def _detect_format (fname : str ) -> ConfigFormat :
86
+ if fname .endswith (".toml" ):
87
+ return ConfigFormat .TOML
88
+ return ConfigFormat .JSON
89
+
90
+
59
91
def _schema_validate (data : dict [str , typing .Any ], version : str ) -> None :
60
92
try :
61
93
import jsonschema # type: ignore[import]
@@ -119,9 +151,14 @@ def read_config_files(
119
151
gconfig = GlobalConfig ()
120
152
readfiles = set ()
121
153
for fname in fnames :
154
+ config_format = _detect_format (str (fname ))
122
155
try :
123
- with _open (fname ) as fh :
124
- gconfig .load (fh , require_validation = require_validation )
156
+ with _open (fname , "rb" ) as fh :
157
+ gconfig .load (
158
+ fh ,
159
+ require_validation = require_validation ,
160
+ config_format = config_format ,
161
+ )
125
162
readfiles .add (fname )
126
163
except OSError as err :
127
164
if getattr (err , "errno" , 0 ) != errno .ENOENT :
@@ -154,9 +191,15 @@ def __init__(
154
191
def load (
155
192
self ,
156
193
source : typing .IO ,
194
+ * ,
157
195
require_validation : typing .Optional [bool ] = None ,
196
+ config_format : typing .Optional [ConfigFormat ] = None ,
158
197
) -> None :
159
- data = json .load (source )
198
+ config_format = config_format or ConfigFormat .JSON
199
+ if config_format == ConfigFormat .TOML :
200
+ data = _load_toml (source )
201
+ else :
202
+ data = json .load (source )
160
203
_check_config_valid (
161
204
data , _check_config_version (data ), require_validation
162
205
)
0 commit comments