7
7
from calibre.ptempfile import PersistentTemporaryFile
8
from calibre.constants import __version__, __author__
8
from calibre.constants import numeric_version
10
10
class Plugin(object):
12
12
A calibre plugin. Useful members include:
14
14
* ``self.plugin_path``: Stores path to the zip file that contains
15
15
this plugin or None if it is a builtin
17
17
* ``self.site_customization``: Stores a customization string entered
20
20
Methods that should be overridden in sub classes:
22
22
* :meth:`initialize`
23
23
* :meth:`customization_help`
27
27
* :meth:`temporary_file`
30
30
#: List of platforms this plugin works on
31
31
#: For example: ``['windows', 'osx', 'linux']
32
32
supported_platforms = []
34
34
#: The name of this plugin
35
35
name = 'Trivial Plugin'
37
37
#: The version of this plugin as a 3-tuple (major, minor, revision)
38
38
version = (1, 0, 0)
40
40
#: A short string describing what this plugin does
41
41
description = _('Does absolutely nothing')
43
43
#: The author of this plugin
44
44
author = _('Unknown')
46
46
#: When more than one plugin exists for a filetype,
47
47
#: the plugins are run in order of decreasing priority
48
48
#: i.e. plugins with higher priority will be run first.
49
49
#: The highest possible priority is ``sys.maxint``.
50
50
#: Default pririty is 1.
53
53
#: The earliest version of calibre this plugin requires
54
54
minimum_calibre_version = (0, 4, 118)
56
56
#: If False, the user will not be able to disable this plugin. Use with
58
58
can_be_disabled = True
60
60
#: The type of this plugin. Used for categorizing plugins in the
64
64
def __init__(self, plugin_path):
65
65
self.plugin_path = plugin_path
66
66
self.site_customization = None
68
68
def initialize(self):
70
70
Called once when calibre plugins are initialized. Plugins are re-initialized
71
71
every time a new plugin is added.
73
73
Perform any plugin specific initialization here, such as extracting
74
74
resources from the plugin zip file. The path to the zip file is
75
75
available as ``self.plugin_path``.
77
77
Note that ``self.site_customization`` is **not** available at this point.
81
81
def customization_help(self, gui=False):
83
83
Return a string giving help on how to customize this plugin.
84
84
By default raise a :class:`NotImplementedError`, which indicates that
85
85
the plugin does not require customization.
87
87
If you re-implement this method in your subclass, the user will
88
88
be asked to enter a string as customization for this plugin.
89
The customization string will be available as
89
The customization string will be available as
90
90
``self.site_customization``.
92
92
Site customization could be anything, for example, the path to
93
93
a needed binary on the user's computer.
95
:param gui: If True return HTML help, otherwise return plain text help.
95
:param gui: If True return HTML help, otherwise return plain text help.
98
98
raise NotImplementedError
100
100
def temporary_file(self, suffix):
102
102
Return a file-like object that is a temporary file on the file system.
103
103
This file will remain available even after being closed and will only
104
104
be removed on interpreter shutdown. Use the ``name`` member of the
105
105
returned object to access the full path to the created temporary file.
107
107
:param suffix: The suffix that the temporary file will have.
109
109
return PersistentTemporaryFile(suffix)
111
111
def is_customizable(self):
113
113
self.customization_help()
115
115
except NotImplementedError:
118
118
def __enter__(self, *args):
119
119
if self.plugin_path is not None:
120
120
sys.path.insert(0, self.plugin_path)
122
122
def __exit__(self, *args):
123
123
if self.plugin_path in sys.path:
124
124
sys.path.remove(self.plugin_path)
127
127
class FileTypePlugin(Plugin):
129
129
A plugin that is associated with a particular set of file types.
132
132
#: Set of file types for which this plugin should be run
133
133
#: For example: ``set(['lit', 'mobi', 'prc'])``
134
134
file_types = set([])
136
136
#: If True, this plugin is run when books are added
137
137
#: to the database
138
138
on_import = False
140
140
#: If True, this plugin is run whenever an any2* tool
141
141
#: is used, on the file passed to the any2* tool.
142
142
on_preprocess = False
144
144
#: If True, this plugin is run after an any2* tool is
145
145
#: used, on the final file produced by the tool.
146
146
on_postprocess = False
148
148
type = _('File type')
150
150
def run(self, path_to_ebook):
152
152
Run the plugin. Must be implemented in subclasses.
153
It should perform whatever modifications are required
154
on the ebook and return the absolute path to the
153
It should perform whatever modifications are required
154
on the ebook and return the absolute path to the
155
155
modified ebook. If no modifications are needed, it should
156
156
return the path to the original ebook. If an error is encountered
157
157
it should raise an Exception. The default implementation
158
158
simply return the path to the original ebook.
160
The modified ebook file should be created with the
160
The modified ebook file should be created with the
161
161
:meth:`temporary_file` method.
163
163
:param path_to_ebook: Absolute path to the ebook.
165
:return: Absolute path to the modified ebook.
165
:return: Absolute path to the modified ebook.
167
167
# Default implementation does nothing
168
168
return path_to_ebook
170
170
class MetadataReaderPlugin(Plugin):
172
172
A plugin that implements reading metadata from a set of file types.
174
174
#: Set of file types for which this plugin should be run
175
175
#: For example: ``set(['lit', 'mobi', 'prc'])``
176
176
file_types = set([])
178
178
supported_platforms = ['windows', 'osx', 'linux']
179
version = tuple(map(int, (__version__.split('.'))[:3]))
179
version = numeric_version
180
180
author = 'Kovid Goyal'
182
182
type = _('Metadata reader')
184
def __init__(self, *args, **kwargs):
185
Plugin.__init__(self, *args, **kwargs)
184
188
def get_metadata(self, stream, type):
186
190
Return metadata for the file represented by stream (a file like object
187
that supports reading). Raise an exception when there is an error
191
that supports reading). Raise an exception when there is an error
188
192
with the input data.
190
194
:param type: The type of file. Guaranteed to be one of the entries
191
195
in :attr:`file_types`.
193
:return: A :class:`calibre.ebooks.metadata.MetaInformation` object
197
:return: A :class:`calibre.ebooks.metadata.MetaInformation` object
197
201
class MetadataWriterPlugin(Plugin):
199
203
A plugin that implements reading metadata from a set of file types.
201
205
#: Set of file types for which this plugin should be run
202
206
#: For example: ``set(['lit', 'mobi', 'prc'])``
203
207
file_types = set([])
205
209
supported_platforms = ['windows', 'osx', 'linux']
206
version = tuple(map(int, (__version__.split('.'))[:3]))
210
version = numeric_version
207
211
author = 'Kovid Goyal'
209
213
type = _('Metadata writer')
211
215
def set_metadata(self, stream, mi, type):
213
217
Set metadata for the file represented by stream (a file like object
214
that supports reading). Raise an exception when there is an error
218
that supports reading). Raise an exception when there is an error
215
219
with the input data.
217
221
:param type: The type of file. Guaranteed to be one of the entries
218
222
in :attr:`file_types`.
219
:param mi: A :class:`calibre.ebooks.metadata.MetaInformation` object
223
:param mi: A :class:`calibre.ebooks.metadata.MetaInformation` object