File: lazy_class_attribute.py

package info (click to toggle)
python-marshmallow-dataclass 8.7.1-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 332 kB
  • sloc: python: 2,351; makefile: 11; sh: 6
file content (45 lines) | stat: -rw-r--r-- 1,070 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
from typing import Any, Callable, Optional


__all__ = ("lazy_class_attribute",)


class LazyClassAttribute:
    """Descriptor decorator implementing a class-level, read-only
    property, which caches its results on the class(es) on which it
    operates.
    """

    __slots__ = ("func", "name", "called", "forward_value")

    def __init__(
        self,
        func: Callable[..., Any],
        name: Optional[str] = None,
        forward_value: Any = None,
    ):
        self.func = func
        self.name = name
        self.called = False
        self.forward_value = forward_value

    def __get__(self, instance, cls=None):
        if not cls:
            cls = type(instance)

        # avoid recursion
        if self.called:
            return self.forward_value

        self.called = True

        setattr(cls, self.name, self.func())

        # "getattr" is used to handle bounded methods
        return getattr(cls, self.name)

    def __set_name__(self, owner, name):
        self.name = self.name or name


lazy_class_attribute = LazyClassAttribute