File: mock.py

package info (click to toggle)
python-apischema 0.18.3-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 1,636 kB
  • sloc: python: 15,281; makefile: 3; sh: 2
file content (57 lines) | stat: -rw-r--r-- 1,861 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
from dataclasses import dataclass
from functools import partial
from types import FunctionType, MethodType
from typing import TYPE_CHECKING, Any, Mapping, Optional, Type, TypeVar

from apischema.fields import FIELDS_SET_ATTR
from apischema.objects import object_fields

if TYPE_CHECKING:
    from apischema.validation.validators import Validator

MOCK_FIELDS_FIELD = "__mock_fields__"
MOCK_CLS_FIELD = "__mock_cls__"


class NonTrivialDependency(Exception):
    def __init__(self, attr: str):
        self.attr = attr
        self.validator: Optional["Validator"] = None


@dataclass(init=False)
class ValidatorMock:
    def __init__(self, cls: Type, values: Mapping[str, Any]):
        self.cls = cls
        self.values = values

    def __getattribute__(self, name: str) -> Any:
        values = super().__getattribute__("values")
        if name in values:
            return values[name]
        cls = super().__getattribute__("cls")
        fields = object_fields(cls, deserialization=True)
        if name in fields:
            if fields[name].required:
                raise NonTrivialDependency(name)
            return fields[name].get_default()
        if name == "__class__":
            return cls
        if name == "__dict__":
            return {**values, FIELDS_SET_ATTR: set(values)}
        if name == FIELDS_SET_ATTR:
            return set(values)
        if hasattr(cls, name):
            member = getattr(cls, name)
            # for classmethod (staticmethod are not handled)
            if isinstance(member, MethodType):
                return member
            if isinstance(member, FunctionType):
                return partial(member, self)
            if isinstance(member, property):
                return member.fget(self)  # type: ignore
            return member
        raise NonTrivialDependency(name)


T = TypeVar("T")