source: OpenRLabs-Git/deploy/rlabs-docker/web2py-rlabs/gluon/contrib/appconfig.py

main
Last change on this file was 42bd667, checked in by David Fuertes <dfuertes@…>, 4 years ago

Historial Limpio

  • Property mode set to 100755
File size: 4.5 KB
Line 
1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3"""
4Read from configuration files easily without hurting performances
5
6USAGE:
7During development you can load a config file either in .ini or .json
8format (by default app/private/appconfig.ini or app/private/appconfig.json)
9The result is a dict holding the configured values. Passing reload=True
10is meant only for development: in production, leave reload to False and all
11values will be cached
12
13from gluon.contrib.appconfig import AppConfig
14myconfig = AppConfig(path_to_configfile, reload=False)
15
16print myconfig['db']['uri']
17
18The returned dict can walk with "dot notation" an arbitrarely nested dict
19
20print myconfig.take('db.uri')
21
22You can even pass a cast function, i.e.
23
24print myconfig.take('auth.expiration', cast=int)
25
26Once the value has been fetched (and casted) it won't change until the process
27is restarted (or reload=True is passed).
28
29"""
30import os
31import json
32from gluon._compat import thread, configparser
33from gluon.globals import current
34
35locker = thread.allocate_lock()
36
37def AppConfig(*args, **vars):
38
39    locker.acquire()
40    reload_ = vars.pop('reload', False)
41    try:
42        instance_name = 'AppConfig_' + current.request.application
43        if reload_ or not hasattr(AppConfig, instance_name):
44            setattr(AppConfig, instance_name, AppConfigLoader(*args, **vars))
45        return getattr(AppConfig, instance_name).settings
46    finally:
47        locker.release()
48
49
50class AppConfigDict(dict):
51    """
52    dict that has a .take() method to fetch nested values and puts
53    them into cache
54    """
55
56    def __init__(self, *args, **kwargs):
57        dict.__init__(self, *args, **kwargs)
58        self.int_cache = {}
59
60    def get(self, path, default=None):
61        try:
62            value = self.take(path).strip()
63            if value.lower() in ('none','null',''):
64                return None
65            elif value.lower() == 'true':
66                return True
67            elif value.lower() == 'false':
68                return False
69            elif value.isdigit() or (value[0]=='-' and value[1:].isdigit()):
70                return int(value)
71            elif ',' in value:
72                return map(lambda x:x.strip(),value.split(','))
73            else:
74                try:
75                    return float(value)
76                except:
77                    return value
78        except:
79            return default
80
81    def take(self, path, cast=None):
82        parts = path.split('.')
83        if path in self.int_cache:
84            return self.int_cache[path]
85        value = self
86        walking = []
87        for part in parts:
88            if part not in value:
89                raise BaseException("%s not in config [%s]" %
90                    (part, '-->'.join(walking)))
91            value = value[part]
92            walking.append(part)
93        if cast is None:
94            self.int_cache[path] = value
95        else:
96            try:
97                value = cast(value)
98                self.int_cache[path] = value
99            except (ValueError, TypeError):
100                raise BaseException("%s can't be converted to %s" %
101                 (value, cast))
102        return value
103
104
105class AppConfigLoader(object):
106
107    def __init__(self, configfile=None):
108        if not configfile:
109            priv_folder = os.path.join(current.request.folder, 'private')
110            configfile = os.path.join(priv_folder, 'appconfig.ini')
111            if not os.path.isfile(configfile):
112                configfile = os.path.join(priv_folder, 'appconfig.json')
113                if not os.path.isfile(configfile):
114                    configfile = None
115        if not configfile or not os.path.isfile(configfile):
116            raise BaseException("Config file not found")
117        self.file = configfile
118        self.ctype = os.path.splitext(configfile)[1][1:]
119        self.settings = None
120        self.read_config()
121
122    def read_config_ini(self):
123        config = configparser.SafeConfigParser()
124        config.read(self.file)
125        settings = {}
126        for section in config.sections():
127            settings[section] = {}
128            for option in config.options(section):
129                settings[section][option] = config.get(section, option)
130        self.settings = AppConfigDict(settings)
131
132    def read_config_json(self):
133        with open(self.file, 'r') as c:
134            self.settings = AppConfigDict(json.load(c))
135
136    def read_config(self):
137        if self.settings is None:
138            try:
139                getattr(self, 'read_config_' + self.ctype)()
140            except AttributeError:
141                raise BaseException("Unsupported config file format")
142        return self.settings
Note: See TracBrowser for help on using the repository browser.