File size: 7,677 Bytes
d6ee7b8
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
from collections import OrderedDict, abc as container_abc
from copy import deepcopy

import inspect


class Fake(object):
    def __init__(self):
        self.fake = 1


def singleton(cls):
    instances = {}

    def _singleton(*args, **kwargs):
        if cls not in instances:
            instances[cls] = cls(*args, **kwargs)
        return instances[cls]

    return _singleton


class Register(dict):
    def __init__(self, *args, **kwargs):
        super(Register, self).__init__(*args, **kwargs)
        self._dict = {}

    def register(self, target):
        def add_register_item(key, value):
            if not callable(value):
                raise Exception(f"register object must be callable! But receice:{value} is not callable!")
            if key in self._dict:
                print(f"warning: \033[33m{value.__name__} has been registered before, so we will overriden it\033[0m")
            self[key] = value
            return value

        if callable(target):
            return add_register_item(target.__name__, target)
        else:
            return lambda x: add_register_item(target, x)

    def register_function(self, target):
        return self.register(target())

    def __call__(self, target):
        return self.register(target)

    def __setitem__(self, key, value):
        self._dict[key] = value

    def __getitem__(self, key):
        return self._dict[key]

    def __contains__(self, key):
        return key in self._dict

    def __str__(self):
        return str(self._dict)

    def keys(self):
        return self._dict.keys()

    def values(self):
        return self._dict.values()

    def items(self):
        return self._dict.items()


def convert_to_yaml(elements):
    if isinstance(elements, tuple) or isinstance(elements, list):
        return [convert_to_yaml(e) for e in elements]
    if isinstance(elements, dict):
        return {key: convert_to_yaml(value) for key, value in elements.items()}
    return elements


class Constructor(Register):
    def __init__(self):
        super(Constructor, self).__init__()
        self.func_args_dict = {}
        self.non_cfg_obj_set = set()

    def no_cfg_register(self, target):
        self.non_cfg_obj_set.add(target.__name__)
        self.register(target)
        return target

    def build_with_cfg(self, name_with_cfg, pop_name=True):
        if name_with_cfg is None:
            return None
        name_with_cfg = name_with_cfg.copy()
        name_with_cfg = ObjDict(name_with_cfg)
        name = name_with_cfg.pop('name')
        if not pop_name:
            name_with_cfg['name'] = name
        if name in self.non_cfg_obj_set:
            return self[name](**name_with_cfg)
        return self[name](name_with_cfg)


class MethodManager(object):
    def __init__(self, cfg):
        self.cfg = cfg

    def __call__(self, name=None):
        if name is None:
            name = self.cfg.name
        return self.__getattribute__(name)


class ObjDict(dict):
    def __getattr__(self, name):
        return self.get(name)

    def __setattr__(self, name, val):
        self[name] = val

    def transform(self):
        for key, item in self.items():
            if isinstance(item, OrderedDict):
                self[key] = ObjDict(item)
                self[key].transform()
        return self

    def to_dict(self):
        re_dict = {}
        for key, item in self.items():
            if isinstance(item, ObjDict):
                re_dict[key] = item.to_dict()
            else:
                re_dict[key] = item
        return re_dict


class AverageMeter(object):
    """Computes and stores the average and current value"""

    def __init__(self):
        self.reset()

    def reset(self):
        self.val = 0
        self.avg = 0
        self.sum = 0
        self.count = 0

    def update(self, val, n=1):
        self.val = val
        self.sum += val * n
        self.count += n
        self.avg = self.sum / self.count


def deep_dict_update(shop, custom):
    for key, value in custom.items():
        if key not in shop:
            shop[key] = value
        elif isinstance(value, container_abc.Mapping):
            deep_dict_update(shop[key], custom[key])
        else:
            shop[key] = custom[key]


def boss_update(shop, custom):
    for key, value in custom.items():
        if key not in shop:
            shop[key] = value
        elif isinstance(value, container_abc.Mapping):
            if 'name' in value and value['name'] != shop[key].get('name', None):
                shop[key] = custom[key]
            else:
                boss_update(shop[key], custom[key])
        else:
            shop[key] = custom[key]


def value_dict_mean(dict_list):
    re_dict = deepcopy(dict_list[0])
    for i in range(1, len(dict_list)):
        for key, value in dict_list[i].items():
            re_dict[key] += value
    for key in re_dict:
        re_dict[key] /= len(dict_list)
    return re_dict


def deep_dict_add(dict_1, dict_2, key_pool=None):
    for key, value in dict_1.items():
        if isinstance(value, container_abc.Mapping):
            dict_1[key] = deep_dict_add(dict_1[key], dict_2[key], key_pool)
            continue
        if key_pool is not None and key not in key_pool:
            continue
        dict_1[key] += dict_2[key]
    return dict_1


def deep_dict_sum(dict_list, key_pool):
    re = dict_list[0]
    for each_dict in dict_list[1:]:
        re = deep_dict_add(re, each_dict, key_pool)
    return re


def deep_dict_search(in_dict, target_key):
    if target_key in in_dict:
        return in_dict[target_key]
    else:
        for key in in_dict:
            if isinstance(in_dict[key], container_abc.Mapping):
                sub_search = deep_dict_search(in_dict[key], target_key)
                if sub_search is not None:
                    return sub_search
        return None


def deep_dict_func(in_dict, func, key_pool=None, strict=False):
    def judge_key(in_key):
        if key_pool is None:
            return False
        if strict and not isinstance(key_pool, list):
            return in_key == key_pool
        return in_key in key_pool

    for key, value in in_dict.items():
        if isinstance(value, container_abc.Mapping):
            in_dict[key] = deep_dict_func(in_dict[key], func, key_pool, strict)
            continue
        if not judge_key(key):
            continue
        in_dict[key] = func(in_dict[key])
    return in_dict


def deep_dict_prefix(in_dict, prefix):
    if not isinstance(in_dict, container_abc.Mapping):
        return in_dict
    return {f'{prefix}_{k}': v for k, v in in_dict.items()}


def deep_dict_mean(dict_list, key_pool):
    re_dict = deep_dict_sum(dict_list, key_pool)
    re_dict = deep_dict_func(re_dict, lambda x: x / len(dict_list), key_pool)
    return re_dict


def merge_dis_dict(gather_list):
    re_dict = {}
    for each_dict in gather_list:
        re_dict.update(each_dict)
    return re_dict


def deep_dict_get(in_dict, target, no_get=None):
    if isinstance(target, list):
        re = []
        for t_i, t in enumerate(target):
            n = no_get[t_i] if no_get is not None else None
            re.append(deep_dict_get(in_dict, t, n))
        if len(re) == 1:
            return re[0]
        return re
    if target in in_dict:
        return in_dict[target]
    re = no_get
    for key, value in in_dict.items():
        if isinstance(value, container_abc.Mapping):
            re = deep_dict_get(value, target, no_get)
            if re != no_get:
                return re
    return re


def str2list(in_str):
    if isinstance(in_str, list):
        return in_str
    return eval(in_str)