diff --git a/datamodel_code_generator/parser/base.py b/datamodel_code_generator/parser/base.py index 6d80891d2..8a8ea898c 100644 --- a/datamodel_code_generator/parser/base.py +++ b/datamodel_code_generator/parser/base.py @@ -700,6 +700,7 @@ def __change_from_import( from_, import_ = full_path = relative( model.module_name, data_type.full_name ) + import_ = import_.replace('-', '_') alias = scoped_model_resolver.add(full_path, import_).name @@ -778,10 +779,18 @@ def __apply_discriminator_type( discriminator_model.path.split('#/')[-1] != path.split('#/')[-1] ): - if '#' in path or discriminator_model.path[ - :-1 - ] != path.lstrip('./'): - continue + if ( + path.startswith('#/') + or discriminator_model.path[:-1] + != path.split('/')[-1] + ): + t_path = path[str(path).find('/') + 1 :] + t_disc = discriminator_model.path[ + : str(discriminator_model.path).find('#') + ].lstrip('../') + t_disc_2 = '/'.join(t_disc.split('/')[1:]) + if t_path != t_disc and t_path != t_disc_2: + continue type_names.append(name) else: type_names = [discriminator_model.path.split('/')[-1]] @@ -1252,6 +1261,7 @@ class Processed(NamedTuple): init = True else: module = (*module[:-1], f'{module[-1]}.py') + module = tuple(part.replace('-', '_') for part in module) else: module = ('__init__.py',) diff --git a/tests/data/expected/main/discriminator_with_external_reference/output.py b/tests/data/expected/main/discriminator_with_external_reference/output.py index a2a1f1d8a..8d87f2bba 100644 --- a/tests/data/expected/main/discriminator_with_external_reference/output.py +++ b/tests/data/expected/main/discriminator_with_external_reference/output.py @@ -4,7 +4,7 @@ from __future__ import annotations -from typing import Union +from typing import Optional, Union from pydantic import BaseModel, Field from typing_extensions import Literal @@ -16,6 +16,15 @@ class Type1(BaseModel): class Type2(BaseModel): type_: Literal['b'] = Field('b', title='Type ') + ref_type: Optional[Type1] = Field(None, description='A referenced type.') + + +class Type4(BaseModel): + type_: Literal['d'] = Field('d', title='Type ') + + +class Type5(BaseModel): + type_: Literal['e'] = Field('e', title='Type ') class Type3(BaseModel): @@ -23,4 +32,6 @@ class Type3(BaseModel): class Response(BaseModel): - inner: Union[Type1, Type2, Type3] = Field(..., discriminator='type_', title='Inner') + inner: Union[Type1, Type2, Type3, Type4, Type5] = Field( + ..., discriminator='type_', title='Inner' + ) diff --git a/tests/data/expected/main/discriminator_with_external_references_folder/__init__.py b/tests/data/expected/main/discriminator_with_external_references_folder/__init__.py new file mode 100644 index 000000000..abc855210 --- /dev/null +++ b/tests/data/expected/main/discriminator_with_external_references_folder/__init__.py @@ -0,0 +1,3 @@ +# generated by datamodel-codegen: +# filename: discriminator_with_external_reference +# timestamp: 2019-07-26T00:00:00+00:00 diff --git a/tests/data/expected/main/discriminator_with_external_references_folder/inner_folder/__init__.py b/tests/data/expected/main/discriminator_with_external_references_folder/inner_folder/__init__.py new file mode 100644 index 000000000..abc855210 --- /dev/null +++ b/tests/data/expected/main/discriminator_with_external_references_folder/inner_folder/__init__.py @@ -0,0 +1,3 @@ +# generated by datamodel-codegen: +# filename: discriminator_with_external_reference +# timestamp: 2019-07-26T00:00:00+00:00 diff --git a/tests/data/expected/main/discriminator_with_external_references_folder/inner_folder/artificial_folder/__init__.py b/tests/data/expected/main/discriminator_with_external_references_folder/inner_folder/artificial_folder/__init__.py new file mode 100644 index 000000000..abc855210 --- /dev/null +++ b/tests/data/expected/main/discriminator_with_external_references_folder/inner_folder/artificial_folder/__init__.py @@ -0,0 +1,3 @@ +# generated by datamodel-codegen: +# filename: discriminator_with_external_reference +# timestamp: 2019-07-26T00:00:00+00:00 diff --git a/tests/data/expected/main/discriminator_with_external_references_folder/inner_folder/artificial_folder/type_1.py b/tests/data/expected/main/discriminator_with_external_references_folder/inner_folder/artificial_folder/type_1.py new file mode 100644 index 000000000..8df555769 --- /dev/null +++ b/tests/data/expected/main/discriminator_with_external_references_folder/inner_folder/artificial_folder/type_1.py @@ -0,0 +1,12 @@ +# generated by datamodel-codegen: +# filename: inner_folder/artificial_folder/type-1.json +# timestamp: 2019-07-26T00:00:00+00:00 + +from __future__ import annotations + +from pydantic import BaseModel, Field +from typing_extensions import Literal + + +class Type1(BaseModel): + type_: Literal['a'] = Field(..., const=True, title='Type ') diff --git a/tests/data/expected/main/discriminator_with_external_references_folder/inner_folder/schema.py b/tests/data/expected/main/discriminator_with_external_references_folder/inner_folder/schema.py new file mode 100644 index 000000000..21806d292 --- /dev/null +++ b/tests/data/expected/main/discriminator_with_external_references_folder/inner_folder/schema.py @@ -0,0 +1,25 @@ +# generated by datamodel-codegen: +# filename: inner_folder/schema.json +# timestamp: 2019-07-26T00:00:00+00:00 + +from __future__ import annotations + +from typing import Union + +from pydantic import BaseModel, Field +from typing_extensions import Literal + +from .. import type_4 +from ..subfolder import type_5 +from . import type_2 +from .artificial_folder import type_1 + + +class Type3(BaseModel): + type_: Literal['c'] = Field(..., const=True, title='Type ') + + +class Response(BaseModel): + inner: Union[type_1.Type1, type_2.Type2, Type3, type_4.Type4, type_5.Type5] = Field( + ..., discriminator='type_', title='Inner' + ) diff --git a/tests/data/expected/main/discriminator_with_external_references_folder/inner_folder/type_2.py b/tests/data/expected/main/discriminator_with_external_references_folder/inner_folder/type_2.py new file mode 100644 index 000000000..95342e63d --- /dev/null +++ b/tests/data/expected/main/discriminator_with_external_references_folder/inner_folder/type_2.py @@ -0,0 +1,16 @@ +# generated by datamodel-codegen: +# filename: inner_folder/type-2.json +# timestamp: 2019-07-26T00:00:00+00:00 + +from __future__ import annotations + +from typing import Optional + +from pydantic import BaseModel, Field + +from .artificial_folder import type_1 + + +class Type2(BaseModel): + type_: Literal['b'] = Field(..., const=True, title='Type ') + ref_type: Optional[type_1.Type1] = Field(None, description='A referenced type.') diff --git a/tests/data/expected/main/discriminator_with_external_references_folder/subfolder/__init__.py b/tests/data/expected/main/discriminator_with_external_references_folder/subfolder/__init__.py new file mode 100644 index 000000000..abc855210 --- /dev/null +++ b/tests/data/expected/main/discriminator_with_external_references_folder/subfolder/__init__.py @@ -0,0 +1,3 @@ +# generated by datamodel-codegen: +# filename: discriminator_with_external_reference +# timestamp: 2019-07-26T00:00:00+00:00 diff --git a/tests/data/expected/main/discriminator_with_external_references_folder/subfolder/type_5.py b/tests/data/expected/main/discriminator_with_external_references_folder/subfolder/type_5.py new file mode 100644 index 000000000..2a1361794 --- /dev/null +++ b/tests/data/expected/main/discriminator_with_external_references_folder/subfolder/type_5.py @@ -0,0 +1,11 @@ +# generated by datamodel-codegen: +# filename: subfolder/type-5.json +# timestamp: 2019-07-26T00:00:00+00:00 + +from __future__ import annotations + +from pydantic import BaseModel, Field + + +class Type5(BaseModel): + type_: Literal['e'] = Field(..., const=True, title='Type ') diff --git a/tests/data/expected/main/discriminator_with_external_references_folder/type_4.py b/tests/data/expected/main/discriminator_with_external_references_folder/type_4.py new file mode 100644 index 000000000..abad814bf --- /dev/null +++ b/tests/data/expected/main/discriminator_with_external_references_folder/type_4.py @@ -0,0 +1,11 @@ +# generated by datamodel-codegen: +# filename: type-4.json +# timestamp: 2019-07-26T00:00:00+00:00 + +from __future__ import annotations + +from pydantic import BaseModel, Field + + +class Type4(BaseModel): + type_: Literal['d'] = Field(..., const=True, title='Type ') diff --git a/tests/data/jsonschema/discriminator_with_external_reference/artificial_folder/type1.json b/tests/data/jsonschema/discriminator_with_external_reference/inner_folder/artificial_folder/type-1.json similarity index 100% rename from tests/data/jsonschema/discriminator_with_external_reference/artificial_folder/type1.json rename to tests/data/jsonschema/discriminator_with_external_reference/inner_folder/artificial_folder/type-1.json diff --git a/tests/data/jsonschema/discriminator_with_external_reference/schema.json b/tests/data/jsonschema/discriminator_with_external_reference/inner_folder/schema.json similarity index 59% rename from tests/data/jsonschema/discriminator_with_external_reference/schema.json rename to tests/data/jsonschema/discriminator_with_external_reference/inner_folder/schema.json index 0fb5c52c7..0fce2310c 100644 --- a/tests/data/jsonschema/discriminator_with_external_reference/schema.json +++ b/tests/data/jsonschema/discriminator_with_external_reference/inner_folder/schema.json @@ -16,21 +16,29 @@ "inner": { "discriminator": { "mapping": { - "a": "./artificial_folder/type1.json", - "b": "./type2.json", - "c": "#/$def/Type3" + "a": "./artificial_folder/type-1.json", + "b": "./type-2.json", + "c": "#/$def/Type3", + "d": "../type-4.json", + "e": "../subfolder/type-5.json" }, "propertyName": "type_" }, "oneOf": [ { - "$ref": "./artificial_folder/type1.json" + "$ref": "./artificial_folder/type-1.json" }, { - "$ref": "./type2.json" + "$ref": "./type-2.json" }, { "$ref": "#/$def/Type3" + }, + { + "$ref": "../type-4.json" + }, + { + "$ref": "../subfolder/type-5.json" } ], "title": "Inner" diff --git a/tests/data/jsonschema/discriminator_with_external_reference/inner_folder/type-2.json b/tests/data/jsonschema/discriminator_with_external_reference/inner_folder/type-2.json new file mode 100644 index 000000000..b76c25b14 --- /dev/null +++ b/tests/data/jsonschema/discriminator_with_external_reference/inner_folder/type-2.json @@ -0,0 +1,15 @@ +{ + "properties": { + "type_": { + "const": "b", + "default": "b", + "title": "Type " + }, + "ref_type": { + "$ref": "./artificial_folder/type-1.json", + "description": "A referenced type." + } + }, + "title": "Type2", + "type": "object" +} \ No newline at end of file diff --git a/tests/data/jsonschema/discriminator_with_external_reference/type2.json b/tests/data/jsonschema/discriminator_with_external_reference/subfolder/type-5.json similarity index 58% rename from tests/data/jsonschema/discriminator_with_external_reference/type2.json rename to tests/data/jsonschema/discriminator_with_external_reference/subfolder/type-5.json index aab0950a1..ada842093 100644 --- a/tests/data/jsonschema/discriminator_with_external_reference/type2.json +++ b/tests/data/jsonschema/discriminator_with_external_reference/subfolder/type-5.json @@ -1,11 +1,11 @@ { "properties": { "type_": { - "const": "b", - "default": "b", + "const": "e", + "default": "e", "title": "Type " } }, - "title": "Type2", + "title": "Type5", "type": "object" } \ No newline at end of file diff --git a/tests/data/jsonschema/discriminator_with_external_reference/type-4.json b/tests/data/jsonschema/discriminator_with_external_reference/type-4.json new file mode 100644 index 000000000..4c357a275 --- /dev/null +++ b/tests/data/jsonschema/discriminator_with_external_reference/type-4.json @@ -0,0 +1,11 @@ +{ + "properties": { + "type_": { + "const": "d", + "default": "d", + "title": "Type " + } + }, + "title": "Type4", + "type": "object" +} \ No newline at end of file diff --git a/tests/test_main.py b/tests/test_main.py index dae1bfcca..49bc9e0bd 100644 --- a/tests/test_main.py +++ b/tests/test_main.py @@ -6133,6 +6133,7 @@ def test_main_jsonschema_external_discriminator(): str( JSON_SCHEMA_DATA_PATH / 'discriminator_with_external_reference' + / 'inner_folder' / 'schema.json' ), '--output', @@ -6152,6 +6153,29 @@ def test_main_jsonschema_external_discriminator(): ) +@freeze_time('2019-07-26') +def test_main_jsonschema_external_discriminator_folder(): + with TemporaryDirectory() as output_dir: + output_path: Path = Path(output_dir) + return_code: Exit = main( + [ + '--input', + str(JSON_SCHEMA_DATA_PATH / 'discriminator_with_external_reference'), + '--output', + str(output_path), + ] + ) + assert return_code == Exit.OK + main_modular_dir = ( + EXPECTED_MAIN_PATH / 'discriminator_with_external_references_folder' + ) + for path in main_modular_dir.rglob('*.py'): + result = output_path.joinpath( + path.relative_to(main_modular_dir) + ).read_text() + assert result == path.read_text() + + @freeze_time('2019-07-26') @pytest.mark.skipif( black.__version__.split('.')[0] == '19',