diff --git a/docs/hooks.rst b/docs/hooks.rst index 6c5dbce..9260eec 100644 --- a/docs/hooks.rst +++ b/docs/hooks.rst @@ -1,7 +1,26 @@ Quilla Plugin Hooks ------------------------ +======================== -.. automodule:: quilla.hookspecs +Configuration hooks +------------------------------------- + +.. automodule:: quilla.hookspecs.configuration + :members: + :undoc-members: + :show-inheritance: + +Steps hooks +----------------------------- + +.. automodule:: quilla.hookspecs.steps + :members: + :undoc-members: + :show-inheritance: + +Report hooks +------------------------------- + +.. automodule:: quilla.hookspecs.reports :members: :undoc-members: :show-inheritance: diff --git a/docs/source/quilla.hookspecs.rst b/docs/source/quilla.hookspecs.rst new file mode 100644 index 0000000..7e1b31f --- /dev/null +++ b/docs/source/quilla.hookspecs.rst @@ -0,0 +1,30 @@ +quilla.hookspecs package +======================== + +Submodules +---------- + +quilla.hookspecs.configuration module +------------------------------------- + +.. automodule:: quilla.hookspecs.configuration + :members: + :undoc-members: + :show-inheritance: + + +quilla.hookspecs.steps module +----------------------------- + +.. automodule:: quilla.hookspecs.steps + :members: + :undoc-members: + :show-inheritance: + +quilla.hookspecs.reports module +------------------------------- + +.. automodule:: quilla.hookspecs.reports + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/source/quilla.rst b/docs/source/quilla.rst index ac0aaab..6626d8f 100644 --- a/docs/source/quilla.rst +++ b/docs/source/quilla.rst @@ -33,14 +33,6 @@ quilla.plugins module :undoc-members: :show-inheritance: -quilla.hookspecs module ------------------------ - -.. automodule:: quilla.hookspecs - :members: - :undoc-members: - :show-inheritance: - Subpackages ----------- @@ -51,3 +43,4 @@ Subpackages quilla.common quilla.reports quilla.steps + quilla.hookspecs diff --git a/src/quilla/hookspecs/__init__.py b/src/quilla/hookspecs/__init__.py new file mode 100644 index 0000000..6ff2486 --- /dev/null +++ b/src/quilla/hookspecs/__init__.py @@ -0,0 +1,3 @@ +import pluggy + +hookspec = pluggy.HookspecMarker('quilla') diff --git a/src/quilla/hookspecs.py b/src/quilla/hookspecs/configuration.py similarity index 51% rename from src/quilla/hookspecs.py rename to src/quilla/hookspecs/configuration.py index e266ec1..3642486 100644 --- a/src/quilla/hookspecs.py +++ b/src/quilla/hookspecs/configuration.py @@ -1,49 +1,40 @@ +''' +Hooks that are related to configuration, such as logger configs, parser additions, +etc. +''' from enum import Enum -from typing import ( - Tuple, - Optional, - Dict, - Type, - TypeVar, -) +from logging import Logger from argparse import ( ArgumentParser, Namespace ) +from typing import ( + Type, + TypeVar, + Optional, +) -import pluggy - +from quilla.hookspecs import hookspec from quilla.ctx import Context -from quilla.common.enums import UITestActions -from quilla.steps.base_steps import BaseStepFactory -from quilla.reports.report_summary import ReportSummary from quilla.ui_validation import UIValidation -hookspec = pluggy.HookspecMarker('quilla') - -StepFactorySelector = Dict[UITestActions, Type[BaseStepFactory]] T = TypeVar('T', bound=Enum) -@hookspec(firstresult=True) -def quilla_context_obj(ctx: Context, root: str, path: Tuple[str]) -> Optional[str]: +@hookspec +def quilla_configure_logger(logger: Logger): ''' - A hook to allow pluggins to resolve a context object given its root - and a path. All plugins that implement this hook *must* return None if they cannot - resolve the context object. + A hook called immediately after the plugin manager is created. This is the very + first hook called, and allows plugins to register additional handlers, formatters, + or otherwise modify the logger used throughout Quilla. Note, the Context is not + yet created - It is not possible to override the default context object handlers + To help in debugging, it is recommended that plugins register their own StreamHandler + to the logger with a filter that shows only the messages relevant to the plugin. Args: - ctx: The runtime context for the application - root: The name of the context object, which is expressed as the root - of a dot-separated path in the validation files - path: The remainder of the context object path, where data is being - retrieved from - - Returns - the data stored at the context object if existing, None otherwise + logger: The configured logger instance for Quilla ''' @@ -74,45 +65,6 @@ def quilla_configure(ctx: Context, args: Namespace): ''' -@hookspec -def quilla_prevalidate(validation: UIValidation): - ''' - A hook called immediately before the validations attempt to be resolved - (i.e. before `validations.validate_all()` is called) - - Args: - validation: The collected validations from the json passed to - the application - ''' - - -@hookspec -def quilla_postvalidate(ctx: Context, reports: ReportSummary): - ''' - A hook called immediately after all validations are executed and the full - ReportSummary is generated - - Args: - ctx: The runtime context for the application - reports: An object capturing all generated reports and giving summary data - ''' - - -@hookspec -def quilla_step_factory_selector(selector: StepFactorySelector): - ''' - A hook called immediately before resolving the step factory for a given step definition. - This is used to register new step factories for custom step objects. - - Most custom steps should just add themselves to the `quilla_step_selector` hook, but if - a custom step requires complex logic it might be beneficial to register a factory to - have more fine-grained control over the logic - - Args: - selector: The factory selector dictionary. - ''' - - @hookspec(firstresult=True) def quilla_resolve_enum_from_name(name: str, enum: Type[T]) -> Optional[T]: ''' @@ -131,3 +83,17 @@ def quilla_resolve_enum_from_name(name: str, enum: Type[T]) -> Optional[T]: The resolved enum, if it can be resolved. None if the plugin can't resolve the value. ''' + + +@hookspec +def quilla_prevalidate(validation: UIValidation): + ''' + A hook called immediately before the validations attempt to be resolved + (i.e. before `validations.validate_all()` is called). + + If the Context object is needed, it is available through ``validations.ctx``. + + Args: + validation: The collected validations from the json passed to + the application + ''' diff --git a/src/quilla/hookspecs/reports.py b/src/quilla/hookspecs/reports.py new file mode 100644 index 0000000..a8c208b --- /dev/null +++ b/src/quilla/hookspecs/reports.py @@ -0,0 +1,19 @@ +''' +Hooks related to outputs and reports +''' + +from quilla.ctx import Context +from quilla.hookspecs import hookspec +from quilla.reports.report_summary import ReportSummary + + +@hookspec +def quilla_postvalidate(ctx: Context, reports: ReportSummary): + ''' + A hook called immediately after all validations are executed and the full + ReportSummary is generated + + Args: + ctx: The runtime context for the application + reports: An object capturing all generated reports and giving summary data + ''' diff --git a/src/quilla/hookspecs/steps.py b/src/quilla/hookspecs/steps.py new file mode 100644 index 0000000..d56dd16 --- /dev/null +++ b/src/quilla/hookspecs/steps.py @@ -0,0 +1,54 @@ +''' +Hooks that allow extension of the behaviour of steps, including output and validation +related steps. This also includes any hooks related to context expressions +''' +from typing import ( + Type, + Dict, + Tuple, + Optional +) + +from quilla.hookspecs import hookspec +from quilla.ctx import Context +from quilla.common.enums import UITestActions +from quilla.steps.base_steps import BaseStepFactory + + +StepFactorySelector = Dict[UITestActions, Type[BaseStepFactory]] + + +@hookspec +def quilla_step_factory_selector(selector: StepFactorySelector): + ''' + A hook called immediately before resolving the step factory for a given step definition. + This is used to register new step factories for custom step objects. + + Most custom steps should just add themselves to one of the non-factory selector hooks, but if + a custom step requires complex logic it might be beneficial to register a factory to + have more fine-grained control over the logic + + Args: + selector: The factory selector dictionary. + ''' + + +@hookspec(firstresult=True) +def quilla_context_obj(ctx: Context, root: str, path: Tuple[str]) -> Optional[str]: + ''' + A hook to allow pluggins to resolve a context object given its root + and a path. All plugins that implement this hook *must* return None if they cannot + resolve the context object. + + It is not possible to override the default context object handlers + + Args: + ctx: The runtime context for the application + root: The name of the context object, which is expressed as the root + of a dot-separated path in the validation files + path: The remainder of the context object path, where data is being + retrieved from + + Returns + the data stored at the context object if existing, None otherwise + '''