1
\$\begingroup\$

I am writing a Model to read, write and store settings. I think my code is pretty good, but I am not 100% sure. Any advice on how I could possibly improve it is welcome.

import ntpath

import yaml


class Settings:
    def __init__(self, paths=None, default_path=None):
        """Load, write and store settings

        This model manages setting files (YAML).

        Keyword Arguments:
            paths {list or None} -- list of full or relative
                                    paths with filenames (default: {None})
            default_path {str or None} -- path to user settings, read last
                                          and default for writing
                                          (default: {None})
        """
        paths = paths or []
        # Make sure paths are unique and sorted by file name
        self.paths = sorted(set(paths), key=lambda p: ntpath.basename(p))
        # Remove default_path from paths (look at next comment)
        try:
            self.paths.remove(default_path)
        except ValueError:
            pass
        # Readd default_path at the end to make sure it's loaded last
        if default_path is not None:
            self.paths.append(default_path)
        # Set remaining attributes
        self.default_path = default_path
        self.settings = {}

        # Load files
        self.reload()

    def reload(self):
        """Reload files into buffer

        Reloads the files specified in self.paths
        and writes them into the buffer.
        """
        # Clear settings to ensure no unwanted leftovers
        self.settings.clear()
        # Load every path (sorted by filename, self.default_path last)
        for path in self.paths:
            with open(path, 'r') as f:
                content = f.read()
            self.settings.update(yaml.load(content) or {})

    def write(self, key, value, path=None):
        """Write into file

        Writes key and value into the file specified
        by path (or self.default_path if None)

        Arguments:
            key {immutable} -- key to use (valid YAML key)
            value {ANY} -- value to save

        Keyword Arguments:
            path {str} -- path to save file (default: {None})
        """
        path = path or self.default_path
        assert path is not None

        with open(path, 'r') as f:
            settings = yaml.load(f.read()) or {}

        settings[key] = value
        self.settings[key] = value

        with open(path, 'w') as f:
            f.write(yaml.dump(settings, default_flow_style=False))
\$\endgroup\$
1
\$\begingroup\$

The module should import os.path instead of ntpath.

os.path is the cross-platform equivalent of ntpath, it automatically picks the appropriate path module for the OS your code is running on. So it will use ntpath behind the scenes when running on Windows, but you will also be able to use the code on more operating systems than just Windows. (See the note at https://docs.python.org/3/library/os.path.html)

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ Thank you, I did it that way initially but changed it after reading the accepted answer to this post: stackoverflow.com/questions/8384737/…; Seems as he was wrong? \$\endgroup\$ – Matthias Schreiber Jun 3 '16 at 11:33
  • \$\begingroup\$ @Matthias: That post is dealing with Windows paths specifically. If you must deal with Windows paths, use ntpath; if you are dealing with whatever paths are used by the OS your program is run on, use os.path. You shouldn't be dealing with only Windows paths because you try to open the files. On Linux, you can't open Windows files. Therefore, you should be using os.path \$\endgroup\$ – zondo Jun 3 '16 at 13:13
0
\$\begingroup\$

One thing I found so far is to either rename the attribute "settings" to "buffer" (or something similar), or to make Settings inherit from dict (or better from collections.MutableMapping as suggested here). Doing something like this is awkward:

settings_instance.settings['test_key']
| improve this answer | |
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.