Skip to content

Commit

Permalink
Merge pull request #1 from untitaker/feat/exact-length-lists
Browse files Browse the repository at this point in the history
Treat heterogenous lists of exact length as tuples
  • Loading branch information
bsamseth authored Aug 11, 2020
2 parents ce6d95f + df4a6a3 commit 54d2f8c
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 0 deletions.
8 changes: 8 additions & 0 deletions jsonschema_typed/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,14 @@ def array(
inner_types = [AnyType(TypeOfAny.unannotated)]
elif items is False:
raise NotImplementedError('"items": false is not supported')
elif isinstance(items, list):
# https://json-schema.org/understanding-json-schema/reference/array.html#tuple-validation
if {schema.get("minItems"), schema.get("maxItems")} - {None, len(items)}:
raise NotImplementedError(
'"items": If list, must have minItems == maxItems'
)
inner_types = [self.get_type(ctx, item) for item in items]
return ctx.api.tuple_type(inner_types)
elif items is not None:
inner_types = [self.get_type(ctx, items)]
else:
Expand Down
28 changes: 28 additions & 0 deletions schema/tuple.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"$schema": "http://json-schema.org/draft-04/schema#",
"$id": "http://foo.qwerty/some/schema#",
"title": "List of tuples",
"type": "array",
"items": {
"type": [
"array",
"null"
],
"items": [
{
"type": [
"string",
"null"
]
},
{
"type": [
"string",
"null"
]
}
],
"maxItems": 2,
"minItems": 2
}
}
15 changes: 15 additions & 0 deletions tests/cases/tuple.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
from jsonschema_typed import JSONSchema
from typing import TYPE_CHECKING


Ty = JSONSchema["schema/tuple.json"]

data: Ty = [("key", "value")]

error0: Ty = [["key", "value"]]
error1: Ty = [("key", "value", "toomuch")]
error2: Ty = [1]
error3: Ty = [(1, 2)]

if TYPE_CHECKING:
reveal_type(data)
15 changes: 15 additions & 0 deletions tests/test_run_mypy.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,21 @@ class Expect(TypedDict):
exit_status=1,
),
),
(
"tuple.py",
Expect(
normal="""
tests/cases/tuple.py:9: error: List item 0 has incompatible type "List[str]"; expected "Optional[Tuple[Optional[str], Optional[str]]]"
tests/cases/tuple.py:10: error: List item 0 has incompatible type "Tuple[str, str, str]"; expected "Optional[Tuple[Optional[str], Optional[str]]]"
tests/cases/tuple.py:11: error: List item 0 has incompatible type "int"; expected "Optional[Tuple[Optional[str], Optional[str]]]"
tests/cases/tuple.py:12: error: List item 0 has incompatible type "Tuple[int, int]"; expected "Optional[Tuple[Optional[str], Optional[str]]]"
tests/cases/tuple.py:15: note: Revealed type is 'builtins.list[Union[Tuple[Union[builtins.str, None], Union[builtins.str, None]], None]]'
Found 4 errors in 1 file (checked 1 source file)
""",
error="",
exit_status=1,
),
),
]


Expand Down

0 comments on commit 54d2f8c

Please sign in to comment.