pluginify 1.0.0.post16.dev0__py3-none-any.whl → 1.0.0.post48.dev0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -4,31 +4,84 @@
4
4
  """Implements a base class for class-based plugins.
5
5
 
6
6
  The base class implemented here would expose the call signature of the child plugin
7
- class as `__call__()` while also providing hooks for pre- and post-processing.
7
+ class as ``__call__()`` while also providing hooks for pre- and post-processing.
8
8
 
9
- The hooks are available as `_pre_call()` and `_post_call()`. They should be used to
9
+ The hooks are available as ``_pre_call()`` and ``_post_call()``. They should be used to
10
10
  implement common functionality that all plugins of this type should posess but which we
11
11
  don't want developers to need to implement. They are intended to be overridden by the
12
- child plugin-type class (e.g. BaseReaderPlugin). They should define what kwargs they
12
+ child plugin-type class (e.g. ``BaseReaderPlugin``). They should define what kwargs they
13
13
  accept when defined on the plugin-type class but should accept their arguments from
14
- `**kwargs` from `__call__()`.
15
-
16
- The `call()` method should be overridden on the actual plugin class. It should provide
17
- the data processing for the plugin. `__call__()`'s signature will be identical to that
18
- of `call()` except that `call()` should not accept `**kwargs`. That should be consumed
19
- by the hooks.
20
-
21
- `__call__()` should not be overridden anywhere.
14
+ ``**kwargs`` from ``__call__()``.
15
+
16
+ The ``call()`` method should be overridden on the actual plugin class. It should provide
17
+ the data processing for the plugin. ``__call__()``'s signature will be identical to that
18
+ of ``call()`` except that ``call()`` should not accept ``**kwargs``. That should be
19
+ consumed by the hooks.
20
+
21
+ ``__call__()`` should not be overridden anywhere.
22
+
23
+ Required attributes
24
+ -------------------
25
+ interface : str
26
+ The interface type the plugin belongs to
27
+ (e.g. ``'configs'``, ``'data_modifiers'``).
28
+ This is typically provided by the interface-level plugin class and not the
29
+ individual plugin class.
30
+ family : str
31
+ The family name of the plugin. This should be defined by the plugin class.
32
+ name : str
33
+ The specific name of the plugin. This should be defined by the plugin class.
34
+
35
+ Required methods
36
+ ----------------
37
+ call()
38
+ The main method that performs the plugin's functionality. This method
39
+ should be implemented by the plugin class.
40
+ _pre_call()
41
+ A hook method that can be overridden to preprocess data before
42
+ calling the main ``call()`` method. This method should accept the same
43
+ arguments as ``call()`` via ``*args`` and ``**kwargs`` and should,
44
+ typically, be implemented by the interface-level plugin class.
45
+ _post_call()
46
+ A hook method that can be overridden to post-process data after
47
+ calling the main ``call()`` method. This method should accept the same
48
+ arguments as ``call()`` via ``*args`` and ``**kwargs`` and should,
49
+ typically, be implemented by the interface-level plugin class.
50
+
51
+ Notes
52
+ -----
53
+ The purpose of ``_pre_call()`` and ``_post_call()`` is to allow for common
54
+ functionality that all plugins of a certain type should possess, without requiring
55
+ developers to implement this functionality in every plugin class. Initially, this
56
+ will be used to convert inputs from DataTree to other formats and back to DataTree
57
+ after processing, but it could be used for other common tasks as well.
22
58
  """
23
59
 
24
60
  from __future__ import annotations
61
+
25
62
  from abc import ABC, abstractmethod
26
63
  import functools
27
64
  import inspect
65
+ from typing import Any
28
66
 
29
67
 
30
- def valid_str_attr(cls, attr_name: str):
31
- """Check that the given attribute is a non-empty string."""
68
+ def valid_str_attr(cls: type, attr_name: str) -> None:
69
+ """Check that the given attribute is a non-empty string.
70
+
71
+ Parameters
72
+ ----------
73
+ cls : type
74
+ The class whose attribute should be checked.
75
+ attr_name : str
76
+ The name of the attribute to check.
77
+
78
+ Raises
79
+ ------
80
+ TypeError
81
+ If the attribute is not a string.
82
+ ValueError
83
+ If the attribute is an empty string.
84
+ """
32
85
  attr_value = getattr(cls, attr_name, None)
33
86
  if not isinstance(attr_value, str):
34
87
  raise TypeError(f"{cls.__name__}.{attr_name} must be a string")
@@ -41,27 +94,35 @@ class BaseClassPlugin(ABC):
41
94
 
42
95
  All plugins are required to carry the following class attributes:
43
96
 
44
- - interface: The interface type the plugin belongs to
45
- (e.g. 'configs', 'data_modifiers').
46
- This is typically provided by the interface-level plugin class and not the
47
- individual plugin class.
48
- - family: The family name of the plugin. This should be defined by the plugin class.
49
- - name: The specific name of the plugin. This should be defined by the plugin class.
97
+ interface : str
98
+ The interface type the plugin belongs to
99
+ (e.g. ``'configs'``, ``'data_modifiers'``).
100
+ This is typically provided by the interface-level plugin class and not the
101
+ individual plugin class.
102
+ family : str
103
+ The family name of the plugin. This should be defined by the plugin class.
104
+ name : str
105
+ The specific name of the plugin. This should be defined by the plugin class.
50
106
 
51
107
  Subclasses of this base class must also implement the following methods:
52
108
 
53
- - call(): The main method that performs the plugin's functionality. This method
54
- should be implemented by the plugin class.
55
- - _pre_call(): A hook method that can be overridden to preprocess data before
56
- calling the main call() method. This method should accept the same arguments as
57
- call() via `*args` and `**kwargs` and should, typically, be implemented by the
58
- interface-level plugin class.
59
- - _post_call(): A hook method that can be overridden to post-process data after
60
- calling the main call() method. This method should accept the same arguments as
61
- call() via `*args` and `**kwargs` and should, typically, be implemented by the
62
- interface-level plugin class.
63
-
64
- The purpose of `_pre_call()` and `_post_call()` is to allow for common
109
+ call()
110
+ The main method that performs the plugin's functionality. This method
111
+ should be implemented by the plugin class.
112
+ _pre_call()
113
+ A hook method that can be overridden to preprocess data before
114
+ calling the main ``call()`` method. This method should accept the same
115
+ arguments as ``call()`` via ``*args`` and ``**kwargs`` and should,
116
+ typically, be implemented by the interface-level plugin class.
117
+ _post_call()
118
+ A hook method that can be overridden to post-process data after
119
+ calling the main ``call()`` method. This method should accept the same
120
+ arguments as ``call()`` via ``*args`` and ``**kwargs`` and should,
121
+ typically, be implemented by the interface-level plugin class.
122
+
123
+ Notes
124
+ -----
125
+ The purpose of ``_pre_call()`` and ``_post_call()`` is to allow for common
65
126
  functionality that all plugins of a certain type should possess, without requiring
66
127
  developers to implement this functionality in every plugin class. Initially, this
67
128
  will be used to convert inputs from DataTree to other formats and back to DataTree
@@ -78,55 +139,100 @@ class BaseClassPlugin(ABC):
78
139
  __plugin_abstract__: bool = False
79
140
 
80
141
  def _check_interface_attribute(cls):
81
- """Check the validity of the 'interface' attribute.
142
+ """Check that the 'interface' attribute is valid.
82
143
 
83
- Checks to be sure that the interface attribute is a non-empty string and that it
84
- is a known plugin interface.
144
+ Ensures the attribute is a non-empty string and a known plugin interface.
145
+
146
+ Parameters
147
+ ----------
148
+ cls : type
149
+ The class whose interface attribute should be checked.
85
150
  """
86
151
  valid_str_attr(cls, "interface")
87
152
 
88
153
  def _check_family_attribute(cls):
89
- """Check the validity of the 'family' attribute."""
154
+ """Check that the 'family' attribute is valid.
155
+
156
+ Ensures the attribute is a non-empty string.
157
+
158
+ Parameters
159
+ ----------
160
+ cls : type
161
+ The class whose family attribute should be checked.
162
+ """
90
163
  valid_str_attr(cls, "family")
91
164
 
92
165
  def _check_name_attribute(cls):
93
- """Check the validity of the 'name' attribute."""
166
+ """Check that the 'name' attribute is valid.
167
+
168
+ Ensures the attribute is a non-empty string.
169
+
170
+ Parameters
171
+ ----------
172
+ cls : type
173
+ The class whose name attribute should be checked.
174
+ """
94
175
  valid_str_attr(cls, "name")
95
176
 
96
177
  @abstractmethod
97
- def call(self, *args, **kwargs):
98
- """Callable method to be implemented by the plugin class."""
178
+ def call(self, *args: Any, **kwargs: Any) -> Any:
179
+ """Callable method to be implemented by the plugin class.
180
+
181
+ Returns
182
+ -------
183
+ Any
184
+ The result of the plugin's processing.
185
+ """
99
186
  pass
100
187
 
101
188
  # hooks are intentionally loose; document their accepted kwargs
102
- def _pre_call(self, data=None, *args, **kwargs):
189
+ def _pre_call(self, data: Any = None, *args: Any, **kwargs: Any) -> Any:
103
190
  """Preprocess the data before calling the main plugin method.
104
191
 
105
192
  Parameters
106
193
  ----------
107
- data : The input data for the plugin.
194
+ data : Any
195
+ The input data for the plugin.
108
196
 
109
197
  Returns
110
198
  -------
111
- The processed data.
199
+ Any
200
+ The processed data.
112
201
  """
113
202
  return data
114
203
 
115
- def _post_call(self, data=None, *args, **kwargs):
204
+ def _post_call(self, data: Any = None, *args: Any, **kwargs: Any) -> Any:
116
205
  """Post-process the data after calling the main plugin method.
117
206
 
118
207
  Parameters
119
208
  ----------
120
- data : R
209
+ data : Any
121
210
  The output data from the plugin.
122
211
 
123
212
  Returns
124
213
  -------
214
+ Any
125
215
  The processed data.
126
216
  """
127
217
  return data
128
218
 
129
- def _invoke(self, data=None, *args, **kwargs):
219
+ def _invoke(self, data: Any = None, *args: Any, **kwargs: Any) -> Any:
220
+ """Invoke the plugin's processing pipeline.
221
+
222
+ If data is provided, runs the full ``_pre_call()`` → ``call()`` →
223
+ ``_post_call()`` pipeline. Otherwise, delegates directly to ``call()``.
224
+
225
+ Parameters
226
+ ----------
227
+ data : Any, optional
228
+ The input data for the plugin. If ``None``, ``call()`` is invoked
229
+ directly with ``*args`` and ``**kwargs``.
230
+
231
+ Returns
232
+ -------
233
+ Any
234
+ The result of the plugin's processing pipeline.
235
+ """
130
236
  if data is None:
131
237
  data = self.call(*args, **kwargs)
132
238
  else:
@@ -135,18 +241,16 @@ class BaseClassPlugin(ABC):
135
241
  data = self._post_call(data, *args, **kwargs)
136
242
  return data
137
243
 
138
- def __init__(self, module=None):
139
- """
140
- Initialize the plugin object inheriting from BaseClasePlugin.
244
+ def __init__(self, module=None) -> None:
245
+ """Initialize the plugin object.
141
246
 
142
247
  Parameters
143
248
  ----------
144
- module: ModuleType, default=None
249
+ module : ModuleType, optional
145
250
  The module from which the class-based plugin originated. This is used to
146
251
  collect metadata from the module and attach it to the plugin object. The
147
252
  metadata can then be used during validation to indicate where failing
148
- plugins originated. If None, the 'testing' attributes will be set to a
149
- string value that can also be used in tests.
253
+ plugins originated. If ``None``, defaults are set.
150
254
  """
151
255
  if module:
152
256
  self.module_name = module.__name__
@@ -155,28 +259,28 @@ class BaseClassPlugin(ABC):
155
259
  self.module_name = "Unknown."
156
260
  self.module_path = "Unknown."
157
261
 
158
- def __init_subclass__(cls, *, abstract=False, **kwargs) -> None:
159
- """
160
- Initialize a subclass of the plugin.
262
+ def __init_subclass__(cls, *, abstract: bool = False, **kwargs: Any) -> None:
263
+ """Initialize a subclass of the plugin.
161
264
 
162
265
  Parameters
163
266
  ----------
164
267
  abstract : bool, optional
165
- If True, the subclass is treated as abstract. When treated as abstract,
166
- validation is disabled in __init_subclass__. Defaults to False.
268
+ If ``True``, the subclass is treated as abstract. When treated as
269
+ abstract, validation is disabled in ``__init_subclass__``. Defaults to
270
+ ``False``.
271
+
272
+ Returns
273
+ -------
274
+ None
167
275
 
168
276
  Raises
169
277
  ------
170
278
  TypeError
171
279
  If the subclass does not define the required attributes.
172
280
  TypeError
173
- If the subclass does not implement the call() method.
281
+ If the subclass does not implement the ``call()`` method.
174
282
  TypeError
175
- If the subclass overrides the __call__() method.
176
-
177
- Returns
178
- -------
179
- None
283
+ If the subclass overrides the ``__call__()`` method.
180
284
  """
181
285
  super().__init_subclass__(**kwargs)
182
286
 
@@ -204,8 +308,8 @@ class BaseClassPlugin(ABC):
204
308
  raise TypeError(f"{cls.__name__} must implement call()")
205
309
  call_method = cls.__dict__["call"]
206
310
 
207
- @functools.wraps(call_method) # type: ignore[arg-type]
208
- def _call(self, data=None, *args, **kwargs):
311
+ @functools.wraps(call_method)
312
+ def _call(self, data: Any = None, *args: Any, **kwargs: Any) -> Any:
209
313
  return cls._invoke(self, data, *args, **kwargs)
210
314
 
211
315
  call_sig = inspect.signature(call_method)
@@ -17,6 +17,8 @@ class ConfigsInterface(BaseYamlInterface):
17
17
  This is a 'dummy' interface which is strictly used for testing pluginify. All
18
18
  plugins of this interface are also 'dummy' plugins strictly used for testing this
19
19
  package.
20
+
21
+ Uses Pydantic model validation instead of JSON schema validation.
20
22
  """
21
23
 
22
24
  name = "configs"