import logging
import warnings
from collections import namedtuple
logger = logging.getLogger(__name__)
Field = namedtuple('Field', ('name', 'type_', 'default', 'desc', 'warn'))
[docs]class Config:
"""配置模块
用户可以在 rc 文件中配置各个选项的值
"""
def __init__(self):
object.__setattr__(self, '_fields', {})
def __getattr__(self, name):
# tips: 这里不能用 getattr 来获取值, 否则会死循环
if name == '_fields':
return object.__getattribute__(self, '_fields')
if name in self._fields:
try:
object.__getattribute__(self, name)
except AttributeError:
return self._fields[name].default
return object.__getattribute__(self, name)
def __setattr__(self, name, value):
if name in self._fields:
field = self._fields[name]
if field.warn is not None:
warnings.warn('Config field({}): {}'.format(name, field.warn),
stacklevel=2)
# TODO: 校验值类型
object.__setattr__(self, name, value)
else:
logger.warning('Assign to an undeclared config key.')
def deffield(self, name, type_=None, default=None, desc='', warn=None):
"""Define a configuration field
:param str name: the field name. It SHOULD be capitalized except the field
refers to a sub-config.
:param type_: feild type.
:param default: default value for the field.
:param desc: description for the field.
:param warn: if field is deprecated, set a warn message.
"""
if name not in self._fields:
self._fields[name] = Field(name=name,
type_=type_,
default=default,
desc=desc,
warn=warn)
else:
raise ValueError('Field({}) is already defined.'.format(name))