lektor_ng.types.base

src/lektor_ng/types/base.py
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
82
83
84
85
86
from jinja2 import Undefined

from lektor_ng.constants import PRIMARY_ALT


class BadValue(Undefined):
    __slots__ = ()


def get_undefined_info(undefined):
    if isinstance(undefined, Undefined):
        try:
            undefined._fail_with_undefined_error()
        except Exception as e:
            return str(e)
    return "defined value"


class RawValue:
    __slots__ = ("field", "name", "pad", "value")

    def __init__(self, name, value=None, field=None, pad=None):
        self.name = name
        self.value = value
        self.field = field
        self.pad = pad

    def _get_hint(self, prefix, reason):
        if self.field is not None:
            return f"{prefix} in field '{self.field.name}': {reason}"
        return f"{prefix}: {reason}"

    def bad_value(self, reason):
        return BadValue(hint=self._get_hint("Bad value", reason), obj=self.value)

    def missing_value(self, reason):
        return Undefined(hint=self._get_hint("Missing value", reason), obj=self.value)


class _NameDescriptor:
    def __get__(self, obj, type):
        rv = type.__name__
        rv = rv.removesuffix("Type")
        return rv.lower()


class Type:
    widget = "multiline-text"

    def __init__(self, env, options):
        self.env = env
        self.options = options

    @property
    def size(self):
        size = self.options.get("size") or "normal"
        if size not in ("normal", "small", "large"):
            size = "normal"
        return size

    @property
    def width(self):
        return self.options.get("width") or "1/1"

    name = _NameDescriptor()

    def to_json(self, pad, record=None, alt=PRIMARY_ALT):
        return {
            "name": self.name,
            "widget": self.widget,
            "size": self.size,
            "width": self.width,
        }

    def value_from_raw(self, raw):
        # pylint: disable=no-self-use
        return raw

    def value_from_raw_with_default(self, raw):
        value = self.value_from_raw(raw)
        if isinstance(value, Undefined) and raw.field is not None and raw.field.default is not None:
            return self.value_from_raw(RawValue(raw.name, raw.field.default, field=raw.field, pad=raw.pad))
        return value

    def __repr__(self):
        return f"{self.__class__.__name__}()"