Coverage for documents/plugins/base.py: 71%
38 statements
« prev ^ index » next coverage.py v7.15.2, created at 2026-10-10 09:07 +0000
« prev ^ index » next coverage.py v7.15.2, created at 2026-10-10 09:07 +0000
1import abc
2from pathlib import Path
3from typing import Final
5from documents.data_models import ConsumableDocument
6from documents.data_models import DocumentMetadataOverrides
7from documents.plugins.helpers import ProgressManager
10class StopConsumeTaskError(Exception):
11 """
12 A plugin setup or run may raise this to exit the asynchronous consume task.
14 Most likely, this means it has created one or more new tasks to execute instead,
15 such as when a barcode has been used to create new documents
16 """
18 def __init__(self, message: str) -> None:
19 self.message = message
20 super().__init__(message)
23class ConsumeTaskPlugin(abc.ABC):
24 """
25 Defines the interface for a plugin for the document consume task
26 Meanings as per RFC2119 (https://datatracker.ietf.org/doc/html/rfc2119)
28 Plugin Implementation
30 The plugin SHALL implement property able_to_run and methods setup, run and cleanup.
31 The plugin property able_to_run SHALL return True if the plugin is able to run, given the conditions, settings and document information.
32 The plugin property able_to_run MAY be hardcoded to return True.
33 The plugin setup SHOULD perform any resource creation or additional initialization needed to run the document.
34 The plugin setup MAY be a non-operation.
35 The plugin cleanup SHOULD perform resource cleanup, including in the event of an error.
36 The plugin cleanup MAY be a non-operation.
37 The plugin run SHALL perform any operations against the document or system state required for the plugin.
38 The plugin run MAY update the document metadata.
39 The plugin run MAY return an informational message.
40 The plugin run MAY raise StopConsumeTaskError to cease any further operations against the document.
42 Plugin Manager Implementation
44 The plugin manager SHALL provide the plugin with the input document, document metadata, progress manager and a created temporary directory.
45 The plugin manager SHALL execute the plugin setup, run and cleanup, in that order IF the plugin property able_to_run is True.
46 The plugin manager SHOULD log the return message of executing a plugin's run.
47 The plugin manager SHALL always execute the plugin cleanup, IF the plugin property able_to_run is True.
48 The plugin manager SHALL cease calling plugins and exit the task IF a plugin raises StopConsumeTaskError.
49 The plugin manager SHOULD return the StopConsumeTaskError message IF a plugin raises StopConsumeTaskError.
50 """
52 NAME: str = "ConsumeTaskPlugin"
54 def __init__(
55 self,
56 input_doc: ConsumableDocument,
57 metadata: DocumentMetadataOverrides,
58 status_mgr: ProgressManager,
59 base_tmp_dir: Path,
60 task_id: str,
61 ) -> None:
62 super().__init__()
63 self.input_doc = input_doc
64 self.metadata = metadata
65 self.base_tmp_dir: Final = base_tmp_dir
66 self.status_mgr = status_mgr
67 self.task_id: Final = task_id
69 @property
70 @abc.abstractmethod
71 def able_to_run(self) -> bool:
72 """
73 Return True if the conditions are met for the plugin to run, False otherwise
75 If False, setup(), run() and cleanup() will not be called
76 """
78 @abc.abstractmethod
79 def setup(self) -> None:
80 """
81 Allows the plugin to perform any additional setup it may need, such as creating
82 a temporary directory, copying a file somewhere, etc.
84 Executed before run()
86 In general, this should be the "light" work, not the bulk of processing
87 """
89 @abc.abstractmethod
90 def run(self) -> str | None:
91 """
92 The bulk of plugin processing, this does whatever action the plugin is for.
94 Executed after setup() and before cleanup()
95 """
97 @abc.abstractmethod
98 def cleanup(self) -> None:
99 """
100 Allows the plugin to execute any cleanup it may require
102 Executed after run(), even in the case of error
103 """
106class AlwaysRunPluginMixin(ConsumeTaskPlugin):
107 """
108 A plugin which is always able to run
109 """
111 @property
112 def able_to_run(self) -> bool:
113 return True
116class NoSetupPluginMixin(ConsumeTaskPlugin):
117 """
118 A plugin which requires no setup
119 """
121 def setup(self) -> None:
122 pass
125class NoCleanupPluginMixin(ConsumeTaskPlugin):
126 """
127 A plugin which needs to clean up no files
128 """
130 def cleanup(self) -> None:
131 pass