Files
Arseny Boykov c24d33e5f1 Generate docs exampels for Python 3.10 and above (#4339)
* Generate docs exampels for Python 3.10 and above

Code quality is not great and main intent here is to show the result.

* Fix docs build on 3.9

* Build docs on 3.10

* What's Python 3.1?

* Create temp dir if not exists

* Refactor and improve imlementetion

* Keep runtime typing in examples

* Revert unrelated formatting changes

* Add changes file

* Allow specifying requirements in examples

* Pin autoflake and pyupgrade

* Add docs/build to Makefile lint/format/mypy

* ignore_missing_imports for ansi2html and devtools

* Add .tmp-projections to .gitignore

* Remove dont-upgrade now when Pattern is supported

* Update postponed evaluation examples

Co-authored-by: Samuel Colvin <s@muelcolvin.com>
2022-08-14 17:21:53 +01:00

558 lines
13 KiB
Python
Executable File

#!/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'<code>\1</code>', 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'<code>{py_type}</code>',
f'<code>{json_type}</code>',
f'<code>{additional}</code>' if additional else '',
md2html(defined_in)
]
rows.append('\n'.join(f' <td>\n {c}\n </td>' for c in cols))
if notes:
rows.append(
f' <td colspan=4 style="border-top: none; padding-top: 0">\n'
f' <em>{md2html(notes)}</em>\n'
f' </td>'
)
heading = '\n'.join(f' <th>{h}</th>' for h in headings)
body = '\n</tr>\n<tr>\n'.join(rows)
text = f"""\
<!--
Generated from docs/build/schema_mapping.py, DO NOT EDIT THIS FILE DIRECTLY.
Instead edit docs/build/schema_mapping.py and run `make docs`.
-->
<table style="width:100%">
<thead>
<tr>
{heading}
</tr>
</thead>
<tbody>
<tr>
{body}
</tr>
</tbody>
</table>
"""
(Path(__file__).parent / '..' / '.tmp_schema_mappings.html').write_text(text)
if __name__ == '__main__':
build_schema_mappings()