diff --git a/docs/code_snippets/error_handling_example_sample.py b/docs/code_snippets/error_handling_example_sample.py new file mode 100644 index 0000000..a270faa --- /dev/null +++ b/docs/code_snippets/error_handling_example_sample.py @@ -0,0 +1,7 @@ +from argenta import App + +def empty_command_handler(): + print("Empty command handler called") + +app: App = App() +app.set_empty_command_handler(empty_command_handler) diff --git a/docs/index.rst b/docs/index.rst index b28a336..3e65160 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -38,6 +38,7 @@ Argenta нужна для создания приложений, которым :caption: Контент: root/quickstart + root/flags root/error_handling root/dependency_injection root/overriding_formatting diff --git a/docs/root/error_handling.rst b/docs/root/error_handling.rst index f3b6765..642dfae 100644 --- a/docs/root/error_handling.rst +++ b/docs/root/error_handling.rst @@ -4,4 +4,160 @@ Конфигурация ******************************** -привет +``Argenta`` в рантайме вызывает исключения в пограничных случаях. Подробнее о типах исключений :ref:`ниже `. +Все исключения обрабатываются системными хэндлерами, но у вас есть возможность их переопределить. Переопределение осуществляется +с помощью сеттеров инстанса ``App`` - ``.set_*_handler(_)``, где ``_`` - это протокол хэндлера нестандартного поведения, подробнее +о каждом протоколе и соответствующем сеттере :ref:`ниже ` + +Краткий сэмпл кода, переопределяющего хэндлер ввода +пустой команды + +.. literalinclude:: ../code_snippets/error_handling_example_sample.py + :language: python + + +.. _possible_errors: +Возможные исключения +******************************** + +UnprocessedInputFlagException: Необрабатываемый ввод от пользователя +-------------------------------------------------------------------- + +Исключение вызывается, когда пользователь вводит команду с некорректным синтаксисом и парсер не может +*распарсить* её. В большинстве случаев это означат, что проблема в синтаксисе введённых флагов команды, подробнее в + +.. code-block:: + + dishka.exceptions.CycleDependenciesError: Cycle dependencies detected. + ◈ Scope.APP, component='' ◈ + ╭─>─╮ __main__.A FirstProvider.get_a + │ ▼ __main__.B FirstProvider.get_b + ╰─<─╯ __main__.C AnotherProvider.get_c + + +This error means that one of the objects cannot be created because some of +its dependencies depend on itself. +You can see the whole path in the error message with types and provider methods. + +Possible actions: + +* **Remove cycle dependency.** + If the cycle was introduced as a result of typo you can fix it. + But in other cases this can lead to a refactoring of your object structure + +* **Implement two-phase initialization.** + Instead of doing constructor injection using dishka you can do attribute injection later when both objects are available. + + +GraphMissingFactoryError: Cannot find factory for ... +------------------------------------------------------- + +.. code-block:: + + dishka.exceptions.GraphMissingFactoryError: Cannot find factory for (C, component=''). It is missing or has invalid scope. + │ ◈ Scope.APP, component='' ◈ + ▼ __main__.A FirstProvider.get_a + ▼ __main__.B FirstProvider.get_b + ╰─> __main__.C ??? + + +There are multiple reasons for this error. If possible, dishka tries to predict possible fixes. + +* **Factory is simply missing.** + Check that you added all required providers and they contain appropriate ``provide``. + +* **Context data is not marked with from_context** + Check that you added all required providers and they contain appropriate ``from_context``. + +* **Object has invalid scope** + Check the scope of provided type and the types dependent on it. + Note, that long-living objects cannot depend on short-living ones. + E.g. object with ``Scope.APP`` cannot depend on one with ``Scope.REQUEST``. + + You should review used scopes. + +* **Object is provided in another component** + Components are isolated and cannot implicitly share objects. + You should either use ``FromComponent`` to call another component directly or + create object separately for appropriate component using ``provide`` annotation + +* **Dependency is parent class while provided child class (or vice versa)** + Use ``provides=`` argument to mark that source and provided types are different. + Use ``WithParents[X]`` to provide an object as its type with parent classes + + +CannotUseProtocolError: Cannot use ... as a factory +------------------------------------------------------- + +.. code-block:: + + dishka.provider.exceptions.CannotUseProtocolError: Cannot use as a factory. + Tip: seems that this is a Protocol. Please subclass it and provide the subclass. + +This error means that you used some protocol class as a source argument of ``provide`` function. +Protocols cannot be instantiated. +Check that you have an implementation for that protocol, and use it. +You can try using the form ``provide(YourImpl, provides=YourProtocol)``. + + +NotAFactoryError: Cannot use ... as a factory. +------------------------------------------------------- + +.. code-block:: + + dishka.provider.exceptions.NotAFactoryError: Cannot use typing.Union[int, str] as a factory. + + +Check what are you passing to ``provide`` function. Probably that object cannot be instantiated directly. + +Note, that you can provide some type by creating an instance of another one using the form ``provide(YourClass, provides=SomeTypeHint)``. + + +ImplicitOverrideDetectedError: Detected multiple factories for ... +------------------------------------------------------------------------- + +.. code-block:: + + dishka.exceptions.ImplicitOverrideDetectedError: Detected multiple factories for (, component='') while `override` flag is not set. + Hint: + * Try specifying `override=True` for SecondProvider.get_a + * Try removing factory FirstProvider.get_a or SecondProvider.get_a + +This error can be seen only if you enabled ``implicit_override=True`` in validation settings. +It means that you have 2 factories for the same type without specifying that the second one should replace the first one. + +* **You meant to have one of factories**. Just remove the second one. + +* **You want to override dependency for tests or other purposes**. Specify ``override=True`` when creating second factory. + +Error text will contain details on both option with names of providers. + + +NothingOverriddenError: Overriding factory found for ..., but there is nothing to override. +--------------------------------------------------------------------------------------------------- + +.. code-block:: + + dishka.exceptions.NothingOverriddenError: Overriding factory found for (, component=''), but there is nothing to override. + Hint: + * Try removing override=True from FirstProvider.get_a + * Check the order of providers + +This error can be seen only if you enabled ``nothing_overridden=True`` in validation settings. +That means you set ``override=True``, but there is no second factory to be overriden or the order of providers is incorrect. + +Check, that you have specified all expected providers in correct order or remove the flag. + + +IndependentDecoratorError: Decorator ... does not depend on provided type. +--------------------------------------------------------------------------------------------------- + +.. code-block:: + + dishka.provider.exceptions.IndependentDecoratorError: Decorator __main__.FirstProvider.get_a does not depend on provided type. + Did you mean @provide instead of @decorate? + +Using ``decorate`` is a special case if you need to apply decorator patter or do modifications with an object created in another provider. +Is requests an object of some type (additional dependencies are allowed) and returns the same type. + +If you are not going to use an object received from another factory, probably you meant to use simple ``provide`` instead? \ No newline at end of file diff --git a/docs/root/flags.rst b/docs/root/flags.rst new file mode 100644 index 0000000..c5b81bc --- /dev/null +++ b/docs/root/flags.rst @@ -0,0 +1,3 @@ +Флаги +===== +