如果我有配置文件default.py
:
HOST = 'localhost'
PORT = 8080
PROTOCOL = 'http' if PORT != 443 else 'https'
ROOT_STR = '%s://%s:%s' % (PROTOCOL, HOST, PORT)
然后我有local.py
覆盖默认变量以适应当地环境:
PORT = 443
我如何动态重新生成PROTOCOL
和ROOT_STR
,就像它们是类的属性一样,而是在模块的根级别?
通过更改一个变量,生成的配置将显示为:
HOST = 'localhost'
PORT = 443
PROTOCOL = 'https'
ROOT_STR = 'https://localhost:443'
预期的行为应该为类属性建模:
class Configuration(object):
def __init__(self):
self.host = 'localhost'
self.port = 8080
@property
def protocol(self):
return 'https' if self.port == 443 else 'http'
@property
def root_str(self):
return '%s://%s:%s' % (self.protocol, self.host, self.port)
...
...
>>> c = Configuration()
>>> c.port = 443
>>> c.root_str
'https://localhost:443'
有没有比修改AST更简洁的方法?
思想?
答案 0 :(得分:1)
我使用了自定义配置import re
import types
CONST_VARS = re.compile(r'[A-Z]+[_A-Z]*')
# Configuration primitives that allow for dynamic
# variable compilation for default/local/dev/etc settings files.
class ConfigType(type):
def __init__(cls, name, bases, odict):
if not hasattr(cls, 'vars'):
cls.vars = {}
reg_vars = filter(lambda x: CONST_VARS.match(x[0]), odict.items())
for k, v in reg_vars:
cls.vars[k] = v
delattr(cls, k)
super(ConfigType, cls).__init__(name, bases, cls.vars)
class Configuration(object):
__metaclass__ = ConfigType
def __init__(self):
pass
def __setattr__(self, key, value):
self.vars[key] = value
def __getattr__(self, item):
ret = self.vars.get(item)
if isinstance(ret, types.FunctionType):
return ret(self)
return ret
def as_module(self):
mod_vars = {}
for k, v in self.vars.items():
if isinstance(v, types.FunctionType) and callable(v):
v = v(self)
mod_vars[k] = v
return type('Configuration', (object,), mod_vars)
和Configuration
,粗略实现如下。
settings/default.py
然后,如果我创建了两个class DatabaseConfig(Configuration):
MYSQL_DB = 'DEFAULT'
MYSQL_USER = os.environ.get('MYSQL_USER')
MYSQL_PASS = os.environ.get('MYSQL_PASS')
MYSQL_HOST = os.environ.get('MYSQL_HOST', 'localhost')
MYSQL_PORT = os.environ.get('MYSQL_PORT', 3306)
def MYSQL_URI(self):
return 'mysql://{user}:{password}@{server}:{port}'.format(
user=self.MYSQL_USER,
password=self.MYSQL_PASS,
server=self.MYSQL_HOST,
port=self.MYSQL_PORT )
def SQLALCHEMY_DATABASE_URI(self):
return str(self.MYSQL_URI) + '/' + self.MYSQL_DB
DatabaseConfig()
个对象:
<强> settings/local.py
强>
class LocalConfig(Configuration):
MYSQL_DB = 'mycoolstuff'
MYSQL_USER = 'root'
MYSQL_PASS = 'rootpass'
MYSQL_HOST = '172.17.42.1' # Docker
MYSQL_PORT = 3306
Config = LocalConfig()
<强> LocalConfig
强>
>>> import settings.default
>>> from settings.local import Config
>>> Config.MYSQL_PORT
3306
>>> Config.MYSQL_URI
mysql://root:rootpass@172.17.42.1:3306
当我导入app.get('/:user_id', function (req, res){
console.log('Test user_id param: ' + req.params.user_id);
});
时,我的变量将自动计算,所有函数都充当属性,所有类属性充当变量。
app.use('\(:user_id\)', function (req, res){
console.log('Test param: ' + req.params.user_id);
});
答案 1 :(得分:-1)
您可以将from default import *
添加到local.py
文件的顶部。这应该使default.py
中的所有变量和函数都可用,就像它们位于local.py
中一样。