Skip to content

Commit b5a361d

Browse files
authored
Fix YAML scientific notation parsing as float (#2913)
1 parent c1682ac commit b5a361d

File tree

4 files changed

+55
-0
lines changed

4 files changed

+55
-0
lines changed

src/datamodel_code_generator/util.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,9 @@ def is_pydantic_v2() -> bool:
5959

6060
_YAML_1_2_BOOL_PATTERN = re.compile(r"^(?:true|false|True|False|TRUE|FALSE)$")
6161
_YAML_DEPRECATED_BOOL_VALUES = {"True", "False", "TRUE", "FALSE"}
62+
# Pattern for scientific notation without decimal point (e.g., 1e-5, 1E+10)
63+
# Standard YAML only matches floats with decimal points, missing patterns like "1e-5"
64+
_YAML_SCIENTIFIC_NOTATION_PATTERN = re.compile(r"^[-+]?[0-9][0-9_]*[eE][-+]?[0-9]+$")
6265

6366

6467
def _construct_yaml_bool_with_warning(loader: Any, node: Any) -> bool:
@@ -104,6 +107,13 @@ class CustomSafeLoader(_SafeLoader): # type: ignore[valid-type,misc]
104107
))
105108
CustomSafeLoader.yaml_constructors["tag:yaml.org,2002:bool"] = _construct_yaml_bool_with_warning
106109

110+
# Add scientific notation without decimal point (e.g., 1e-5) as float
111+
for key in ["-", "+", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9"]:
112+
CustomSafeLoader.yaml_implicit_resolvers.setdefault(key, []).append((
113+
"tag:yaml.org,2002:float",
114+
_YAML_SCIENTIFIC_NOTATION_PATTERN,
115+
))
116+
107117
return CustomSafeLoader
108118

109119

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# generated by datamodel-codegen:
2+
# filename: scientific_notation.yaml
3+
# timestamp: 2019-07-26T00:00:00+00:00
4+
5+
from __future__ import annotations
6+
7+
from pydantic import BaseModel
8+
9+
10+
class Model(BaseModel):
11+
exponential_default: float | None = 1e-05
12+
positive_exp: float | None = 20000000000.0
13+
negative_prefix: float | None = -30000.0
14+
with_decimal: float | None = 1.5e-05
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
$schema: http://json-schema.org/draft-07/schema#
2+
type: object
3+
properties:
4+
exponential_default:
5+
type: number
6+
default: 1e-5
7+
positive_exp:
8+
type: number
9+
default: 2E+10
10+
negative_prefix:
11+
type: number
12+
default: -3e4
13+
with_decimal:
14+
type: number
15+
default: 1.5e-5

tests/main/test_main_yaml.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,3 +73,19 @@ def test_main_yaml_deprecated_bool(output_file: Path) -> None:
7373
output_path=output_file,
7474
input_file_type="openapi",
7575
)
76+
77+
78+
def test_main_yaml_scientific_notation(output_file: Path) -> None:
79+
"""Test YAML file with scientific notation default values (issue #1955).
80+
81+
Scientific notation without decimal point (e.g., 1e-5) should be parsed as float,
82+
not as string.
83+
"""
84+
run_main_and_assert(
85+
input_path=YAML_DATA_PATH / "scientific_notation.yaml",
86+
output_path=output_file,
87+
input_file_type="jsonschema",
88+
extra_args=["--output-model-type", "pydantic_v2.BaseModel"],
89+
assert_func=assert_file_content,
90+
expected_file="yaml/scientific_notation.py",
91+
)

0 commit comments

Comments
 (0)