Completed
Push — master ( da3b73...3279ec )
by Kenny
01:17
created

Conf.get()   B

Complexity

Conditions 6

Size

Total Lines 28

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 6
c 0
b 0
f 0
dl 0
loc 28
rs 7.5384
1
# -*- coding: utf-8 -*-
2
"""Simple configuration file helpers for small configurations in yaml.
3
4
.. moduleauthor:: Kenny Freeman <[email protected]>
5
6
"""
7
__author__ = 'Kenny Freeman'
8
__email__ = '[email protected]'
9
__license__     = "ISCL"
10
__docformat__   = 'reStructuredText'
11
12
import os.path
13
import glob
14
15
import yaml # pip install pyaml
16
17
import plumd
18
19
20
def ls(dname, ext):
21
    """Helper to return a list of the yaml files in a directory.
22
23
    :param dname: Path to list files in
24
    :type name: str
25
    :param ext: Extension to use in glob call, default "yaml"
26
    :type name: str
27
    :rtype: list -- a list of of the filenames found or []
28
    """
29
    ret = []
30
    if os.path.isdir(dname):
31
        try:
32
            ret = glob.glob(os.path.join(dname, "*.{0}".format(ext)))
33
        except AttributeError as e:
34
            raise plumd.ConfigError("invalid path? {0} : {1}".format(dname, e))
35
    return ret
36
37
38
class Conf(object):
39
    """Simple key/value configuration helper class for small yaml files.
40
41
    :param cfile: Full path to the configuration file to load
42
    :type name: str
43
    :raises: ConfigError: if the specified file does not exist
44
    """
45
46
    def __init__(self, cfile):
47
        """conf constructor.
48
49
        :param cfile: Full path to the configuration file to load
50
        :type name: str
51
        :rtype: conf -- an instance of conf
52
        :raises: ConfigError: if the specified file does not exist
53
        """
54
        self.conf = {}
55
        self.path = cfile
56
        if not os.path.isfile(cfile):
57
            raise plumd.ConfigError("file {0} does not exist".format(cfile))
58
        with open(cfile) as fd:
59
            try:
60
                self.conf = yaml.safe_load(fd)
61
            except yaml.scanner.ScannerError as e:
62
                msg = "invalid: {0} : {1}".format(cfile, e)
63
                raise plumd.ConfigError(msg)
64
65
66
    def __str__(self):
67
        """Return a nicely formatted string of our config.
68
        :rtype: str
69
        """
70
        return yaml.dump(self.conf,allow_unicode=False,default_flow_style=False)
71
72
73
    def __repr__(self):
74
        """Return a nicely formatted string of our config.
75
        :rtype: str
76
        """
77
        return yaml.dump(self.conf,allow_unicode=True,default_flow_style=False)
78
79
80
    def get(self, name, exception=False, default=None, rtype=None):
81
        """Returns the requested value, the provided default or None.
82
83
        raises:
84
            ConfigError if exception=True and the requested key is not found.
85
86
        :param name: The configuration value to lookup and return
87
        :type name: str
88
        :param exception: If True raise a ConfigError if the vlaue is not present
89
        :type exception: bool
90
        :param default: The default value to return if value is not found
91
        :rtype: value -- the configured value for the requested name or default
92
        :raises: ConfigError
93
        """
94
        val = default
95
        if name in self.conf and self.conf[name] is not None:
96
            val = self.conf[name]
97
        elif exception:
98
            msg = "missing {0} in: {1}".format(name, self.path)
99
            raise plumd.ConfigError(msg)
100
        if rtype:
101
            try:
102
                val = rtype(val)
103
            except (ValueError, TypeError) as e:
104
                msg = "{0} from file: {1} is not a(n) {2}, exception: {3}"
105
                rname = rtype.__name__
106
                raise plumd.ConfigError(msg.format(name, self.path, rname, e))
107
        return val
108
109
110
    def set_conf(self, name, val, overwrite=False):
111
        """Sets the named configuration to the provided value.
112
113
        If overwrite is False and the value exists it will be left unchanged.
114
115
        :param name: The configuration key to set
116
        :type name: str
117
        :param val: The configuration key is set to this value
118
        :rtype: self -- this object - allows chaining calls
119
        """
120
        name = name.strip()
121
        if name in self.conf and overwrite:
122
            self.conf[name] = val
123
        elif name not in self.conf:
124
            self.conf[name] = val
125
        return self
126
127
128
    def defaults(self, defconf):
129
        """Updates any missing configurations with values from defconf.
130
131
        :param defconf: dict of default values to set
132
        :type defconf: dict
133
        :rtype: self -- this object - allows chaining calls
134
        """
135
        for key, val in defconf.items():
136
            key = key.strip()
137
            if key not in self.conf or self.conf[key] is None:
138
                self.conf[key] = val
139
        return self
140