Skip to content

Commit 9ca6624

Browse files
maximilian-techMaximilian Sander
authored andcommitted
Extend parsing of Scientific Notation to JSON capabilites
1 parent 117a31d commit 9ca6624

File tree

4 files changed

+37
-11
lines changed

4 files changed

+37
-11
lines changed

src/datamodel_code_generator/__init__.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
PythonVersionMin,
3131
)
3232
from datamodel_code_generator.parser import DefaultPutDict, LiteralType
33-
from datamodel_code_generator.util import SafeLoader
33+
from datamodel_code_generator.util import SafeLoader, get_SafeLoader
3434

3535
MIN_VERSION: Final[int] = 9
3636
MAX_VERSION: Final[int] = 13
@@ -46,9 +46,12 @@
4646

4747
DEFAULT_BASE_CLASS: str = "pydantic.BaseModel"
4848

49+
g_extend_yaml_scientifc_notation = False
50+
def get_SafeLoader_(SafeLoader):
51+
return get_SafeLoader(SafeLoader, g_extend_yaml_scientifc_notation)
4952

5053
def load_yaml(stream: str | TextIO) -> Any:
51-
return yaml.load(stream, Loader=SafeLoader) # noqa: S506
54+
return yaml.load(stream, Loader=get_SafeLoader_(SafeLoader)) # noqa: S506
5255

5356

5457
def load_yaml_from_path(path: Path, encoding: str) -> Any:
@@ -262,6 +265,7 @@ def generate( # noqa: PLR0912, PLR0913, PLR0914, PLR0915
262265
use_title_as_name: bool = False,
263266
use_operation_id_as_name: bool = False,
264267
use_unique_items_as_set: bool = False,
268+
extend_yaml_scientifc_notation: bool = False,
265269
http_headers: Sequence[tuple[str, str]] | None = None,
266270
http_ignore_tls: bool = False,
267271
use_annotated: bool = False,
@@ -288,6 +292,8 @@ def generate( # noqa: PLR0912, PLR0913, PLR0914, PLR0915
288292
no_alias: bool = False,
289293
formatters: list[Formatter] = DEFAULT_FORMATTERS,
290294
) -> None:
295+
global g_extend_yaml_scientifc_notation
296+
g_extend_yaml_scientifc_notation = extend_yaml_scientifc_notation
291297
remote_text_cache: DefaultPutDict[str, str] = DefaultPutDict()
292298
if isinstance(input_, str):
293299
input_text: str | None = input_

src/datamodel_code_generator/__main__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,6 @@
5656
model_validator,
5757
)
5858

59-
6059
class Exit(IntEnum):
6160
"""Exit reasons."""
6261

@@ -290,6 +289,7 @@ def validate_root(cls, values: Any) -> Any: # noqa: N805
290289
use_title_as_name: bool = False
291290
use_operation_id_as_name: bool = False
292291
use_unique_items_as_set: bool = False
292+
extend_yaml_scientifc_notation: bool = False
293293
http_headers: Optional[Sequence[tuple[str, str]]] = None # noqa: UP045
294294
http_ignore_tls: bool = False
295295
use_annotated: bool = False
@@ -498,6 +498,7 @@ def main(args: Sequence[str] | None = None) -> Exit: # noqa: PLR0911, PLR0912,
498498
use_title_as_name=config.use_title_as_name,
499499
use_operation_id_as_name=config.use_operation_id_as_name,
500500
use_unique_items_as_set=config.use_unique_items_as_set,
501+
extend_yaml_scientifc_notation=config.extend_yaml_scientifc_notation,
501502
http_headers=config.http_headers,
502503
http_ignore_tls=config.http_ignore_tls,
503504
use_annotated=config.use_annotated,

src/datamodel_code_generator/arguments.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,12 @@ def start_section(self, heading: str | None) -> None:
286286
action="store_true",
287287
default=None,
288288
)
289+
typing_options.add_argument(
290+
"--extend-yaml-scientifc-notation",
291+
help="Parse scientific floating point as specified by json instead of yaml.",
292+
action="store_true",
293+
default=None,
294+
)
289295

290296
# ======================================================================================
291297
# Customization options for generated model fields

src/datamodel_code_generator/util.py

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from __future__ import annotations
22

33
import copy
4+
import re
45
from typing import TYPE_CHECKING, Any, Callable, TypeVar
56

67
import pydantic
@@ -34,14 +35,26 @@ def load_toml(path: Path) -> dict[str, Any]:
3435
with path.open("rb") as f:
3536
return load_tomllib(f)
3637

37-
38-
SafeLoaderTemp = copy.deepcopy(SafeLoader)
39-
SafeLoaderTemp.yaml_constructors = copy.deepcopy(SafeLoader.yaml_constructors)
40-
SafeLoaderTemp.add_constructor(
41-
"tag:yaml.org,2002:timestamp",
42-
SafeLoaderTemp.yaml_constructors["tag:yaml.org,2002:str"],
43-
)
44-
SafeLoader = SafeLoaderTemp
38+
def get_SafeLoader(SafeLoader, extend_yaml_scientifc_notation=False):
39+
SafeLoaderTemp = copy.deepcopy(SafeLoader)
40+
SafeLoaderTemp.yaml_constructors = copy.deepcopy(SafeLoader.yaml_constructors)
41+
SafeLoaderTemp.add_constructor(
42+
"tag:yaml.org,2002:timestamp",
43+
SafeLoaderTemp.yaml_constructors["tag:yaml.org,2002:str"],
44+
)
45+
if extend_yaml_scientifc_notation is True:
46+
SafeLoaderTemp.add_implicit_resolver(
47+
u'tag:yaml.org,2002:float',
48+
re.compile(u'''^(?:
49+
[-+]?(?:[0-9][0-9_]*)\\.[0-9_]*(?:[eE][-+]?[0-9]+)?
50+
|[-+]?(?:[0-9][0-9_]*)(?:[eE][-+]?[0-9]+)
51+
|\\.[0-9_]+(?:[eE][-+][0-9]+)?
52+
|[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+\\.[0-9_]*
53+
|[-+]?\\.(?:inf|Inf|INF)
54+
|\\.(?:nan|NaN|NAN))$''', re.X),
55+
list(u'-+0123456789.')
56+
)
57+
return SafeLoaderTemp
4558

4659
Model = TypeVar("Model", bound=_BaseModel)
4760

0 commit comments

Comments
 (0)