0
인스턴스 - resp에서 구성 파일 항목에 액세스하는 방법을 찾고있었습니다. 클래스 바인딩 된 변수. Configurable
클래스는 지금 여러 하위 클래스에 의해 상속인스턴스는 생성 후 다른 인스턴스에 속성을 전달합니다.
from ..lib.files import ConfigFile
from abc import abstractmethod
__all__ = ['ClassConfig',
'InstanceConfig',
'Configurable']
class ConfigEntry():
"""
A Config entry
"""
__value = None
def __init__(self, value=None):
"""
Initializes the
"""
self.__value = value
def __set__(self, __, value):
self.__value = value
@property
def value(self):
"""
Returns the value
"""
return self.__value
class ClassConfig(ConfigEntry):
"""
A class config entry
"""
def __get__(self, obj, cls):
"""
Returns its value, when called by a class, else itself
"""
if obj == None:
return self.value
else:
return self
class InstanceConfig(ConfigEntry):
"""
An instance config entry
"""
def __get__(self, obj, cls):
"""
Returns its value, when called by an instance, else itself
"""
if obj != None:
return self.value
else:
return self
class Configurable():
"""
Configuration file binding
"""
__SUFFIX = '.conf'
__TYPES = {int: 'int',
float: 'float',
str: 'str',
bool: 'bool'}
__file_ = None
__lbi = '['
__lei = ']'
__ls = ','
__ts = '←'
__loaded = False
def __init__(self, path, suffix=None):
"""
Initialize the config file
"""
# Initializes instance methods
self.__setinstattr()
suffix = suffix if suffix != None else self.__SUFFIX
self.__file_ = ConfigFile(path + suffix)
self.load()
def __setinstattr(self):
"""
Set instance attributes
"""
self.__fields = self.__inst___fields
self._file = self.__inst____file
self._force_load = self.__inst__force_load
self.load = self.__inst_load
self.store = self.__inst_store
@staticmethod
def __filter(attrs):
return [a for a in attrs
if a == a.upper()
and not a.startswith('_')]
@staticmethod
def __encode(val):
"""
Encode a value
"""
t = type(val)
if t == list:
return Configurable.__lbi + \
Configurable.__ls.join([Configurable.__encode(i)
for i in val]) \
+ Configurable.__lei
elif val == None:
return None
else:
return Configurable.__ts.join([str(val),
Configurable.__TYPES.get(t, '?')])
@staticmethod
def __decode(val):
"""
Decode a value
"""
def det_type(token):
"""
Determine the type of a token
"""
t = token.strip().split(Configurable.__ts)
if len(t) == 2:
raw_val = t[0]
tpe = t[1]
if tpe == Configurable.__TYPES[str]:
return str(raw_val)
elif tpe == Configurable.__TYPES[int]:
return int(raw_val)
elif tpe == Configurable.__TYPES[float]:
return float(raw_val)
elif tpe == Configurable.__TYPES[bool]:
return True if raw_val.lower() in ['1',
'true',
't'] else False
else:
try:
return int(raw_val)
except:
try:
return float(raw_val)
except:
return raw_val
return token
def str2list(s):
"""
Try to parse a list from a string
"""
def getlist(val):
"""
Get a list from a reversed character list of a string
"""
result = []
token = ''
while val:
c = val.pop()
if c == Configurable.__lei:
token = Configurable.__lei
result = [getlist(val)] + result
elif c == Configurable.__lbi:
if (not Configurable.__lbi in token) and (not Configurable.__lei in token):
result = [det_type(token)] + result
token = c
return result
elif c == Configurable.__ls:
if (not Configurable.__lbi in token) and (not Configurable.__lei in token):
result = [det_type(token)] + result
token = ''
else:
token = c + token
if token:
result = [det_type(token)] + result
return result
l = []
for char in s:
l.append(char)
l = getlist(l)
if len(l) == 0:
return l
return l.pop()
return str2list(val)
@classmethod
def __fields(cls):
"""
Get fields for an instance
"""
result = {}
class Subclass(cls):
def __init__(self):
pass
instance = Subclass()
attrs = Configurable.__filter(dir(instance))
for a in attrs:
aval = getattr(instance, a)
if isinstance(aval, ClassConfig):
value = getattr(cls, a)
result[a] = value
return result
def __inst___fields(self):
"""
Get fields of an instance
"""
result = {}
cls = self.__class__
attrs = Configurable.__filter(dir(cls))
for a in attrs:
val = getattr(cls, a)
if isinstance(val, InstanceConfig):
value = getattr(self, a)
result[a] = value
return result
@classmethod
@abstractmethod
def _file(cls):
"""
Returns the file
XXX: Implement by calling
super()._file(static_path)
"""
pass
@classmethod
def _file_path(cls, path, suffix=None):
"""
Returns the file relative to a path
"""
suffix = suffix if suffix != None else cls.__SUFFIX
f = ConfigFile(path + suffix)
f.create()
return f
def __inst____file(self):
"""
Returns the file
"""
return self.__file_
@classmethod
def load(cls):
"""
Loads the config file content, if not yet done into the class
"""
if not cls.__loaded:
return cls._force_load()
return True
def __inst_load(self):
"""
Loads the config file content, if not yet done into the instance
"""
if not self.__loaded:
return self._force_load()
return True
@classmethod
def _force_load(cls):
"""
Loads the config file's content to the class
"""
if cls._file().exists:
data = cls._file().dict()
for field in Configurable.__filter(data):
setattr(cls, field,
Configurable.__decode(data[field]))
cls.__loaded = True
return True
return False
def __inst__force_load(self):
"""
Loads the config file's content to the instance
"""
if self._file().exists:
data = self._file().dict()
for field in Configurable.__filter(data):
setattr(self, field,
Configurable.__decode(data[field]))
self.__loaded = True
return True
return False
@classmethod
def store(cls):
"""
Writes class config to file
"""
result = True
content = cls.__fields()
if not cls._file().exists:
cls._file().create()
for new_field in content:
set_result = cls._file().set(new_field,
Configurable.__encode(content[new_field]))
result = False if not set_result else result
return result
def __inst_store(self):
"""
Writes instance config to file
"""
result = True
content = self.__fields()
if not self._file().exists:
self._file().create()
for new_field in content:
set_result = self._file().set(new_field,
Configurable.__encode(content[new_field]))
result = False if not set_result else result
return result
, 글로벌 구성 (클래스 바인딩 재료) 및 사용자 dependen 구성 (인스턴스 바인딩 물건이있을 수 있습니다 : 그 때문에 나는 다음과 같은 모듈을 만들었습니다) 그와 같은
지금은load()
순서에 많은 경우에서 수행 될 때마다 상기 InstanceConfigEntry가 previuos 인스턴스의 값을 복사 것이라는 문제를 직면
class Spam(Configurable):
EGGS = InstanceConfig('foo')
GLOBAL_EGGS = ClassConfig('bar')
:
class RETARD(Daemon):
"""
Real Estate Translation, Archiving and Redirection Daemon
"""
__source = None # The source interface instance
__targets = [] # The target interface instances
__locked = False # System locked state flag
__start_time = None # Start time of loop
__sleeping = 0 # Remaining time to sleep
#===========================================================================
# Default customer config
#===========================================================================
SOURCE = InstanceConfig('') # Name of the source interface
TARGETS = InstanceConfig([]) # Names of the target interfaces
INTERVAL = InstanceConfig(120.0) # Loop interval
DEBUG = InstanceConfig(False) # Print the import config?
def __init__(self, customer):
"""
Constructor
"""
print('SOURCE1: ' + str(self.SOURCE))
super().__init__(customer)
print('SOURCE2: ' + str(self.SOURCE))
self.__load()
print('SOURCE3: ' + str(self.SOURCE))
# Disable logger on high level to prevent PyXB
# from printing messages to the terminal
logging.disable(9999)
<SNIP>
다음과 같이로드 할 때
은 (데몬 네 다른 인스턴스를 포함) : 난을 변경하지 않았기 때문에,
SOURCE1:
SOURCE2: IS24
SOURCE3: IS24
SOURCE1: IS24
SOURCE2: is24
SOURCE3: is24
SOURCE1: is24
SOURCE2: infobase
SOURCE3: infobase
SOURCE1: infobase
SOURCE2: infobase
SOURCE3: infobase
나는이 문제를 이해하지 :이 출력을 생성
daemons = []
for customer in customers:
daemons.append(RETARD(customer))
클래스 '속성을 인스턴스의 인스턴스가 아닌 다른 곳에 배치 할 수 있습니다. 인스턴스가 변경된 속성을 다음 인스턴스로 전달하지 않도록하려면 어떻게해야합니까?