diff --git a/HISTORY.rst b/HISTORY.rst index a9a02c2b6c..4591aa3694 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -10,6 +10,7 @@ v0.26 (unreleased) * fix return type hint for ``create_model``, #526 by @dmontagu * **Breaking Change:** fix ``.dict(skip_keys=True)`` skipping values set via alias (this involves changing ``validate_model()`` to always returns ``Tuple[Dict[str, Any], Set[str], Optional[ValidationError]]``), #517 by @sommd +* fix to schema generation for ``IPv4Address``, ``IPv6Address``, ``IPv4Interface``, ``IPv6Interface``, ``IPv4Network``, ``IPv6Network`` #532 by @euri10 v0.25 (2019-05-05) .................. diff --git a/docs/schema_mapping.py b/docs/schema_mapping.py index 1325fa5a7b..10c99f08b9 100755 --- a/docs/schema_mapping.py +++ b/docs/schema_mapping.py @@ -254,6 +254,20 @@ 'Pydantic standard "format" extension', '' ], + [ + 'IPv4Address', + 'string', + '{"format": "ipv4"}', + 'JSON Schema Validation', + '' + ], + [ + 'IPv6Address', + 'string', + '{"format": "ipv6"}', + 'JSON Schema Validation', + '' + ], [ 'IPvAnyAddress', 'string', @@ -261,6 +275,20 @@ 'Pydantic standard "format" extension', 'IPv4 or IPv6 address as used in ``ipaddress`` module', ], + [ + 'IPv4Interface', + 'string', + '{"format": "ipv4interface"}', + 'Pydantic standard "format" extension', + 'IPv4 interface as used in ``ipaddress`` module', + ], + [ + 'IPv6Interface', + 'string', + '{"format": "ipv6interface"}', + 'Pydantic standard "format" extension', + 'IPv6 interface as used in ``ipaddress`` module', + ], [ 'IPvAnyInterface', 'string', @@ -268,6 +296,20 @@ 'Pydantic standard "format" extension', 'IPv4 or IPv6 interface as used in ``ipaddress`` module', ], + [ + 'IPv4Network', + 'string', + '{"format": "ipv4network"}', + 'Pydantic standard "format" extension', + 'IPv4 network as used in ``ipaddress`` module', + ], + [ + 'IPv6Network', + 'string', + '{"format": "ipv6network"}', + 'Pydantic standard "format" extension', + 'IPv6 network as used in ``ipaddress`` module', + ], [ 'IPvAnyNetwork', 'string', diff --git a/pydantic/schema.py b/pydantic/schema.py index 6fcab3689f..63fea001cd 100644 --- a/pydantic/schema.py +++ b/pydantic/schema.py @@ -22,6 +22,12 @@ DirectoryPath, EmailStr, FilePath, + IPv4Address, + IPv4Interface, + IPv4Network, + IPv6Address, + IPv6Interface, + IPv6Network, IPvAnyAddress, IPvAnyInterface, IPvAnyNetwork, @@ -635,9 +641,15 @@ def field_singleton_sub_fields_schema( (time, {'type': 'string', 'format': 'time'}), (timedelta, {'type': 'number', 'format': 'time-delta'}), (Json, {'type': 'string', 'format': 'json-string'}), - (IPvAnyAddress, {'type': 'string', 'format': 'ipvanyaddress'}), - (IPvAnyInterface, {'type': 'string', 'format': 'ipvanyinterface'}), + (IPv4Network, {'type': 'string', 'format': 'ipv4network'}), + (IPv6Network, {'type': 'string', 'format': 'ipv6network'}), (IPvAnyNetwork, {'type': 'string', 'format': 'ipvanynetwork'}), + (IPv4Interface, {'type': 'string', 'format': 'ipv4interface'}), + (IPv6Interface, {'type': 'string', 'format': 'ipv6interface'}), + (IPvAnyInterface, {'type': 'string', 'format': 'ipvanyinterface'}), + (IPv4Address, {'type': 'string', 'format': 'ipv4'}), + (IPv6Address, {'type': 'string', 'format': 'ipv6'}), + (IPvAnyAddress, {'type': 'string', 'format': 'ipvanyaddress'}), ) diff --git a/tests/test_schema.py b/tests/test_schema.py index 306ee284d0..e0f78e5f2c 100644 --- a/tests/test_schema.py +++ b/tests/test_schema.py @@ -26,6 +26,12 @@ DirectoryPath, EmailStr, FilePath, + IPv4Address, + IPv4Interface, + IPv4Network, + IPv6Address, + IPv6Interface, + IPv6Network, IPvAnyAddress, IPvAnyInterface, IPvAnyNetwork, @@ -665,6 +671,32 @@ class Model(BaseModel): } +def test_ipv4address_type(): + class Model(BaseModel): + ip_address: IPv4Address + + model_schema = Model.schema() + assert model_schema == { + 'title': 'Model', + 'type': 'object', + 'properties': {'ip_address': {'title': 'Ip_Address', 'type': 'string', 'format': 'ipv4'}}, + 'required': ['ip_address'], + } + + +def test_ipv6address_type(): + class Model(BaseModel): + ip_address: IPv6Address + + model_schema = Model.schema() + assert model_schema == { + 'title': 'Model', + 'type': 'object', + 'properties': {'ip_address': {'title': 'Ip_Address', 'type': 'string', 'format': 'ipv6'}}, + 'required': ['ip_address'], + } + + def test_ipvanyaddress_type(): class Model(BaseModel): ip_address: IPvAnyAddress @@ -678,6 +710,32 @@ class Model(BaseModel): } +def test_ipv4interface_type(): + class Model(BaseModel): + ip_interface: IPv4Interface + + model_schema = Model.schema() + assert model_schema == { + 'title': 'Model', + 'type': 'object', + 'properties': {'ip_interface': {'title': 'Ip_Interface', 'type': 'string', 'format': 'ipv4interface'}}, + 'required': ['ip_interface'], + } + + +def test_ipv6interface_type(): + class Model(BaseModel): + ip_interface: IPv6Interface + + model_schema = Model.schema() + assert model_schema == { + 'title': 'Model', + 'type': 'object', + 'properties': {'ip_interface': {'title': 'Ip_Interface', 'type': 'string', 'format': 'ipv6interface'}}, + 'required': ['ip_interface'], + } + + def test_ipvanyinterface_type(): class Model(BaseModel): ip_interface: IPvAnyInterface @@ -691,6 +749,32 @@ class Model(BaseModel): } +def test_ipv4network_type(): + class Model(BaseModel): + ip_network: IPv4Network + + model_schema = Model.schema() + assert model_schema == { + 'title': 'Model', + 'type': 'object', + 'properties': {'ip_network': {'title': 'Ip_Network', 'type': 'string', 'format': 'ipv4network'}}, + 'required': ['ip_network'], + } + + +def test_ipv6network_type(): + class Model(BaseModel): + ip_network: IPv6Network + + model_schema = Model.schema() + assert model_schema == { + 'title': 'Model', + 'type': 'object', + 'properties': {'ip_network': {'title': 'Ip_Network', 'type': 'string', 'format': 'ipv6network'}}, + 'required': ['ip_network'], + } + + def test_ipvanynetwork_type(): class Model(BaseModel): ip_network: IPvAnyNetwork