# Module `lib.tools.jsonconfig`

Functions for managing the json configuration. All configuration classes end the name with the word Config. For each of these classes, a json file with the same name is stored in the config directory of the board.

Expand source code

    # Distributed under Pycameresp License
    # Copyright (c) 2023 Remi BERTHOLET
    # pylint:disable=consider-using-f-string
    """ Functions for managing the json configuration.
    All configuration classes end the name with the word Config.
    For each of these classes, a json file with the same name is stored in the config directory of the board. """
    # pylint:disable=consider-using-dict-items
    # pylint:disable=consider-iterating-dictionary
    import time
    import json
    import re
    try:
            import uos
    except:
            import os as uos
    import tools.logger
    import tools.strings
    import tools.filesystem
    import tools.date

    jsonconfig_self  = None
    jsonconfig_value = None

    class JsonConfig:
            """ Manage json configuration """
            classes = set()
            def __init__(self):
                    """ Constructor """
                    self.modification_date = 0
                    self.last_refresh = 0
                    JsonConfig.classes.add(self.__class__)

            def config_root(self):
                    """ Configuration root path """
                    if tools.filesystem.ismicropython():
                            return "/config"
                    else:
                            return uos.path.expanduser('~') + "/.pycameresp"

            def purify(self, datas):
                    """ Remove unwanted items """
                    result = datas
                    if type(datas) == type(b""):
                            result = datas
                    elif type(datas) == type([]):
                            result = []
                            for item in datas:
                                    result.append(self.purify(item))
                    elif type(datas) == type((0,0)):
                            result = []
                            for item in datas:
                                    result.append(self.purify(item))
                            result = tuple(result)
                    elif type(datas) == type({}):
                            result = {}
                            for key, value in datas.items():
                                    if key not in ["last_refresh","modification_date"]:
                                            result[key] = self.purify(value)
                    elif isinstance(datas, JsonConfig):
                            result = self.purify(datas.__dict__.copy())
                            result["__class__"] = datas.__class__.__name__
                    return result

            def save(self, file=None, part_filename=""):
                    """ Save object in json file """
                    try:
                            filename = self.get_pathname(tools.strings.tofilename(part_filename))
                            str_data = self.to_string()

                            file, filename = self.open(file=file, read_write="w", part_filename=part_filename)
                            file.write(str_data)
                            file.close()

                            self.modification_date = uos.stat(filename)[8]
                            self.last_refresh = time.time()
                            return True
                    except Exception as _err:
                            str_data = self.to_string()
                            tools.logger.syslog(_err, "Cannot save %s "%(filename))
                            return False

            def to_string(self):
                    """ Convert the configuration to string """
                    return json.dumps(self.to_dict(),separators=(',', ':'))

            def to_dict(self):
                    """ Convert the configuration to dictionnary """
                    return tools.strings.tostrings(self.purify(self.__dict__.copy()))

            def get_pathname(self, part_filename=""):
                    """ Get the configuration filename according to the class name """
                    return self.config_root()+"/"+self.get_filename(part_filename) + ".json"

            def list_all(self):
                    """ List all configuration files """
                    result = []
                    pattern = self.get_filename() + ".*"
                    for fileinfo in tools.filesystem.list_directory(self.config_root()):
                            name = fileinfo[0]
                            typ  = fileinfo[1]
                            if typ & 0xF000 != 0x4000:
                                    if re.match(pattern, name):
                                            result.append(tools.strings.tobytes(name[len(self.get_filename()):-len(".json")]))
                    return result

            def get_filename(self, part_filename=""):
                    """ Return the config filename """
                    if self.__class__.__name__[-len("Config"):] == "Config":
                            name = self.__class__.__name__[:-len("Config")]
                    else:
                            name = self.__class__.__name__
                    return name + tools.strings.tostrings(part_filename)

            def open(self, file=None, read_write="r", part_filename=""):
                    """ Create or open configuration file """
                    # pylint:disable=unspecified-encoding
                    filename = file
                    if tools.filesystem.exists(self.config_root()) is False:
                            tools.filesystem.makedir(self.config_root())
                    if file is None:
                            filename = self.get_pathname(tools.strings.tofilename(part_filename))
                            file = open(filename, read_write)
                    elif type(file) == type(""):
                            file = open(filename, read_write)
                    return file, filename

            def update(self, params, show_error=True):
                    """ Update object with html request params """
                    if b"name" in params and b"value" in params and len(params) == 2:
                            setmany = False
                            params = {params[b"name"]:params[b"value"]}
                    else:
                            setmany = True

                    for name in self.__dict__.keys():
                            # Case of web input is missing when bool is false
                            if type(self.__dict__[name]) == type(True):
                                    name = tools.strings.tobytes(name)
                                    if name in params:
                                            if type(params[name]) == type(""):
                                                    if params[name] == "":
                                                            params[name] = True
                                                    elif params[name] == "1" or params[name].lower() == "true":
                                                            params[name] = True
                                                    elif params[name] == "0" or params[name].lower() == "false":
                                                            params[name] = False
                                            elif type(params[name]) == type(b""):
                                                    if params[name] == b"":
                                                            params[name] = True
                                                    elif params[name] == b"1" or params[name].lower() == b"true":
                                                            params[name] = True
                                                    elif params[name] == b"0" or params[name].lower() == b"false":
                                                            params[name] = False
                                    else:
                                            if setmany:
                                                    params[name] = False
                            # Case of web input is integer but string with number received
                            elif type(self.__dict__[name]) == type(0):
                                    name = tools.strings.tobytes(name)
                                    if name in params:
                                            try:
                                                    params[name] = int(params[name])
                                            except:
                                                    if b"date" in name:
                                                            try:
                                                                    params[name] = tools.date.html_to_date(params[name])
                                                            except:
                                                                    params[name] = 0
                                                    elif b"time" in name:
                                                            try:
                                                                    params[name] = tools.date.html_to_time(params[name])
                                                            except:
                                                                    params[name] = 0
                                                    else:
                                                            params[name] = 0
                            elif type(self.__dict__[name]) == type(0.):
                                    name = tools.strings.tobytes(name)
                                    if name in params:
                                            try:
                                                    params[name] = float(params[name])
                                            except:
                                                    params[name] = 0

                    result = True
                    for name, value in params.items():
                            res = self.exec(name, value, show_error)
                            if res is not True:
                                    result = res
                    return result

            def exec(self, name, value, show_error=True):
                    """ Add attribute to current object """
                    result = True
                    global jsonconfig_self, jsonconfig_value
                    name = tools.strings.tostrings(name)
                    try:
                            try:
                                    # pylint: disable=exec-used
                                    jsonconfig_self = self
                                    exec("a = jsonconfig_self.%s"%name)
                                    jsonconfig_self  = None
                                    existing = True
                            except Exception as _err:
                                    if "'NoneType' object" in str(_err):
                                            result = None
                                    existing = False

                            if existing:
                                    execval = "jsonconfig_self.%s = jsonconfig_value"%(name)
                                    # pylint: disable=exec-used
                                    jsonconfig_value = self.instantiate(value)
                                    jsonconfig_self  = self
                                    exec(execval)
                                    jsonconfig_self  = None
                                    jsonconfig_value = None
                            else:
                                    if name != "action" and show_error and result is not None:
                                            print("%s.%s not existing"%(self.__class__.__name__, tools.strings.tostrings(name)))
                    except Exception as _err:
                            tools.logger.syslog(_err, "Error on %s"%(name))
                            result = False
                    return result

            def search_class(self, class_name):
                    """ Search class with class name """
                    for class_ in JsonConfig.classes:
                            if class_.__name__ == class_name:
                                    return class_
                    return None

            def instantiate(self, values):
                    """ Instantiate all objects with its classes """
                    result = values
                    if type(values) == type({}):
                            class_name = values.setdefault(b"__class__",None)
                            instance = None
                            if class_name is not None:
                                    class_ = self.search_class(tools.strings.tostrings(class_name))
                                    del values[b"__class__"]
                                    if class_ is not None:
                                            instance = class_()
                                            for key, value in values.items():
                                                    instance.exec(key,value)
                                            result = instance
                    elif type(values) == type([]):
                            result = []
                            for value in values:
                                    result.append(self.instantiate(value))
                    return result

            def load(self, file=None, part_filename="", tobytes=True, errorlog=True):
                    """ Load object with the file specified """
                    filename = ""
                    try:
                            filename = self.get_pathname(tools.strings.tofilename(part_filename))
                            file, filename = self.open(file=file, read_write="r", part_filename=part_filename)

                            data = json.load(file)
                            if tobytes:
                                    data = tools.strings.tobytes(data)
                            self.update(data)
                            file.close()
                            self.last_refresh = time.time()
                            return True
                    except OSError as _err:
                            if _err.args[0] == 2:
                                    if errorlog:
                                            tools.logger.syslog("Not existing %s "%(filename))
                            else:
                                    tools.logger.syslog(_err, "Cannot load %s "%(filename))
                            return False
                    except Exception as _err:
                            tools.logger.syslog(_err, "Cannot load %s "%(filename))
                            return False

            def forget(self, part_filename=""):
                    """ Forget configuration """
                    tools.filesystem.remove(self.get_pathname(part_filename=part_filename))

            def is_changed(self, part_filename=""):
                    """ Indicates if the configuration changed """
                    if self.last_refresh + 31 < time.time():
                            try:
                                    modification_date = uos.stat(self.get_pathname(tools.strings.tofilename(part_filename)))[8]
                                    if self.modification_date != modification_date:
                                            self.modification_date = modification_date
                                            return True
                            except:
                                    pass
                    return False

            def load_create(self, file=None, part_filename="", tobytes=True, errorlog=True):
                    """ Load and create file if not existing """
                    if self.load(file, part_filename, tobytes, errorlog) is False:
                            self.save(file, part_filename)

            def refresh(self, file=None, part_filename="", tobytes=True, errorlog=True):
                    """ refresh the configuration if it has changed since then """
                    if self.is_changed(part_filename):
                            self.load(file, part_filename, tobytes, errorlog)
                            return True
                    return False

            def exists(self, part_filename=""):
                    """ Indicates if the configuration file existing """
                    return tools.filesystem.exists(self.get_pathname(tools.strings.tofilename(part_filename)))

## Classes

`class JsonConfig`

  Manage json configuration

  Constructor

  Expand source code

      class JsonConfig:
              """ Manage json configuration """
              classes = set()
              def __init__(self):
                      """ Constructor """
                      self.modification_date = 0
                      self.last_refresh = 0
                      JsonConfig.classes.add(self.__class__)

              def config_root(self):
                      """ Configuration root path """
                      if tools.filesystem.ismicropython():
                              return "/config"
                      else:
                              return uos.path.expanduser('~') + "/.pycameresp"

              def purify(self, datas):
                      """ Remove unwanted items """
                      result = datas
                      if type(datas) == type(b""):
                              result = datas
                      elif type(datas) == type([]):
                              result = []
                              for item in datas:
                                      result.append(self.purify(item))
                      elif type(datas) == type((0,0)):
                              result = []
                              for item in datas:
                                      result.append(self.purify(item))
                              result = tuple(result)
                      elif type(datas) == type({}):
                              result = {}
                              for key, value in datas.items():
                                      if key not in ["last_refresh","modification_date"]:
                                              result[key] = self.purify(value)
                      elif isinstance(datas, JsonConfig):
                              result = self.purify(datas.__dict__.copy())
                              result["__class__"] = datas.__class__.__name__
                      return result

              def save(self, file=None, part_filename=""):
                      """ Save object in json file """
                      try:
                              filename = self.get_pathname(tools.strings.tofilename(part_filename))
                              str_data = self.to_string()

                              file, filename = self.open(file=file, read_write="w", part_filename=part_filename)
                              file.write(str_data)
                              file.close()

                              self.modification_date = uos.stat(filename)[8]
                              self.last_refresh = time.time()
                              return True
                      except Exception as _err:
                              str_data = self.to_string()
                              tools.logger.syslog(_err, "Cannot save %s "%(filename))
                              return False

              def to_string(self):
                      """ Convert the configuration to string """
                      return json.dumps(self.to_dict(),separators=(',', ':'))

              def to_dict(self):
                      """ Convert the configuration to dictionnary """
                      return tools.strings.tostrings(self.purify(self.__dict__.copy()))

              def get_pathname(self, part_filename=""):
                      """ Get the configuration filename according to the class name """
                      return self.config_root()+"/"+self.get_filename(part_filename) + ".json"

              def list_all(self):
                      """ List all configuration files """
                      result = []
                      pattern = self.get_filename() + ".*"
                      for fileinfo in tools.filesystem.list_directory(self.config_root()):
                              name = fileinfo[0]
                              typ  = fileinfo[1]
                              if typ & 0xF000 != 0x4000:
                                      if re.match(pattern, name):
                                              result.append(tools.strings.tobytes(name[len(self.get_filename()):-len(".json")]))
                      return result

              def get_filename(self, part_filename=""):
                      """ Return the config filename """
                      if self.__class__.__name__[-len("Config"):] == "Config":
                              name = self.__class__.__name__[:-len("Config")]
                      else:
                              name = self.__class__.__name__
                      return name + tools.strings.tostrings(part_filename)

              def open(self, file=None, read_write="r", part_filename=""):
                      """ Create or open configuration file """
                      # pylint:disable=unspecified-encoding
                      filename = file
                      if tools.filesystem.exists(self.config_root()) is False:
                              tools.filesystem.makedir(self.config_root())
                      if file is None:
                              filename = self.get_pathname(tools.strings.tofilename(part_filename))
                              file = open(filename, read_write)
                      elif type(file) == type(""):
                              file = open(filename, read_write)
                      return file, filename

              def update(self, params, show_error=True):
                      """ Update object with html request params """
                      if b"name" in params and b"value" in params and len(params) == 2:
                              setmany = False
                              params = {params[b"name"]:params[b"value"]}
                      else:
                              setmany = True

                      for name in self.__dict__.keys():
                              # Case of web input is missing when bool is false
                              if type(self.__dict__[name]) == type(True):
                                      name = tools.strings.tobytes(name)
                                      if name in params:
                                              if type(params[name]) == type(""):
                                                      if params[name] == "":
                                                              params[name] = True
                                                      elif params[name] == "1" or params[name].lower() == "true":
                                                              params[name] = True
                                                      elif params[name] == "0" or params[name].lower() == "false":
                                                              params[name] = False
                                              elif type(params[name]) == type(b""):
                                                      if params[name] == b"":
                                                              params[name] = True
                                                      elif params[name] == b"1" or params[name].lower() == b"true":
                                                              params[name] = True
                                                      elif params[name] == b"0" or params[name].lower() == b"false":
                                                              params[name] = False
                                      else:
                                              if setmany:
                                                      params[name] = False
                              # Case of web input is integer but string with number received
                              elif type(self.__dict__[name]) == type(0):
                                      name = tools.strings.tobytes(name)
                                      if name in params:
                                              try:
                                                      params[name] = int(params[name])
                                              except:
                                                      if b"date" in name:
                                                              try:
                                                                      params[name] = tools.date.html_to_date(params[name])
                                                              except:
                                                                      params[name] = 0
                                                      elif b"time" in name:
                                                              try:
                                                                      params[name] = tools.date.html_to_time(params[name])
                                                              except:
                                                                      params[name] = 0
                                                      else:
                                                              params[name] = 0
                              elif type(self.__dict__[name]) == type(0.):
                                      name = tools.strings.tobytes(name)
                                      if name in params:
                                              try:
                                                      params[name] = float(params[name])
                                              except:
                                                      params[name] = 0

                      result = True
                      for name, value in params.items():
                              res = self.exec(name, value, show_error)
                              if res is not True:
                                      result = res
                      return result

              def exec(self, name, value, show_error=True):
                      """ Add attribute to current object """
                      result = True
                      global jsonconfig_self, jsonconfig_value
                      name = tools.strings.tostrings(name)
                      try:
                              try:
                                      # pylint: disable=exec-used
                                      jsonconfig_self = self
                                      exec("a = jsonconfig_self.%s"%name)
                                      jsonconfig_self  = None
                                      existing = True
                              except Exception as _err:
                                      if "'NoneType' object" in str(_err):
                                              result = None
                                      existing = False

                              if existing:
                                      execval = "jsonconfig_self.%s = jsonconfig_value"%(name)
                                      # pylint: disable=exec-used
                                      jsonconfig_value = self.instantiate(value)
                                      jsonconfig_self  = self
                                      exec(execval)
                                      jsonconfig_self  = None
                                      jsonconfig_value = None
                              else:
                                      if name != "action" and show_error and result is not None:
                                              print("%s.%s not existing"%(self.__class__.__name__, tools.strings.tostrings(name)))
                      except Exception as _err:
                              tools.logger.syslog(_err, "Error on %s"%(name))
                              result = False
                      return result

              def search_class(self, class_name):
                      """ Search class with class name """
                      for class_ in JsonConfig.classes:
                              if class_.__name__ == class_name:
                                      return class_
                      return None

              def instantiate(self, values):
                      """ Instantiate all objects with its classes """
                      result = values
                      if type(values) == type({}):
                              class_name = values.setdefault(b"__class__",None)
                              instance = None
                              if class_name is not None:
                                      class_ = self.search_class(tools.strings.tostrings(class_name))
                                      del values[b"__class__"]
                                      if class_ is not None:
                                              instance = class_()
                                              for key, value in values.items():
                                                      instance.exec(key,value)
                                              result = instance
                      elif type(values) == type([]):
                              result = []
                              for value in values:
                                      result.append(self.instantiate(value))
                      return result

              def load(self, file=None, part_filename="", tobytes=True, errorlog=True):
                      """ Load object with the file specified """
                      filename = ""
                      try:
                              filename = self.get_pathname(tools.strings.tofilename(part_filename))
                              file, filename = self.open(file=file, read_write="r", part_filename=part_filename)

                              data = json.load(file)
                              if tobytes:
                                      data = tools.strings.tobytes(data)
                              self.update(data)
                              file.close()
                              self.last_refresh = time.time()
                              return True
                      except OSError as _err:
                              if _err.args[0] == 2:
                                      if errorlog:
                                              tools.logger.syslog("Not existing %s "%(filename))
                              else:
                                      tools.logger.syslog(_err, "Cannot load %s "%(filename))
                              return False
                      except Exception as _err:
                              tools.logger.syslog(_err, "Cannot load %s "%(filename))
                              return False

              def forget(self, part_filename=""):
                      """ Forget configuration """
                      tools.filesystem.remove(self.get_pathname(part_filename=part_filename))

              def is_changed(self, part_filename=""):
                      """ Indicates if the configuration changed """
                      if self.last_refresh + 31 < time.time():
                              try:
                                      modification_date = uos.stat(self.get_pathname(tools.strings.tofilename(part_filename)))[8]
                                      if self.modification_date != modification_date:
                                              self.modification_date = modification_date
                                              return True
                              except:
                                      pass
                      return False

              def load_create(self, file=None, part_filename="", tobytes=True, errorlog=True):
                      """ Load and create file if not existing """
                      if self.load(file, part_filename, tobytes, errorlog) is False:
                              self.save(file, part_filename)

              def refresh(self, file=None, part_filename="", tobytes=True, errorlog=True):
                      """ refresh the configuration if it has changed since then """
                      if self.is_changed(part_filename):
                              self.load(file, part_filename, tobytes, errorlog)
                              return True
                      return False

              def exists(self, part_filename=""):
                      """ Indicates if the configuration file existing """
                      return tools.filesystem.exists(self.get_pathname(tools.strings.tofilename(part_filename)))

  ### Class variables

  `var classes`

  ### Methods

  `def config_root(self)`

    Configuration root path

    Expand source code

        def config_root(self):
                """ Configuration root path """
                if tools.filesystem.ismicropython():
                        return "/config"
                else:
                        return uos.path.expanduser('~') + "/.pycameresp"

  `def exec(self, name, value, show_error=True)`

    Add attribute to current object

    Expand source code

        def exec(self, name, value, show_error=True):
                """ Add attribute to current object """
                result = True
                global jsonconfig_self, jsonconfig_value
                name = tools.strings.tostrings(name)
                try:
                        try:
                                # pylint: disable=exec-used
                                jsonconfig_self = self
                                exec("a = jsonconfig_self.%s"%name)
                                jsonconfig_self  = None
                                existing = True
                        except Exception as _err:
                                if "'NoneType' object" in str(_err):
                                        result = None
                                existing = False

                        if existing:
                                execval = "jsonconfig_self.%s = jsonconfig_value"%(name)
                                # pylint: disable=exec-used
                                jsonconfig_value = self.instantiate(value)
                                jsonconfig_self  = self
                                exec(execval)
                                jsonconfig_self  = None
                                jsonconfig_value = None
                        else:
                                if name != "action" and show_error and result is not None:
                                        print("%s.%s not existing"%(self.__class__.__name__, tools.strings.tostrings(name)))
                except Exception as _err:
                        tools.logger.syslog(_err, "Error on %s"%(name))
                        result = False
                return result

  `def exists(self, part_filename='')`

    Indicates if the configuration file existing

    Expand source code

        def exists(self, part_filename=""):
                """ Indicates if the configuration file existing """
                return tools.filesystem.exists(self.get_pathname(tools.strings.tofilename(part_filename)))

  `def forget(self, part_filename='')`

    Forget configuration

    Expand source code

        def forget(self, part_filename=""):
                """ Forget configuration """
                tools.filesystem.remove(self.get_pathname(part_filename=part_filename))

  `def get_filename(self, part_filename='')`

    Return the config filename

    Expand source code

        def get_filename(self, part_filename=""):
                """ Return the config filename """
                if self.__class__.__name__[-len("Config"):] == "Config":
                        name = self.__class__.__name__[:-len("Config")]
                else:
                        name = self.__class__.__name__
                return name + tools.strings.tostrings(part_filename)

  `def get_pathname(self, part_filename='')`

    Get the configuration filename according to the class name

    Expand source code

        def get_pathname(self, part_filename=""):
                """ Get the configuration filename according to the class name """
                return self.config_root()+"/"+self.get_filename(part_filename) + ".json"

  `def instantiate(self, values)`

    Instantiate all objects with its classes

    Expand source code

        def instantiate(self, values):
                """ Instantiate all objects with its classes """
                result = values
                if type(values) == type({}):
                        class_name = values.setdefault(b"__class__",None)
                        instance = None
                        if class_name is not None:
                                class_ = self.search_class(tools.strings.tostrings(class_name))
                                del values[b"__class__"]
                                if class_ is not None:
                                        instance = class_()
                                        for key, value in values.items():
                                                instance.exec(key,value)
                                        result = instance
                elif type(values) == type([]):
                        result = []
                        for value in values:
                                result.append(self.instantiate(value))
                return result

  `def is_changed(self, part_filename='')`

    Indicates if the configuration changed

    Expand source code

        def is_changed(self, part_filename=""):
                """ Indicates if the configuration changed """
                if self.last_refresh + 31 < time.time():
                        try:
                                modification_date = uos.stat(self.get_pathname(tools.strings.tofilename(part_filename)))[8]
                                if self.modification_date != modification_date:
                                        self.modification_date = modification_date
                                        return True
                        except:
                                pass
                return False

  `def list_all(self)`

    List all configuration files

    Expand source code

        def list_all(self):
                """ List all configuration files """
                result = []
                pattern = self.get_filename() + ".*"
                for fileinfo in tools.filesystem.list_directory(self.config_root()):
                        name = fileinfo[0]
                        typ  = fileinfo[1]
                        if typ & 0xF000 != 0x4000:
                                if re.match(pattern, name):
                                        result.append(tools.strings.tobytes(name[len(self.get_filename()):-len(".json")]))
                return result

  `def load(self, file=None, part_filename='', tobytes=True, errorlog=True)`

    Load object with the file specified

    Expand source code

        def load(self, file=None, part_filename="", tobytes=True, errorlog=True):
                """ Load object with the file specified """
                filename = ""
                try:
                        filename = self.get_pathname(tools.strings.tofilename(part_filename))
                        file, filename = self.open(file=file, read_write="r", part_filename=part_filename)

                        data = json.load(file)
                        if tobytes:
                                data = tools.strings.tobytes(data)
                        self.update(data)
                        file.close()
                        self.last_refresh = time.time()
                        return True
                except OSError as _err:
                        if _err.args[0] == 2:
                                if errorlog:
                                        tools.logger.syslog("Not existing %s "%(filename))
                        else:
                                tools.logger.syslog(_err, "Cannot load %s "%(filename))
                        return False
                except Exception as _err:
                        tools.logger.syslog(_err, "Cannot load %s "%(filename))
                        return False

  `def load_create(self, file=None, part_filename='', tobytes=True, errorlog=True)`

    Load and create file if not existing

    Expand source code

        def load_create(self, file=None, part_filename="", tobytes=True, errorlog=True):
                """ Load and create file if not existing """
                if self.load(file, part_filename, tobytes, errorlog) is False:
                        self.save(file, part_filename)

  `def open(self, file=None, read_write='r', part_filename='')`

    Create or open configuration file

    Expand source code

        def open(self, file=None, read_write="r", part_filename=""):
                """ Create or open configuration file """
                # pylint:disable=unspecified-encoding
                filename = file
                if tools.filesystem.exists(self.config_root()) is False:
                        tools.filesystem.makedir(self.config_root())
                if file is None:
                        filename = self.get_pathname(tools.strings.tofilename(part_filename))
                        file = open(filename, read_write)
                elif type(file) == type(""):
                        file = open(filename, read_write)
                return file, filename

  `def purify(self, datas)`

    Remove unwanted items

    Expand source code

        def purify(self, datas):
                """ Remove unwanted items """
                result = datas
                if type(datas) == type(b""):
                        result = datas
                elif type(datas) == type([]):
                        result = []
                        for item in datas:
                                result.append(self.purify(item))
                elif type(datas) == type((0,0)):
                        result = []
                        for item in datas:
                                result.append(self.purify(item))
                        result = tuple(result)
                elif type(datas) == type({}):
                        result = {}
                        for key, value in datas.items():
                                if key not in ["last_refresh","modification_date"]:
                                        result[key] = self.purify(value)
                elif isinstance(datas, JsonConfig):
                        result = self.purify(datas.__dict__.copy())
                        result["__class__"] = datas.__class__.__name__
                return result

  `def refresh(self, file=None, part_filename='', tobytes=True, errorlog=True)`

    refresh the configuration if it has changed since then

    Expand source code

        def refresh(self, file=None, part_filename="", tobytes=True, errorlog=True):
                """ refresh the configuration if it has changed since then """
                if self.is_changed(part_filename):
                        self.load(file, part_filename, tobytes, errorlog)
                        return True
                return False

  `def save(self, file=None, part_filename='')`

    Save object in json file

    Expand source code

        def save(self, file=None, part_filename=""):
                """ Save object in json file """
                try:
                        filename = self.get_pathname(tools.strings.tofilename(part_filename))
                        str_data = self.to_string()

                        file, filename = self.open(file=file, read_write="w", part_filename=part_filename)
                        file.write(str_data)
                        file.close()

                        self.modification_date = uos.stat(filename)[8]
                        self.last_refresh = time.time()
                        return True
                except Exception as _err:
                        str_data = self.to_string()
                        tools.logger.syslog(_err, "Cannot save %s "%(filename))
                        return False

  `def search_class(self, class_name)`

    Search class with class name

    Expand source code

        def search_class(self, class_name):
                """ Search class with class name """
                for class_ in JsonConfig.classes:
                        if class_.__name__ == class_name:
                                return class_
                return None

  `def to_dict(self)`

    Convert the configuration to dictionnary

    Expand source code

        def to_dict(self):
                """ Convert the configuration to dictionnary """
                return tools.strings.tostrings(self.purify(self.__dict__.copy()))

  `def to_string(self)`

    Convert the configuration to string

    Expand source code

        def to_string(self):
                """ Convert the configuration to string """
                return json.dumps(self.to_dict(),separators=(',', ':'))

  `def update(self, params, show_error=True)`

    Update object with html request params

    Expand source code

        def update(self, params, show_error=True):
                """ Update object with html request params """
                if b"name" in params and b"value" in params and len(params) == 2:
                        setmany = False
                        params = {params[b"name"]:params[b"value"]}
                else:
                        setmany = True

                for name in self.__dict__.keys():
                        # Case of web input is missing when bool is false
                        if type(self.__dict__[name]) == type(True):
                                name = tools.strings.tobytes(name)
                                if name in params:
                                        if type(params[name]) == type(""):
                                                if params[name] == "":
                                                        params[name] = True
                                                elif params[name] == "1" or params[name].lower() == "true":
                                                        params[name] = True
                                                elif params[name] == "0" or params[name].lower() == "false":
                                                        params[name] = False
                                        elif type(params[name]) == type(b""):
                                                if params[name] == b"":
                                                        params[name] = True
                                                elif params[name] == b"1" or params[name].lower() == b"true":
                                                        params[name] = True
                                                elif params[name] == b"0" or params[name].lower() == b"false":
                                                        params[name] = False
                                else:
                                        if setmany:
                                                params[name] = False
                        # Case of web input is integer but string with number received
                        elif type(self.__dict__[name]) == type(0):
                                name = tools.strings.tobytes(name)
                                if name in params:
                                        try:
                                                params[name] = int(params[name])
                                        except:
                                                if b"date" in name:
                                                        try:
                                                                params[name] = tools.date.html_to_date(params[name])
                                                        except:
                                                                params[name] = 0
                                                elif b"time" in name:
                                                        try:
                                                                params[name] = tools.date.html_to_time(params[name])
                                                        except:
                                                                params[name] = 0
                                                else:
                                                        params[name] = 0
                        elif type(self.__dict__[name]) == type(0.):
                                name = tools.strings.tobytes(name)
                                if name in params:
                                        try:
                                                params[name] = float(params[name])
                                        except:
                                                params[name] = 0

                result = True
                for name, value in params.items():
                        res = self.exec(name, value, show_error)
                        if res is not True:
                                result = res
                return result