mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Add documentation for plugin system
This commit is contained in:
parent
7a3d089f17
commit
627f6be0ef
@ -19,12 +19,12 @@ class Plugin(object):
|
||||
|
||||
Methods that should be overridden in sub classes:
|
||||
|
||||
* :method:`initialize`
|
||||
* :method:`customization_help`
|
||||
* :meth:`initialize`
|
||||
* :meth:`customization_help`
|
||||
|
||||
Useful methods:
|
||||
|
||||
* :method:`temporary_file`
|
||||
* :meth:`temporary_file`
|
||||
|
||||
'''
|
||||
#: List of platforms this plugin works on
|
||||
@ -93,6 +93,7 @@ class Plugin(object):
|
||||
a needed binary on the user's computer.
|
||||
|
||||
:param gui: If True return HTML help, otherwise return plain text help.
|
||||
|
||||
'''
|
||||
raise NotImplementedError
|
||||
|
||||
@ -157,9 +158,10 @@ class FileTypePlugin(Plugin):
|
||||
simply return the path to the original ebook.
|
||||
|
||||
The modified ebook file should be created with the
|
||||
:method:`temporary_file` method.
|
||||
:meth:`temporary_file` method.
|
||||
|
||||
:param path_to_ebook: Absolute path to the ebook.
|
||||
|
||||
:return: Absolute path to the modified ebook.
|
||||
'''
|
||||
# Default implementation does nothing
|
||||
@ -186,7 +188,8 @@ class MetadataReaderPlugin(Plugin):
|
||||
with the input data.
|
||||
|
||||
:param type: The type of file. Guaranteed to be one of the entries
|
||||
in :member:`file_types`.
|
||||
in :attr:`file_types`.
|
||||
|
||||
:return: A :class:`calibre.ebooks.metadata.MetaInformation` object
|
||||
'''
|
||||
return None
|
||||
@ -212,8 +215,9 @@ class MetadataWriterPlugin(Plugin):
|
||||
with the input data.
|
||||
|
||||
:param type: The type of file. Guaranteed to be one of the entries
|
||||
in :member:`file_types`.
|
||||
in :attr:`file_types`.
|
||||
:param mi: A :class:`calibre.ebooks.metadata.MetaInformation` object
|
||||
|
||||
'''
|
||||
pass
|
||||
|
||||
|
||||
|
@ -112,7 +112,8 @@ def get_file_type_metadata(stream, ftype):
|
||||
try:
|
||||
plugin = _metadata_readers[ftype.lower().strip()]
|
||||
if not is_disabled(plugin):
|
||||
mi = plugin.get_metadata(stream, ftype.lower().strip())
|
||||
with plugin:
|
||||
mi = plugin.get_metadata(stream, ftype.lower().strip())
|
||||
except:
|
||||
pass
|
||||
return mi
|
||||
@ -121,7 +122,8 @@ def set_file_type_metadata(stream, mi, ftype):
|
||||
try:
|
||||
plugin = _metadata_writers[ftype.lower().strip()]
|
||||
if not is_disabled(plugin):
|
||||
plugin.set_metadata(stream, mi, ftype.lower().strip())
|
||||
with plugin:
|
||||
plugin.set_metadata(stream, mi, ftype.lower().strip())
|
||||
except:
|
||||
traceback.print_exc()
|
||||
|
||||
@ -288,4 +290,4 @@ def main(args=sys.argv):
|
||||
return 0
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main())
|
||||
sys.exit(main())
|
||||
|
@ -72,7 +72,7 @@
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="currentIndex" >
|
||||
<number>4</number>
|
||||
<number>0</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="page_3" >
|
||||
<layout class="QVBoxLayout" name="verticalLayout" >
|
||||
|
BIN
src/calibre/gui2/images/news/endgadget.png
Normal file
BIN
src/calibre/gui2/images/news/endgadget.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 698 B |
BIN
src/calibre/gui2/images/news/fudzilla.png
Normal file
BIN
src/calibre/gui2/images/news/fudzilla.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 519 B |
112
src/calibre/manual/customize.rst
Normal file
112
src/calibre/manual/customize.rst
Normal file
@ -0,0 +1,112 @@
|
||||
.. include:: global.rst
|
||||
|
||||
.. currentmodule:: calibre.customize.__init__
|
||||
|
||||
.. _customize:
|
||||
|
||||
Customizing |app|
|
||||
==================================
|
||||
|
||||
|app| has a highly modular design. Various parts of it can be customized. You can learn how to create
|
||||
*recipes* to add new sources of online content to |app| in the Section :ref:`news`. Here, you will learn how to
|
||||
use *plugins* to customize and control various aspects of |app|'s behavior.
|
||||
|
||||
Theer are different kinds of plugins, corresponding to different aspects of |app|. As more and more aspects of |app|
|
||||
are modularized, new plugin types will be added.
|
||||
|
||||
.. contents::
|
||||
:depth: 2
|
||||
:local:
|
||||
|
||||
A Hello World plugin
|
||||
------------------------
|
||||
|
||||
Suppose you have an installation of |app| that you are using to self publish various e-documents in EPUB and LRF
|
||||
format. You would like all file generated by |app| to have their publisher set as "Hello world", here's how to do it.
|
||||
Create a file name :file:`my_plugin.py` (the file name must end with plugin.py) and enter the following Python code into it:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
import os
|
||||
from calibre.customize import FileTypePlugin
|
||||
|
||||
class HelloWorld(FileTypePlugin):
|
||||
|
||||
name = 'Hello World Plugin' # Name of the plugin
|
||||
description = 'Set the publisher to Hello World for all new conversions'
|
||||
supported_platforms = ['windows', 'osx', 'linux'] # Platforms this plugin will run on
|
||||
author = 'Acme Inc.' # The author of this plugin
|
||||
version = (1, 0, 0) # The version number of this plugin
|
||||
file_types = set(['epub', 'lrf']) # The file types that this plugin will be applied to
|
||||
on_postprocess = True # Run this plugin after conversion is complete
|
||||
|
||||
def run(self, path_to_ebook):
|
||||
from calibre.ebooks.metadata.meta import get_metadata, set_metadata
|
||||
file = open(path_to_ebook, 'r+b')
|
||||
ext = os.path.splitext(path_to_ebook)[-1][1:].lower()
|
||||
mi = get_metadata(file, ext)
|
||||
mi.publisher = 'Hello World'
|
||||
set_metadata(file, ext, mi)
|
||||
return path_to_ebook
|
||||
|
||||
That's all. To add this code to |app| as a plugin, simply create a zip file with::
|
||||
|
||||
zip plugin.zip my_plugin.py
|
||||
|
||||
Now either use the configuration dialog in |app| GUI to add this zip file as a plugin, or
|
||||
use the command::
|
||||
|
||||
calibre-customize -a plugin.zip
|
||||
|
||||
Every time you use calibre to convert a book, the plugin's :meth:`run` method will be called and the
|
||||
converted book will have its publisher set to "Hello World". For more information about
|
||||
|app|'s plugin system, read on...
|
||||
|
||||
The Plugin base class
|
||||
------------------------
|
||||
|
||||
As you may have noticed above, all |app| plugins are classes. The Plugin classes are organized in a hierarchy at the top of which
|
||||
is :class:`calibre.customize.Plugin`. The has excellent in source documentation for its various features, here I will discuss a
|
||||
few of the important ones.
|
||||
|
||||
First, all plugins must supply a list of platforms they have been tested on by setting the ``supported_platforms`` member as in the
|
||||
example above.
|
||||
|
||||
If the plugin needs to do any initialization, it should implement the :meth:`initialize` method. The path to the plugin zip file
|
||||
is available as ``self.plugin_path``. The initialization method could be used to load any needed resources from the zip file.
|
||||
|
||||
If the plugin needs to be customized (i.e. it needs some information from the user), it should implement the :meth:`customization_help`
|
||||
method, to indicate to |app| that it needs user input. This can be useful, for example, to ask the user to input the path to a needed system
|
||||
binary or the URL of a website, etc. When |app| asks the user for the customization information, the string retuned by the :meth:`customization_help`
|
||||
method is used as help text to le thte user know what information is needed.
|
||||
|
||||
Another useful method is :meth:`temporary_file`, which returns a file handle to an opened temporary file. If your plugin needs to make use
|
||||
of temporary files, it should use this method. Temporary file cleanup is then taken care of automatically.
|
||||
|
||||
In addition, whenever plugins are run, their zip files are automatically added to the start of ``sys.path``, so you can directly import
|
||||
any python files you bundle in the zip files. Note that this is not available when the plugin is being initialized, only when it is being run.
|
||||
|
||||
Finally, plugins can have a priority (a positive integer). Higher priority plugins are run in preference tolower priority ones in a given context.
|
||||
By default all plugins have priority 1. You can change that by setting the member :attr:'priority` in your subclass.
|
||||
|
||||
See :ref:`pluginsPlugin` for details.
|
||||
|
||||
File type plugins
|
||||
-------------------
|
||||
|
||||
File type plugins are intended to be associated with specific file types (as identified by extension). They can be run on several different occassions.
|
||||
|
||||
* When books/formats are added ot the |app| database (if :attr:`on_import` is set to True).
|
||||
* Just before an any2whatever converter is run on an input file (if :attr:`on_preprocess` is set to True).
|
||||
* After an any2whatever converter has run, on the output file (if :attr:`on_postprocess` is set to True).
|
||||
|
||||
File type plugins specify which file types they are associated with by specifying the :attr:`file_types` member as in the above example.
|
||||
the actual work should be done in the :meth:`run` method, which must return the path to the modified ebook (it can be the same as the original
|
||||
if the modifcations are done in place).
|
||||
|
||||
See :ref:`pluginsFTPlugin` for details.
|
||||
|
||||
Metadata plugins
|
||||
-------------------
|
||||
|
||||
Metadata plugins add the ability to read/write metadata from ebook files to |app|. See :ref:`pluginsMetadataPlugin` for details.
|
@ -30,6 +30,7 @@ Sections
|
||||
metadata
|
||||
faq
|
||||
xpath
|
||||
customize
|
||||
glossary
|
||||
|
||||
Convenience
|
||||
|
100
src/calibre/manual/plugins.rst
Normal file
100
src/calibre/manual/plugins.rst
Normal file
@ -0,0 +1,100 @@
|
||||
.. include:: global.rst
|
||||
|
||||
.. _plugins:
|
||||
|
||||
API Documentation for plugins
|
||||
===============================
|
||||
|
||||
.. module:: calibre.customize.__init__
|
||||
:synopsis: Defines various abstract base classes that can be subclassed to create plugins.
|
||||
|
||||
Defines various abstract base classes that can be subclassed to create powerful plugins. The useful
|
||||
classes are:
|
||||
|
||||
.. contents::
|
||||
:depth: 1
|
||||
:local:
|
||||
|
||||
.. _pluginsPlugin:
|
||||
|
||||
Plugin
|
||||
-----------------
|
||||
|
||||
.. class:: Plugin
|
||||
|
||||
Abstract base class that contains a number of members and methods to create your plugin. All
|
||||
plugins must inherit from this class or a subclass of it.
|
||||
|
||||
The members and methods are:
|
||||
|
||||
.. automember:: Plugin.name
|
||||
|
||||
.. automember:: Plugin.author
|
||||
|
||||
.. automember:: Plugin.description
|
||||
|
||||
.. automember:: Plugin.version
|
||||
|
||||
.. automember:: Plugin.supported_platforms
|
||||
|
||||
.. automember:: Plugin.priority
|
||||
|
||||
.. automember:: Plugin.minimum_calibre_version
|
||||
|
||||
.. automember:: Plugin.can_be_disabled
|
||||
|
||||
.. automethod:: Plugin.initialize
|
||||
|
||||
.. automethod:: Plugin.customization_help
|
||||
|
||||
.. automethod:: Plugin.temporary_file
|
||||
|
||||
.. _pluginsFTPlugin:
|
||||
|
||||
FileTypePlugin
|
||||
-----------------
|
||||
|
||||
.. class:: Plugin
|
||||
|
||||
Abstract base class that contains a number of members and methods to create your file type plugin. All file type
|
||||
plugins must inherit from this class or a subclass of it.
|
||||
|
||||
The members and methods are:
|
||||
|
||||
.. automember:: FileTypePlugin.file_types
|
||||
|
||||
.. automember:: FileTypePlugin.on_import
|
||||
|
||||
.. automember:: FileTypePlugin.on_preprocess
|
||||
|
||||
.. automember:: FileTypePlugin.on_postprocess
|
||||
|
||||
.. automethod:: FileTypePlugin.run
|
||||
|
||||
.. _pluginsMetadataPlugin:
|
||||
|
||||
Metadata plugins
|
||||
-------------------
|
||||
|
||||
.. class:: MetadataReaderPlugin
|
||||
|
||||
Abstract base class that contains a number of members and methods to create your metadata reader plugin. All metadata
|
||||
reader plugins must inherit from this class or a subclass of it.
|
||||
|
||||
The members and methods are:
|
||||
|
||||
.. automember:: MetadataReaderPlugin.file_types
|
||||
|
||||
.. automethod:: MetadataReaderPlugin.get_metadata
|
||||
|
||||
|
||||
.. class:: MetadataWriterPlugin
|
||||
|
||||
Abstract base class that contains a number of members and methods to create your metadata writer plugin. All metadata
|
||||
writer plugins must inherit from this class or a subclass of it.
|
||||
|
||||
The members and methods are:
|
||||
|
||||
.. automember:: MetadataWriterPlugin.file_types
|
||||
|
||||
.. automethod:: MetadataWriterPlugin.set_metadata
|
30
src/calibre/web/feeds/recipes/endgadget.py
Normal file
30
src/calibre/web/feeds/recipes/endgadget.py
Normal file
@ -0,0 +1,30 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
__license__ = 'GPL v3'
|
||||
__copyright__ = '2008, Darko Miletic <darko.miletic at gmail.com>'
|
||||
'''
|
||||
engadget.com
|
||||
'''
|
||||
|
||||
import string,re
|
||||
from calibre.web.feeds.news import BasicNewsRecipe
|
||||
|
||||
class Engadget(BasicNewsRecipe):
|
||||
title = u'Engadget'
|
||||
__author__ = 'Darko Miletic'
|
||||
description = 'Tech news'
|
||||
oldest_article = 7
|
||||
max_articles_per_feed = 100
|
||||
no_stylesheets = True
|
||||
use_embedded_content = False
|
||||
|
||||
keep_only_tags = [ dict(name='div', attrs={'class':'post'}) ]
|
||||
remove_tags = [
|
||||
dict(name='object')
|
||||
,dict(name='div', attrs={'class':'postmeta'})
|
||||
,dict(name='div', attrs={'class':'quigoads'})
|
||||
]
|
||||
|
||||
|
||||
feeds = [ (u'Posts', u'http://www.engadget.com/rss.xml')]
|
||||
|
26
src/calibre/web/feeds/recipes/fudzilla.py
Normal file
26
src/calibre/web/feeds/recipes/fudzilla.py
Normal file
@ -0,0 +1,26 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
__license__ = 'GPL v3'
|
||||
__copyright__ = '2008, Darko Miletic <darko.miletic at gmail.com>'
|
||||
'''
|
||||
fudzilla.com
|
||||
'''
|
||||
|
||||
import string,re
|
||||
from calibre.web.feeds.news import BasicNewsRecipe
|
||||
|
||||
class Fudzilla(BasicNewsRecipe):
|
||||
title = u'Fudzilla'
|
||||
__author__ = 'Darko Miletic'
|
||||
description = 'Tech news'
|
||||
oldest_article = 7
|
||||
max_articles_per_feed = 100
|
||||
no_stylesheets = True
|
||||
use_embedded_content = False
|
||||
|
||||
feeds = [ (u'Posts', u'http://www.fudzilla.com/index.php?option=com_rss&feed=RSS2.0&no_html=1')]
|
||||
|
||||
def print_version(self, url):
|
||||
nurl = url.replace('http://www.fudzilla.com/index.php','http://www.fudzilla.com/index2.php')
|
||||
nmain, nsep, nrest = nurl.partition('&Itemid=')
|
||||
return nmain + '&pop=1&page=0&Itemid=1'
|
Loading…
x
Reference in New Issue
Block a user