mirror of
https://github.com/aiogram/aiogram.git
synced 2025-12-11 09:55:21 +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
|
||||
from _contextvars import ContextVar
|
||||
|
||||
|
|
@ -116,7 +117,7 @@ class StateFilter(BaseFilter):
|
|||
ctx_state = ContextVar('user_state')
|
||||
|
||||
def __init__(self, dispatcher, state):
|
||||
from aiogram.dispatcher.filters.state import State
|
||||
from aiogram.dispatcher.filters.state import State, StatesGroup
|
||||
|
||||
super().__init__(dispatcher)
|
||||
states = []
|
||||
|
|
@ -125,8 +126,8 @@ class StateFilter(BaseFilter):
|
|||
for item in state:
|
||||
if isinstance(item, State):
|
||||
states.append(item.state)
|
||||
elif hasattr(item, 'state_names'): # issubclass() cannot be used in this place
|
||||
states.extend(item.state_names)
|
||||
elif inspect.isclass(item) and issubclass(item, StatesGroup):
|
||||
states.extend(item.all_state_names)
|
||||
else:
|
||||
states.append(item)
|
||||
self.states = states
|
||||
|
|
|
|||
|
|
@ -1,16 +1,38 @@
|
|||
import inspect
|
||||
from typing import Optional
|
||||
|
||||
from ..dispatcher import Dispatcher
|
||||
|
||||
|
||||
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):
|
||||
if self.state is None:
|
||||
group_name = getattr(owner, '__group_name__')
|
||||
if group_name is None:
|
||||
group_name = owner.__name__
|
||||
self.state = f"{group_name}:{name}"
|
||||
if self._state is None:
|
||||
self._state = name
|
||||
self.set_parent(owner)
|
||||
|
||||
def __str__(self):
|
||||
return f"<State '{self.state}>'"
|
||||
|
|
@ -27,26 +49,64 @@ class MetaStatesGroup(type):
|
|||
cls = super(MetaStatesGroup, mcs).__new__(mcs, name, bases, namespace)
|
||||
|
||||
states = []
|
||||
for name, prop in ((name, prop) for name, prop in namespace.items() if isinstance(prop, State)):
|
||||
states.append(prop)
|
||||
childs = []
|
||||
|
||||
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._state_names = tuple(state.state for state in states)
|
||||
|
||||
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
|
||||
def states(cls) -> tuple:
|
||||
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
|
||||
def state_names(cls) -> tuple:
|
||||
return cls._state_names
|
||||
|
||||
|
||||
class StatesGroup(metaclass=MetaStatesGroup):
|
||||
__group_name__ = None
|
||||
|
||||
@classmethod
|
||||
async def next(cls) -> str:
|
||||
state = Dispatcher.current().current_state()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue