1
0
mirror of https://github.com/gryf/ebook-converter.git synced 2026-01-01 07:22:26 +01:00

More cleanup

This commit is contained in:
2020-05-03 15:37:23 +02:00
parent 1a79146bf7
commit 35445cb736
4 changed files with 155 additions and 1297 deletions

View File

@@ -820,21 +820,6 @@ plugins += input_profiles + output_profiles
#]
# }}}
# New metadata download plugins {{{
#from ebook_converter.ebooks.metadata.sources.google import GoogleBooks
#from ebook_converter.ebooks.metadata.sources.amazon import Amazon
#from ebook_converter.ebooks.metadata.sources.edelweiss import Edelweiss
#from ebook_converter.ebooks.metadata.sources.openlibrary import OpenLibrary
#from ebook_converter.ebooks.metadata.sources.overdrive import OverDrive
#from ebook_converter.ebooks.metadata.sources.douban import Douban
#from ebook_converter.ebooks.metadata.sources.ozon import Ozon
#from ebook_converter.ebooks.metadata.sources.google_images import GoogleImages
#from ebook_converter.ebooks.metadata.sources.big_book_search import BigBookSearch
#
#plugins += [GoogleBooks, GoogleImages, Amazon, Edelweiss, OpenLibrary, OverDrive, Douban, Ozon, BigBookSearch]
# }}}
# Interface Actions {{{
@@ -1098,823 +1083,6 @@ plugins += [ActionAdd, ActionFetchAnnotations, ActionGenerateCatalog,
# }}}
# Preferences Plugins {{{
# class LookAndFeel(PreferencesPlugin):
# name = 'Look & Feel'
# icon = I('lookfeel.png')
# gui_name = _('Look & feel')
# category = 'Interface'
# gui_category = _('Interface')
# category_order = 1
# name_order = 1
# config_widget = 'ebook_converter.gui2.preferences.look_feel'
# description = _('Adjust the look and feel of the calibre interface'
# ' to suit your tastes')
# class Behavior(PreferencesPlugin):
# name = 'Behavior'
# icon = I('config.png')
# gui_name = _('Behavior')
# category = 'Interface'
# gui_category = _('Interface')
# category_order = 1
# name_order = 2
# config_widget = 'ebook_converter.gui2.preferences.behavior'
# description = _('Change the way calibre behaves')
# class Columns(PreferencesPlugin):
# name = 'Custom Columns'
# icon = I('column.png')
# gui_name = _('Add your own columns')
# category = 'Interface'
# gui_category = _('Interface')
# category_order = 1
# name_order = 3
# config_widget = 'ebook_converter.gui2.preferences.columns'
# description = _('Add/remove your own columns to the calibre book list')
# class Toolbar(PreferencesPlugin):
# name = 'Toolbar'
# icon = I('wizard.png')
# gui_name = _('Toolbars & menus')
# category = 'Interface'
# gui_category = _('Interface')
# category_order = 1
# name_order = 4
# config_widget = 'ebook_converter.gui2.preferences.toolbar'
# description = _('Customize the toolbars and context menus, changing which'
# ' actions are available in each')
# class Search(PreferencesPlugin):
# name = 'Search'
# icon = I('search.png')
# gui_name = _('Searching')
# category = 'Interface'
# gui_category = _('Interface')
# category_order = 1
# name_order = 5
# config_widget = 'ebook_converter.gui2.preferences.search'
# description = _('Customize the way searching for books works in calibre')
# class InputOptions(PreferencesPlugin):
# name = 'Input Options'
# icon = I('arrow-down.png')
# gui_name = _('Input options')
# category = 'Conversion'
# gui_category = _('Conversion')
# category_order = 2
# name_order = 1
# config_widget = 'ebook_converter.gui2.preferences.conversion:InputOptions'
# description = _('Set conversion options specific to each input format')
# def create_widget(self, *args, **kwargs):
# # The DOC Input plugin tries to override this
# self.config_widget = 'ebook_converter.gui2.preferences.conversion:InputOptions'
# return PreferencesPlugin.create_widget(self, *args, **kwargs)
# class CommonOptions(PreferencesPlugin):
# name = 'Common Options'
# icon = I('convert.png')
# gui_name = _('Common options')
# category = 'Conversion'
# gui_category = _('Conversion')
# category_order = 2
# name_order = 2
# config_widget = 'ebook_converter.gui2.preferences.conversion:CommonOptions'
# description = _('Set conversion options common to all formats')
# class OutputOptions(PreferencesPlugin):
# name = 'Output Options'
# icon = I('arrow-up.png')
# gui_name = _('Output options')
# category = 'Conversion'
# gui_category = _('Conversion')
# category_order = 2
# name_order = 3
# config_widget = 'ebook_converter.gui2.preferences.conversion:OutputOptions'
# description = _('Set conversion options specific to each output format')
# class Adding(PreferencesPlugin):
# name = 'Adding'
# icon = I('add_book.png')
# gui_name = _('Adding books')
# category = 'Import/Export'
# gui_category = _('Import/export')
# category_order = 3
# name_order = 1
# config_widget = 'ebook_converter.gui2.preferences.adding'
# description = _('Control how calibre reads metadata from files when '
# 'adding books')
# class Saving(PreferencesPlugin):
# name = 'Saving'
# icon = I('save.png')
# gui_name = _('Saving books to disk')
# category = 'Import/Export'
# gui_category = _('Import/export')
# category_order = 3
# name_order = 2
# config_widget = 'ebook_converter.gui2.preferences.saving'
# description = _('Control how calibre exports files from its database '
# 'to disk when using Save to disk')
# class Sending(PreferencesPlugin):
# name = 'Sending'
# icon = I('sync.png')
# gui_name = _('Sending books to devices')
# category = 'Import/Export'
# gui_category = _('Import/export')
# category_order = 3
# name_order = 3
# config_widget = 'ebook_converter.gui2.preferences.sending'
# description = _('Control how calibre transfers files to your '
# 'e-book reader')
# class Plugboard(PreferencesPlugin):
# name = 'Plugboard'
# icon = I('plugboard.png')
# gui_name = _('Metadata plugboards')
# category = 'Import/Export'
# gui_category = _('Import/export')
# category_order = 3
# name_order = 4
# config_widget = 'ebook_converter.gui2.preferences.plugboard'
# description = _('Change metadata fields before saving/sending')
# class TemplateFunctions(PreferencesPlugin):
# name = 'TemplateFunctions'
# icon = I('template_funcs.png')
# gui_name = _('Template functions')
# category = 'Advanced'
# gui_category = _('Advanced')
# category_order = 5
# name_order = 5
# config_widget = 'ebook_converter.gui2.preferences.template_functions'
# description = _('Create your own template functions')
# class Email(PreferencesPlugin):
# name = 'Email'
# icon = I('mail.png')
# gui_name = _('Sharing books by email')
# category = 'Sharing'
# gui_category = _('Sharing')
# category_order = 4
# name_order = 1
# config_widget = 'ebook_converter.gui2.preferences.emailp'
# description = _('Setup sharing of books via email. Can be used '
# 'for automatic sending of downloaded news to your devices')
# class Server(PreferencesPlugin):
# name = 'Server'
# icon = I('network-server.png')
# gui_name = _('Sharing over the net')
# category = 'Sharing'
# gui_category = _('Sharing')
# category_order = 4
# name_order = 2
# config_widget = 'ebook_converter.gui2.preferences.server'
# description = _('Setup the calibre Content server which will '
# 'give you access to your calibre library from anywhere, '
# 'on any device, over the internet')
# class MetadataSources(PreferencesPlugin):
# name = 'Metadata download'
# icon = I('download-metadata.png')
# gui_name = _('Metadata download')
# category = 'Sharing'
# gui_category = _('Sharing')
# category_order = 4
# name_order = 3
# config_widget = 'ebook_converter.gui2.preferences.metadata_sources'
# description = _('Control how calibre downloads e-book metadata from the net')
# class IgnoredDevices(PreferencesPlugin):
# name = 'Ignored Devices'
# icon = I('reader.png')
# gui_name = _('Ignored devices')
# category = 'Sharing'
# gui_category = _('Sharing')
# category_order = 4
# name_order = 4
# config_widget = 'ebook_converter.gui2.preferences.ignored_devices'
# description = _('Control which devices calibre will ignore when they are connected '
# 'to the computer.')
# class Plugins(PreferencesPlugin):
# name = 'Plugins'
# icon = I('plugins.png')
# gui_name = _('Plugins')
# category = 'Advanced'
# gui_category = _('Advanced')
# category_order = 5
# name_order = 1
# config_widget = 'ebook_converter.gui2.preferences.plugins'
# description = _('Add/remove/customize various bits of calibre '
# 'functionality')
# class Tweaks(PreferencesPlugin):
# name = 'Tweaks'
# icon = I('tweaks.png')
# gui_name = _('Tweaks')
# category = 'Advanced'
# gui_category = _('Advanced')
# category_order = 5
# name_order = 2
# config_widget = 'ebook_converter.gui2.preferences.tweaks'
# description = _('Fine tune how calibre behaves in various contexts')
# class Keyboard(PreferencesPlugin):
# name = 'Keyboard'
# icon = I('keyboard-prefs.png')
# gui_name = _('Shortcuts')
# category = 'Advanced'
# gui_category = _('Advanced')
# category_order = 5
# name_order = 4
# config_widget = 'ebook_converter.gui2.preferences.keyboard'
# description = _('Customize the keyboard shortcuts used by calibre')
# class Misc(PreferencesPlugin):
# name = 'Misc'
# icon = I('exec.png')
# gui_name = _('Miscellaneous')
# category = 'Advanced'
# gui_category = _('Advanced')
# category_order = 5
# name_order = 3
# config_widget = 'ebook_converter.gui2.preferences.misc'
# description = _('Miscellaneous advanced configuration')
# plugins += [LookAndFeel, Behavior, Columns, Toolbar, Search, InputOptions,
# CommonOptions, OutputOptions, Adding, Saving, Sending, Plugboard,
# Email, Server, Plugins, Tweaks, Misc, TemplateFunctions,
# MetadataSources, Keyboard, IgnoredDevices]
# }}}
# Store plugins {{{
class StoreAmazonKindleStore(StoreBase):
name = 'Amazon Kindle'
description = 'Kindle books from Amazon.'
actual_plugin = 'ebook_converter.gui2.store.stores.amazon_plugin:AmazonKindleStore'
headquarters = 'US'
formats = ['KINDLE']
affiliate = False
class StoreAmazonAUKindleStore(StoreBase):
name = 'Amazon AU Kindle'
author = 'Kovid Goyal'
description = 'Kindle books from Amazon.'
actual_plugin = 'ebook_converter.gui2.store.stores.amazon_au_plugin:AmazonKindleStore'
headquarters = 'AU'
formats = ['KINDLE']
class StoreAmazonCAKindleStore(StoreBase):
name = 'Amazon CA Kindle'
author = 'Kovid Goyal'
description = 'Kindle books from Amazon.'
actual_plugin = 'ebook_converter.gui2.store.stores.amazon_ca_plugin:AmazonKindleStore'
headquarters = 'CA'
formats = ['KINDLE']
class StoreAmazonINKindleStore(StoreBase):
name = 'Amazon IN Kindle'
author = 'Kovid Goyal'
description = 'Kindle books from Amazon.'
actual_plugin = 'ebook_converter.gui2.store.stores.amazon_in_plugin:AmazonKindleStore'
headquarters = 'IN'
formats = ['KINDLE']
class StoreAmazonDEKindleStore(StoreBase):
name = 'Amazon DE Kindle'
author = 'Kovid Goyal'
description = 'Kindle Bücher von Amazon.'
actual_plugin = 'ebook_converter.gui2.store.stores.amazon_de_plugin:AmazonKindleStore'
headquarters = 'DE'
formats = ['KINDLE']
class StoreAmazonFRKindleStore(StoreBase):
name = 'Amazon FR Kindle'
author = 'Kovid Goyal'
description = 'Tous les e-books Kindle'
actual_plugin = 'ebook_converter.gui2.store.stores.amazon_fr_plugin:AmazonKindleStore'
headquarters = 'FR'
formats = ['KINDLE']
class StoreAmazonITKindleStore(StoreBase):
name = 'Amazon IT Kindle'
author = 'Kovid Goyal'
description = 'e-book Kindle a prezzi incredibili'
actual_plugin = 'ebook_converter.gui2.store.stores.amazon_it_plugin:AmazonKindleStore'
headquarters = 'IT'
formats = ['KINDLE']
class StoreAmazonESKindleStore(StoreBase):
name = 'Amazon ES Kindle'
author = 'Kovid Goyal'
description = 'e-book Kindle en España'
actual_plugin = 'ebook_converter.gui2.store.stores.amazon_es_plugin:AmazonKindleStore'
headquarters = 'ES'
formats = ['KINDLE']
class StoreAmazonUKKindleStore(StoreBase):
name = 'Amazon UK Kindle'
author = 'Kovid Goyal'
description = 'Kindle books from Amazon\'s UK web site. Also, includes French language e-books.'
actual_plugin = 'ebook_converter.gui2.store.stores.amazon_uk_plugin:AmazonKindleStore'
headquarters = 'UK'
formats = ['KINDLE']
class StoreArchiveOrgStore(StoreBase):
name = 'Archive.org'
description = 'An Internet library offering permanent access for researchers, historians, scholars, people with disabilities, and the general public to historical collections that exist in digital format.' # noqa
actual_plugin = 'ebook_converter.gui2.store.stores.archive_org_plugin:ArchiveOrgStore'
drm_free_only = True
headquarters = 'US'
formats = ['DAISY', 'DJVU', 'EPUB', 'MOBI', 'PDF', 'TXT']
class StoreBubokPublishingStore(StoreBase):
name = 'Bubok Spain'
description = 'Bubok Publishing is a publisher, library and store of books of authors from all around the world. They have a big amount of books of a lot of topics' # noqa
actual_plugin = 'ebook_converter.gui2.store.stores.bubok_publishing_plugin:BubokPublishingStore'
drm_free_only = True
headquarters = 'ES'
formats = ['EPUB', 'PDF']
class StoreBubokPortugalStore(StoreBase):
name = 'Bubok Portugal'
description = 'Bubok Publishing Portugal is a publisher, library and store of books of authors from Portugal. They have a big amount of books of a lot of topics' # noqa
actual_plugin = 'ebook_converter.gui2.store.stores.bubok_portugal_plugin:BubokPortugalStore'
drm_free_only = True
headquarters = 'PT'
formats = ['EPUB', 'PDF']
class StoreBaenWebScriptionStore(StoreBase):
name = 'Baen Ebooks'
description = 'Sci-Fi & Fantasy brought to you by Jim Baen.'
actual_plugin = 'ebook_converter.gui2.store.stores.baen_webscription_plugin:BaenWebScriptionStore'
drm_free_only = True
headquarters = 'US'
formats = ['EPUB', 'LIT', 'LRF', 'MOBI', 'RB', 'RTF', 'ZIP']
class StoreBNStore(StoreBase):
name = 'Barnes and Noble'
description = 'The world\'s largest book seller. As the ultimate destination for book lovers, Barnes & Noble.com offers an incredible array of content.'
actual_plugin = 'ebook_converter.gui2.store.stores.bn_plugin:BNStore'
headquarters = 'US'
formats = ['NOOK']
class StoreBeamEBooksDEStore(StoreBase):
name = 'Beam EBooks DE'
author = 'Charles Haley'
description = 'Bei uns finden Sie: Tausende deutschsprachige e-books; Alle e-books ohne hartes DRM; PDF, ePub und Mobipocket Format; Sofortige Verfügbarkeit - 24 Stunden am Tag; Günstige Preise; e-books für viele Lesegeräte, PC,Mac und Smartphones; Viele Gratis e-books' # noqa
actual_plugin = 'ebook_converter.gui2.store.stores.beam_ebooks_de_plugin:BeamEBooksDEStore'
drm_free_only = True
headquarters = 'DE'
formats = ['EPUB', 'MOBI', 'PDF']
class StoreBiblioStore(StoreBase):
name = 'Библио.бг'
author = 'Alex Stanev'
description = 'Електронна книжарница за книги и списания във формати ePUB и PDF. Част от заглавията са с активна DRM защита.'
actual_plugin = 'ebook_converter.gui2.store.stores.biblio_plugin:BiblioStore'
headquarters = 'BG'
formats = ['EPUB, PDF']
class StoreChitankaStore(StoreBase):
name = 'Моята библиотека'
author = 'Alex Stanev'
description = 'Независим сайт за DRM свободна литература на български език'
actual_plugin = 'ebook_converter.gui2.store.stores.chitanka_plugin:ChitankaStore'
drm_free_only = True
headquarters = 'BG'
formats = ['FB2', 'EPUB', 'TXT', 'SFB']
class StoreEbookNLStore(StoreBase):
name = 'eBook.nl'
description = 'De eBookwinkel van Nederland'
actual_plugin = 'ebook_converter.gui2.store.stores.ebook_nl_plugin:EBookNLStore'
headquarters = 'NL'
formats = ['EPUB', 'PDF']
affiliate = False
class StoreEbookpointStore(StoreBase):
name = 'Ebookpoint'
author = 'Tomasz Długosz'
description = 'E-booki wolne od DRM, 3 formaty w pakiecie, wysyłanie na Kindle'
actual_plugin = 'ebook_converter.gui2.store.stores.ebookpoint_plugin:EbookpointStore'
drm_free_only = True
headquarters = 'PL'
formats = ['EPUB', 'MOBI', 'PDF']
affiliate = True
class StoreEbookscomStore(StoreBase):
name = 'eBooks.com'
description = 'Sells books in multiple electronic formats in all categories. Technical infrastructure is cutting edge, robust and scalable, with servers in the US and Europe.' # noqa
actual_plugin = 'ebook_converter.gui2.store.stores.ebooks_com_plugin:EbookscomStore'
headquarters = 'US'
formats = ['EPUB', 'LIT', 'MOBI', 'PDF']
affiliate = True
class StoreEbooksGratuitsStore(StoreBase):
name = 'EbooksGratuits.com'
description = 'Ebooks Libres et Gratuits'
actual_plugin = 'ebook_converter.gui2.store.stores.ebooksgratuits_plugin:EbooksGratuitsStore'
headquarters = 'FR'
formats = ['EPUB', 'MOBI', 'PDF', 'PDB']
drm_free_only = True
# class StoreEBookShoppeUKStore(StoreBase):
# name = 'ebookShoppe UK'
# author = 'Charles Haley'
# description = 'We made this website in an attempt to offer the widest range of UK eBooks possible across and as many formats as we could manage.'
# actual_plugin = 'ebook_converter.gui2.store.stores.ebookshoppe_uk_plugin:EBookShoppeUKStore'
#
# headquarters = 'UK'
# formats = ['EPUB', 'PDF']
# affiliate = True
class StoreEKnigiStore(StoreBase):
name = 'еКниги'
author = 'Alex Stanev'
description = 'Онлайн книжарница за електронни книги и аудио риалити романи'
actual_plugin = 'ebook_converter.gui2.store.stores.eknigi_plugin:eKnigiStore'
headquarters = 'BG'
formats = ['EPUB', 'PDF', 'HTML']
affiliate = True
class StoreEmpikStore(StoreBase):
name = 'Empik'
author = 'Tomasz Długosz'
description = 'Empik to marka o unikalnym dziedzictwie i legendarne miejsce, dawne “okno na świat”. Jest obecna w polskim krajobrazie kulturalnym od 60 lat (wcześniej jako Kluby Międzynarodowej Prasy i Książki).' # noqa
actual_plugin = 'ebook_converter.gui2.store.stores.empik_plugin:EmpikStore'
headquarters = 'PL'
formats = ['EPUB', 'MOBI', 'PDF']
affiliate = True
class StoreFeedbooksStore(StoreBase):
name = 'Feedbooks'
description = 'Feedbooks is a cloud publishing and distribution service, connected to a large ecosystem of reading systems and social networks. Provides a variety of genres from independent and classic books.' # noqa
actual_plugin = 'ebook_converter.gui2.store.stores.feedbooks_plugin:FeedbooksStore'
headquarters = 'FR'
formats = ['EPUB', 'MOBI', 'PDF']
class StoreGoogleBooksStore(StoreBase):
name = 'Google Books'
description = 'Google Books'
actual_plugin = 'ebook_converter.gui2.store.stores.google_books_plugin:GoogleBooksStore'
headquarters = 'US'
formats = ['EPUB', 'PDF', 'TXT']
class StoreGutenbergStore(StoreBase):
name = 'Project Gutenberg'
description = 'The first producer of free e-books. Free in the United States because their copyright has expired. They may not be free of copyright in other countries. Readers outside of the United States must check the copyright laws of their countries before downloading or redistributing our e-books.' # noqa
actual_plugin = 'ebook_converter.gui2.store.stores.gutenberg_plugin:GutenbergStore'
drm_free_only = True
headquarters = 'US'
formats = ['EPUB', 'HTML', 'MOBI', 'PDB', 'TXT']
class StoreKoboStore(StoreBase):
name = 'Kobo'
description = 'With over 2.3 million e-books to browse we have engaged readers in over 200 countries in Kobo eReading. Our e-book listings include New York Times Bestsellers, award winners, classics and more!' # noqa
actual_plugin = 'ebook_converter.gui2.store.stores.kobo_plugin:KoboStore'
headquarters = 'CA'
formats = ['EPUB']
affiliate = True
class StoreLegimiStore(StoreBase):
name = 'Legimi'
author = 'Tomasz Długosz'
description = 'E-booki w formacie EPUB, MOBI i PDF'
actual_plugin = 'ebook_converter.gui2.store.stores.legimi_plugin:LegimiStore'
headquarters = 'PL'
formats = ['EPUB', 'PDF', 'MOBI']
affiliate = True
class StoreLibreDEStore(StoreBase):
name = 'ebook.de'
author = 'Charles Haley'
description = 'All Ihre Bücher immer dabei. Suchen, finden, kaufen: so einfach wie nie. ebook.de war libre.de'
actual_plugin = 'ebook_converter.gui2.store.stores.libri_de_plugin:LibreDEStore'
headquarters = 'DE'
formats = ['EPUB', 'PDF']
affiliate = True
class StoreLitResStore(StoreBase):
name = 'LitRes'
description = 'e-books from LitRes.ru'
actual_plugin = 'ebook_converter.gui2.store.stores.litres_plugin:LitResStore'
author = 'Roman Mukhin'
drm_free_only = False
headquarters = 'RU'
formats = ['EPUB', 'TXT', 'RTF', 'HTML', 'FB2', 'LRF', 'PDF', 'MOBI', 'LIT', 'ISILO3', 'JAR', 'RB', 'PRC']
affiliate = True
class StoreManyBooksStore(StoreBase):
name = 'ManyBooks'
description = 'Public domain and creative commons works from many sources.'
actual_plugin = 'ebook_converter.gui2.store.stores.manybooks_plugin:ManyBooksStore'
drm_free_only = True
headquarters = 'US'
formats = ['EPUB', 'FB2', 'JAR', 'LIT', 'LRF', 'MOBI', 'PDB', 'PDF', 'RB', 'RTF', 'TCR', 'TXT', 'ZIP']
class StoreMillsBoonUKStore(StoreBase):
name = 'Mills and Boon UK'
author = 'Charles Haley'
description = '"Bring Romance to Life" "[A] hallmark for romantic fiction, recognised around the world."'
actual_plugin = 'ebook_converter.gui2.store.stores.mills_boon_uk_plugin:MillsBoonUKStore'
headquarters = 'UK'
formats = ['EPUB']
affiliate = False
class StoreMobileReadStore(StoreBase):
name = 'MobileRead'
description = 'E-books handcrafted with the utmost care.'
actual_plugin = 'ebook_converter.gui2.store.stores.mobileread.mobileread_plugin:MobileReadStore'
drm_free_only = True
headquarters = 'CH'
formats = ['EPUB', 'IMP', 'LRF', 'LIT', 'MOBI', 'PDF']
class StoreNextoStore(StoreBase):
name = 'Nexto'
author = 'Tomasz Długosz'
description = 'Największy w Polsce sklep internetowy z audiobookami mp3, ebookami pdf oraz prasą do pobrania on-line.'
actual_plugin = 'ebook_converter.gui2.store.stores.nexto_plugin:NextoStore'
headquarters = 'PL'
formats = ['EPUB', 'MOBI', 'PDF']
affiliate = True
class StoreOzonRUStore(StoreBase):
name = 'OZON.ru'
description = 'e-books from OZON.ru'
actual_plugin = 'ebook_converter.gui2.store.stores.ozon_ru_plugin:OzonRUStore'
author = 'Roman Mukhin'
drm_free_only = True
headquarters = 'RU'
formats = ['TXT', 'PDF', 'DJVU', 'RTF', 'DOC', 'JAR', 'FB2']
affiliate = True
class StorePragmaticBookshelfStore(StoreBase):
name = 'Pragmatic Bookshelf'
description = 'The Pragmatic Bookshelf\'s collection of programming and tech books avaliable as e-books.'
actual_plugin = 'ebook_converter.gui2.store.stores.pragmatic_bookshelf_plugin:PragmaticBookshelfStore'
drm_free_only = True
headquarters = 'US'
formats = ['EPUB', 'MOBI', 'PDF']
class StorePublioStore(StoreBase):
name = 'Publio'
description = 'Publio.pl to księgarnia internetowa, w której mogą Państwo nabyć e-booki i audiobooki.'
actual_plugin = 'ebook_converter.gui2.store.stores.publio_plugin:PublioStore'
author = 'Tomasz Długosz'
headquarters = 'PL'
formats = ['EPUB', 'MOBI', 'PDF']
affiliate = True
class StoreRW2010Store(StoreBase):
name = 'RW2010'
description = 'Polski serwis self-publishingowy. Pliki PDF, EPUB i MOBI.'
actual_plugin = 'ebook_converter.gui2.store.stores.rw2010_plugin:RW2010Store'
author = 'Tomasz Długosz'
drm_free_only = True
headquarters = 'PL'
formats = ['EPUB', 'MOBI', 'PDF']
class StoreSmashwordsStore(StoreBase):
name = 'Smashwords'
description = 'An e-book publishing and distribution platform for e-book authors, publishers and readers. Covers many genres and formats.'
actual_plugin = 'ebook_converter.gui2.store.stores.smashwords_plugin:SmashwordsStore'
drm_free_only = True
headquarters = 'US'
formats = ['EPUB', 'HTML', 'LRF', 'MOBI', 'PDB', 'RTF', 'TXT']
affiliate = True
class StoreSwiatEbookowStore(StoreBase):
name = 'Świat Ebooków'
author = 'Tomasz Długosz'
description = 'Ebooki maje tę zaletę, że są zawsze i wszędzie tam, gdzie tylko nas dopadnie ochota na czytanie.'
actual_plugin = 'ebook_converter.gui2.store.stores.swiatebookow_plugin:SwiatEbookowStore'
drm_free_only = True
headquarters = 'PL'
formats = ['EPUB', 'MOBI', 'PDF']
affiliate = True
class StoreVirtualoStore(StoreBase):
name = 'Virtualo'
author = 'Tomasz Długosz'
description = 'Księgarnia internetowa, która oferuje bezpieczny i szeroki dostęp do książek w formie cyfrowej.'
actual_plugin = 'ebook_converter.gui2.store.stores.virtualo_plugin:VirtualoStore'
headquarters = 'PL'
formats = ['EPUB', 'MOBI', 'PDF']
affiliate = True
class StoreWeightlessBooksStore(StoreBase):
name = 'Weightless Books'
description = 'An independent DRM-free e-book site devoted to e-books of all sorts.'
actual_plugin = 'ebook_converter.gui2.store.stores.weightless_books_plugin:WeightlessBooksStore'
drm_free_only = True
headquarters = 'US'
formats = ['EPUB', 'HTML', 'LIT', 'MOBI', 'PDF']
class StoreWHSmithUKStore(StoreBase):
name = 'WH Smith UK'
author = 'Charles Haley'
description = u"Shop for savings on Books, discounted Magazine subscriptions and great prices on Stationery, Toys & Games"
actual_plugin = 'ebook_converter.gui2.store.stores.whsmith_uk_plugin:WHSmithUKStore'
headquarters = 'UK'
formats = ['EPUB', 'PDF']
class StoreWolneLekturyStore(StoreBase):
name = 'Wolne Lektury'
author = 'Tomasz Długosz'
description = 'Wolne Lektury to biblioteka internetowa czynna 24 godziny na dobę, 365 dni w roku, której zasoby dostępne są całkowicie za darmo. Wszystkie dzieła są odpowiednio opracowane - opatrzone przypisami, motywami i udostępnione w kilku formatach - HTML, TXT, PDF, EPUB, MOBI, FB2.' # noqa
actual_plugin = 'ebook_converter.gui2.store.stores.wolnelektury_plugin:WolneLekturyStore'
headquarters = 'PL'
formats = ['EPUB', 'MOBI', 'PDF', 'TXT', 'FB2']
class StoreWoblinkStore(StoreBase):
name = 'Woblink'
author = 'Tomasz Długosz'
description = 'Czytanie zdarza się wszędzie!'
actual_plugin = 'ebook_converter.gui2.store.stores.woblink_plugin:WoblinkStore'
headquarters = 'PL'
formats = ['EPUB', 'MOBI', 'PDF', 'WOBLINK']
affiliate = True
class XinXiiStore(StoreBase):
name = 'XinXii'
description = ''
actual_plugin = 'ebook_converter.gui2.store.stores.xinxii_plugin:XinXiiStore'
headquarters = 'DE'
formats = ['EPUB', 'PDF']
plugins += [
StoreArchiveOrgStore,
StoreBubokPublishingStore,
StoreBubokPortugalStore,
StoreAmazonKindleStore,
StoreAmazonAUKindleStore,
StoreAmazonCAKindleStore,
StoreAmazonINKindleStore,
StoreAmazonDEKindleStore,
StoreAmazonESKindleStore,
StoreAmazonFRKindleStore,
StoreAmazonITKindleStore,
StoreAmazonUKKindleStore,
StoreBaenWebScriptionStore,
StoreBNStore,
StoreBeamEBooksDEStore,
StoreBiblioStore,
StoreChitankaStore,
StoreEbookNLStore,
StoreEbookpointStore,
StoreEbookscomStore,
StoreEbooksGratuitsStore,
StoreEKnigiStore,
StoreEmpikStore,
StoreFeedbooksStore,
StoreGoogleBooksStore,
StoreGutenbergStore,
StoreKoboStore,
StoreLegimiStore,
StoreLibreDEStore,
StoreLitResStore,
StoreManyBooksStore,
StoreMillsBoonUKStore,
StoreMobileReadStore,
StoreNextoStore,
StoreOzonRUStore,
StorePragmaticBookshelfStore,
StorePublioStore,
StoreRW2010Store,
StoreSmashwordsStore,
StoreSwiatEbookowStore,
StoreVirtualoStore,
StoreWeightlessBooksStore,
StoreWHSmithUKStore,
StoreWolneLekturyStore,
StoreWoblinkStore,
XinXiiStore
]
# }}}
if __name__ == '__main__':
# Test load speed

View File

@@ -1,28 +1,21 @@
import os, shutil, traceback, functools, sys
from collections import defaultdict
from itertools import chain
import collections
import functools
import itertools
import os
import shutil
import sys
import traceback
from ebook_converter.customize import (CatalogPlugin, FileTypePlugin, PluginNotFound,
MetadataReaderPlugin, MetadataWriterPlugin,
InterfaceActionBase as InterfaceAction,
PreferencesPlugin, platform, InvalidPlugin,
StoreBase as Store, EditBookToolPlugin,
LibraryClosedPlugin)
from ebook_converter.customize.conversion import InputFormatPlugin, OutputFormatPlugin
from ebook_converter.customize.profiles import InputProfile, OutputProfile
from ebook_converter.customize.builtins import plugins as builtin_plugins
# from ebook_converter.devices.interface import DevicePlugin
from ebook_converter.ebooks.metadata import MetaInformation
from ebook_converter.utils.config import (make_config_dir, Config, ConfigProxy,
plugin_dir, OptionParser)
# from ebook_converter.ebooks.metadata.sources.base import Source
from ebook_converter.constants import DEBUG, numeric_version
from ebook_converter import customize
from ebook_converter.customize import conversion
from ebook_converter.customize import profiles
from ebook_converter.customize import builtins
from ebook_converter.ebooks import metadata
from ebook_converter.utils import config as cfg
from ebook_converter import constants
__license__ = 'GPL v3'
__copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net>'
builtin_names = frozenset(p.name for p in builtin_plugins)
builtin_names = frozenset(p.name for p in builtins.plugins)
BLACKLISTED_PLUGINS = frozenset({'Marvin XD', 'iOS reader applications'})
@@ -31,107 +24,40 @@ class NameConflict(ValueError):
def _config():
c = Config('customize')
c = cfg.Config('customize')
c.add_opt('plugins', default={}, help=_('Installed plugins'))
c.add_opt('filetype_mapping', default={}, help=_('Mapping for filetype plugins'))
c.add_opt('plugin_customization', default={}, help=_('Local plugin customization'))
c.add_opt('filetype_mapping', default={},
help=_('Mapping for filetype plugins'))
c.add_opt('plugin_customization', default={},
help=_('Local plugin customization'))
c.add_opt('disabled_plugins', default=set(), help=_('Disabled plugins'))
c.add_opt('enabled_plugins', default=set(), help=_('Enabled plugins'))
return ConfigProxy(c)
return cfg.ConfigProxy(c)
config = _config()
def find_plugin(name):
for plugin in _initialized_plugins:
if plugin.name == name:
return plugin
def load_plugin(path_to_zip_file): # {{{
'''
Load plugin from ZIP file or raise InvalidPlugin error
:return: A :class:`Plugin` instance.
'''
return loader.load(path_to_zip_file)
# }}}
# Enable/disable plugins {{{
def disable_plugin(plugin_or_name):
x = getattr(plugin_or_name, 'name', plugin_or_name)
plugin = find_plugin(x)
if not plugin.can_be_disabled:
raise ValueError('Plugin %s cannot be disabled'%x)
dp = config['disabled_plugins']
dp.add(x)
config['disabled_plugins'] = dp
ep = config['enabled_plugins']
if x in ep:
ep.remove(x)
config['enabled_plugins'] = ep
def enable_plugin(plugin_or_name):
x = getattr(plugin_or_name, 'name', plugin_or_name)
dp = config['disabled_plugins']
if x in dp:
dp.remove(x)
config['disabled_plugins'] = dp
ep = config['enabled_plugins']
ep.add(x)
config['enabled_plugins'] = ep
def restore_plugin_state_to_default(plugin_or_name):
x = getattr(plugin_or_name, 'name', plugin_or_name)
dp = config['disabled_plugins']
if x in dp:
dp.remove(x)
config['disabled_plugins'] = dp
ep = config['enabled_plugins']
if x in ep:
ep.remove(x)
config['enabled_plugins'] = ep
default_disabled_plugins = {
'Overdrive', 'Douban Books', 'OZON.ru', 'Edelweiss', 'Google Images', 'Big Book Search',
}
def is_disabled(plugin):
if plugin.name in config['enabled_plugins']:
return False
return plugin.name in config['disabled_plugins'] or \
plugin.name in default_disabled_plugins
# }}}
# File type plugins {{{
_on_import = {}
_on_postimport = {}
_on_preprocess = {}
_on_postprocess = {}
_on_postadd = []
# File type plugins
_on_import = {}
_on_postimport = {}
_on_preprocess = {}
_on_postprocess = {}
_on_postadd = []
def reread_filetype_plugins():
global _on_import, _on_postimport, _on_preprocess, _on_postprocess, _on_postadd
_on_import = defaultdict(list)
_on_postimport = defaultdict(list)
_on_preprocess = defaultdict(list)
_on_postprocess = defaultdict(list)
_on_postadd = []
global _on_import, _on_postimport, _on_preprocess, _on_postprocess
global _on_postadd
_on_import = collections.defaultdict(list)
_on_postimport = collections.defaultdict(list)
_on_preprocess = collections.defaultdict(list)
_on_postprocess = collections.defaultdict(list)
_on_postadd = []
for plugin in _initialized_plugins:
if isinstance(plugin, FileTypePlugin):
if isinstance(plugin, customize.FileTypePlugin):
for ft in plugin.file_types:
if plugin.on_import:
_on_import[ft].append(plugin)
@@ -145,12 +71,12 @@ def reread_filetype_plugins():
def plugins_for_ft(ft, occasion):
op = {
'import':_on_import, 'preprocess':_on_preprocess, 'postprocess':_on_postprocess, 'postimport':_on_postimport,
}[occasion]
for p in chain(op.get(ft, ()), op.get('*', ())):
if not is_disabled(p):
yield p
op = {'import': _on_import,
'preprocess': _on_preprocess,
'postprocess': _on_postprocess,
'postimport': _on_postimport}[occasion]
for p in itertools.chain(op.get(ft, ()), op.get('*', ())):
yield p
def _run_filetype_plugins(path_to_file, ft=None, occasion='preprocess'):
@@ -160,7 +86,9 @@ def _run_filetype_plugins(path_to_file, ft=None, occasion='preprocess'):
nfp = path_to_file
for plugin in plugins_for_ft(ft, occasion):
plugin.site_customization = customization.get(plugin.name, '')
oo, oe = sys.stdout, sys.stderr # Some file type plugins out there override the output streams with buggy implementations
# Some file type plugins out there override the output streams with
# buggy implementations
oo, oe = sys.stdout, sys.stderr
with plugin:
try:
plugin.original_path_to_file = path_to_file
@@ -169,7 +97,8 @@ def _run_filetype_plugins(path_to_file, ft=None, occasion='preprocess'):
try:
nfp = plugin.run(nfp) or nfp
except:
print('Running file type plugin %s failed with traceback:'%plugin.name, file=oe)
print('Running file type plugin %s failed with traceback:' %
plugin.name, file=oe)
traceback.print_exc(file=oe)
sys.stdout, sys.stderr = oo, oe
x = lambda j: os.path.normpath(os.path.normcase(j))
@@ -179,9 +108,12 @@ def _run_filetype_plugins(path_to_file, ft=None, occasion='preprocess'):
return nfp
run_plugins_on_import = functools.partial(_run_filetype_plugins, occasion='import')
run_plugins_on_preprocess = functools.partial(_run_filetype_plugins, occasion='preprocess')
run_plugins_on_postprocess = functools.partial(_run_filetype_plugins, occasion='postprocess')
run_plugins_on_import = functools.partial(_run_filetype_plugins,
occasion='import')
run_plugins_on_preprocess = functools.partial(_run_filetype_plugins,
occasion='preprocess')
run_plugins_on_postprocess = functools.partial(_run_filetype_plugins,
occasion='postprocess')
def run_plugins_on_postimport(db, book_id, fmt):
@@ -192,31 +124,26 @@ def run_plugins_on_postimport(db, book_id, fmt):
with plugin:
try:
plugin.postimport(book_id, fmt, db)
except:
print('Running file type plugin %s failed with traceback:'%
plugin.name)
except Exception:
print('Running file type plugin %s failed with traceback:' %
plugin.name)
traceback.print_exc()
def run_plugins_on_postadd(db, book_id, fmt_map):
customization = config['plugin_customization']
for plugin in _on_postadd:
if is_disabled(plugin):
continue
plugin.site_customization = customization.get(plugin.name, '')
with plugin:
try:
plugin.postadd(book_id, fmt_map, db)
except Exception:
print('Running file type plugin %s failed with traceback:'%
plugin.name)
print('Running file type plugin %s failed with traceback:' %
plugin.name)
traceback.print_exc()
# }}}
# Plugin customization {{{
# Plugin customization
def customize_plugin(plugin, custom):
d = config['plugin_customization']
d[plugin.name] = custom.strip()
@@ -226,82 +153,64 @@ def customize_plugin(plugin, custom):
def plugin_customization(plugin):
return config['plugin_customization'].get(plugin.name, '')
# }}}
# Input/Output profiles {{{
# Input/Output profiles
def input_profiles():
for plugin in _initialized_plugins:
if isinstance(plugin, InputProfile):
if isinstance(plugin, profiles.InputProfile):
yield plugin
def output_profiles():
for plugin in _initialized_plugins:
if isinstance(plugin, OutputProfile):
if isinstance(plugin, profiles.OutputProfile):
yield plugin
# }}}
# Interface Actions # {{{
# Interface Actions #
def interface_actions():
customization = config['plugin_customization']
for plugin in _initialized_plugins:
if isinstance(plugin, InterfaceAction):
if not is_disabled(plugin):
plugin.site_customization = customization.get(plugin.name, '')
yield plugin
# }}}
# Preferences Plugins # {{{
if isinstance(plugin, customize.InterfaceActionBase):
yield plugin
# Preferences Plugins
def preferences_plugins():
customization = config['plugin_customization']
for plugin in _initialized_plugins:
if isinstance(plugin, PreferencesPlugin):
if not is_disabled(plugin):
plugin.site_customization = customization.get(plugin.name, '')
yield plugin
# }}}
# Library Closed Plugins # {{{
if isinstance(plugin, customize.PreferencesPlugin):
plugin.site_customization = customization.get(plugin.name, '')
yield plugin
# Library Closed Plugins
def available_library_closed_plugins():
customization = config['plugin_customization']
for plugin in _initialized_plugins:
if isinstance(plugin, LibraryClosedPlugin):
if not is_disabled(plugin):
plugin.site_customization = customization.get(plugin.name, '')
yield plugin
if isinstance(plugin, customize.LibraryClosedPlugin):
plugin.site_customization = customization.get(plugin.name, '')
yield plugin
def has_library_closed_plugins():
for plugin in _initialized_plugins:
if isinstance(plugin, LibraryClosedPlugin):
if not is_disabled(plugin):
return True
if isinstance(plugin, customize.LibraryClosedPlugin):
return True
return False
# }}}
# Store Plugins # {{{
# Store Plugins
def store_plugins():
customization = config['plugin_customization']
for plugin in _initialized_plugins:
if isinstance(plugin, Store):
if isinstance(plugin, customize.StoreBase):
plugin.site_customization = customization.get(plugin.name, '')
yield plugin
def available_store_plugins():
for plugin in store_plugins():
if not is_disabled(plugin):
yield plugin
yield plugin
def stores():
@@ -317,11 +226,8 @@ def available_stores():
stores.add(plugin.name)
return stores
# }}}
# Metadata read/write {{{
# Metadata read/write
_metadata_readers = {}
_metadata_writers = {}
@@ -329,13 +235,13 @@ _metadata_writers = {}
def reread_metadata_plugins():
global _metadata_readers
global _metadata_writers
_metadata_readers = defaultdict(list)
_metadata_writers = defaultdict(list)
_metadata_readers = collections.defaultdict(list)
_metadata_writers = collections.defaultdict(list)
for plugin in _initialized_plugins:
if isinstance(plugin, MetadataReaderPlugin):
if isinstance(plugin, customize.MetadataReaderPlugin):
for ft in plugin.file_types:
_metadata_readers[ft].append(plugin)
elif isinstance(plugin, MetadataWriterPlugin):
elif isinstance(plugin, customize.MetadataWriterPlugin):
for ft in plugin.file_types:
_metadata_writers[ft].append(plugin)
@@ -408,109 +314,61 @@ class ForceIdentifiers(object):
self.force_identifiers = False
force_identifiers = ForceIdentifiers()
def get_file_type_metadata(stream, ftype):
mi = MetaInformation(None, None)
mi = metadata.MetaInformation(None, None)
ftype = ftype.lower().strip()
if ftype in _metadata_readers:
for plugin in _metadata_readers[ftype]:
if not is_disabled(plugin):
with plugin:
try:
plugin.quick = quick_metadata.quick
if hasattr(stream, 'seek'):
stream.seek(0)
mi = plugin.get_metadata(stream, ftype.lower().strip())
break
except:
traceback.print_exc()
continue
with plugin:
try:
plugin.quick = quick_metadata.quick
if hasattr(stream, 'seek'):
stream.seek(0)
mi = plugin.get_metadata(stream, ftype.lower().strip())
break
except Exception:
traceback.print_exc()
continue
return mi
def set_file_type_metadata(stream, mi, ftype, report_error=None):
fi = ForceIdentifiers()
ftype = ftype.lower().strip()
if ftype in _metadata_writers:
customization = config['plugin_customization']
for plugin in _metadata_writers[ftype]:
if not is_disabled(plugin):
with plugin:
try:
plugin.apply_null = apply_null_metadata.apply_null
plugin.force_identifiers = force_identifiers.force_identifiers
plugin.site_customization = customization.get(plugin.name, '')
plugin.set_metadata(stream, mi, ftype.lower().strip())
break
except:
if report_error is None:
from ebook_converter import prints
prints('Failed to set metadata for the', ftype.upper(), 'format of:', getattr(mi, 'title', ''), file=sys.stderr)
traceback.print_exc()
else:
report_error(mi, ftype, traceback.format_exc())
with plugin:
try:
plugin.apply_null = apply_null_metadata.apply_null
plugin.force_identifiers = fi.force_identifiers
plugin.site_customization = customization.get(
plugin.name, '')
plugin.set_metadata(stream, mi, ftype.lower().strip())
break
except Exception:
if report_error is None:
from ebook_converter import prints
prints('Failed to set metadata for the', ftype.upper(),
'format of:', getattr(mi, 'title', ''),
file=sys.stderr)
traceback.print_exc()
else:
report_error(mi, ftype, traceback.format_exc())
def can_set_metadata(ftype):
ftype = ftype.lower().strip()
for plugin in _metadata_writers.get(ftype, ()):
if not is_disabled(plugin):
return True
return True
return False
# }}}
# Add/remove plugins {{{
def add_plugin(path_to_zip_file):
make_config_dir()
plugin = load_plugin(path_to_zip_file)
if plugin.name in builtin_names:
raise NameConflict(
'A builtin plugin with the name %r already exists' % plugin.name)
plugin = initialize_plugin(plugin, path_to_zip_file)
plugins = config['plugins']
zfp = os.path.join(plugin_dir, plugin.name+'.zip')
if os.path.exists(zfp):
os.remove(zfp)
shutil.copyfile(path_to_zip_file, zfp)
plugins[plugin.name] = zfp
config['plugins'] = plugins
initialize_plugins()
return plugin
def remove_plugin(plugin_or_name):
name = getattr(plugin_or_name, 'name', plugin_or_name)
plugins = config['plugins']
removed = False
if name in plugins:
removed = True
try:
zfp = os.path.join(plugin_dir, name+'.zip')
if os.path.exists(zfp):
os.remove(zfp)
zfp = plugins[name]
if os.path.exists(zfp):
os.remove(zfp)
except:
pass
plugins.pop(name)
config['plugins'] = plugins
initialize_plugins()
return removed
# }}}
# Input/Output format plugins {{{
# Input/Output format plugins
def input_format_plugins():
for plugin in _initialized_plugins:
if isinstance(plugin, InputFormatPlugin):
if isinstance(plugin, conversion.InputFormatPlugin):
yield plugin
@@ -533,16 +391,16 @@ def all_input_formats():
def available_input_formats():
formats = set()
for plugin in input_format_plugins():
if not is_disabled(plugin):
for format in plugin.file_types:
formats.add(format)
formats.add('zip'), formats.add('rar')
for format in plugin.file_types:
formats.add(format)
formats.add('zip')
formats.add('rar')
return formats
def output_format_plugins():
for plugin in _initialized_plugins:
if isinstance(plugin, OutputFormatPlugin):
if isinstance(plugin, conversion.OutputFormatPlugin):
yield plugin
@@ -557,27 +415,22 @@ def plugin_for_output_format(fmt):
def available_output_formats():
formats = set()
for plugin in output_format_plugins():
if not is_disabled(plugin):
formats.add(plugin.file_type)
formats.add(plugin.file_type)
return formats
# }}}
# Catalog plugins {{{
# Catalog plugins
def catalog_plugins():
for plugin in _initialized_plugins:
if isinstance(plugin, CatalogPlugin):
if isinstance(plugin, customize.CatalogPlugin):
yield plugin
def available_catalog_formats():
formats = set()
for plugin in catalog_plugins():
if not is_disabled(plugin):
for format in plugin.file_types:
formats.add(format)
for format in plugin.file_types:
formats.add(format)
return formats
@@ -586,74 +439,15 @@ def plugin_for_catalog_format(fmt):
if fmt.lower() in plugin.file_types:
return plugin
# }}}
# Device plugins {{{
def device_plugins(include_disabled=False):
for plugin in _initialized_plugins:
if isinstance(plugin, DevicePlugin):
if include_disabled or not is_disabled(plugin):
if platform in plugin.supported_platforms:
if getattr(plugin, 'plugin_needs_delayed_initialization',
False):
plugin.do_delayed_plugin_initialization()
yield plugin
def disabled_device_plugins():
for plugin in _initialized_plugins:
if isinstance(plugin, DevicePlugin):
if is_disabled(plugin):
if platform in plugin.supported_platforms:
yield plugin
# }}}
# Metadata sources2 {{{
def metadata_plugins(capabilities):
capabilities = frozenset(capabilities)
for plugin in all_metadata_plugins():
if plugin.capabilities.intersection(capabilities) and \
not is_disabled(plugin):
yield plugin
def all_metadata_plugins():
for plugin in _initialized_plugins:
if isinstance(plugin, Source):
yield plugin
def patch_metadata_plugins(possibly_updated_plugins):
patches = {}
for i, plugin in enumerate(_initialized_plugins):
if isinstance(plugin, Source) and plugin.name in builtin_names:
pup = possibly_updated_plugins.get(plugin.name)
if pup is not None:
if pup.version > plugin.version and pup.minimum_calibre_version <= numeric_version:
patches[i] = pup(None)
# Metadata source plugins dont use initialize() but that
# might change in the future, so be safe.
patches[i].initialize()
for i, pup in patches.items():
_initialized_plugins[i] = pup
# }}}
# Editor plugins {{{
# Editor plugins
def all_edit_book_tool_plugins():
for plugin in _initialized_plugins:
if isinstance(plugin, EditBookToolPlugin):
if isinstance(plugin, customize.EditBookToolPlugin):
yield plugin
# }}}
# Initialize plugins {{{
# Initialize plugins
_initialized_plugins = []
@@ -665,8 +459,8 @@ def initialize_plugin(plugin, path_to_zip_file):
except Exception:
print('Failed to initialize plugin:', plugin.name, plugin.version)
tb = traceback.format_exc()
raise InvalidPlugin((_('Initialization of plugin %s failed with traceback:')
%tb) + '\n'+tb)
raise customize.InvalidPlugin((_('Initialization of plugin %s failed '
'with traceback:') % tb) + '\n'+tb)
def has_external_plugins():
@@ -674,49 +468,23 @@ def has_external_plugins():
return bool(config['plugins'])
def initialize_plugins(perf=False):
def initialize_plugins():
global _initialized_plugins
_initialized_plugins = []
conflicts = [name for name in config['plugins'] if name in
builtin_names]
for p in conflicts:
remove_plugin(p)
external_plugins = config['plugins'].copy()
for name in BLACKLISTED_PLUGINS:
external_plugins.pop(name, None)
ostdout, ostderr = sys.stdout, sys.stderr
if perf:
from collections import defaultdict
import time
times = defaultdict(lambda:0)
for zfp in list(external_plugins) + builtin_plugins:
for zfp in list(external_plugins) + builtins.plugins:
try:
if not isinstance(zfp, type):
# We have a plugin name
pname = zfp
zfp = os.path.join(plugin_dir, zfp+'.zip')
if not os.path.exists(zfp):
zfp = external_plugins[pname]
try:
plugin = load_plugin(zfp) if not isinstance(zfp, type) else zfp
except PluginNotFound:
continue
if perf:
st = time.time()
plugin = initialize_plugin(plugin, None if isinstance(zfp, type) else zfp)
if perf:
times[plugin.name] = time.time() - st
plugin = initialize_plugin(zfp, None)
_initialized_plugins.append(plugin)
except:
except Exception:
print('Failed to initialize plugin:', repr(zfp))
if DEBUG:
traceback.print_exc()
# Prevent a custom plugin from overriding stdout/stderr as this breaks
# ipython
sys.stdout, sys.stderr = ostdout, ostderr
if perf:
for x in sorted(times, key=lambda x: times[x]):
print('%50s: %.3f'%(x, times[x]))
_initialized_plugins.sort(key=lambda x: x.priority, reverse=True)
reread_filetype_plugins()
reread_metadata_plugins()
@@ -729,31 +497,11 @@ def initialized_plugins():
for plugin in _initialized_plugins:
yield plugin
# }}}
# CLI {{{
def build_plugin(path):
from ebook_converter import prints
from ebook_converter.ptempfile import PersistentTemporaryFile
from ebook_converter.utils.zipfile import ZipFile, ZIP_STORED
path = str(path)
names = frozenset(os.listdir(path))
if '__init__.py' not in names:
prints(path, ' is not a valid plugin')
raise SystemExit(1)
t = PersistentTemporaryFile(u'.zip')
with ZipFile(t, 'w', ZIP_STORED) as zf:
zf.add_dir(path, simple_filter=lambda x:x in {'.git', '.bzr', '.svn', '.hg'})
t.close()
plugin = add_plugin(t.name)
os.remove(t.name)
prints('Plugin updated:', plugin.name, plugin.version)
# CLI
def option_parser():
parser = OptionParser(usage=_('''\
parser = cfg.OptionParser(usage=_('''\
%prog options
Customize calibre by loading external plugins.
@@ -775,59 +523,3 @@ def option_parser():
parser.add_option('--disable-plugin', default=None,
help=_('Disable the named plugin'))
return parser
def main(args=sys.argv):
parser = option_parser()
if len(args) < 2:
parser.print_help()
return 1
opts, args = parser.parse_args(args)
if opts.add_plugin is not None:
plugin = add_plugin(opts.add_plugin)
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 remove_plugin(opts.remove_plugin):
print('Plugin removed')
else:
print('No custom plugin named', opts.remove_plugin)
if opts.customize_plugin is not None:
name, custom = opts.customize_plugin.split(',')
plugin = find_plugin(name.strip())
if plugin is None:
print('No plugin with the name %s exists'%name)
return 1
customize_plugin(plugin, custom)
if opts.enable_plugin is not None:
enable_plugin(opts.enable_plugin.strip())
if opts.disable_plugin is not None:
disable_plugin(opts.disable_plugin.strip())
if opts.list_plugins:
type_len = name_len = 0
for plugin in initialized_plugins():
type_len, name_len = max(type_len, len(plugin.type)), max(name_len, len(plugin.name))
fmt = '%-{}s%-{}s%-15s%-15s%s'.format(type_len+1, name_len+1)
print(fmt%tuple(('Type|Name|Version|Disabled|Site Customization'.split('|'))))
print()
for plugin in initialized_plugins():
print(fmt%(
plugin.type, plugin.name,
plugin.version, is_disabled(plugin),
plugin_customization(plugin)
))
print('\t', plugin.description)
if plugin.is_customizable():
try:
print('\t', plugin.customization_help())
except NotImplementedError:
pass
print()
return 0
if __name__ == '__main__':
sys.exit(main())
# }}}

View File

@@ -1,9 +1,11 @@
"""
Command line interface to conversion sub-system
"""
import sys, os, numbers
from optparse import OptionGroup, Option
from collections import OrderedDict
import collections
import numbers
import optparse
import os
import sys
from ebook_converter.utils.config import OptionParser
from ebook_converter.utils.logging import Log
@@ -12,10 +14,6 @@ from ebook_converter import patheq
from ebook_converter.utils.localization import localize_user_manual_link
__license__ = 'GPL 3'
__copyright__ = '2009, Kovid Goyal <kovid@kovidgoyal.net>'
__docformat__ = 'restructuredtext en'
USAGE = '%prog ' + _('''\
input_file output_file [options]
@@ -110,7 +108,7 @@ def option_recommendation_to_cli_option(add_option, rec):
)
if opt.name in DEFAULT_TRUE_OPTIONS and rec.recommended_value is True:
switches = ['--disable-'+opt.long_switch]
add_option(Option(*switches, **attrs))
add_option(optparse.Option(*switches, **attrs))
def group_titles():
@@ -156,27 +154,27 @@ def add_input_output_options(parser, plumber):
def add_options(group, options):
for opt in options:
if plumber.input_fmt == 'recipe' and opt.option.long_switch == 'test':
group(Option('--test', dest='test', action='callback', callback=recipe_test))
group(optparse.Option('--test', dest='test', action='callback', callback=recipe_test))
else:
option_recommendation_to_cli_option(group, opt)
if input_options:
title = group_titles()[0]
io = OptionGroup(parser, title, _('Options to control the processing'
io = optparse.OptionGroup(parser, title, _('Options to control the processing'
' of the input %s file')%plumber.input_fmt)
add_options(io.add_option, input_options)
parser.add_option_group(io)
if output_options:
title = group_titles()[1]
oo = OptionGroup(parser, title, _('Options to control the processing'
oo = optparse.OptionGroup(parser, title, _('Options to control the processing'
' of the output %s')%plumber.output_fmt)
add_options(oo.add_option, output_options)
parser.add_option_group(oo)
def add_pipeline_options(parser, plumber):
groups = OrderedDict((
groups = collections.OrderedDict((
('' , ('',
[
'input_profile',
@@ -254,7 +252,7 @@ def add_pipeline_options(parser, plumber):
for group, (desc, options) in groups.items():
if group:
group = OptionGroup(parser, group, desc)
group = optparse.OptionGroup(parser, group, desc)
parser.add_option_group(group)
add_option = group.add_option if group != '' else parser.add_option

View File

@@ -1,5 +1,9 @@
import os, re, sys, shutil, pprint, json
from functools import partial
import functools
import json
import os
import pprint
import shutil
import sys
from ebook_converter.customize.conversion import OptionRecommendation, DummyReporter
from ebook_converter.customize.ui import input_profiles, output_profiles, \
@@ -11,14 +15,10 @@ from ebook_converter.ptempfile import PersistentTemporaryDirectory
from ebook_converter.utils.date import parse_date
from ebook_converter.utils.zipfile import ZipFile
from ebook_converter import (extract, walk, isbytestring, filesystem_encoding,
get_types_map)
get_types_map)
from ebook_converter.constants import __version__
__license__ = 'GPL 3'
__copyright__ = '2009, Kovid Goyal <kovid@kovidgoyal.net>'
__docformat__ = 'restructuredtext en'
DEBUG_README=b'''
This debug directory contains snapshots of the e-book as it passes through the
various stages of conversion. The stages are:
@@ -1224,7 +1224,7 @@ OptionRecommendation(name='search_replace',
page_break_on_body=self.output_plugin.file_type in ('mobi',
'lit'),
transform_css_rules=transform_css_rules,
specializer=partial(self.output_plugin.specialize_css_for_output,
specializer=functools.partial(self.output_plugin.specialize_css_for_output,
self.log, self.opts))
flattener(self.oeb, self.opts)
self.opts._final_base_font_size = fbase