jsons._compatibility_impl.get_naked_class()   A
last analyzed

Complexity

Conditions 1

Size

Total Lines 7
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 3
dl 0
loc 7
rs 10
c 0
b 0
f 0
cc 1
nop 1
1
"""
2
PRIVATE MODULE: do not import (from) it directly.
3
4
This module contains functionality for supporting the compatibility of jsons
5
with multiple Python versions.
6
"""
7
import sys
8
import typing
9
from enum import Enum
10
11
from jsons._cache import cached
12
13
14
class Flag(Enum):
15
    """
16
    This is a light version of the Flag enum type that was introduced in
17
    Python3.6. It supports the use of pipes for members (Flag.A | Flag.B).
18
    """
19
20
    @classmethod
21
    def _get_inst(cls, value):
22
        try:
23
            result = cls(value)
24
        except ValueError:
25
            pseudo_member = object.__new__(cls)
26
            pseudo_member._value_ = value
27
            contained = [elem.name for elem in cls if elem in pseudo_member]
28
            pseudo_member._name_ = '|'.join(contained)
29
            result = pseudo_member
30
        return result
31
32
    def __or__(self, other: 'Flag') -> 'Flag':
33
        new_value = other.value | self.value
34
        return self._get_inst(new_value)
35
36
    def __contains__(self, item: 'Flag') -> bool:
37
        return item.value == self.value & item.value
38
39
    __ror__ = __or__
40
41
42
@cached
43
def tuple_with_ellipsis(tup: type) -> bool:
44
    # Python3.5: Tuples have __tuple_use_ellipsis__
45
    # Python3.7: Tuples have __args__
46
    use_el = getattr(tup, '__tuple_use_ellipsis__', None)
47
    if use_el is None:
48
        use_el = tup.__args__[-1] is ...
49
    return use_el
50
51
52
@cached
53
def get_union_params(un: type) -> list:
54
    # Python3.5: Unions have __union_params__
55
    # Python3.7: Unions have __args__
56
    return getattr(un, '__union_params__', getattr(un, '__args__', None))
57
58
59
@cached
60
def get_naked_class(cls: type) -> type:
61
    # Python3.5: typing classes have __extra__
62
    # Python3.6: typing classes have __extra__
63
    # Python3.7: typing classes have __origin__
64
    # Return the non-generic class (e.g. dict) of a generic type (e.g. Dict).
65
    return getattr(cls, '__extra__', getattr(cls, '__origin__', cls))
66
67
68
@cached
69
def get_type_hints(callable_: callable, fallback_ns=None):
70
    # Python3.5: get_type_hints raises on classes without explicit constructor.
71
    # Python3.10: get_type_hints on classes does not take the constructor.
72
    try:
73
        result = typing.get_type_hints(callable_)
74
    except AttributeError:
75
        result = {}
76
    except NameError:
77
        # attempt to resolve in global namespace - this works around an
78
        # issue in 3.7 whereby __init__ created by dataclasses fails
79
        # to find it's context. See https://bugs.python.org/issue34776
80
        if fallback_ns is not None:
81
            context_dict = sys.modules[fallback_ns].__dict__
82
            result = typing.get_type_hints(callable_, globalns=context_dict)
83
84
    if sys.version_info.minor >= 10 and type(callable_) is type:
85
        annotations_from_init = typing.get_type_hints(callable_.__init__)
86
        if 'return' in annotations_from_init:
87
            # Python3.10: 'return' is a key that holds the returning type.
88
            del annotations_from_init['return']
89
        result = {**result, **annotations_from_init}
90
91
    return result
92