Beispiel #1
0
    def __init__(self, name=None, default_params={}):
        """name is going to be the generic name of the config folder
        e.g., /home/user/.config/<name>/<name>.cfg
        """
        if name is None:
            raise Exception("Name parameter must be provided")
        else:
            # use input parameters
            self.name = name
            self._default_params = copy.deepcopy(default_params)
            self.params = copy.deepcopy(default_params)

            # useful tool to handle XDG config file, path and parameters
            self.appdirs = appdirs.AppDirs(self.name)

            # useful tool to handle the config ini file
            self.config_parser = DynamicConfigParser()

            # Now, create the missing directories if needed
            self.init() # and read the user config file updating params if needed
Beispiel #2
0
    def __init__(self, name=None, default_params={}):
        """name is going to be the generic name of the config folder

        e.g., /home/user/.config/<name>/<name>.cfg

        """
        if name is None:
            raise Exception("Name parameter must be provided")
        else:
            # use input parameters
            self.name = name
            self._default_params = copy.deepcopy(default_params)
            self.params = copy.deepcopy(default_params)

            # useful tool to handle XDG config file, path and parameters
            self.appdirs = appdirs.AppDirs(self.name)

            # useful tool to handle the config ini file
            self.config_parser = DynamicConfigParser()

            # Now, create the missing directories if needed
            self.init() # and read the user config file updating params if needed
Beispiel #3
0
class ConfigReadOnly(object):
    """A generic Config file handler
    Uses appdirs from pypi to handle the XDG protocol
    Read the configuration in the XDG directory. If not found, the
    config and cache directories are created. Then, reads the configuration
    file. If not found, nothing happens. A dictionary should be provided
    to initialise the default parameters. This dictionary is updated
    wit the content of the user config file if any. Reset the parameters
    to the default values is possible at any time. Re-read the user
    config file is possible at any time (meth:`read_`)
    """
    def __init__(self, name=None, default_params={}):
        """name is going to be the generic name of the config folder
        e.g., /home/user/.config/<name>/<name>.cfg
        """
        if name is None:
            raise Exception("Name parameter must be provided")
        else:
            # use input parameters
            self.name = name
            self._default_params = copy.deepcopy(default_params)
            self.params = copy.deepcopy(default_params)

            # useful tool to handle XDG config file, path and parameters
            self.appdirs = appdirs.AppDirs(self.name)

            # useful tool to handle the config ini file
            self.config_parser = DynamicConfigParser()

            # Now, create the missing directories if needed
            self.init() # and read the user config file updating params if needed

    def read_user_config_file_and_update_params(self):
        """Read the configuration file and update parameters
        Read the configuration file (file with extension cfg and name of your
        app). Section and option found will be used to update the :attr:`params`.
        If a set of section/option is not correct (not in the :attr:`params`) then
        it is ignored.
        The :attr:`params` is a dictionary with keys being labelled as <section>.<option>
        For instance, the key "cache.on" should be written in the configuration file as::
            [cache]
            on = True
        where True is the expected value.
        """
        try:
            self.config_parser.read(self.user_config_file_path)
        except IOError:

            msg = "Welcome to %s" % self.name.capitalize()
            print(underline(msg))
            print("It looks like you do not have a configuration file.")
            print("We are creating one with default values in %s ." % self.user_config_file_path)
            print("Done")
            self.create_default_config_file()

        # now, update the params attribute if needed
        for section in self.config_parser.sections():
            dic = self.config_parser.section2dict(section)
            for key in dic.keys():
                value = dic[key]
                newkey = section + '.' + key
                if newkey in self.params.keys():
                    # the type should be self.params[newkey][1]
                    cast = self.params[newkey][1]
                    # somehow
                    if isinstance(value, cast) is True:
                        self.params[newkey][0] = value
                    else:
                        print("Warning:: found an incorrect type while parsing {} file. In section '{}', the option '{}' should be a {}. Found value {}. Trying a cast...".format(self.user_config_file_path, section, key, cast, value))
                        self.params[newkey][0] = cast(value)
                else:
                    print("Warning:: found invalid option or section in %s (ignored):" % self.user_config_file_path)
                    print("   %s %s" % (section, option))

    def _get_home(self):
        # This function should be robust
        # First, let us try with expanduser
        try:
            homedir = os.path.expanduser("~")
        except ImportError:
            # This may happen.
            pass
        else:
            if os.path.isdir(homedir):
                return homedir
        # Then, with getenv
        for this in ('HOME', 'USERPROFILE', 'TMP'):
            # getenv is same as os.environ.get
            homedir = os.environ.get(this)
            if homedir is not None and os.path.isdir(homedir):
                return homedir
        return None
    home = property(_get_home)

    def _mkdirs(self, newdir, mode=0o777):
        """from matplotlib mkdirs
        make directory *newdir* recursively, and set *mode*.  Equivalent to ::
        > mkdir -p NEWDIR
        > chmod MODE NEWDIR
        """
        try:
            if not os.path.exists(newdir):
                parts = os.path.split(newdir)
                for i in range(1, len(parts) + 1):
                    thispart = os.path.join(*parts[:i])
                    if not os.path.exists(thispart):
                        os.makedirs(thispart, mode)

        except OSError as err:
            # Reraise the error unless it's about an already existing directory
            if err.errno != errno.EEXIST or not os.path.isdir(newdir):
                raise

    def _get_and_create(self, sdir):
        if not os.path.exists(sdir):
            print("Creating directory %s " % sdir)
            try:
                self._mkdirs(sdir)
            except Exception:
                print("Could not create the path %s " % sdir)
                return None
        return sdir

    def _get_config_dir(self):
        sdir = self.appdirs.user_config_dir
        return self._get_and_create(sdir)
    user_config_dir = property(_get_config_dir,
            doc="return directory of this configuration file")

    def _get_cache_dir(self):
        sdir = self.appdirs.user_cache_dir
        return self._get_and_create(sdir)
    user_cache_dir = property(_get_cache_dir,
            doc="return directory of the cache")

    def _get_config_file_path(self):
        return self.user_config_dir + os.sep +self.config_file
    user_config_file_path = property(_get_config_file_path,
            doc="return configuration filename (with fullpath)")

    def _get_config_file(self):
        return self.name + ".cfg"
    config_file = property(_get_config_file,
            doc="config filename (without path)")

    def init(self):
        """Reads the user_config_file and update params.
        Creates the directories for config and cache if they do not exsits
        """
        # Let us create the directories by simply getting these 2 attributes:
        try:
            _ = self.user_config_dir
        except:
            print("Could not retrieve or create the config file and/or directory in %s" % self.name)
        try:
            _ = self.user_cache_dir
        except:
            print("Could not retrieve or create the cache file and/or directory in %s" % self.name)
        self.read_user_config_file_and_update_params()

    def create_default_config_file(self, force=False):

        # if the file already exists, we should save the file into
        # a backup file
        if os.path.exists(self.user_config_file_path):
            # we need to copy the file into a backup file
            filename = self.user_config_file_path + '.bk'
            if os.path.exists(filename) and force is False:
                print("""Trying to save the current config file {} into a backup file {}\n but it exists already. Please remove the backup file first or set the 'force' parameter to True""".format(self.user_config_file_path, filename))
                return
            else:
                shutil.copy(self.user_config_file_path, filename)

        # Now, we can rewrite the configuration file
        sections = sorted(set([x.split(".")[0] for x in self._default_params.keys()]))
        if 'general' in sections:
            sections = ["general"] + [x for x in sections if x!="general"]

        fh = open(self.user_config_file_path, "w") # open and delete content
        for section in sections:
            fh.write("[" + section +"]\n")
            options = [x.split(".")[1] for x in self._default_params.keys() if x.startswith(section+".")]
            for option in options:
                key = section + '.' + option
                value = self._default_params[key]
                try:
                    fh.write("# {}\n{} = {}\n".format(value[2], 
                        option, value[0]))
                except:
                    print('Could not write this value/option. skipped')
                    print(value, option)

            fh.write("\n")
        fh.close()

    def reload_default_params(self):
        self.params = copy.deepcopy(self._default_params)
Beispiel #4
0
class ConfigReadOnly(object):
    """A generic Config file handler

    Uses appdirs from ypi to handle the XDG protocol

    Read the configuration in the XDG directory. If not found, the
    config and cache directories are created. Then, reads the configuration
    file. If not found, nothing happens. A dictionary should be provided
    to initialise the default parameters. This dictionary is updated
    wit the content of the user config file if any. Reset the parameters
    to the default values is possible at any time. Re-read the user
    config file is possible at any time (meth:`read_`)

    """
    def __init__(self, name=None, default_params={}):
        """name is going to be the generic name of the config folder

        e.g., /home/user/.config/<name>/<name>.cfg

        """
        if name is None:
            raise Exception("Name parameter must be provided")
        else:
            # use input parameters
            self.name = name
            self._default_params = copy.deepcopy(default_params)
            self.params = copy.deepcopy(default_params)

            # useful tool to handle XDG config file, path and parameters
            self.appdirs = appdirs.AppDirs(self.name)

            # useful tool to handle the config ini file
            self.config_parser = DynamicConfigParser()

            # Now, create the missing directories if needed
            self.init() # and read the user config file updating params if needed

    def read_user_config_file_and_update_params(self):
        """Read the configuration file and update parameters

        Read the configuration file (file with extension cfg and name of your
        app). Section and option found will be used to update the :attr:`params`.

        If a set of section/option is not correct (not in the :attr:`params`) then
        it is ignored.

        The :attr:`params` is a dictionary with keys being labelled as <section>.<option>
        For instance, the key "cache.on" should be written in the configuration file as::

            [cache]
            on = True

        where True is the expected value.


        """
        try:
            self.config_parser.read(self.user_config_file_path)
        except IOError:

            msg = "Welcome to %s" % self.name.capitalize()
            print(underline(msg))
            print("It looks like you do not have a configuration file.")
            print("We are creating one with default values in %s ." % self.user_config_file_path)
            print("Done")
            self.create_default_config_file()

        # now, update the params attribute if needed
        for section in self.config_parser.sections():
            dic = self.config_parser.section2dict(section)
            for key in dic.keys():
                value = dic[key]
                newkey = section + '.' + key
                if newkey in self.params.keys():
                    # the type should be self.params[newkey][1]
                    cast = self.params[newkey][1]
                    # somehow
                    if isinstance(value, cast) is True:
                        self.params[newkey][0] = value
                    else:
                        print("Warning:: found an incorrect type while parsing {} file. In section '{}', the option '{}' should be a {}. Found value {}. Trying a cast...".format(self.user_config_file_path, section, key, cast, value))
                        self.params[newkey][0] = cast(value)
                else:
                    print("Warning:: found invalid option or section in %s (ignored):" % self.user_config_file_path)
                    print("   %s %s" % (section, option))

    def _get_home(self):
        # This function should be robust
        # First, let us try with expanduser
        try:
            homedir = os.path.expanduser("~")
        except ImportError:
            # This may happen.
            pass
        else:
            if os.path.isdir(homedir):
                return homedir
        # Then, with getenv
        for this in ('HOME', 'USERPROFILE', 'TMP'):
            # getenv is same as os.environ.get
            homedir = os.environ.get(this)
            if homedir is not None and os.path.isdir(homedir):
                return homedir
        return None
    home = property(_get_home)

    def _mkdirs(self, newdir, mode=0o777):
        """from matplotlib mkdirs

        make directory *newdir* recursively, and set *mode*.  Equivalent to ::

        > mkdir -p NEWDIR
        > chmod MODE NEWDIR
        """
        try:
            if not os.path.exists(newdir):
                parts = os.path.split(newdir)
                for i in range(1, len(parts) + 1):
                    thispart = os.path.join(*parts[:i])
                    if not os.path.exists(thispart):
                        os.makedirs(thispart, mode)

        except OSError as err:
            # Reraise the error unless it's about an already existing directory
            if err.errno != errno.EEXIST or not os.path.isdir(newdir):
                raise

    def _get_and_create(self, sdir):
        if not os.path.exists(sdir):
            print("Creating directory %s " % sdir)
            try:
                self._mkdirs(sdir)
            except Exception:
                print("Could not create the path %s " % sdir)
                return None
        return sdir

    def _get_config_dir(self):
        sdir = self.appdirs.user_config_dir
        return self._get_and_create(sdir)
    user_config_dir = property(_get_config_dir,
            doc="return directory of this configuration file")

    def _get_cache_dir(self):
        sdir = self.appdirs.user_cache_dir
        return self._get_and_create(sdir)
    user_cache_dir = property(_get_cache_dir,
            doc="return directory of the cache")

    def _get_config_file_path(self):
        return self.user_config_dir + os.sep +self.config_file
    user_config_file_path = property(_get_config_file_path,
            doc="return configuration filename (with fullpath)")

    def _get_config_file(self):
        return self.name + ".cfg"
    config_file = property(_get_config_file,
            doc="config filename (without path)")

    def init(self):
        """Reads the user_config_file and update params.
        Creates the directories for config and cache if they do not exsits

        """
        # Let us create the directories by simply getting these 2 attributes:
        try:
            _ = self.user_config_dir
        except:
            print("Could not retrieve or create the config file and/or directory in %s" % self.name)
        try:
            _ = self.user_cache_dir
        except:
            print("Could not retrieve or create the cache file and/or directory in %s" % self.name)
        self.read_user_config_file_and_update_params()

    def create_default_config_file(self, force=False):

        # if the file already exists, we should save the file into
        # a backup file
        if os.path.exists(self.user_config_file_path):
            # we need to copy the file into a backup file
            filename = self.user_config_file_path + '.bk'
            if os.path.exists(filename) and force is False:
                print("""Trying to save the current config file {} into a backup file {}\n but it exists already. Please remove the backup file first or set the 'force' parameter to True""".format(self.user_config_file_path, filename))
                return
            else:
                shutil.copy(self.user_config_file_path, filename)

        # Now, we can rewrite the configuration file
        sections = sorted(set([x.split(".")[0] for x in self._default_params.keys()]))
        if 'general' in sections:
            sections = ["general"] + [x for x in sections if x!="general"]

        fh = open(self.user_config_file_path, "w") # open and delete content
        for section in sections:
            fh.write("[" + section +"]\n")
            options = [x.split(".")[1] for x in self._default_params.keys() if x.startswith(section+".")]
            for option in options:
                key = section + '.' + option
                value = self._default_params[key]
                try:
                    fh.write("# {}\n{} = {}\n".format(value[2], 
                        option, value[0]))
                except:
                    print('Could not write this value/option. skipped')
                    print(value, option)

            fh.write("\n")
        fh.close()

    def reload_default_params(self):
        self.params = copy.deepcopy(self._default_params)