Completed
Pull Request — master (#27)
by Philip
01:23
created

json_decoder_hook()   C

Complexity

Conditions 7

Size

Total Lines 21

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
cc 7
c 1
b 0
f 1
dl 0
loc 21
rs 6.4705
1
import collections
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
from functools import partial
3
from itertools import chain
4
from types import MappingProxyType
5
from typing import Callable
0 ignored issues
show
Configuration introduced by
The import typing could not be resolved.

This can be caused by one of the following:

1. Missing Dependencies

This error could indicate a configuration issue of Pylint. Make sure that your libraries are available by adding the necessary commands.

# .scrutinizer.yml
before_commands:
    - sudo pip install abc # Python2
    - sudo pip3 install abc # Python3
Tip: We are currently not using virtualenv to run pylint, when installing your modules make sure to use the command for the correct version.

2. Missing __init__.py files

This error could also result from missing __init__.py files in your module folders. Make sure that you place one file in each sub-folder.

Loading history...
6
from uuid import UUID
7
8
import iso8601
0 ignored issues
show
Configuration introduced by
The import iso8601 could not be resolved.

This can be caused by one of the following:

1. Missing Dependencies

This error could indicate a configuration issue of Pylint. Make sure that your libraries are available by adding the necessary commands.

# .scrutinizer.yml
before_commands:
    - sudo pip install abc # Python2
    - sudo pip3 install abc # Python3
Tip: We are currently not using virtualenv to run pylint, when installing your modules make sure to use the command for the correct version.

2. Missing __init__.py files

This error could also result from missing __init__.py files in your module folders. Make sure that you place one file in each sub-folder.

Loading history...
9
from foil.parsers import parse_iso_date as _parse_iso_date
10
11
12
def parse_uuid(value):
0 ignored issues
show
Coding Style introduced by
This function 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...
13
    try:
14
        value = UUID(value, version=4)
15
    except ValueError:
16
        pass
17
18
    return value
19
20
21
def parse_iso_date(value):
0 ignored issues
show
Coding Style introduced by
This function 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...
22
    try:
23
        value = _parse_iso_date(value)
24
    except AttributeError:
25
        pass
26
27
    return value
28
29
30
def parse_iso_datetime(value):
0 ignored issues
show
Coding Style introduced by
This function 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...
31
    try:
32
        value = iso8601.parse_date(value)
33
    except iso8601.ParseError:
34
        pass
35
36
    return value
37
38
39
STRING_DECODERS = (parse_uuid, parse_iso_date, parse_iso_datetime)
40
41
42
def json_decoder_hook(dct, str_decoders=STRING_DECODERS,
43
                      converters=MappingProxyType(dict())) -> dict:
44
    """Decoder for parsing typical objects like uuid's and dates."""
45
46
    for k, v in dct.items():
47
        if k in converters:
48
            parse_func = converters[k]
49
            dct[k] = parse_func(v)
50
51
        elif isinstance(v, str):
52
            for decode_func in str_decoders:
53
                v = decode_func(v)
54
55
                if not isinstance(v, str):
56
                    break
57
58
            dct[k] = v
59
        elif isinstance(v, collections.Mapping):
60
            dct[k] = json_decoder_hook(v, str_decoders=str_decoders)
61
62
    return dct
63
64
65
def make_json_decoder_hook(str_decoders=STRING_DECODERS,
66
                           extra_str_decoders=tuple(),
67
                           converters=None) -> Callable:
68
    """Customize JSON string decoder hooks.
69
70
    Object hook for typical deserialization scenarios.
71
72
    Notes
73
    -----
74
    Specifying a field in converters will ensure custom decoding/passthrough.
75
76
    Parameters
77
    ----------
78
    str_decoders: functions for decoding strings to objects.
79
    extra_str_decoders: appends additional string decoders to str_decoders.
80
    converters: field / parser function mapping.
81
    """
82
83
    str_decoders = tuple(chain(str_decoders, extra_str_decoders))
84
    object_hook = partial(json_decoder_hook, str_decoders=str_decoders,
85
                          converters=converters)
86
87
    return object_hook
88