Passed
Push — master ( 9b1fb7...3baa10 )
by Ramon
01:08
created

jsons._common_impl.load_impl()   B

Complexity

Conditions 6

Size

Total Lines 46
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 6
eloc 10
nop 3
dl 0
loc 46
rs 8.6666
c 0
b 0
f 0
1
import re
0 ignored issues
show
Coding Style introduced by
This module should have a docstring.

The coding style of this project requires that you add a docstring to this code element. Below, you find an example for methods:

class SomeClass:
    def some_method(self):
        """Do x and return foo."""

If you would like to know more about docstrings, we recommend to read PEP-257: Docstring Conventions.

Loading history...
2
3
JSON_TYPES = (str, int, float, bool)
4
RFC3339_DATETIME_PATTERN = '%Y-%m-%dT%H:%M:%S'
5
CLASSES = list()
6
SERIALIZERS = dict()
7
DESERIALIZERS = dict()
8
9
10
def dump_impl(obj: object, **kwargs) -> dict:
11
    '''
12
    Serialize the given ``obj`` to a dict.
13
14
    The way objects are serialized can be finetuned by setting serializer
15
    functions for the specific type using ``set_serializer``.
16
    :param obj: a Python instance of any sort.
17
    :param kwargs: the keyword args are passed on to the serializer function.
18
    :return: the serialized obj as a dict.
19
    '''
20
    serializer = SERIALIZERS.get(obj.__class__.__name__, None)
21
    if not serializer:
22
        parents = [cls for cls in CLASSES if isinstance(obj, cls)]
23
        if parents:
24
            serializer = SERIALIZERS[parents[0].__name__]
25
    return serializer(obj, **kwargs)
26
27
28
def load_impl(json_obj: dict, cls: type = None, **kwargs) -> object:
29
    '''
30
    Deserialize the given ``json_obj`` to an object of type ``cls``. If the
31
    contents of ``json_obj`` do not match the interface of ``cls``, a
32
    TypeError is raised.
33
34
    If ``json_obj`` contains a value that belongs to a custom class, there must
35
    be a type hint present for that value in ``cls`` to let this function know
36
    what type it should deserialize that value to.
37
38
39
    **Example**:
40
41
        ``class Person:``
42
            ``# No type hint required for name``
43
44
        ``class Person:``
45
            ``# No type hint required for name``
46
47
            ``def __init__(self, name):``
48
                ``self.name = name``
49
        ````
50
        ``class Family:``
51
            ``# Person is a custom class, use a type hint``
52
53
            ``def __init__(self, persons: List[Person]):``
54
                ``self.persons = persons``
55
56
        ``jsons.load(some_dict, Family)``
57
58
    If no ``cls`` is given, a dict is simply returned, but contained values
59
    (e.g. serialized ``datetime`` values) are still deserialized.
60
    :param json_obj: the dict that is to be deserialized.
61
    :param cls: a matching class of which an instance should be returned.
62
    :param kwargs: the keyword args are passed on to the deserializer function.
63
    :return: an instance of ``cls`` if given, a dict otherwise.
64
    '''
65
    cls = cls or type(json_obj)
66
    cls_name = cls.__name__ if hasattr(cls, '__name__') \
67
        else cls.__origin__.__name__
68
    deserializer = DESERIALIZERS.get(cls_name, None)
69
    if not deserializer:
70
        parents = [cls_ for cls_ in CLASSES if issubclass(cls, cls_)]
71
        if parents:
72
            deserializer = DESERIALIZERS[parents[0].__name__]
73
    return deserializer(json_obj, cls, **kwargs)
74
75
76
def camelcase(s: str) -> str:
0 ignored issues
show
Coding Style Naming introduced by
The name s does not conform to the argument naming conventions ((([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$).

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
77
    """
78
    Return `s` in camelCase.
79
    :param s: the string that is to be transformed.
80
    :return: a string in camelCase.
81
    """
82
    s = s.replace('-', '_')
83
    splitted = s.split('_')
84
    if len(splitted) > 1:
85
        s = ''.join([x.title() for x in splitted])
86
    return s[0].lower() + s[1:]
87
88
89
def snakecase(s: str) -> str:
0 ignored issues
show
Coding Style Naming introduced by
The name s does not conform to the argument naming conventions ((([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$).

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
90
    """
91
    Return `s` in snake_case.
92
    :param s: the string that is to be transformed.
93
    :return: a string in snake_case.
94
    """
95
    s = s.replace('-', '_')
96
    s = s[0].lower() + s[1:]
97
    return re.sub(r'([a-z])([A-Z])', '\\1_\\2', s).lower()
98
99
100
def pascalcase(s: str) -> str:
0 ignored issues
show
Coding Style Naming introduced by
The name s does not conform to the argument naming conventions ((([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$).

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
101
    """
102
    Return `s` in PascalCase.
103
    :param s: the string that is to be transformed.
104
    :return: a string in PascalCase.
105
    """
106
    camelcase_str = camelcase(s)
107
    return camelcase_str[0].upper() + camelcase_str[1:]
108
109
110
def lispcase(s: str) -> str:
0 ignored issues
show
Coding Style Naming introduced by
The name s does not conform to the argument naming conventions ((([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$).

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
111
    """
112
    Return `s` in lisp-case.
113
    :param s: the string that is to be transformed.
114
    :return: a string in lisp-case.
115
    """
116
    return snakecase(s).replace('_', '-')
117