Skip to content

Commit

Permalink
Support memoryview fields in json schema
Browse files Browse the repository at this point in the history
  • Loading branch information
jcrist committed Jan 5, 2024
1 parent 19a37da commit fc75a28
Show file tree
Hide file tree
Showing 5 changed files with 30 additions and 4 deletions.
1 change: 1 addition & 0 deletions docs/source/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@ Inspect
.. autoclass:: StrType
.. autoclass:: BytesType
.. autoclass:: ByteArrayType
.. autoclass:: MemoryViewType
.. autoclass:: DateTimeType
.. autoclass:: TimeType
.. autoclass:: DateType
Expand Down
2 changes: 1 addition & 1 deletion msgspec/_json_schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,7 @@ def to_schema(self, t: mi.Type, check_ref: bool = True) -> dict[str, Any]:
schema["minLength"] = t.min_length
if t.pattern is not None:
schema["pattern"] = t.pattern
elif isinstance(t, (mi.BytesType, mi.ByteArrayType)):
elif isinstance(t, (mi.BytesType, mi.ByteArrayType, mi.MemoryViewType)):
schema["type"] = "string"
schema["contentEncoding"] = "base64"
if t.max_length is not None:
Expand Down
20 changes: 20 additions & 0 deletions msgspec/inspect.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
"StrType",
"BytesType",
"ByteArrayType",
"MemoryViewType",
"DateTimeType",
"TimeType",
"DateType",
Expand Down Expand Up @@ -222,6 +223,23 @@ class ByteArrayType(Type):
max_length: Union[int, None] = None


class MemoryViewType(Type):
"""A type corresponding to `memoryview`.
Parameters
----------
min_length: int, optional
If set, an instance of this type must have length greater than or equal
to ``min_length``.
max_length: int, optional
If set, an instance of this type must have length less than or equal
to ``max_length``.
"""

min_length: Union[int, None] = None
max_length: Union[int, None] = None


class DateTimeType(Type):
"""A type corresponding to `datetime.datetime`.
Expand Down Expand Up @@ -803,6 +821,8 @@ def _translate_inner(
return BytesType(min_length=min_length, max_length=max_length)
elif t is bytearray:
return ByteArrayType(min_length=min_length, max_length=max_length)
elif t is memoryview:
return MemoryViewType(min_length=min_length, max_length=max_length)
elif t is datetime.datetime:
return DateTimeType(tz=tz)
elif t is datetime.time:
Expand Down
7 changes: 6 additions & 1 deletion tests/test_inspect.py
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,12 @@ def test_string(kw):
[{}, dict(min_length=0), dict(max_length=3)],
)
@pytest.mark.parametrize(
"typ, info_type", [(bytes, mi.BytesType), (bytearray, mi.ByteArrayType)]
"typ, info_type",
[
(bytes, mi.BytesType),
(bytearray, mi.ByteArrayType),
(memoryview, mi.MemoryViewType),
],
)
def test_binary(kw, typ, info_type):
if kw:
Expand Down
4 changes: 2 additions & 2 deletions tests/test_schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ def test_string():
assert msgspec.json.schema(str) == {"type": "string"}


@pytest.mark.parametrize("typ", [bytes, bytearray])
@pytest.mark.parametrize("typ", [bytes, bytearray, memoryview])
def test_binary(typ):
assert msgspec.json.schema(typ) == {
"type": "string",
Expand Down Expand Up @@ -1108,7 +1108,7 @@ def test_dict_key_metadata(field, val, constraint):
}


@pytest.mark.parametrize("typ", [bytes, bytearray])
@pytest.mark.parametrize("typ", [bytes, bytearray, memoryview])
@pytest.mark.parametrize(
"field, n, constraint",
[("min_length", 2, "minLength"), ("max_length", 7, "maxLength")],
Expand Down

0 comments on commit fc75a28

Please sign in to comment.