Skip to content

Commit

Permalink
fix external definitions (#265)
Browse files Browse the repository at this point in the history
  • Loading branch information
koxudaxi authored Nov 17, 2020
1 parent 9111036 commit 4e4848f
Show file tree
Hide file tree
Showing 6 changed files with 74 additions and 1 deletion.
5 changes: 5 additions & 0 deletions datamodel_code_generator/parser/jsonschema.py
Original file line number Diff line number Diff line change
Expand Up @@ -708,6 +708,8 @@ def parse_ref(self, obj: JsonSchemaObject, path: List[str]) -> None:
if obj.ref.startswith('#'):
# Local Reference – $ref: '#/definitions/myElement'
pass
elif self.model_resolver.is_after_load(obj.ref):
pass
else:
if (
not obj.ref.startswith(('https://', 'http://'))
Expand Down Expand Up @@ -811,6 +813,9 @@ def parse_raw(self) -> None:
isinstance(self.source, Path) and self.source.is_dir()
):
self.current_source_path = Path()
self.model_resolver.after_load_files = [
str(s.path) for s in self.iter_source
]
for source in self.iter_source:
if self.current_source_path is not None:
self.current_source_path = source.path
Expand Down
9 changes: 8 additions & 1 deletion datamodel_code_generator/reference.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ def __init__(self, aliases: Optional[Mapping[str, str]] = None) -> None:
self._current_root: List[str] = []
self._root_id_base_path: Optional[str] = None
self.ids: DefaultDict[str, Dict[str, str]] = defaultdict(dict)
self.after_load_files: List[str] = []

@property
def current_root(self) -> List[str]:
Expand Down Expand Up @@ -67,6 +68,9 @@ def _get_path(self, path: List[str]) -> str:
return f'{self.root_id_base_path}/{joined_path}#/'
return f'{joined_path}#/'

def is_after_load(self, ref: str) -> bool:
return '#/' in ref and ref.split('#/', 1)[0] in self.after_load_files

def add_ref(self, ref: str, actual_module_name: Optional[str] = None) -> Reference:
path = self._get_path(ref.split('/'))
reference = self.references.get(path)
Expand All @@ -78,7 +82,10 @@ def add_ref(self, ref: str, actual_module_name: Optional[str] = None) -> Referen
parents, original_name = self.root_id_base_path, Path(split_ref[0]).stem
else:
parents, original_name = split_ref
loaded: bool = not ref.startswith(('https://', 'http://'))
if self.is_after_load(ref):
loaded: bool = False
else:
loaded = '#/' not in ref
if not original_name:
original_name = Path(parents).stem # type: ignore
loaded = False
Expand Down
15 changes: 15 additions & 0 deletions tests/data/expected/main/main_external_definitions/output.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# generated by datamodel-codegen:
# filename: external_definitions_root.json
# timestamp: 2019-07-26T00:00:00+00:00

from __future__ import annotations

from pydantic import BaseModel, constr


class ElegantName(BaseModel):
__root__: constr(min_length=3)


class Person(BaseModel):
name: ElegantName
7 changes: 7 additions & 0 deletions tests/data/jsonschema/external_definitions.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"$schema": "http://json-schema.org/draft-04/schema#",
"elegantName": {
"type": "string",
"minLength": 3
}
}
14 changes: 14 additions & 0 deletions tests/data/jsonschema/external_definitions_root.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"$schema": "http://json-schema.org/draft-04/schema#",
"title": "Person",
"type": "object",
"additionalProperties": false,
"properties": {
"name": {
"$ref": "external_definitions.json#/elegantName"
}
},
"required": [
"name"
]
}
25 changes: 25 additions & 0 deletions tests/test_main.py
Original file line number Diff line number Diff line change
Expand Up @@ -1064,3 +1064,28 @@ def test_main_use_standard_collections(tmpdir_factory: TempdirFactory) -> None:
path.relative_to(main_use_standard_collections_dir)
).read_text()
assert result == path.read_text()


@freeze_time('2019-07-26')
def test_main_external_definitions():
with TemporaryDirectory() as output_dir:
output_file: Path = Path(output_dir) / 'output.py'
return_code: Exit = main(
[
'--input',
str(JSON_SCHEMA_DATA_PATH / 'external_definitions_root.json'),
'--output',
str(output_file),
'--input-file-type',
'jsonschema',
]
)
assert return_code == Exit.OK
assert (
output_file.read_text()
== (
EXPECTED_MAIN_PATH / 'main_external_definitions' / 'output.py'
).read_text()
)
with pytest.raises(SystemExit):
main()

0 comments on commit 4e4848f

Please sign in to comment.