Replace ValueError with SceneException in scenes. Added error safety in scene resolver.

This commit is contained in:
Alex Root Junior 2023-08-26 18:36:49 +03:00
parent bcdf8ea9da
commit 99ed0f53ec
No known key found for this signature in database
GPG key ID: 074C1D455EBEA4AC
2 changed files with 24 additions and 14 deletions

View file

@ -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.

View file

@ -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