Last active
November 15, 2022 12:22
-
-
Save samuelcolvin/ae5fa158e67fbf36b8dd1d0d2280359b to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<style> | |
main { | |
display: flex; | |
} | |
pre { | |
margin: 0; | |
padding: 0; | |
} | |
code, #output { | |
white-space: pre-wrap; | |
padding: 2px; | |
margin: 2px; | |
flex: 1 1; | |
} | |
</style> | |
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.6.0/styles/default.min.css"> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.6.0/highlight.min.js"></script> | |
<script src="https://cdn.jsdelivr.net/pyodide/v0.21.0a3/full/pyodide.js"></script> | |
<main> | |
<pre id="code"> | |
<!-- language=python --> | |
<code class="language-python"> | |
import time | |
import micropip | |
await micropip.install([ | |
'https://smokeshow.helpmanual.io/5y5m0h4s3k415a5s430c/pydantic_core-0.0.1-cp310-cp310-emscripten_3_1_14_wasm32.whl', | |
'devtools' | |
]) | |
from pydantic_core import SchemaValidator | |
import devtools | |
def schema(*, strict: bool = False) -> dict: | |
class MyModel: | |
# __slots__ is not required, but it avoids __fields_set__ falling into __dict__ | |
__slots__ = '__dict__', '__fields_set__' | |
def append_func(input_value, **kwargs): | |
return f'{input_value} Changed' | |
def wrap_function(input_value, *, validator, **kwargs): | |
return f'Input {validator(input_value)} Changed' | |
return { | |
'type': 'model-class', | |
'class_type': MyModel, | |
'config': {'strict': strict}, | |
'schema': { | |
'type': 'typed-dict', | |
'return_fields_set': True, | |
'fields': { | |
'field_str': {'schema': 'str'}, | |
'field_str_con': {'schema': {'type': 'str', 'min_length': 3, 'max_length': 5, 'pattern': '^[a-z]+$'}}, | |
'field_int': {'schema': 'int'}, | |
'field_int_con': {'schema': {'type': 'int', 'gt': 1, 'lt': 10, 'multiple_of': 2}}, | |
'field_float': {'schema': 'float'}, | |
'field_float_con': {'schema': {'type': 'float', 'ge': 1.0, 'le': 10.0, 'multiple_of': 0.5}}, | |
'field_bool': {'schema': 'bool'}, | |
'field_bytes': {'schema': 'bytes'}, | |
'field_bytes_con': {'schema': {'type': 'bytes', 'min_length': 6, 'max_length': 1000}}, | |
'field_date': {'schema': 'date'}, | |
'field_date_con': {'schema': {'type': 'date', 'ge': '2020-01-01', 'lt': '2020-01-02'}}, | |
'field_time': {'schema': 'time'}, | |
'field_time_con': {'schema': {'type': 'time', 'ge': '06:00:00', 'lt': '12:13:14'}}, | |
'field_datetime': {'schema': 'datetime'}, | |
'field_datetime_con': { | |
'schema': {'type': 'datetime', 'ge': '2000-01-01T06:00:00', 'lt': '2020-01-02T12:13:14'} | |
}, | |
'field_list_any': {'schema': 'list'}, | |
'field_list_str': {'schema': {'type': 'list', 'items_schema': 'str'}}, | |
'field_list_str_con': { | |
'schema': {'type': 'list', 'items_schema': 'str', 'min_items': 3, 'max_items': 42} | |
}, | |
'field_set_any': {'schema': 'set'}, | |
'field_set_int': {'schema': {'type': 'set', 'items_schema': 'int'}}, | |
'field_set_int_con': { | |
'schema': {'type': 'set', 'items_schema': 'int', 'min_items': 3, 'max_items': 42} | |
}, | |
'field_frozenset_any': {'schema': 'frozenset'}, | |
'field_frozenset_bytes': {'schema': {'type': 'frozenset', 'items_schema': 'bytes'}}, | |
'field_frozenset_bytes_con': { | |
'schema': {'type': 'frozenset', 'items_schema': 'bytes', 'min_items': 3, 'max_items': 42} | |
}, | |
'field_tuple_var_len_any': {'schema': 'tuple-var-len'}, | |
'field_tuple_var_len_float': {'schema': {'type': 'tuple-var-len', 'items_schema': 'float'}}, | |
'field_tuple_var_len_float_con': { | |
'schema': {'type': 'tuple-var-len', 'items_schema': 'float', 'min_items': 3, 'max_items': 42} | |
}, | |
'field_tuple_fix_len': { | |
'schema': {'type': 'tuple-fix-len', 'items_schema': ['str', 'int', 'float', 'bool']} | |
}, | |
'field_dict_any': {'schema': 'dict'}, | |
'field_dict_str_float': {'schema': {'type': 'dict', 'keys_schema': 'str', 'values_schema': 'float'}}, | |
'field_literal_1_int': {'schema': {'type': 'literal', 'expected': [1]}}, | |
'field_literal_1_str': {'schema': {'type': 'literal', 'expected': ['foobar']}}, | |
'field_literal_mult_int': {'schema': {'type': 'literal', 'expected': [1, 2, 3]}}, | |
'field_literal_mult_str': {'schema': {'type': 'literal', 'expected': ['foo', 'bar', 'baz']}}, | |
'field_literal_assorted': {'schema': {'type': 'literal', 'expected': [1, 'foo', True]}}, | |
'field_list_nullable_int': { | |
'schema': {'type': 'list', 'items_schema': {'type': 'nullable', 'schema': 'int'}} | |
}, | |
'field_union': { | |
'schema': { | |
'type': 'union', | |
'choices': [ | |
'str', | |
{ | |
'type': 'typed-dict', | |
'fields': { | |
'field_str': {'schema': 'str'}, | |
'field_int': {'schema': 'int'}, | |
'field_float': {'schema': 'float'}, | |
}, | |
}, | |
{ | |
'type': 'typed-dict', | |
'fields': { | |
'field_float': {'schema': 'float'}, | |
'field_bytes': {'schema': 'bytes'}, | |
'field_date': {'schema': 'date'}, | |
}, | |
}, | |
], | |
} | |
}, | |
'field_functions_model': { | |
'schema': { | |
'type': 'typed-dict', | |
'fields': { | |
'field_before': { | |
'schema': { | |
'type': 'function', | |
'mode': 'before', | |
'function': append_func, | |
'schema': {'type': 'str'}, | |
} | |
}, | |
'field_after': { | |
'schema': { | |
'type': 'function', | |
'mode': 'after', | |
'function': append_func, | |
'schema': {'type': 'str'}, | |
} | |
}, | |
'field_wrap': { | |
'schema': { | |
'type': 'function', | |
'mode': 'wrap', | |
'function': wrap_function, | |
'schema': {'type': 'str'}, | |
} | |
}, | |
'field_plain': {'schema': {'type': 'function', 'mode': 'plain', 'function': append_func}}, | |
}, | |
} | |
}, | |
'field_recursive': { | |
'schema': { | |
'ref': 'Branch', | |
'type': 'typed-dict', | |
'fields': { | |
'name': {'schema': 'str'}, | |
'sub_branch': { | |
'schema': { | |
'type': 'nullable', | |
'schema': {'type': 'recursive-ref', 'schema_ref': 'Branch'}, | |
}, | |
'default': None, | |
}, | |
}, | |
} | |
}, | |
}, | |
}, | |
} | |
def input_data_lax(): | |
return { | |
'field_str': 'fo', | |
'field_str_con': 'fooba', | |
'field_int': 1, | |
'field_int_con': 8, | |
'field_float': 1.0, | |
'field_float_con': 10.0, | |
'field_bool': True, | |
'field_bytes': b'foobar', | |
'field_bytes_con': b'foobar', | |
'field_date': '2010-02-03', | |
'field_date_con': '2020-01-01', | |
'field_time': '12:00:00', | |
'field_time_con': '12:00:00', | |
'field_datetime': '2020-01-01T12:13:14', | |
'field_datetime_con': '2020-01-01T00:00:00', | |
'field_list_any': ['a', b'b', True, 1.0, None] * 10, | |
'field_list_str': ['a', 'b', 'c'] * 10, | |
'field_list_str_con': ['a', 'b', 'c'] * 10, | |
'field_set_any': {'a', b'b', True, 1.0, None}, | |
'field_set_int': set(range(100)), | |
'field_set_int_con': set(range(42)), | |
'field_frozenset_any': frozenset({'a', b'b', True, 1.0, None}), | |
'field_frozenset_bytes': frozenset([f'{i}'.encode() for i in range(100)]), | |
'field_frozenset_bytes_con': frozenset([f'{i}'.encode() for i in range(42)]), | |
'field_tuple_var_len_any': ('a', b'b', True, 1.0, None), | |
'field_tuple_var_len_float': tuple((i + 0.5 for i in range(100))), | |
'field_tuple_var_len_float_con': tuple((i + 0.5 for i in range(42))), | |
'field_tuple_fix_len': ('a', 1, 1.0, True), | |
'field_dict_any': {'a': 'b', 1: True, 1.0: 1.0}, | |
'field_dict_str_float': {f'{i}': i + 0.5 for i in range(100)}, | |
'field_literal_1_int': 1, | |
'field_literal_1_str': 'foobar', | |
'field_literal_mult_int': 3, | |
'field_literal_mult_str': 'foo', | |
'field_literal_assorted': 'foo', | |
'field_list_nullable_int': [1, None, 2, None, 3, None, 4, None], | |
'field_union': {'field_str': 'foo', 'field_int': 1, 'field_float': 1.0}, | |
'field_functions_model': { | |
'field_before': 'foo', | |
'field_after': 'foo', | |
'field_wrap': 'foo', | |
'field_plain': 'foo', | |
}, | |
'field_recursive': { | |
'name': 'foo', | |
'sub_branch': {'name': 'bar', 'sub_branch': {'name': 'baz', 'sub_branch': None}}, | |
}, | |
} | |
lax_schema = schema() | |
lax_validator = SchemaValidator(lax_schema) | |
start = time.perf_counter_ns() | |
for i in range(1000): | |
m = lax_validator.validate_python(input_data_lax()) | |
diff = time.perf_counter_ns() - start | |
f'\n\ntime taken: {diff / 1000 / 1000:0.0f}us\n\noutput:{devtools.pformat(m.__dict__)}' | |
</code> | |
</pre> | |
<pre id="output"> | |
</pre> | |
</main> | |
<script> | |
hljs.highlightAll() | |
async function main() { | |
const pyodide = await loadPyodide() | |
await pyodide.loadPackage(['micropip']) | |
const code = document.getElementById('code').innerText | |
let output = await pyodide.runPythonAsync(code) | |
console.log(output) | |
document.getElementById('output').innerText = output | |
} | |
main() | |
</script> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment