#!/usr/bin/env python3 """ Build a table of Python / Pydantic to JSON Schema mappings. Done like this rather than as a raw rst table to make future edits easier. Please edit this file directly not .tmp_schema_mappings.html """ from __future__ import annotations import json import re from pathlib import Path from typing import Any table: list[tuple[str, str, str | dict[str, Any], str, str]] = [ ( 'None', 'null', '', 'JSON Schema Core', 'Same for `type(None)` or `Literal[None]`', ), ( 'bool', 'boolean', '', 'JSON Schema Core', '', ), ( 'str', 'string', '', 'JSON Schema Core', '', ), ( 'float', 'number', '', 'JSON Schema Core', '', ), ( 'int', 'integer', '', 'JSON Schema Validation', '', ), ( 'dict', 'object', '', 'JSON Schema Core', '', ), ( 'list', 'array', {'items': {}}, 'JSON Schema Core', '', ), ( 'tuple', 'array', {'items': {}}, 'JSON Schema Core', '', ), ( 'set', 'array', {'items': {}, 'uniqueItems': True}, 'JSON Schema Validation', '', ), ( 'frozenset', 'array', {'items': {}, 'uniqueItems': True}, 'JSON Schema Validation', '', ), ( 'List[str]', 'array', {'items': {'type': 'string'}}, 'JSON Schema Validation', 'And equivalently for any other sub type, e.g. `List[int]`.', ), ( 'Tuple[str, ...]', 'array', {'items': {'type': 'string'}}, 'JSON Schema Validation', 'And equivalently for any other sub type, e.g. `Tuple[int, ...]`.', ), ( 'Tuple[str, int]', 'array', {'items': [{'type': 'string'}, {'type': 'integer'}], 'minItems': 2, 'maxItems': 2}, 'JSON Schema Validation', ( 'And equivalently for any other set of subtypes. Note: If using schemas for OpenAPI, ' "you shouldn't use this declaration, as it would not be valid in OpenAPI (although it is " 'valid in JSON Schema).' ), ), ( 'Dict[str, int]', 'object', {'additionalProperties': {'type': 'integer'}}, 'JSON Schema Validation', ( 'And equivalently for any other subfields for dicts. Have in mind that although you can use other types as ' 'keys for dicts with Pydantic, only strings are valid keys for JSON, and so, only str is valid as ' 'JSON Schema key types.' ), ), ( 'Union[str, int]', 'anyOf', {'anyOf': [{'type': 'string'}, {'type': 'integer'}]}, 'JSON Schema Validation', 'And equivalently for any other subfields for unions.', ), ( 'Enum', 'enum', '{"enum": [...]}', 'JSON Schema Validation', 'All the literal values in the enum are included in the definition.', ), ( 'SecretStr', 'string', {'writeOnly': True}, 'JSON Schema Validation', '', ), ( 'SecretBytes', 'string', {'writeOnly': True}, 'JSON Schema Validation', '', ), ( 'EmailStr', 'string', {'format': 'email'}, 'JSON Schema Validation', '', ), ( 'NameEmail', 'string', {'format': 'name-email'}, 'Pydantic standard "format" extension', '', ), ( 'AnyUrl', 'string', {'format': 'uri'}, 'JSON Schema Validation', '', ), ( 'Pattern', 'string', {'format': 'regex'}, 'JSON Schema Validation', '', ), ( 'bytes', 'string', {'format': 'binary'}, 'OpenAPI', '', ), ( 'Decimal', 'number', '', 'JSON Schema Core', '', ), ( 'UUID1', 'string', {'format': 'uuid1'}, 'Pydantic standard "format" extension', '', ), ( 'UUID3', 'string', {'format': 'uuid3'}, 'Pydantic standard "format" extension', '', ), ( 'UUID4', 'string', {'format': 'uuid4'}, 'Pydantic standard "format" extension', '', ), ( 'UUID5', 'string', {'format': 'uuid5'}, 'Pydantic standard "format" extension', '', ), ( 'UUID', 'string', {'format': 'uuid'}, 'Pydantic standard "format" extension', 'Suggested in OpenAPI.', ), ( 'FilePath', 'string', {'format': 'file-path'}, 'Pydantic standard "format" extension', '', ), ( 'DirectoryPath', 'string', {'format': 'directory-path'}, 'Pydantic standard "format" extension', '', ), ( 'Path', 'string', {'format': 'path'}, 'Pydantic standard "format" extension', '', ), ( 'datetime', 'string', {'format': 'date-time'}, 'JSON Schema Validation', '', ), ( 'date', 'string', {'format': 'date'}, 'JSON Schema Validation', '', ), ( 'time', 'string', {'format': 'time'}, 'JSON Schema Validation', '', ), ( 'timedelta', 'number', {'format': 'time-delta'}, 'Difference in seconds (a `float`), with Pydantic standard "format" extension', "Suggested in JSON Schema repository's issues by maintainer.", ), ( 'Json', 'string', {'format': 'json-string'}, 'Pydantic standard "format" extension', '', ), ( 'IPv4Address', 'string', {'format': 'ipv4'}, 'JSON Schema Validation', '', ), ( 'IPv6Address', 'string', {'format': 'ipv6'}, 'JSON Schema Validation', '', ), ( 'IPvAnyAddress', 'string', {'format': 'ipvanyaddress'}, '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', {'format': 'ipvanyinterface'}, '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', {'format': 'ipvanynetwork'}, 'Pydantic standard "format" extension', 'IPv4 or IPv6 network as used in `ipaddress` module', ), ( 'StrictBool', 'boolean', '', 'JSON Schema Core', '', ), ( 'StrictStr', 'string', '', 'JSON Schema Core', '', ), ( 'ConstrainedStr', 'string', '', 'JSON Schema Core', ( 'If the type has values declared for the constraints, they are included as validations. ' 'See the mapping for `constr` below.' ), ), ( "constr(regex='^text$', min_length=2, max_length=10)", 'string', {'pattern': '^text$', 'minLength': 2, 'maxLength': 10}, 'JSON Schema Validation', 'Any argument not passed to the function (not defined) will not be included in the schema.', ), ( 'ConstrainedInt', 'integer', '', 'JSON Schema Core', ( 'If the type has values declared for the constraints, they are included as validations. ' 'See the mapping for `conint` below.' ), ), ( 'conint(gt=1, ge=2, lt=6, le=5, multiple_of=2)', 'integer', {'maximum': 5, 'exclusiveMaximum': 6, 'minimum': 2, 'exclusiveMinimum': 1, 'multipleOf': 2}, '', 'Any argument not passed to the function (not defined) will not be included in the schema.', ), ( 'PositiveInt', 'integer', {'exclusiveMinimum': 0}, 'JSON Schema Validation', '', ), ( 'NegativeInt', 'integer', {'exclusiveMaximum': 0}, 'JSON Schema Validation', '', ), ( 'NonNegativeInt', 'integer', {'minimum': 0}, 'JSON Schema Validation', '', ), ( 'NonPositiveInt', 'integer', {'maximum': 0}, 'JSON Schema Validation', '', ), ( 'ConstrainedFloat', 'number', '', 'JSON Schema Core', ( 'If the type has values declared for the constraints, they are included as validations. ' 'See the mapping for `confloat` below.' ), ), ( 'confloat(gt=1, ge=2, lt=6, le=5, multiple_of=2)', 'number', {'maximum': 5, 'exclusiveMaximum': 6, 'minimum': 2, 'exclusiveMinimum': 1, 'multipleOf': 2}, 'JSON Schema Validation', 'Any argument not passed to the function (not defined) will not be included in the schema.', ), ( 'PositiveFloat', 'number', {'exclusiveMinimum': 0}, 'JSON Schema Validation', '', ), ( 'NegativeFloat', 'number', {'exclusiveMaximum': 0}, 'JSON Schema Validation', '', ), ( 'NonNegativeFloat', 'number', {'minimum': 0}, 'JSON Schema Validation', '', ), ( 'NonPositiveFloat', 'number', {'maximum': 0}, 'JSON Schema Validation', '', ), ( 'ConstrainedDecimal', 'number', '', 'JSON Schema Core', ( 'If the type has values declared for the constraints, they are included as validations. ' 'See the mapping for `condecimal` below.' ), ), ( 'condecimal(gt=1, ge=2, lt=6, le=5, multiple_of=2)', 'number', {'maximum': 5, 'exclusiveMaximum': 6, 'minimum': 2, 'exclusiveMinimum': 1, 'multipleOf': 2}, 'JSON Schema Validation', 'Any argument not passed to the function (not defined) will not be included in the schema.', ), ( 'BaseModel', 'object', '', 'JSON Schema Core', 'All the properties defined will be defined with standard JSON Schema, including submodels.', ), ( 'Color', 'string', {'format': 'color'}, 'Pydantic standard "format" extension', '', ), ] headings = [ 'Python type', 'JSON Schema Type', 'Additional JSON Schema', 'Defined in', ] def md2html(s: str) -> str: return re.sub(r'`(.+?)`', r'\1', s) def build_schema_mappings() -> None: rows = [] for py_type, json_type, additional, defined_in, notes in table: if additional and not isinstance(additional, str): additional = json.dumps(additional) cols = [ f'{py_type}', f'{json_type}', f'{additional}' if additional else '', md2html(defined_in) ] rows.append('\n'.join(f' \n {c}\n ' for c in cols)) if notes: rows.append( f' \n' f' {md2html(notes)}\n' f' ' ) heading = '\n'.join(f' {h}' for h in headings) body = '\n\n\n'.join(rows) text = f"""\ {heading} {body}
""" (Path(__file__).parent / '..' / '.tmp_schema_mappings.html').write_text(text) if __name__ == '__main__': build_schema_mappings()