Project

Profile

Help

How to connect?
Download (4.43 KB) Statistics View on GitHub Reload from mirrored respository
| Branch: | Tag: | Revision:

github / src / config.py @ e1d2d0dc

1
"""This module defines the default configuration."""
2

    
3
import os
4
import os.path
5
from textwrap import dedent
6

    
7
from configobj import ConfigObj
8
from validate import Validator
9

    
10
class Configuration:
11

    
12
    """Class describing CocoMUD's configuration.
13

14
    Each configuration file is loaded here. Each file is loaded and validated with ConfigObj.  If everything goes smoothly, the ConfigObj objects can be found in _getitem__-ing these values, specifying the directory structure.
15

16
    Example:
17

18
        >>> config = Configuration()
19
        >>> config.load()
20
        >>> # In the settings/global.conf file is the following line:
21
        >>> #     name = CocoMUD
22
        >>> # You can access this configuration through:
23
        >>> configuration["options"]["global"]["name"]
24
        >>> # Or, more readable
25
        >>> configuration["options.global.name"]
26

27
    """
28

    
29
    def __init__(self, root_dir):
30
        self.root_dir = root_dir
31
        self.values = {}
32

    
33
    def __getitem__(self, key):
34
        """Return the configured value at the specified key.
35

36
        The key is a string.  It can be an identifier without periods
37
        (.).  In which case, the top-level data at this key is returned
38
        or a KeyError exception is raised.
39
        The 'key' can also be a list of identifiers in a string separated
40
        by a period.  In this case, the data is looked for in the
41
        directory/file/ConfigObj hierarchy.  A KeyError exception
42
        is raised if the expected key cannot be found.
43

44
        Thus, the two following lines are identical:
45
            >>> configuration["settings"]["global"]["name"]
46
            >>> configuration["settings.global.name"]
47

48
        """
49
        if "." in key:
50
            keys = key.split(".")
51
            value = self.values
52
            for sub_key in keys:
53
                if sub_key not in value:
54
                    raise KeyError("the key {} cannot be found, cannot " \
55
                            "find {}".format(repr(key), repr(sub_key)))
56

    
57
                value = value[sub_key]
58

    
59
        else:
60
            value = self.values[key]
61

    
62
        return value
63

    
64
    def __setitem__(self, key, value):
65
        """Change the value of 'key'.
66

67
        'key' is a string, and can be specified in the two ways supported
68
        by '__getitem__'.
69

70
        """
71
        if "." in key:
72
            keys = key.split(".")
73
            last = keys[-1]
74
            del keys[-1]
75
            dictionary = self.values
76
            for sub_key in keys:
77
                if sub_key not in dictionary:
78
                    raise KeyError("the key {} cannot be found, cannot " \
79
                            "find {}".format(repr(key), repr(sub_key)))
80

    
81
                dictionary = dictionary[sub_key]
82

    
83
            dictionary[last] = value
84
        else:
85
            self.values[key] = value
86

    
87
    def load(self):
88
        """Load the configuration."""
89
        raise NotImplementedError
90

    
91
    def load_file(self, filename, spec):
92
        """Load the specified file using ConfigObj."""
93
        fullpath = self.root_dir + os.sep + filename
94

    
95
        # Create the directory structure if necessary
96
        directories = os.path.dirname(fullpath).split("/")
97
        base = directories[0]
98
        if not os.path.exists(base):
99
            os.mkdir(base)
100

    
101
        for directory in directories[1:]:
102
            base += os.path + directory
103
            if not os.path.exists(base):
104
                os.mkdir(base)
105

    
106
        filename = os.path.basename(fullpath) + ".conf"
107

    
108
        # Create the ConfigObj
109
        config = ConfigObj(fullpath + ".conf", configspec=spec.split("\n"))
110

    
111
        # Validates the configuration
112
        validator = Validator()
113
        result = config.validate(validator)
114

    
115
        # Saves the ConfigObj
116
        values = self.values
117
        for path in os.path.dirname(fullpath).split("/")[1:]:
118
            if path not in values:
119
                values[path] = {}
120
            values = values[path]
121

    
122
        values[os.path.basename(fullpath)] = config
123

    
124

    
125
class Settings(Configuration):
126

    
127
    """Special configuration in the 'settings' directory."""
128

    
129
    def __init__(self):
130
        Configuration.__init__(self, "settings")
131

    
132
    def load(self):
133
        """Load all the files."""
134
        self.load_options()
135

    
136
    def load_options(self):
137
        """Load the file containing the options."""
138
        spec = dedent("""
139
            # Text-to-speech configuration
140
            [TTS]
141
                on = boolean(default=True)
142
                outside = boolean(default=True)
143
        """.strip("\n"))
144
        self.load_file("options", spec)
(5-5/6)