Skip to content

Commit f3ef9c6

Browse files
authored
Fix merged result in parse_item not passed back to parse_object_fields (#2997)
* Fix merged result in parse_item not passed back to parse_object_fields (#2995) * Simplify docstring in test_ref_merge_field_metadata
1 parent 5011903 commit f3ef9c6

12 files changed

Lines changed: 269 additions & 11 deletions

File tree

src/datamodel_code_generator/parser/jsonschema.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2745,6 +2745,9 @@ def parse_object_fields(
27452745
)
27462746
continue
27472747

2748+
if field.has_ref_with_schema_keywords and not field.is_ref_with_nullable_only:
2749+
field = self._merge_ref_with_schema(field) # noqa: PLW2901
2750+
27482751
field_type = self.parse_item(modular_name, field, [*path, field_name])
27492752

27502753
effective_default, effective_has_default = self.model_resolver.resolve_default_value(
@@ -2814,18 +2817,21 @@ def parse_object(
28142817
if fields or not isinstance(obj.additionalProperties, JsonSchemaObject):
28152818
data_model_type_class = self.data_model_type
28162819
else:
2820+
additional_props = obj.additionalProperties
2821+
if additional_props.has_ref_with_schema_keywords and not additional_props.is_ref_with_nullable_only:
2822+
additional_props = self._merge_ref_with_schema(additional_props)
28172823
fields.append(
28182824
self.get_object_field(
28192825
field_name=None,
2820-
field=obj.additionalProperties,
2826+
field=additional_props,
28212827
required=True,
28222828
original_field_name=None,
28232829
field_type=self.data_type(
28242830
data_types=[
28252831
self.parse_item(
28262832
# TODO: Improve naming for nested ClassName
28272833
name,
2828-
obj.additionalProperties,
2834+
additional_props,
28292835
[*path, "additionalProperties"],
28302836
)
28312837
],

src/datamodel_code_generator/parser/openapi.py

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -508,7 +508,7 @@ def _get_model_name(cls, path_name: str, method: str, suffix: str) -> str:
508508
camel_path_name = snake_to_upper_camel(normalized)
509509
return f"{camel_path_name}{method.capitalize()}{suffix}"
510510

511-
def parse_all_parameters( # noqa: PLR0912, PLR0914
511+
def parse_all_parameters( # noqa: PLR0912, PLR0914, PLR0915
512512
self,
513513
name: str,
514514
parameters: list[ReferenceObject | ParameterObject],
@@ -541,10 +541,13 @@ def parse_all_parameters( # noqa: PLR0912, PLR0914
541541
class_name=name,
542542
)
543543
if parameter.schema_:
544+
param_schema = parameter.schema_
545+
if param_schema.has_ref_with_schema_keywords and not param_schema.is_ref_with_nullable_only:
546+
param_schema = self._merge_ref_with_schema(param_schema)
544547
effective_default, effective_has_default = self.model_resolver.resolve_default_value(
545548
parameter_name,
546-
parameter.schema_.default,
547-
parameter.schema_.has_default,
549+
param_schema.default,
550+
param_schema.has_default,
548551
class_name=reference.name,
549552
)
550553
effective_required = parameter.required
@@ -553,8 +556,8 @@ def parse_all_parameters( # noqa: PLR0912, PLR0914
553556
fields.append(
554557
self.get_object_field(
555558
field_name=field_name,
556-
field=parameter.schema_,
557-
field_type=self.parse_item(field_name, parameter.schema_, [*path, name, parameter_name]),
559+
field=param_schema,
560+
field_type=self.parse_item(field_name, param_schema, [*path, name, parameter_name]),
558561
original_field_name=parameter_name,
559562
required=effective_required,
560563
alias=alias,

tests/data/expected/main/jsonschema/ids/ContactPoint.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,15 @@
66

77
from enum import Enum
88

9-
from pydantic import BaseModel, EmailStr
9+
from pydantic import BaseModel, EmailStr, Field
1010

1111

1212
class Type(Enum):
1313
ContactPoint = 'ContactPoint'
1414

1515

1616
class Schema(BaseModel):
17-
type: Type
17+
type: Type = Field(..., description='Type of this object.', title='type')
1818
contactType: str | None = None
1919
email: EmailStr
2020
telephone: str | None = None

tests/data/expected/main/jsonschema/ids/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
from enum import Enum
88

9-
from pydantic import BaseModel
9+
from pydantic import BaseModel, Field
1010

1111
from . import URI, ContactPoint
1212
from . import id as id_1
@@ -20,7 +20,7 @@ class Type(Enum):
2020

2121
class Organization(BaseModel):
2222
id: id_1.Schema | None = None
23-
type: Type
23+
type: Type = Field(..., description='Type of this object.', title='type')
2424
name: name_1.Schema
2525
contactPoint: ContactPoint.Schema | None = None
2626
sameAs: sameAs_1.Schema | None = None
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# generated by datamodel-codegen:
2+
# filename: ref_merge_additional_properties.json
3+
# timestamp: 2019-07-26T00:00:00+00:00
4+
5+
from __future__ import annotations
6+
7+
from typing import Annotated, Literal
8+
9+
from pydantic import BaseModel, Field, RootModel
10+
11+
12+
class ConstrainedString(RootModel[str]):
13+
root: Annotated[str, Field(max_length=100, min_length=1)]
14+
15+
16+
class DictModel(RootModel[Literal['fixed']]):
17+
root: Annotated[Literal['fixed'], Field(max_length=100, min_length=1)]
18+
19+
20+
class Model(BaseModel):
21+
data: DictModel | None = None
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# generated by datamodel-codegen:
2+
# filename: ref_merge_field_metadata.json
3+
# timestamp: 2019-07-26T00:00:00+00:00
4+
5+
from __future__ import annotations
6+
7+
from typing import Annotated, Literal
8+
9+
from pydantic import BaseModel, Field, RootModel
10+
11+
12+
class Model(BaseModel):
13+
readonly_via_ref: Annotated[Literal['fixed_readonly'], Field(frozen=True)]
14+
readonly_direct: Annotated[Literal['fixed_readonly'], Field(frozen=True)]
15+
constrained_via_ref: Annotated[
16+
Literal['constrained_value'], Field(max_length=100, min_length=1)
17+
]
18+
constrained_direct: Annotated[
19+
Literal['constrained_value'], Field(max_length=100, min_length=1)
20+
]
21+
default_via_ref: Literal['default_value'] = 'default_value'
22+
default_direct: Literal['default_value'] = 'default_value'
23+
nullable_via_ref: Literal['nullable_value']
24+
nullable_direct: Literal['nullable_value']
25+
26+
27+
class ReadOnlyString(RootModel[str]):
28+
root: str
29+
30+
31+
class ConstrainedString(RootModel[str]):
32+
root: Annotated[str, Field(max_length=100, min_length=1)]
33+
34+
35+
class DefaultString(RootModel[str]):
36+
root: str = 'default_value'
37+
38+
39+
class NullableString(RootModel[str | None]):
40+
root: str | None = None
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# generated by datamodel-codegen:
2+
# filename: ref_merge_parameters.yaml
3+
# timestamp: 2019-07-26T00:00:00+00:00
4+
5+
from __future__ import annotations
6+
7+
from typing import Annotated, Literal
8+
9+
from pydantic import BaseModel, Field, RootModel
10+
11+
12+
class StatusString(RootModel[str]):
13+
root: str
14+
15+
16+
class ItemsGetParametersQuery(BaseModel):
17+
status: Annotated[Literal['active'], Field(frozen=True)]
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
{
2+
"$schema": "http://json-schema.org/draft-07/schema#",
3+
"definitions": {
4+
"ConstrainedString": {
5+
"type": "string",
6+
"minLength": 1,
7+
"maxLength": 100
8+
},
9+
"DictModel": {
10+
"type": "object",
11+
"additionalProperties": {
12+
"$ref": "#/definitions/ConstrainedString",
13+
"const": "fixed"
14+
}
15+
}
16+
},
17+
"type": "object",
18+
"properties": {
19+
"data": {
20+
"$ref": "#/definitions/DictModel"
21+
}
22+
}
23+
}
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
{
2+
"$schema": "http://json-schema.org/draft-07/schema#",
3+
"definitions": {
4+
"ReadOnlyString": {
5+
"type": "string",
6+
"readOnly": true
7+
},
8+
"ConstrainedString": {
9+
"type": "string",
10+
"minLength": 1,
11+
"maxLength": 100
12+
},
13+
"DefaultString": {
14+
"type": "string",
15+
"default": "default_value"
16+
},
17+
"NullableString": {
18+
"type": "string",
19+
"nullable": true
20+
}
21+
},
22+
"type": "object",
23+
"properties": {
24+
"readonly_via_ref": {
25+
"$ref": "#/definitions/ReadOnlyString",
26+
"const": "fixed_readonly"
27+
},
28+
"readonly_direct": {
29+
"type": "string",
30+
"readOnly": true,
31+
"const": "fixed_readonly"
32+
},
33+
"constrained_via_ref": {
34+
"$ref": "#/definitions/ConstrainedString",
35+
"const": "constrained_value"
36+
},
37+
"constrained_direct": {
38+
"type": "string",
39+
"minLength": 1,
40+
"maxLength": 100,
41+
"const": "constrained_value"
42+
},
43+
"default_via_ref": {
44+
"$ref": "#/definitions/DefaultString",
45+
"const": "default_value"
46+
},
47+
"default_direct": {
48+
"type": "string",
49+
"default": "default_value",
50+
"const": "default_value"
51+
},
52+
"nullable_via_ref": {
53+
"$ref": "#/definitions/NullableString",
54+
"const": "nullable_value"
55+
},
56+
"nullable_direct": {
57+
"type": "string",
58+
"nullable": true,
59+
"const": "nullable_value"
60+
}
61+
},
62+
"required": [
63+
"readonly_via_ref",
64+
"readonly_direct",
65+
"constrained_via_ref",
66+
"constrained_direct",
67+
"nullable_via_ref",
68+
"nullable_direct"
69+
]
70+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
openapi: "3.0.0"
2+
info:
3+
version: 1.0.0
4+
title: Test
5+
paths:
6+
/items:
7+
get:
8+
operationId: getItems
9+
parameters:
10+
- name: status
11+
in: query
12+
required: true
13+
schema:
14+
$ref: "#/components/schemas/StatusString"
15+
const: "active"
16+
responses:
17+
'200':
18+
description: OK
19+
components:
20+
schemas:
21+
StatusString:
22+
type: string
23+
readOnly: true

0 commit comments

Comments
 (0)