|
1 | 1 | import inspect |
| 2 | +from collections.abc import Callable |
2 | 3 | from typing import ( |
3 | 4 | Annotated, |
4 | 5 | Any, |
|
19 | 20 | from exasol.toolbox.util.version import Version |
20 | 21 |
|
21 | 22 |
|
| 23 | +def get_methods_with_hook_implementation( |
| 24 | + plugin_class: type[Any], |
| 25 | +) -> tuple[tuple[str, Callable], ...]: |
| 26 | + """ |
| 27 | + Get all methods from a plugin_class which were specified with a @hookimpl. |
| 28 | + """ |
| 29 | + return tuple( |
| 30 | + (name, method) |
| 31 | + for name, method in inspect.getmembers(plugin_class, inspect.isroutine) |
| 32 | + if hasattr(method, PLUGIN_ATTR_NAME) |
| 33 | + ) |
| 34 | + |
| 35 | + |
| 36 | +def filter_not_specified_methods( |
| 37 | + methods: tuple[tuple[str, Callable], ...], |
| 38 | +) -> tuple[str, ...]: |
| 39 | + """ |
| 40 | + Filter methods which were specified with a @hookimpl but where not specified |
| 41 | + in `exasol.toolbox.nox.plugins.NoxTasks`. |
| 42 | + """ |
| 43 | + return tuple(name for name, _ in methods if name not in METHODS_SPECIFIED_FOR_HOOKS) |
| 44 | + |
| 45 | + |
22 | 46 | def validate_plugin_hook(plugin_class: type[Any]): |
23 | 47 | """ |
24 | | - Checks methods in a class for at least one specific pluggy @hookimpl marker |
25 | | - and verifies that this method is also specified in |
26 | | - `exasol.toolbox.nox.plugins.NoxTasks`. |
| 48 | + Validate methods in a class for at least one pluggy @hookimpl marker and verifies |
| 49 | + that this method is also specified in `exasol.toolbox.nox.plugins.NoxTasks`. |
27 | 50 | """ |
28 | | - has_hook_implementation = False |
29 | | - not_specified_decorated_methods = [] |
30 | | - for name, method in inspect.getmembers(plugin_class, inspect.isroutine): |
31 | | - if hasattr(method, PLUGIN_ATTR_NAME): |
32 | | - has_hook_implementation = True |
33 | | - if name not in METHODS_SPECIFIED_FOR_HOOKS: |
34 | | - not_specified_decorated_methods.append(name) |
35 | | - |
36 | | - if not has_hook_implementation: |
| 51 | + methods_with_hook = get_methods_with_hook_implementation(plugin_class=plugin_class) |
| 52 | + |
| 53 | + if len(methods_with_hook) == 0: |
37 | 54 | raise ValueError( |
38 | 55 | f"No methods in `{plugin_class.__name__}` were found to be decorated" |
39 | 56 | "with `@hookimpl`. The `@hookimpl` decorator indicates that this" |
40 | 57 | "will be used with pluggy and used in specific nox sessions." |
41 | 58 | "Without it, this class does not modify any nox sessions." |
42 | 59 | ) |
43 | 60 |
|
44 | | - if not_specified_decorated_methods: |
| 61 | + if not_specified_methods := filter_not_specified_methods(methods_with_hook): |
45 | 62 | raise ValueError( |
46 | | - f"{len(not_specified_decorated_methods)} method(s) were " |
| 63 | + f"{len(not_specified_methods)} method(s) were " |
47 | 64 | "decorated with `@hookimpl`, but these methods were not " |
48 | 65 | "specified in `exasol.toolbox.nox.plugins.NoxTasks`: " |
49 | | - f"{not_specified_decorated_methods}. The `@hookimpl` decorator indicates " |
| 66 | + f"{not_specified_methods}. The `@hookimpl` decorator indicates " |
50 | 67 | "that these methods will be used by pluggy to modify specific nox sessions." |
51 | 68 | "If the method was not previously specified, then no nox sessions will" |
52 | 69 | "be modified. The `@hookimpl` is only used by nox sessions provided by the" |
|
0 commit comments