File: base.py

package info (click to toggle)
python-aiopyarr 23.4.0-2
  • links: PTS, VCS
  • area: main
  • in suites: sid, trixie
  • size: 2,300 kB
  • sloc: python: 25,335; makefile: 22; javascript: 11
file content (132 lines) | stat: -rw-r--r-- 3,706 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
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
"""PyArr base model."""
from __future__ import annotations

from dataclasses import dataclass
from datetime import date, datetime
from enum import Enum
from typing import Any

import ciso8601

from ..const import ATTR_DATA
from .const import (
    CONVERT_TO_BOOL,
    CONVERT_TO_DATE,
    CONVERT_TO_DATETIME,
    CONVERT_TO_ENUM,
    CONVERT_TO_FLOAT,
    CONVERT_TO_INTEGER,
    ProtocolType,
)


def get_datetime(
    _input: datetime | str | None, utc: bool = False
) -> datetime | str | int | None:
    """Convert input to datetime object."""
    if isinstance(_input, str):
        if _input.isnumeric():
            return int(_input)
        if utc:
            return ciso8601.parse_datetime(_input)
        return ciso8601.parse_datetime_as_naive(_input)
    return _input


def get_date(_input: datetime | str | None) -> date | None:
    """Convert input to date object."""
    if (result := get_datetime(_input)) and isinstance(result, datetime):
        return result.date()
    return None


def get_enum_value(val: str) -> str | Enum:
    """Convert input to the correct enum."""
    for protocol in ProtocolType:
        if (
            val.isnumeric()
            and protocol.value == int(val)
            or protocol.name.lower() == val
        ):
            return protocol
    return val


def toraw(obj):
    """Convert object to dict."""
    if isinstance(obj, dict):
        return {k: toraw(v) for k, v in obj.items()}
    if hasattr(obj, "__iter__") and not isinstance(obj, str):
        return [toraw(v) for v in obj]
    if hasattr(obj, "attributes"):
        return obj.attributes
    if isinstance(obj, datetime):
        return f"{obj.isoformat()}Z"
    return obj


def generate_data(
    data: dict[str, Any] | list[dict[str, Any]], datatype: Any = None
) -> Any:
    """Generate data."""
    if datatype is None:
        return data

    if isinstance(data, list):
        return [datatype(item) for item in data]

    return datatype(data)


@dataclass(init=False)
class BaseModel:
    """BaseModel."""

    def __init__(
        self,
        data: dict[str, Any] | list[dict[str, Any]],
        datatype: Any = None,
    ) -> None:
        """Init."""
        self.basedata = None
        if isinstance(data, dict):
            for key, value in data.items():
                if key == ATTR_DATA:
                    value = generate_data(value, datatype)
                elif key in CONVERT_TO_DATETIME:
                    if key == "airDateUtc":
                        value = get_datetime(value, utc=True)
                    else:
                        value = get_datetime(value)
                elif key in CONVERT_TO_DATE:
                    value = get_date(value)
                elif key in CONVERT_TO_ENUM:
                    value = get_enum_value(value)
                elif key in CONVERT_TO_FLOAT and value is not None:
                    value = float(value)
                elif key in CONVERT_TO_INTEGER and value is not None:
                    try:
                        value = int(value)
                    except ValueError:
                        pass
                elif key in CONVERT_TO_BOOL:
                    value = False if value == "False" else bool(value)
                self.__setattr__(key, value)

        self.__post_init__()

    def __post_init__(self):
        """Post init."""

    @property
    def attributes(self):
        """Return attributes of the object."""
        return {
            k: v
            if isinstance(v, bool)
            else str(v)
            if k in CONVERT_TO_INTEGER
            else toraw(v)
            for k, v in self.__dict__.items()
            if k != ATTR_DATA
        }