Merge from trunk

This commit is contained in:
Charles Haley 2012-07-06 21:34:48 +02:00
commit 440151a0f3
3 changed files with 47 additions and 16 deletions

View File

@ -15,7 +15,7 @@ Here, we will teach you how to create your own plugins to add new features to |a
:depth: 2 :depth: 2
:local: :local:
.. note:: This only applies to calibre releases >= 0.7.53 .. note:: This only applies to calibre releases >= 0.8.60
Anatomy of a |app| plugin Anatomy of a |app| plugin
--------------------------- ---------------------------
@ -32,11 +32,15 @@ and enter the following Python code into it:
.. literalinclude:: plugin_examples/helloworld/__init__.py .. literalinclude:: plugin_examples/helloworld/__init__.py
:lines: 10- :lines: 10-
That's all. To add this code to |app| as a plugin, simply create a zip file with:: That's all. To add this code to |app| as a plugin, simply run the following in
the directory in which you created :file:`__init__.py`::
zip plugin.zip __init__.py calibre-customize -b .
Add this plugin to |app| via :guilabel:`Preferences->Plugins`. .. note::
On OS X you have to first install the |app| command line tools, by
going to :guilabel:`Preferences->Miscellaneous` and clicking the
:guilabel:`Install command line tools` button.
You can download the Hello World plugin from You can download the Hello World plugin from
`helloworld_plugin.zip <http://calibre-ebook.com/downloads/helloworld_plugin.zip>`_. `helloworld_plugin.zip <http://calibre-ebook.com/downloads/helloworld_plugin.zip>`_.
@ -191,14 +195,12 @@ When running from the command line, debug output will be printed to the console,
You can insert print statements anywhere in your plugin code, they will be output in debug mode. Remember, this is python, you really shouldn't need anything more than print statements to debug ;) I developed all of |app| using just this debugging technique. You can insert print statements anywhere in your plugin code, they will be output in debug mode. Remember, this is python, you really shouldn't need anything more than print statements to debug ;) I developed all of |app| using just this debugging technique.
It can get tiresome to keep re-adding a plugin to calibre to test small changes. The plugin zip files are stored in the calibre config directory in plugins/ (goto Preferences->Misc and click open config directory to see the config directory). You can quickly test changes to your plugin by using the following command
line::
Once you've located the zip file of your plugin you can then directly update it with your changes instead of re-adding it each time. To do so from the command line, in the directory that contains your plugin source code, use:: calibre -s; calibre-customize -b /path/to/your/plugin/directory; calibre
calibre -s; zip -r /path/to/plugin/zip/file.zip *; calibre This will shutdown a running calibre, wait for the shutdown to complete, then update your plugin in |app| and relaunch |app|.
This will shutdown a running calibre. Wait for the shutdown to complete, then update your plugin files and relaunch calibre.
It relies on the freely available zip command line tool.
More plugin examples More plugin examples
---------------------- ----------------------

View File

@ -1,21 +1,27 @@
__license__ = 'GPL v3' __license__ = 'GPL v3'
__author__ = 'faber1971'
description = 'Italian rock webzine - v1.01 (6, July 2012)'
from calibre.web.feeds.news import BasicNewsRecipe from calibre.web.feeds.news import BasicNewsRecipe
class AdvancedUserRecipe1328535130(BasicNewsRecipe): class AdvancedUserRecipe1328535130(BasicNewsRecipe):
title = u'Onda Rock' title = u'Onda Rock'
__author__ = 'faber1971' __author__ = 'faber1971'
description = 'Italian rock webzine' description = 'Italian rock webzine'
language = 'it' language = 'it'
oldest_article = 15
oldest_article = 7
max_articles_per_feed = 100 max_articles_per_feed = 100
auto_cleanup = False auto_cleanup = False
remove_tags = [ remove_tags = [
dict(name='div', attrs={'id':['boxHeader','boxlinks_med','footer','boxinterviste','box_special_med','boxdiscografia_head','path']}), dict(name='div', attrs={'id':['boxHeader','boxlinks_med','footer','boxinterviste','box_special_med','boxdiscografia_head','path','widget','menuarea','headerarea']}),
dict(name='div', attrs={'align':'left'}), dict(name='div', attrs={'align':'left'}),
dict(name='div', attrs={'class':['media','boxarticoli']}),
dict(name='div', attrs={'style':'text-align: center'}), dict(name='div', attrs={'style':'text-align: center'}),
dict(name='table', attrs={'cellpadding':'0'}),
dict(name='span', attrs={'class':'liketext'}),
] ]
no_stylesheets = True no_stylesheets = True
feeds = [(u'Onda Rock', u'http://www.ondarock.it/feed.php')] feeds = [(u'Onda Rock', u'http://www.ondarock.it/feed.php')]
masthead_url = 'http://profile.ak.fbcdn.net/hprofile-ak-snc4/71135_45820579767_4993043_n.jpg' masthead_url = 'http://api.ning.com/files/4ot8ampp*-rYQuwL2NoaHvVqcyu7VMyWyan12a9QMsJUWxk-q5V1-34wnD-Wj9B5qWjc1yPMLGiwQg8hZJxaySeaG2lx8hpV/2009_banner_ondarock.gif'
extra_css = '''
.boxtabscontain_page {border: 1px solid #E0E0E0;clear: both;font-family: "Verdana", "Arial", "Helvetica", sans-serif;font-size: 10px;line-height: 17px;margin: 0px 0px 20px;padding: 10px 10px 10px 40px;position: relative;top: -1px;width: 258px;z-index: 1;}
'''

View File

@ -555,6 +555,23 @@ def initialized_plugins():
# CLI {{{ # CLI {{{
def build_plugin(path):
from calibre import prints
from calibre.ptempfile import PersistentTemporaryFile
from calibre.utils.zipfile import ZipFile, ZIP_STORED
path = type(u'')(path)
names = frozenset(os.listdir(path))
if u'__init__.py' not in names:
prints(path, ' is not a valid plugin')
raise SystemExit(1)
t = PersistentTemporaryFile(u'.zip')
with ZipFile(t, u'w', ZIP_STORED) as zf:
zf.add_dir(path)
t.close()
plugin = add_plugin(t.name)
os.remove(t.name)
prints(u'Plugin updated:', plugin.name, plugin.version)
def option_parser(): def option_parser():
parser = OptionParser(usage=_('''\ parser = OptionParser(usage=_('''\
%prog options %prog options
@ -563,6 +580,10 @@ def option_parser():
''')) '''))
parser.add_option('-a', '--add-plugin', default=None, parser.add_option('-a', '--add-plugin', default=None,
help=_('Add a plugin by specifying the path to the zip file containing it.')) help=_('Add a plugin by specifying the path to the zip file containing it.'))
parser.add_option('-b', '--build-plugin', default=None,
help=_('For plugin developers: Path to the directory where you are'
' developing the plugin. This command will automatically zip '
'up the plugin and update it in calibre.'))
parser.add_option('-r', '--remove-plugin', default=None, parser.add_option('-r', '--remove-plugin', default=None,
help=_('Remove a custom plugin by name. Has no effect on builtin plugins')) help=_('Remove a custom plugin by name. Has no effect on builtin plugins'))
parser.add_option('--customize-plugin', default=None, parser.add_option('--customize-plugin', default=None,
@ -584,6 +605,8 @@ def main(args=sys.argv):
if opts.add_plugin is not None: if opts.add_plugin is not None:
plugin = add_plugin(opts.add_plugin) plugin = add_plugin(opts.add_plugin)
print 'Plugin added:', plugin.name, plugin.version print 'Plugin added:', plugin.name, plugin.version
if opts.build_plugin is not None:
build_plugin(opts.build_plugin)
if opts.remove_plugin is not None: if opts.remove_plugin is not None:
if remove_plugin(opts.remove_plugin): if remove_plugin(opts.remove_plugin):
print 'Plugin removed' print 'Plugin removed'