mirror of
https://github.com/kennethreitz/pydantic.git
synced 2026-06-05 14:50:19 +00:00
594effa279
* working on core schema generation * adapting main.py * getting tests to run * fix tests * disable pyright, fix mypy * moving to class-based model generation * working on validators * change how models are created * start fixing test_main.py * fixing mypy * SelfType * recursive models working, more tests fixed * fix tests on <3.10 * get docs build to pass * starting to cleanup types.py * starting works on custom types * working on using annotated-types * using annoated types for constraints * lots of cleanup, fixing network tests * network tests passing 🎉 * working on types * working on types and cleanup * fixing UUID type, restructing again * more types and newer pydantic-core * working on Iterable * more test_types tests * support newer pydantic-core, fixing more test_types.py * working through more test_types.py * test_types.py at last passing locally 🎉 * fixing more tests in test_types.py * fix datetime_parse tests and linting * get tests running again, rename to test_datetime.py * renaming internal modules * working through mypy errors * fixing mypy * refactoring _generate_schema.py * test_main.py passing * uprev deps * fix conftest and linting? * importing Annotated * ltining * import Annotated from typing_extensions * fixing 3.7 compatibility * fixing tests on 3.9 * fix linting * fixing SecretField and 3.9 tests * customising get_type_hints * ignore warnings on 3.11 * spliting repr out of utils * removing unused bits of _repr, fix tests for 3.7 * more cleanup, removing many type aliases * clean up repr * support namedtuples and typeddicts * test is_union * removing errors, uprev pydantic-core * fix tests on 3.8 * fixing private attributes and model_post_init * renaming and cleanup * remove unnecessary PydanticMetadata inheritance * fixing forward refs and mypy tests * fix signatures, change how xfail works * revert mypy tests to 3.7 syntax * correct model title * try to fix tests * fixing ClassVar forward refs * uprev pydantic-core, new error format * add "force" argument to model_rebuild * Apply suggestions from code review Suggestions from @tiangolo and @hramezani 🙏 Co-authored-by: Hasan Ramezani <hasan.r67@gmail.com> Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com> * more suggestions from @tiangolo * extra -> json_schema_extra on Field Co-authored-by: Hasan Ramezani <hasan.r67@gmail.com> Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
83 lines
2.4 KiB
Python
83 lines
2.4 KiB
Python
import importlib
|
|
import inspect
|
|
import re
|
|
import secrets
|
|
import sys
|
|
import textwrap
|
|
from dataclasses import dataclass
|
|
from types import FunctionType
|
|
from typing import Any, Optional
|
|
|
|
import pytest
|
|
from _pytest.assertion.rewrite import AssertionRewritingHook
|
|
|
|
|
|
def _extract_source_code_from_function(function):
|
|
if function.__code__.co_argcount:
|
|
raise RuntimeError(f'function {function.__qualname__} cannot have any arguments')
|
|
|
|
code_lines = ''
|
|
body_started = False
|
|
for line in textwrap.dedent(inspect.getsource(function)).split('\n'):
|
|
if line.startswith('def '):
|
|
body_started = True
|
|
continue
|
|
elif body_started:
|
|
code_lines += f'{line}\n'
|
|
|
|
return textwrap.dedent(code_lines)
|
|
|
|
|
|
def _create_module_file(code, tmp_path, name):
|
|
name = f'{name}_{secrets.token_hex(5)}'
|
|
path = tmp_path / f'{name}.py'
|
|
path.write_text(code)
|
|
return name, str(path)
|
|
|
|
|
|
@pytest.fixture
|
|
def create_module(tmp_path, request):
|
|
def run(source_code_or_function, rewrite_assertions=True):
|
|
"""
|
|
Create module object, execute it and return
|
|
Can be used as a decorator of the function from the source code of which the module will be constructed
|
|
|
|
:param source_code_or_function string or function with body as a source code for created module
|
|
:param rewrite_assertions: whether to rewrite assertions in module or not
|
|
|
|
"""
|
|
if isinstance(source_code_or_function, FunctionType):
|
|
source_code = _extract_source_code_from_function(source_code_or_function)
|
|
else:
|
|
source_code = source_code_or_function
|
|
|
|
module_name, filename = _create_module_file(source_code, tmp_path, request.node.name)
|
|
|
|
if rewrite_assertions:
|
|
loader = AssertionRewritingHook(config=request.config)
|
|
loader.mark_rewrite(module_name)
|
|
else:
|
|
loader = None
|
|
|
|
spec = importlib.util.spec_from_file_location(module_name, filename, loader=loader)
|
|
sys.modules[module_name] = module = importlib.util.module_from_spec(spec)
|
|
spec.loader.exec_module(module)
|
|
return module
|
|
|
|
return run
|
|
|
|
|
|
@dataclass
|
|
class Err:
|
|
message: str
|
|
errors: Optional[Any] = None
|
|
|
|
def __repr__(self):
|
|
if self.errors:
|
|
return f'Err({self.message!r}, errors={self.errors!r})'
|
|
else:
|
|
return f'Err({self.message!r})'
|
|
|
|
def message_escaped(self):
|
|
return re.escape(self.message)
|