Completed
Push — master ( 2d5fd3...e2acfa )
by Klaus
01:03
created

sacred.config.normalize_or_die()   B

Complexity

Conditions 7

Size

Total Lines 17

Duplication

Lines 0
Ratio 0 %
Metric Value
cc 7
dl 0
loc 17
rs 7.3333
1
#!/usr/bin/env python
2
# coding=utf-8
3
from __future__ import division, print_function, unicode_literals
4
5
import json
6
7
import sacred.optional as opt
8
import six
9
from sacred.config.custom_containers import DogmaticDict, DogmaticList
10
from sacred.utils import PYTHON_IDENTIFIER
11
12
13
def assert_is_valid_key(key):
14
    if not isinstance(key, six.string_types):
15
        raise KeyError('Invalid key "{}". Config-keys have to be strings, '
16
                       'but was {}'.format(key, type(key)))
17
    elif key.find('.') > -1 or key.find('$') > -1:
18
        raise KeyError('Invalid key "{}". Config-keys cannot '
19
                       'contain "." or "$"'.format(key))
20
    elif not PYTHON_IDENTIFIER.match(key):
21
        raise KeyError('Key "{}" is not a valid python identifier'.format(key))
22
23
24
def normalize_numpy(obj):
25
    if isinstance(obj, opt.np.generic):
26
        try:
27
            return opt.np.asscalar(obj)
28
        except ValueError:
29
            pass
30
    elif isinstance(obj, opt.np.ndarray):
31
        try:
32
            return obj.tolist()
33
        except (AttributeError, ValueError):
34
            pass
35
    return obj
36
37
38
def normalize_or_die(obj):
39
    if isinstance(obj, dict):
40
        res = dict()
41
        for key, value in obj.items():
42
            assert_is_valid_key(key)
43
            res[key] = normalize_or_die(value)
44
        return res
45
    elif isinstance(obj, (list, tuple)):
46
        return list([normalize_or_die(value) for value in obj])
47
    elif opt.has_numpy:
48
        obj = normalize_numpy(obj)
49
    try:
50
        json.dumps(obj)
51
        return obj
52
    except TypeError:
53
        raise ValueError("Invalid value '{}'. All values have to be"
54
                         "JSON-serializeable".format(obj))
55
56
57
def recursive_fill_in(config, preset):
58
    for key in preset:
59
        if key not in config:
60
            config[key] = preset[key]
61
        elif isinstance(config[key], dict):
62
            recursive_fill_in(config[key], preset[key])
63
64
65
def chain_evaluate_config_scopes(config_scopes, fixed=None, preset=None,
66
                                 fallback=None):
67
    fixed = fixed or {}
68
    fallback = fallback or {}
69
    final_config = dict(preset or {})
70
    config_summaries = []
71
    for config in config_scopes:
72
        cfg = config(fixed=fixed,
73
                     preset=final_config,
74
                     fallback=fallback)
75
        config_summaries.append(cfg)
76
        final_config.update(cfg)
77
78
    if not config_scopes:
79
        final_config.update(fixed)
80
81
    return undogmatize(final_config), config_summaries
82
83
84
def dogmatize(obj):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
85
    if isinstance(obj, dict):
86
        return DogmaticDict({key: dogmatize(val) for key, val in obj.items()})
87
    elif isinstance(obj, list):
88
        return DogmaticList([dogmatize(value) for value in obj])
89
    elif isinstance(obj, tuple):
90
        return tuple(dogmatize(value) for value in obj)
91
    else:
92
        return obj
93
94
95
def undogmatize(obj):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
96
    if isinstance(obj, DogmaticDict):
97
        return dict({key: undogmatize(value) for key, value in obj.items()})
98
    elif isinstance(obj, DogmaticList):
99
        return list([undogmatize(value) for value in obj])
100
    elif isinstance(obj, tuple):
101
        return tuple(undogmatize(value) for value in obj)
102
    else:
103
        return obj
104