Coverage for /home/runner/work/bijux-cli/bijux-cli/src/bijux_cli/contracts/registry.py: 100%

12 statements  

« prev     ^ index     » next       coverage.py v7.10.4, created at 2025-08-19 23:36 +0000

1# SPDX-License-Identifier: MIT 

2# Copyright © 2025 Bijan Mousavi 

3 

4"""Defines the contract for the plugin registry service. 

5 

6This module specifies the `RegistryProtocol`, a formal interface that any 

7service responsible for managing the lifecycle of CLI plugins must implement. 

8This includes registering, retrieving, and invoking hooks on plugins. 

9""" 

10 

11from __future__ import annotations 

12 

13from typing import Any, Protocol, TypeVar, runtime_checkable 

14 

15T = TypeVar("T") 

16 

17 

18@runtime_checkable 

19class RegistryProtocol(Protocol): 

20 """Defines the contract for plugin management. 

21 

22 This interface specifies the methods for registering, deregistering, and 

23 interacting with plugins, as well as for invoking plugin hooks. 

24 """ 

25 

26 def register( 

27 self, 

28 name: str, 

29 plugin: object, 

30 *, 

31 alias: str | None = None, 

32 version: str | None = None, 

33 ) -> None: 

34 """Registers a plugin with the registry. 

35 

36 Args: 

37 name (str): The primary name of the plugin. 

38 plugin (object): The plugin object to register. 

39 alias (str | None): An optional alias for the plugin. 

40 version (str | None): An optional version string for the plugin. 

41 

42 Returns: 

43 None: 

44 """ 

45 ... 

46 

47 def deregister(self, name: str) -> None: 

48 """Deregisters a plugin from the registry. 

49 

50 Args: 

51 name (str): The name or alias of the plugin to deregister. 

52 

53 Returns: 

54 None: 

55 """ 

56 ... 

57 

58 def get(self, name: str) -> object: 

59 """Retrieves a plugin by its name or alias. 

60 

61 Args: 

62 name (str): The name or alias of the plugin. 

63 

64 Returns: 

65 object: The registered plugin object. 

66 

67 Raises: 

68 KeyError: If no plugin with the given name or alias is registered. 

69 """ 

70 ... 

71 

72 def has(self, name: str) -> bool: 

73 """Checks if a plugin exists in the registry. 

74 

75 Args: 

76 name (str): The name or alias of the plugin. 

77 

78 Returns: 

79 bool: True if the plugin is registered, False otherwise. 

80 """ 

81 ... 

82 

83 def names(self) -> list[str]: 

84 """Returns all registered plugin names. 

85 

86 Returns: 

87 list[str]: A list of the primary names of all registered plugins. 

88 """ 

89 ... 

90 

91 def meta(self, name: str) -> dict[str, str]: 

92 """Returns metadata for a specific plugin. 

93 

94 Args: 

95 name (str): The name or alias of the plugin. 

96 

97 Returns: 

98 dict[str, str]: A dictionary containing the plugin's metadata, such 

99 as its version and alias. 

100 """ 

101 ... 

102 

103 async def call_hook(self, hook: str, *args: Any, **kwargs: Any) -> Any: 

104 """Invokes a hook on all registered plugins that implement it. 

105 

106 Args: 

107 hook (str): The name of the hook to invoke. 

108 *args (Any): Positional arguments to pass to the hook. 

109 **kwargs (Any): Keyword arguments to pass to the hook. 

110 

111 Returns: 

112 Any: The result of the hook invocation. The exact return type 

113 depends on the specific hook's definition and implementation. 

114 """ 

115 ...