structured_data._doc_wrapper   A
last analyzed

Complexity

Total Complexity 10

Size/Duplication

Total Lines 61
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 10
eloc 36
dl 0
loc 61
rs 10
c 0
b 0
f 0

8 Methods

Rating   Name   Duplication   Size   Complexity  
A ProxyWrapper.__get__() 0 6 2
A ProxyWrapper.__init__() 0 3 1
A DocWrapper.__get__() 0 6 2
A DocWrapper.__init__() 0 2 1
A DocWrapper.wrap_class() 0 7 1
A DocWrapper.__delete__() 0 2 1
A DocWrapper.__set__() 0 2 1
A ProxyWrapper.wrap_class() 0 9 1
1
"""Wrapper to control documentation visibility."""
2
3
from __future__ import annotations
4
5
import typing
6
7
T = typing.TypeVar("T")
8
9
10
class DocWrapper:
11
    """Custom descriptor that hides class doc on instances."""
12
13
    def __init__(self, doc: typing.Optional[str] = None) -> None:
14
        self.doc = doc
15
16
    @classmethod
17
    def wrap_class(
18
        cls: typing.Type[DocWrapper], klass: typing.Type[T]
19
    ) -> typing.Type[T]:
20
        """Wrap a class's docstring to conceal it from instances."""
21
        klass.__doc__ = cls(klass.__doc__)  # type: ignore
22
        return klass
23
24
    def __get__(
25
        self, instance: typing.Optional[T], owner: typing.Type[T]
26
    ) -> typing.Optional[str]:
27
        if instance is None:
28
            return self.doc
29
        return vars(instance).get("__doc__")
30
31
    def __set__(self, instance: T, value: typing.Optional[str]) -> None:
32
        vars(instance)["__doc__"] = value
33
34
    def __delete__(self, instance: T) -> None:
35
        vars(instance).pop("__doc__", None)
36
37
38
class ProxyWrapper:
39
    """Custom descriptor that forwards instance doc to an attribute."""
40
41
    def __init__(self, name: str, doc: typing.Optional[str]) -> None:
42
        self.name = name
43
        self.doc = doc
44
45
    @classmethod
46
    def wrap_class(cls, name: str) -> typing.Callable[[typing.Type[T]], typing.Type[T]]:
47
        """Wrap a proxy's docstring to forward it for instances."""
48
49
        def decorator(klass: typing.Type[T]) -> typing.Type[T]:
50
            klass.__doc__ = cls(name, klass.__doc__)  # type: ignore
51
            return klass
52
53
        return decorator
54
55
    def __get__(
56
        self, instance: typing.Optional[T], owner: typing.Type[T]
57
    ) -> typing.Optional[str]:
58
        if instance is None:
59
            return self.doc
60
        return getattr(instance, self.name).__doc__
61