mirror of
https://github.com/aiogram/aiogram.git
synced 2026-04-08 16:37:47 +00:00
Replace ValueError with SceneException in scenes. Added error safety in scene resolver.
This commit is contained in:
parent
bcdf8ea9da
commit
99ed0f53ec
2 changed files with 24 additions and 14 deletions
|
|
@ -37,6 +37,12 @@ class CallbackAnswerException(AiogramError):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
class SceneException(AiogramError):
|
||||||
|
"""
|
||||||
|
Exception for scenes.
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
class UnsupportedKeywordArgument(DetailedAiogramError):
|
class UnsupportedKeywordArgument(DetailedAiogramError):
|
||||||
"""
|
"""
|
||||||
Exception raised when a keyword argument is passed as filter.
|
Exception raised when a keyword argument is passed as filter.
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ from typing_extensions import Self
|
||||||
from aiogram import Dispatcher, Router, loggers
|
from aiogram import Dispatcher, Router, loggers
|
||||||
from aiogram.dispatcher.event.bases import NextMiddlewareType
|
from aiogram.dispatcher.event.bases import NextMiddlewareType
|
||||||
from aiogram.dispatcher.event.handler import CallableObject, CallbackType
|
from aiogram.dispatcher.event.handler import CallableObject, CallbackType
|
||||||
|
from aiogram.exceptions import SceneException
|
||||||
from aiogram.filters import StateFilter
|
from aiogram.filters import StateFilter
|
||||||
from aiogram.fsm.context import FSMContext
|
from aiogram.fsm.context import FSMContext
|
||||||
from aiogram.scenes._history import HistoryManager
|
from aiogram.scenes._history import HistoryManager
|
||||||
|
|
@ -341,7 +342,7 @@ class SceneWizard:
|
||||||
|
|
||||||
async def _on_action(self, action: SceneAction, **kwargs: Any) -> bool:
|
async def _on_action(self, action: SceneAction, **kwargs: Any) -> bool:
|
||||||
if not self.scene:
|
if not self.scene:
|
||||||
raise ValueError("Scene is not initialized")
|
raise SceneException("Scene is not initialized")
|
||||||
|
|
||||||
loggers.scene.debug("Call action %r in scene %r", action.name, self.scene_config.state)
|
loggers.scene.debug("Call action %r in scene %r", action.name, self.scene_config.state)
|
||||||
action_config = self.scene_config.actions.get(action, {})
|
action_config = self.scene_config.actions.get(action, {})
|
||||||
|
|
@ -387,7 +388,7 @@ class ScenesManager:
|
||||||
update_type: str,
|
update_type: str,
|
||||||
event: TelegramObject,
|
event: TelegramObject,
|
||||||
state: FSMContext,
|
state: FSMContext,
|
||||||
data: dict[str, Any],
|
data: Dict[str, Any],
|
||||||
) -> None:
|
) -> None:
|
||||||
self.registry = registry
|
self.registry = registry
|
||||||
self.update_type = update_type
|
self.update_type = update_type
|
||||||
|
|
@ -412,7 +413,10 @@ class ScenesManager:
|
||||||
|
|
||||||
async def _get_active_scene(self) -> Optional[Scene]:
|
async def _get_active_scene(self) -> Optional[Scene]:
|
||||||
state = await self.state.get_state()
|
state = await self.state.get_state()
|
||||||
return await self._get_scene(state)
|
try:
|
||||||
|
return await self._get_scene(state)
|
||||||
|
except SceneException:
|
||||||
|
return None
|
||||||
|
|
||||||
async def enter(
|
async def enter(
|
||||||
self,
|
self,
|
||||||
|
|
@ -420,24 +424,22 @@ class ScenesManager:
|
||||||
_check_active: bool = True,
|
_check_active: bool = True,
|
||||||
**kwargs: Any,
|
**kwargs: Any,
|
||||||
) -> None:
|
) -> None:
|
||||||
scene = await self._get_scene(scene_type)
|
|
||||||
|
|
||||||
if _check_active:
|
if _check_active:
|
||||||
active_scene = await self._get_active_scene()
|
active_scene = await self._get_active_scene()
|
||||||
if active_scene is not None:
|
if active_scene is not None:
|
||||||
await active_scene.wizard.exit(**kwargs)
|
await active_scene.wizard.exit(**kwargs)
|
||||||
|
|
||||||
if not scene:
|
try:
|
||||||
loggers.scene.debug("Reset state")
|
scene = await self._get_scene(scene_type)
|
||||||
|
except SceneException:
|
||||||
|
if scene_type is not None:
|
||||||
|
raise
|
||||||
await self.state.set_state(None)
|
await self.state.set_state(None)
|
||||||
else:
|
else:
|
||||||
await scene.wizard.enter(**kwargs)
|
await scene.wizard.enter(**kwargs)
|
||||||
|
|
||||||
async def close(self, **kwargs: Any) -> None:
|
async def close(self, **kwargs: Any) -> None:
|
||||||
try:
|
scene = await self._get_active_scene()
|
||||||
scene = await self._get_active_scene()
|
|
||||||
except ValueError:
|
|
||||||
return
|
|
||||||
if not scene:
|
if not scene:
|
||||||
return
|
return
|
||||||
await scene.wizard.exit(**kwargs)
|
await scene.wizard.exit(**kwargs)
|
||||||
|
|
@ -501,7 +503,9 @@ class SceneRegistry:
|
||||||
|
|
||||||
for scene in scenes:
|
for scene in scenes:
|
||||||
if scene.__scene_config__.state in self._scenes:
|
if scene.__scene_config__.state in self._scenes:
|
||||||
raise ValueError(f"Scene {scene.__scene_config__.state} already exists")
|
raise SceneException(
|
||||||
|
f"Scene with state {scene.__scene_config__.state!r} already exists"
|
||||||
|
)
|
||||||
|
|
||||||
self._scenes[scene.__scene_config__.state] = scene
|
self._scenes[scene.__scene_config__.state] = scene
|
||||||
|
|
||||||
|
|
@ -511,12 +515,12 @@ class SceneRegistry:
|
||||||
if inspect.isclass(scene) and issubclass(scene, Scene):
|
if inspect.isclass(scene) and issubclass(scene, Scene):
|
||||||
scene = scene.__scene_config__.state
|
scene = scene.__scene_config__.state
|
||||||
if scene is not None and not isinstance(scene, str):
|
if scene is not None and not isinstance(scene, str):
|
||||||
raise TypeError("Scene must be a subclass of Scene or a string")
|
raise SceneException("Scene must be a subclass of Scene or a string")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
return self._scenes[scene]
|
return self._scenes[scene]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
raise ValueError(f"Scene {scene!r} is not registered")
|
raise SceneException(f"Scene {scene!r} is not registered")
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue