summaryrefslogtreecommitdiff
path: root/sqlplain/configurator.py
blob: 8bef7d17de640008fc22ec04012d66224de4a984 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
"""
This module defines a singleton configurator object with a single
public method .get_uri(alias).
When .get_uri is called, the environment variable $SQLPLAIN is looked at.
It should contain the name of a configuration file. If $SQLPLAIN is missing,
the configuration file name is assumed to be ~/.sqlplain. The configuration
file must exists and must contain a section [uri] as follows:

[uri]
dev: mssql://user:passwd@host:port/dev_db
test: mssql://user:passwd@host:port/test_db
prod: mssql://user:passwd@host:port/prod_db

Then .get_alias('dev') returns the URI mssql://user:passwd@host:port/dev_db.
Analogously for 'test' and 'prod'.

The configuration file may also contain a [dir] section specifying the
full pathname for the directory containing the creational scripts of
the corresponding database.
"""

import os
from ConfigParser import RawConfigParser # no magic interpolation

class ReadOnlyObject(object):
    """
    Take a list [(name, value), ...] and returns a read-only object
    with associated attributes. The names cannot be private. The ordering
    is preserved in the list ._names. The object has a ._name attribute
    useful for debugging (the default is 'anonymous').
    """
    def __init__(self, items, name='anonymous'):
        names = []
        for name, value in items:
            if name.startswith('_'):
                raise TypeError('Inner attributes cannot begin with "_"')
            object.__setattr__(self, name, value)
            names.append(name)
        object.__setattr__(self, '_names', names)
        object.__setattr__(self, '_name', name)
    def __iter__(self):
        for name in self._names:
            yield name, getattr(self, name)
    def __contains__(self, name):
        return name in self._names
    def __len__(self):
        return self(self._names)
    def __setattr__(self, name, value):
        if name in self._dic:
            raise TypeError('Read-only object!')
        else:
            object.__setattr__(self, name, value)
    def __str__(self):
        return '\n'.join('%s=%s' % (k, v) for k, v in self)
    def __repr__(self):
        return '<%s:%s>' % (self.__class__.__name__, self._name)

class _Configurator(object): # singleton
    _initialized = False
    
    def _initialize(self):
        "You may want to call this again if you modify the config file"
        cfp = RawConfigParser()
        self._conf_file = os.environ.get(
            'SQLPLAIN', os.path.expanduser('~/.sqlplain'))
        cfp.readfp(file(self._conf_file))
        self._conf_obj = ReadOnlyObject(
            [(sect, ReadOnlyObject(cfp.items(sect), sect))
            for sect in cfp.sections()], self._conf_file)
        self._initialized = True
        self._databases = self._conf_obj.uri._names
        
    def __getattr__(self, name):
        if not self._initialized:
            self._initialize()
        return getattr(self._conf_obj, name)

configurator = _Configurator()