Passed
Push — main ( 7e2a98...f6a351 )
by
unknown
02:02
created

pincer.utils.api_object   A

Complexity

Total Complexity 12

Size/Duplication

Total Lines 114
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 12
eloc 40
dl 0
loc 114
rs 10
c 0
b 0
f 0

2 Methods

Rating   Name   Duplication   Size   Complexity  
A APIObject.from_dict() 0 11 2
A APIObject.to_dict() 0 5 1

1 Function

Rating   Name   Duplication   Size   Complexity  
C _asdict_ignore_none() 0 38 9
1
# -*- coding: utf-8 -*-
0 ignored issues
show
introduced by
Missing module docstring
Loading history...
2
# MIT License
3
#
4
# Copyright (c) 2021 Pincer
5
#
6
# Permission is hereby granted, free of charge, to any person obtaining
7
# a copy of this software and associated documentation files
8
# (the "Software"), to deal in the Software without restriction,
9
# including without limitation the rights to use, copy, modify, merge,
10
# publish, distribute, sublicense, and/or sell copies of the Software,
11
# and to permit persons to whom the Software is furnished to do so,
12
# subject to the following conditions:
13
#
14
# The above copyright notice and this permission notice shall be
15
# included in all copies or substantial portions of the Software.
16
#
17
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20
# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
21
# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
22
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
23
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24
25
from __future__ import annotations
26
27
import copy
28
from dataclasses import dataclass, fields, _is_dataclass_instance
29
from enum import Enum
30
from typing import Dict, Union, Generic, TypeVar
31
32
from websockets.typing import Data
33
34
from .types import MissingType
35
36
T = TypeVar("T")
37
38
39
def _asdict_ignore_none(obj: Generic[T]) -> Union[tuple, dict, T]:
40
    """
41
    Returns a dict from a dataclass that ignores
42
    all values that are None
43
    Modification of _asdict_inner from dataclasses
44
45
    :param obj:
46
        Dataclass obj
47
    """
48
49
    if _is_dataclass_instance(obj):
0 ignored issues
show
unused-code introduced by
Unnecessary "elif" after "return"
Loading history...
50
        result = []
51
        for f in fields(obj):
52
            value = _asdict_ignore_none(getattr(obj, f.name))
53
54
            if isinstance(value, Enum):
55
                result.append((f.name, value.value))
56
            # This if statement was added to the function
57
            elif not isinstance(value, MissingType):
58
                result.append((f.name, value))
59
60
        return dict(result)
61
62
    elif isinstance(obj, tuple) and hasattr(obj, '_fields'):
63
        return type(obj)(*[_asdict_ignore_none(v) for v in obj])
64
65
    elif isinstance(obj, (list, tuple)):
66
        return type(obj)(_asdict_ignore_none(v) for v in obj)
67
68
    elif isinstance(obj, dict):
69
        return type(obj)(
70
            (
71
                _asdict_ignore_none(k),
72
                _asdict_ignore_none(v)
73
            ) for k, v in obj.items()
74
        )
75
    else:
76
        return copy.deepcopy(obj)
77
78
79
@dataclass
80
class APIObject:
81
    """
82
    Represents an object which has been fetched from the Discord API.
83
    """
84
85
    # def __post_init__(self):
86
    #     fin = {
87
    #         key: _eval_type(ForwardRef(value), globals(), globals())
88
    #         for key, value in self.__annotations__.items()
89
    #     }
90
    #
91
    #     # pprint(self.__annotations__)
92
    #     # pprint(get_type_hints(self))
93
    #     print(fin)
94
    #     print("Post init", self)
95
96
    @classmethod
97
    def from_dict(cls: Generic[T], data: Data[str, Union[str, bool, int]]) -> T:
98
        """
99
        Parse an API object from a dictionary.
100
        """
101
        # Disable inspection for IDE because this is valid code for the
102
        # inherited classes:
103
        # noinspection PyArgumentList
104
        return cls(**{
105
            key: (value.value if isinstance(value, Enum)
106
                  else value) for key, value in data.items()
107
        })
108
109
    def to_dict(self) -> Dict:
110
        """
111
        Transform the current object to a dictionary representation.
112
        """
113
        return _asdict_ignore_none(self)
114