mirror of
https://github.com/aiogram/aiogram.git
synced 2025-12-12 18:19:34 +00:00
More usable state groups. All child groups know about name of parent group.
This commit is contained in:
parent
d8909ffe35
commit
051b92a716
2 changed files with 75 additions and 14 deletions
|
|
@ -1,3 +1,4 @@
|
||||||
|
import inspect
|
||||||
import re
|
import re
|
||||||
from _contextvars import ContextVar
|
from _contextvars import ContextVar
|
||||||
|
|
||||||
|
|
@ -116,7 +117,7 @@ class StateFilter(BaseFilter):
|
||||||
ctx_state = ContextVar('user_state')
|
ctx_state = ContextVar('user_state')
|
||||||
|
|
||||||
def __init__(self, dispatcher, state):
|
def __init__(self, dispatcher, state):
|
||||||
from aiogram.dispatcher.filters.state import State
|
from aiogram.dispatcher.filters.state import State, StatesGroup
|
||||||
|
|
||||||
super().__init__(dispatcher)
|
super().__init__(dispatcher)
|
||||||
states = []
|
states = []
|
||||||
|
|
@ -125,8 +126,8 @@ class StateFilter(BaseFilter):
|
||||||
for item in state:
|
for item in state:
|
||||||
if isinstance(item, State):
|
if isinstance(item, State):
|
||||||
states.append(item.state)
|
states.append(item.state)
|
||||||
elif hasattr(item, 'state_names'): # issubclass() cannot be used in this place
|
elif inspect.isclass(item) and issubclass(item, StatesGroup):
|
||||||
states.extend(item.state_names)
|
states.extend(item.all_state_names)
|
||||||
else:
|
else:
|
||||||
states.append(item)
|
states.append(item)
|
||||||
self.states = states
|
self.states = states
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,38 @@
|
||||||
|
import inspect
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
from ..dispatcher import Dispatcher
|
from ..dispatcher import Dispatcher
|
||||||
|
|
||||||
|
|
||||||
class State:
|
class State:
|
||||||
def __init__(self, state=None):
|
"""
|
||||||
self.state = state
|
State object
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, state: Optional[str] = None, group_name: Optional[str] = None):
|
||||||
|
self._state = state
|
||||||
|
self._group_name = group_name
|
||||||
|
self._group = None
|
||||||
|
|
||||||
|
@property
|
||||||
|
def state(self):
|
||||||
|
if self._group_name is None and self._group:
|
||||||
|
group = self._group.__full_group_name__
|
||||||
|
elif self._group_name:
|
||||||
|
group = self._group_name
|
||||||
|
else:
|
||||||
|
group = '*'
|
||||||
|
return f"{group}:{self._state}"
|
||||||
|
|
||||||
|
def set_parent(self, group):
|
||||||
|
if not issubclass(group, StatesGroup):
|
||||||
|
raise ValueError('Group must be subclass of StatesGroup')
|
||||||
|
self._group = group
|
||||||
|
|
||||||
def __set_name__(self, owner, name):
|
def __set_name__(self, owner, name):
|
||||||
if self.state is None:
|
if self._state is None:
|
||||||
group_name = getattr(owner, '__group_name__')
|
self._state = name
|
||||||
if group_name is None:
|
self.set_parent(owner)
|
||||||
group_name = owner.__name__
|
|
||||||
self.state = f"{group_name}:{name}"
|
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return f"<State '{self.state}>'"
|
return f"<State '{self.state}>'"
|
||||||
|
|
@ -27,26 +49,64 @@ class MetaStatesGroup(type):
|
||||||
cls = super(MetaStatesGroup, mcs).__new__(mcs, name, bases, namespace)
|
cls = super(MetaStatesGroup, mcs).__new__(mcs, name, bases, namespace)
|
||||||
|
|
||||||
states = []
|
states = []
|
||||||
for name, prop in ((name, prop) for name, prop in namespace.items() if isinstance(prop, State)):
|
childs = []
|
||||||
states.append(prop)
|
|
||||||
|
|
||||||
|
cls._group_name = name
|
||||||
|
|
||||||
|
for name, prop in namespace.items():
|
||||||
|
|
||||||
|
if isinstance(prop, State):
|
||||||
|
states.append(prop)
|
||||||
|
elif inspect.isclass(prop) and issubclass(prop, StatesGroup):
|
||||||
|
childs.append(prop)
|
||||||
|
prop._parent = cls
|
||||||
|
# continue
|
||||||
|
|
||||||
|
cls._parent = None
|
||||||
|
cls._childs = tuple(childs)
|
||||||
cls._states = tuple(states)
|
cls._states = tuple(states)
|
||||||
cls._state_names = tuple(state.state for state in states)
|
cls._state_names = tuple(state.state for state in states)
|
||||||
|
|
||||||
return cls
|
return cls
|
||||||
|
|
||||||
|
@property
|
||||||
|
def __group_name__(cls):
|
||||||
|
return cls._group_name
|
||||||
|
|
||||||
|
@property
|
||||||
|
def __full_group_name__(cls):
|
||||||
|
if cls._parent:
|
||||||
|
return cls._parent.__full_group_name__ + '.' + cls._group_name
|
||||||
|
return cls._group_name
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def states(cls) -> tuple:
|
def states(cls) -> tuple:
|
||||||
return cls._states
|
return cls._states
|
||||||
|
|
||||||
|
@property
|
||||||
|
def childs(cls):
|
||||||
|
return cls._childs
|
||||||
|
|
||||||
|
@property
|
||||||
|
def all_states(cls):
|
||||||
|
result = cls.states
|
||||||
|
for group in cls.childs:
|
||||||
|
result += group.all_states
|
||||||
|
return result
|
||||||
|
|
||||||
|
@property
|
||||||
|
def all_state_names(cls):
|
||||||
|
return tuple(state.state for state in cls.all_states)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return f"<StatesGroup '{self.__full_group_name__}'>"
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def state_names(cls) -> tuple:
|
def state_names(cls) -> tuple:
|
||||||
return cls._state_names
|
return cls._state_names
|
||||||
|
|
||||||
|
|
||||||
class StatesGroup(metaclass=MetaStatesGroup):
|
class StatesGroup(metaclass=MetaStatesGroup):
|
||||||
__group_name__ = None
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
async def next(cls) -> str:
|
async def next(cls) -> str:
|
||||||
state = Dispatcher.current().current_state()
|
state = Dispatcher.current().current_state()
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue