BS 0.1.0
This commit is contained in:
@@ -1,24 +1,24 @@
|
||||
from .Config import *
|
||||
from .Reflection import *
|
||||
from abs import ABC, abstractmethod
|
||||
from abc import ABC, abstractmethod
|
||||
|
||||
class ISignal(ABC):
|
||||
pass
|
||||
|
||||
class IModel(ABC):
|
||||
@absstractmethod
|
||||
@abstractmethod
|
||||
def Save(self) -> str:
|
||||
pass
|
||||
@absstractmethod
|
||||
@abstractmethod
|
||||
def Load(self, data:str) -> None:
|
||||
pass
|
||||
|
||||
class IConvertable[T](ABC):
|
||||
@absstractmethod
|
||||
def ConvertTo() -> T:
|
||||
@abstractmethod
|
||||
def ConvertTo(self) -> T:
|
||||
pass
|
||||
|
||||
class IConvertModel[T](ABC, IConventable[T], IModel):
|
||||
class IConvertModel[T](IConvertable[T], IModel):
|
||||
pass
|
||||
|
||||
class SingletonModel[T](IModel):
|
||||
@@ -26,22 +26,23 @@ class SingletonModel[T](IModel):
|
||||
|
||||
@staticmethod
|
||||
def GetInstance(t:Typen[T]) -> T:
|
||||
return _InjectInstances[t]
|
||||
return SingletonModel._InjectInstances[t]
|
||||
@staticmethod
|
||||
def SetInstance(t:Typen[T], obj:T) -> None:
|
||||
_InjectInstances[t] = obj
|
||||
SingletonModel._InjectInstances[t] = obj
|
||||
|
||||
def __init__(self, t:Typen[T]) -> None:
|
||||
self.typen: type = t
|
||||
|
||||
@override
|
||||
def Save() -> str:
|
||||
return GetInstance(self.typen).Save()
|
||||
def Save(self) -> str:
|
||||
return SingletonModel.GetInstance(self.typen).Save()
|
||||
|
||||
def DependenceModel(IConvertModel[bool]):
|
||||
class DependenceModel(IConvertModel[bool]):
|
||||
def __init__(self, queries:Sequence[IConvertModel[bool]]) -> None:
|
||||
self.queries:list[IConventModel] = list(queries)
|
||||
self.queries:list[IConvertModel[bool]] = list(queries)
|
||||
|
||||
@override
|
||||
def ConvertTo(self) -> bool:
|
||||
for query in self.queries:
|
||||
if query.ConvertTo() == False:
|
||||
@@ -49,38 +50,54 @@ def DependenceModel(IConvertModel[bool]):
|
||||
return True
|
||||
|
||||
def __iter__(self):
|
||||
return self.queries
|
||||
return iter(self.queries)
|
||||
|
||||
def Load(self, data:str):
|
||||
raise NotImplementedError()
|
||||
|
||||
|
||||
def Save(self) -> str:
|
||||
return NotImplement
|
||||
raise NotImplementedError()
|
||||
|
||||
class Achitecture:
|
||||
SignalListener = Callable[[ISignal], None]
|
||||
|
||||
class Architecture:
|
||||
@staticmethod
|
||||
def FormatType(t:type) -> str:
|
||||
return f"{t.__module__}::{t.__name__}"
|
||||
|
||||
@staticmethod
|
||||
def LoadFromFormat(data:str) -> type|None:
|
||||
module,name = data.split("::")
|
||||
return StringWithModule2Type(module,name)
|
||||
def LoadFromFormat(data:str, exception:Exception|None=None) -> type|None:
|
||||
try:
|
||||
module,name = data.split("::")
|
||||
return StringWithModel2Type(name, module=module)
|
||||
except Exception as ex:
|
||||
if exception is not None:
|
||||
exception = ex
|
||||
return None
|
||||
|
||||
@classmethod
|
||||
def InternalReset(cls) -> None:
|
||||
# Register System
|
||||
cls._RegisterHistory.clear()
|
||||
cls._UncompleteTargets.clear()
|
||||
cls._Completer.clear()
|
||||
cls._Dependences.clear()
|
||||
cls._Childs.clear()
|
||||
# Event Listener
|
||||
cls._SignalListener.clear()
|
||||
# Linear Chain for Dependence
|
||||
cls._TimelineQueues.clear()
|
||||
cls._TimelineContentID = 0
|
||||
|
||||
#region Objects Registered
|
||||
|
||||
class TypeQuery(IConvertModel[bool]):
|
||||
def __init__(self, queryType:type) -> None:
|
||||
self._quertType = quertType
|
||||
self._queryType = queryType
|
||||
|
||||
@override
|
||||
def ConvertTo(self) -> bool:
|
||||
return self._queryType in Architectrue.Childs
|
||||
return self._queryType in Architecture._Childs
|
||||
|
||||
def Load(self, data:str) -> None:
|
||||
raise NotImplementedError()
|
||||
@@ -100,31 +117,167 @@ class Achitecture:
|
||||
|
||||
@override
|
||||
def ConvertTo(self) -> bool:
|
||||
return self._registerSlot in Architecture.Childs
|
||||
return self._registerSlot in Architecture._Childs
|
||||
|
||||
@override
|
||||
def Load(self,data:str) -> None:
|
||||
raise InvalidOperationError()
|
||||
raise InvalidOperationError(f"Cannot use {self.__class__.__name__} to load type")
|
||||
|
||||
@override
|
||||
def Save(self) -> str:
|
||||
raise InalidOperationError()
|
||||
return f"{Architecture.FormatType(self._registerSlot)}[{self.ConvertTo()}]"
|
||||
|
||||
@classmethod
|
||||
def _InternalRegisteringComplete(cls) -> bool,Set[type]:
|
||||
def _InternalRegisteringComplete(cls) -> tuple[bool,Set[type]]:
|
||||
resultSet: Set[type] = set()
|
||||
stats: bool = False
|
||||
for dependence in cls._Dependences.keys:
|
||||
if cls._Dependences[dependence].ConventTo():
|
||||
resultSet.insert(dependence)
|
||||
for dependence in cls._Dependences.keys():
|
||||
if cls._Dependences[dependence].ConvertTo():
|
||||
resultSet.add(dependence)
|
||||
stats = True
|
||||
return stats,resultSet
|
||||
|
||||
@classmethod
|
||||
def _InternalRegisteringUpdate(cls, internalUpdateBuffer:Set[type]):
|
||||
for complete in cls._InternalUpdateBuffer:
|
||||
cls._Dependences.remove(complete)
|
||||
# TODO
|
||||
for complete in internalUpdateBuffer:
|
||||
cls._Dependences.pop(complete, None)
|
||||
for complete in internalUpdateBuffer:
|
||||
cls._Completer[complete]()
|
||||
cls._Completer.pop(complete, None)
|
||||
for complete in internalUpdateBuffer:
|
||||
cls._Childs[complete] = cls._UncompleteTargets[complete]
|
||||
cls._UncompleteTargets.pop(complete, None)
|
||||
|
||||
@classmethod
|
||||
def Register(cls, slot:type, target:object, completer:Action, *dependences:type) -> 'Architecture.Registering':
|
||||
if slot in cls._RegisterHistory:
|
||||
raise InvalidOperationError("Illegal duplicate registrations")
|
||||
|
||||
cls._RegisterHistory.add(slot)
|
||||
cls._Completer[slot] = completer
|
||||
cls._UncompleteTargets[slot] = target
|
||||
|
||||
# 过滤掉自身依赖
|
||||
filtered_deps = [dep for dep in dependences if dep != slot]
|
||||
type_queries = [cls.TypeQuery(dep) for dep in filtered_deps]
|
||||
cls._Dependences[slot] = DependenceModel(type_queries)
|
||||
|
||||
while True:
|
||||
has_complete, buffer = cls._InternalRegisteringComplete()
|
||||
if not has_complete:
|
||||
break
|
||||
cls._InternalRegisteringUpdate(buffer)
|
||||
|
||||
return cls.Registering(slot)
|
||||
|
||||
@classmethod
|
||||
def RegisterGeneric[T](cls, target:T, completer:Action, *dependences:type) -> 'Architecture.Registering':
|
||||
return cls.Register(type(target), target, completer, *dependences)
|
||||
|
||||
@classmethod
|
||||
def Contains(cls, type_:type) -> bool:
|
||||
return type_ in cls._Childs
|
||||
|
||||
@classmethod
|
||||
def ContainsGeneric[T](cls) -> bool:
|
||||
return cls.Contains(type(T))
|
||||
|
||||
@classmethod
|
||||
def InternalGet(cls, type_:type) -> object:
|
||||
return cls._Childs[type_]
|
||||
|
||||
@classmethod
|
||||
def Get(cls, type_:type) -> object:
|
||||
return cls.InternalGet(type_)
|
||||
|
||||
@classmethod
|
||||
def GetGeneric[T](cls) -> T:
|
||||
return cls.Get(type(T))
|
||||
|
||||
#endregion
|
||||
|
||||
#region Signal & Update
|
||||
|
||||
_SignalListener: Dict[type, Set[SignalListener]] = {}
|
||||
|
||||
class Listening:
|
||||
def __init__(self, action:SignalListener, type_:type):
|
||||
self._action = action
|
||||
self._type = type_
|
||||
|
||||
def StopListening(self):
|
||||
if self._type in Architecture._SignalListener:
|
||||
Architecture._SignalListener[self._type].discard(self._action)
|
||||
|
||||
@classmethod
|
||||
def AddListenerGeneric[Signal](cls, slot:type, listener:SignalListener) -> 'Architecture.Listening':
|
||||
if slot not in cls._SignalListener:
|
||||
cls._SignalListener[slot] = set()
|
||||
|
||||
def action(signal:ISignal):
|
||||
if isinstance(signal, slot):
|
||||
listener(signal)
|
||||
|
||||
result = cls.Listening(action, slot)
|
||||
cls._SignalListener[slot].add(action)
|
||||
return result
|
||||
|
||||
@classmethod
|
||||
def SendMessage(cls, slot:type, signal:ISignal):
|
||||
if slot in cls._SignalListener:
|
||||
for action in cls._SignalListener[slot]:
|
||||
action(signal)
|
||||
|
||||
#endregion
|
||||
|
||||
#region Timeline/Chain & Update
|
||||
|
||||
class TimelineQueueEntry:
|
||||
def __init__(self):
|
||||
self.predicate: Callable[[], bool] = lambda: False
|
||||
self.actions: List[Action] = []
|
||||
|
||||
class Timeline:
|
||||
def __init__(self):
|
||||
self.predicate_mapper: Dict[Callable[[], bool], int] = {}
|
||||
self.queue: List[Architecture.TimelineQueueEntry] = []
|
||||
self.context: int = 0
|
||||
|
||||
_TimelineQueues: Dict[int, Timeline] = {}
|
||||
_TimelineContentID: int = 0
|
||||
|
||||
@classmethod
|
||||
def CreateTimeline(cls) -> int:
|
||||
cls._TimelineQueues[cls._TimelineContentID] = cls.Timeline()
|
||||
cls._TimelineContentID += 1
|
||||
return cls._TimelineContentID - 1
|
||||
|
||||
@classmethod
|
||||
def AddStep(cls, timeline_id:int, predicate:Callable[[], bool], *actions:Action):
|
||||
timeline = cls._TimelineQueues[timeline_id]
|
||||
if predicate in timeline.predicate_mapper:
|
||||
time = timeline.predicate_mapper[predicate]
|
||||
timeline.queue[time].actions.extend(actions)
|
||||
else:
|
||||
time = len(timeline.queue)
|
||||
timeline.predicate_mapper[predicate] = time
|
||||
entry = cls.TimelineQueueEntry()
|
||||
entry.predicate = predicate
|
||||
entry.actions = list(actions)
|
||||
timeline.queue.append(entry)
|
||||
|
||||
@classmethod
|
||||
def UpdateTimeline(cls):
|
||||
for timeline in cls._TimelineQueues.values():
|
||||
if timeline.context < len(timeline.queue):
|
||||
if timeline.queue[timeline.context].predicate():
|
||||
for action in timeline.queue[timeline.context].actions:
|
||||
action()
|
||||
timeline.context += 1
|
||||
|
||||
@classmethod
|
||||
def ResetTimelineContext(cls, timeline_id:int):
|
||||
cls._TimelineQueues[timeline_id].context = 0
|
||||
|
||||
#endregion
|
||||
|
||||
|
Reference in New Issue
Block a user