# Copyright (c) Facebook, Inc. and its affiliates. # All rights reserved. # # This source code is licensed under the license found in the # LICENSE file in the root directory of this source tree. # import os, json from os import path as osp from pathlib import Path from collections import namedtuple support_types = ("str", "int", "bool", "float", "none") def convert_param(original_lists): assert isinstance(original_lists, list), "The type is not right : {:}".format( original_lists ) ctype, value = original_lists[0], original_lists[1] assert ctype in support_types, "Ctype={:}, support={:}".format(ctype, support_types) is_list = isinstance(value, list) if not is_list: value = [value] outs = [] for x in value: if ctype == "int": x = int(x) elif ctype == "str": x = str(x) elif ctype == "bool": x = bool(int(x)) elif ctype == "float": x = float(x) elif ctype == "none": if x.lower() != "none": raise ValueError( "For the none type, the value must be none instead of {:}".format(x) ) x = None else: raise TypeError("Does not know this type : {:}".format(ctype)) outs.append(x) if not is_list: outs = outs[0] return outs def load_config(path, extra, logger): path = str(path) if hasattr(logger, "log"): logger.log(path) assert os.path.exists(path), "Can not find {:}".format(path) # Reading data back with open(path, "r") as f: data = json.load(f) content = {k: convert_param(v) for k, v in data.items()} assert extra is None or isinstance( extra, dict ), "invalid type of extra : {:}".format(extra) if isinstance(extra, dict): content = {**content, **extra} Arguments = namedtuple("Configure", " ".join(content.keys())) content = Arguments(**content) if hasattr(logger, "log"): logger.log("{:}".format(content)) return content def configure2str(config, xpath=None): if not isinstance(config, dict): config = config._asdict() def cstring(x): return '"{:}"'.format(x) def gtype(x): if isinstance(x, list): x = x[0] if isinstance(x, str): return "str" elif isinstance(x, bool): return "bool" elif isinstance(x, int): return "int" elif isinstance(x, float): return "float" elif x is None: return "none" else: raise ValueError("invalid : {:}".format(x)) def cvalue(x, xtype): if isinstance(x, list): is_list = True else: is_list, x = False, [x] temps = [] for temp in x: if xtype == "bool": temp = cstring(int(temp)) elif xtype == "none": temp = cstring("None") else: temp = cstring(temp) temps.append(temp) if is_list: return "[{:}]".format(", ".join(temps)) else: return temps[0] xstrings = [] for key, value in config.items(): xtype = gtype(value) string = " {:20s} : [{:8s}, {:}]".format( cstring(key), cstring(xtype), cvalue(value, xtype) ) xstrings.append(string) Fstring = "{\n" + ",\n".join(xstrings) + "\n}" if xpath is not None: parent = Path(xpath).resolve().parent parent.mkdir(parents=True, exist_ok=True) if osp.isfile(xpath): os.remove(xpath) with open(xpath, "w") as text_file: text_file.write("{:}".format(Fstring)) return Fstring def dict2config(xdict, logger): assert isinstance(xdict, dict), "invalid type : {:}".format(type(xdict)) Arguments = namedtuple("Configure", " ".join(xdict.keys())) content = Arguments(**xdict) if hasattr(logger, "log"): logger.log("{:}".format(content)) return content