File: mixins.py

package info (click to toggle)
python-django 3%3A5.2.5-1
  • links: PTS, VCS
  • area: main
  • in suites: experimental
  • size: 61,236 kB
  • sloc: python: 361,585; javascript: 19,250; xml: 211; makefile: 182; sh: 28
file content (81 lines) | stat: -rw-r--r-- 2,478 bytes parent folder | download
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
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
import warnings

from django.core import checks
from django.utils.deprecation import RemovedInDjango60Warning
from django.utils.functional import cached_property

NOT_PROVIDED = object()


class FieldCacheMixin:
    """
    An API for working with the model's fields value cache.

    Subclasses must set self.cache_name to a unique entry for the cache -
    typically the field’s name.
    """

    # RemovedInDjango60Warning.
    def get_cache_name(self):
        raise NotImplementedError

    @cached_property
    def cache_name(self):
        # RemovedInDjango60Warning: when the deprecation ends, replace with:
        # raise NotImplementedError
        cache_name = self.get_cache_name()
        warnings.warn(
            f"Override {self.__class__.__qualname__}.cache_name instead of "
            "get_cache_name().",
            RemovedInDjango60Warning,
            stacklevel=3,
        )
        return cache_name

    def get_cached_value(self, instance, default=NOT_PROVIDED):
        try:
            return instance._state.fields_cache[self.cache_name]
        except KeyError:
            if default is NOT_PROVIDED:
                raise
            return default

    def is_cached(self, instance):
        return self.cache_name in instance._state.fields_cache

    def set_cached_value(self, instance, value):
        instance._state.fields_cache[self.cache_name] = value

    def delete_cached_value(self, instance):
        del instance._state.fields_cache[self.cache_name]


class CheckFieldDefaultMixin:
    _default_hint = ("<valid default>", "<invalid default>")

    def _check_default(self):
        if (
            self.has_default()
            and self.default is not None
            and not callable(self.default)
        ):
            return [
                checks.Warning(
                    "%s default should be a callable instead of an instance "
                    "so that it's not shared between all field instances."
                    % (self.__class__.__name__,),
                    hint=(
                        "Use a callable instead, e.g., use `%s` instead of "
                        "`%s`." % self._default_hint
                    ),
                    obj=self,
                    id="fields.E010",
                )
            ]
        else:
            return []

    def check(self, **kwargs):
        errors = super().check(**kwargs)
        errors.extend(self._check_default())
        return errors