mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Added support for metadata reading/writing plugins
This commit is contained in:
parent
5769ce558c
commit
21e5196614
@ -5,6 +5,7 @@ __copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net>'
|
||||
import sys
|
||||
|
||||
from calibre.ptempfile import PersistentTemporaryFile
|
||||
from calibre.constants import __version__, __author__
|
||||
|
||||
class Plugin(object):
|
||||
'''
|
||||
@ -127,7 +128,7 @@ class FileTypePlugin(Plugin):
|
||||
A plugin that is associated with a particular set of file types.
|
||||
'''
|
||||
|
||||
#: List of file types for which this plugin should be run
|
||||
#: Set of file types for which this plugin should be run
|
||||
#: For example: ``set(['lit', 'mobi', 'prc'])``
|
||||
file_types = set([])
|
||||
|
||||
@ -163,3 +164,56 @@ class FileTypePlugin(Plugin):
|
||||
'''
|
||||
# Default implementation does nothing
|
||||
return path_to_ebook
|
||||
|
||||
class MetadataReaderPlugin(Plugin):
|
||||
'''
|
||||
A plugin that implements reading metadata from a set of file types.
|
||||
'''
|
||||
#: Set of file types for which this plugin should be run
|
||||
#: For example: ``set(['lit', 'mobi', 'prc'])``
|
||||
file_types = set([])
|
||||
|
||||
supported_platforms = ['windows', 'osx', 'linux']
|
||||
version = tuple(map(int, (__version__.split('.'))[:3]))
|
||||
author = 'Kovid Goyal'
|
||||
|
||||
type = _('Metadata reader')
|
||||
|
||||
def get_metadata(self, stream, type):
|
||||
'''
|
||||
Return metadata for the file represented by stream (a file like object
|
||||
that supports reading). Raise an exception when there is an error
|
||||
with the input data.
|
||||
|
||||
:param type: The type of file. Guaranteed to be one of the entries
|
||||
in :member:`file_types`.
|
||||
:return: A :class:`calibre.ebooks.metadata.MetaInformation` object
|
||||
'''
|
||||
return None
|
||||
|
||||
class MetadataWriterPlugin(Plugin):
|
||||
'''
|
||||
A plugin that implements reading metadata from a set of file types.
|
||||
'''
|
||||
#: Set of file types for which this plugin should be run
|
||||
#: For example: ``set(['lit', 'mobi', 'prc'])``
|
||||
file_types = set([])
|
||||
|
||||
supported_platforms = ['windows', 'osx', 'linux']
|
||||
version = tuple(map(int, (__version__.split('.'))[:3]))
|
||||
author = 'Kovid Goyal'
|
||||
|
||||
type = _('Metadata writer')
|
||||
|
||||
def set_metadata(self, stream, mi, type):
|
||||
'''
|
||||
Set metadata for the file represented by stream (a file like object
|
||||
that supports reading). Raise an exception when there is an error
|
||||
with the input data.
|
||||
|
||||
:param type: The type of file. Guaranteed to be one of the entries
|
||||
in :member:`file_types`.
|
||||
:param mi: A :class:`calibre.ebooks.metadata.MetaInformation` object
|
||||
'''
|
||||
pass
|
||||
|
@ -2,8 +2,8 @@ from __future__ import with_statement
|
||||
__license__ = 'GPL v3'
|
||||
__copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net>'
|
||||
|
||||
import textwrap
|
||||
from calibre.customize import FileTypePlugin
|
||||
import textwrap, os
|
||||
from calibre.customize import FileTypePlugin, MetadataReaderPlugin, MetadataWriterPlugin
|
||||
from calibre.constants import __version__
|
||||
|
||||
class HTML2ZIP(FileTypePlugin):
|
||||
@ -15,7 +15,7 @@ file containing all linked files. This plugin is run \
|
||||
every time you add an HTML file to the library.\
|
||||
'''))
|
||||
version = tuple(map(int, (__version__.split('.'))[:3]))
|
||||
file_types = ['html', 'htm', 'xhtml', 'xhtm']
|
||||
file_types = set(['html', 'htm', 'xhtml', 'xhtm'])
|
||||
supported_platforms = ['windows', 'osx', 'linux']
|
||||
on_import = True
|
||||
|
||||
@ -25,5 +25,181 @@ every time you add an HTML file to the library.\
|
||||
html2oeb(htmlfile, of)
|
||||
return of.name
|
||||
|
||||
class RTFMetadataReader(MetadataReaderPlugin):
|
||||
|
||||
name = 'Read RTF metadata'
|
||||
file_types = set(['rtf'])
|
||||
description = _('Read metadata from %s files')%'RTF'
|
||||
|
||||
def get_metadata(self, stream, ftype):
|
||||
from calibre.ebooks.metadata.rtf import get_metadata
|
||||
return get_metadata(stream)
|
||||
|
||||
class FB2MetadataReader(MetadataReaderPlugin):
|
||||
|
||||
name = 'Read FB2 metadata'
|
||||
file_types = set(['fb2'])
|
||||
description = _('Read metadata from %s files')%'FB2'
|
||||
|
||||
def get_metadata(self, stream, ftype):
|
||||
from calibre.ebooks.metadata.fb2 import get_metadata
|
||||
return get_metadata(stream)
|
||||
|
||||
|
||||
class LRFMetadataReader(MetadataReaderPlugin):
|
||||
|
||||
name = 'Read LRF metadata'
|
||||
file_types = set(['lrf'])
|
||||
description = _('Read metadata from %s files')%'LRF'
|
||||
|
||||
def get_metadata(self, stream, ftype):
|
||||
from calibre.ebooks.lrf.meta import get_metadata
|
||||
return get_metadata(stream)
|
||||
|
||||
class PDFMetadataReader(MetadataReaderPlugin):
|
||||
|
||||
name = 'Read PDF metadata'
|
||||
file_types = set(['pdf'])
|
||||
description = _('Read metadata from %s files')%'PDF'
|
||||
|
||||
def get_metadata(self, stream, ftype):
|
||||
from calibre.ebooks.metadata.pdf import get_metadata
|
||||
return get_metadata(stream)
|
||||
|
||||
class LITMetadataReader(MetadataReaderPlugin):
|
||||
|
||||
name = 'Read LIT metadata'
|
||||
file_types = set(['lit'])
|
||||
description = _('Read metadata from %s files')%'LIT'
|
||||
|
||||
def get_metadata(self, stream, ftype):
|
||||
from calibre.ebooks.metadata.lit import get_metadata
|
||||
return get_metadata(stream)
|
||||
|
||||
class IMPMetadataReader(MetadataReaderPlugin):
|
||||
|
||||
name = 'Read IMP metadata'
|
||||
file_types = set(['imp'])
|
||||
description = _('Read metadata from %s files')%'IMP'
|
||||
author = 'Ashish Kulkarni'
|
||||
|
||||
def get_metadata(self, stream, ftype):
|
||||
from calibre.ebooks.metadata.imp import get_metadata
|
||||
return get_metadata(stream)
|
||||
|
||||
class RBMetadataReader(MetadataReaderPlugin):
|
||||
|
||||
name = 'Read RB metadata'
|
||||
file_types = set(['rb'])
|
||||
description = _('Read metadata from %s files')%'RB'
|
||||
author = 'Ashish Kulkarni'
|
||||
|
||||
def get_metadata(self, stream, ftype):
|
||||
from calibre.ebooks.metadata.rb import get_metadata
|
||||
return get_metadata(stream)
|
||||
|
||||
class EPUBMetadataReader(MetadataReaderPlugin):
|
||||
|
||||
name = 'Read EPUB metadata'
|
||||
file_types = set(['epub'])
|
||||
description = _('Read metadata from %s files')%'EPUB'
|
||||
|
||||
def get_metadata(self, stream, ftype):
|
||||
from calibre.ebooks.metadata.epub import get_metadata
|
||||
return get_metadata(stream)
|
||||
|
||||
class HTMLMetadataReader(MetadataReaderPlugin):
|
||||
|
||||
name = 'Read HTML metadata'
|
||||
file_types = set(['html'])
|
||||
description = _('Read metadata from %s files')%'HTML'
|
||||
|
||||
def get_metadata(self, stream, ftype):
|
||||
from calibre.ebooks.metadata.html import get_metadata
|
||||
return get_metadata(stream)
|
||||
|
||||
class MOBIMetadataReader(MetadataReaderPlugin):
|
||||
|
||||
name = 'Read MOBI metadata'
|
||||
file_types = set(['mobi'])
|
||||
description = _('Read metadata from %s files')%'MOBI'
|
||||
|
||||
def get_metadata(self, stream, ftype):
|
||||
from calibre.ebooks.mobi.reader import get_metadata
|
||||
return get_metadata(stream)
|
||||
|
||||
class ODTMetadataReader(MetadataReaderPlugin):
|
||||
|
||||
name = 'Read ODT metadata'
|
||||
file_types = set(['odt'])
|
||||
description = _('Read metadata from %s files')%'ODT'
|
||||
|
||||
def get_metadata(self, stream, ftype):
|
||||
from calibre.ebooks.metadata.odt import get_metadata
|
||||
return get_metadata(stream)
|
||||
|
||||
class LRXMetadataReader(MetadataReaderPlugin):
|
||||
|
||||
name = 'Read LRX metadata'
|
||||
file_types = set(['lrx'])
|
||||
description = _('Read metadata from %s files')%'LRX'
|
||||
|
||||
def get_metadata(self, stream, ftype):
|
||||
from calibre.ebooks.metadata.lrx import get_metadata
|
||||
return get_metadata(stream)
|
||||
|
||||
class ComicMetadataReader(MetadataReaderPlugin):
|
||||
|
||||
name = 'Read comic metadata'
|
||||
file_types = set(['cbr', 'cbz'])
|
||||
description = _('Extract cover from comic files')
|
||||
|
||||
def get_metadata(self, stream, ftype):
|
||||
if ftype == 'cbr':
|
||||
from calibre.libunrar import extract_member as extract_first
|
||||
else:
|
||||
from calibre.libunzip import extract_member as extract_first
|
||||
from calibre.ebooks.metadata import MetaInformation
|
||||
ret = extract_first(stream)
|
||||
mi = MetaInformation(None, None)
|
||||
if ret is not None:
|
||||
path, data = ret
|
||||
ext = os.path.splitext(path)[1][1:]
|
||||
mi.cover_data = (ext.lower(), data)
|
||||
return mi
|
||||
|
||||
class EPUBMetadataWriter(MetadataWriterPlugin):
|
||||
|
||||
name = 'Set EPUB metadata'
|
||||
file_types = set(['epub'])
|
||||
description = _('Set metadata in EPUB files')
|
||||
|
||||
def set_metadata(self, stream, mi, type):
|
||||
from calibre.ebooks.metadata.epub import set_metadata
|
||||
set_metadata(stream, mi)
|
||||
|
||||
class LRFMetadataWriter(MetadataWriterPlugin):
|
||||
|
||||
name = 'Set LRF metadata'
|
||||
file_types = set(['lrf'])
|
||||
description = _('Set metadata in LRF files')
|
||||
|
||||
def set_metadata(self, stream, mi, type):
|
||||
from calibre.ebooks.lrf.meta import set_metadata
|
||||
set_metadata(stream, mi)
|
||||
|
||||
class RTFMetadataWriter(MetadataWriterPlugin):
|
||||
|
||||
name = 'Set RTF metadata'
|
||||
file_types = set(['rtf'])
|
||||
description = _('Set metadata in RTF files')
|
||||
|
||||
def set_metadata(self, stream, mi, type):
|
||||
from calibre.ebooks.metadata.rtf import set_metadata
|
||||
set_metadata(stream, mi)
|
||||
|
||||
plugins = [HTML2ZIP]
|
||||
plugins += [x for x in list(locals().values()) if isinstance(x, type) and \
|
||||
x.__name__.endswith('MetadataReader')]
|
||||
plugins += [x for x in list(locals().values()) if isinstance(x, type) and \
|
||||
x.__name__.endswith('MetadataWriter')]
|
@ -4,9 +4,11 @@ __copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net>'
|
||||
|
||||
import os, shutil, traceback, functools, sys
|
||||
|
||||
from calibre.customize import Plugin, FileTypePlugin
|
||||
from calibre.customize import Plugin, FileTypePlugin, MetadataReaderPlugin, \
|
||||
MetadataWriterPlugin
|
||||
from calibre.customize.builtins import plugins as builtin_plugins
|
||||
from calibre.constants import __version__, iswindows, isosx
|
||||
from calibre.ebooks.metadata import MetaInformation
|
||||
from calibre.utils.config import make_config_dir, Config, ConfigProxy, \
|
||||
plugin_dir, OptionParser
|
||||
|
||||
@ -91,6 +93,37 @@ def reread_filetype_plugins():
|
||||
_on_postprocess[ft] = []
|
||||
_on_postprocess[ft].append(plugin)
|
||||
|
||||
_metadata_readers = {}
|
||||
_metadata_writers = {}
|
||||
def reread_metadata_plugins():
|
||||
global _metadata_readers
|
||||
global _metadata_writers
|
||||
_metadata_readers = {}
|
||||
for plugin in _initialized_plugins:
|
||||
if isinstance(plugin, MetadataReaderPlugin):
|
||||
for ft in plugin.file_types:
|
||||
_metadata_readers[ft] = plugin
|
||||
elif isinstance(plugin, MetadataWriterPlugin):
|
||||
for ft in plugin.file_types:
|
||||
_metadata_writers[ft] = plugin
|
||||
|
||||
def get_file_type_metadata(stream, ftype):
|
||||
mi = MetaInformation(None, None)
|
||||
try:
|
||||
plugin = _metadata_readers[ftype.lower().strip()]
|
||||
if not is_disabled(plugin):
|
||||
mi = plugin.get_metadata(stream, ftype.lower().strip())
|
||||
except:
|
||||
pass
|
||||
return mi
|
||||
|
||||
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())
|
||||
except:
|
||||
traceback.print_exc()
|
||||
|
||||
def _run_filetype_plugins(path_to_file, ft=None, occasion='preprocess'):
|
||||
occasion = {'import':_on_import, 'preprocess':_on_preprocess,
|
||||
@ -184,6 +217,7 @@ def initialize_plugins():
|
||||
traceback.print_exc()
|
||||
_initialized_plugins.sort(cmp=lambda x,y:cmp(x.priority, y.priority), reverse=True)
|
||||
reread_filetype_plugins()
|
||||
reread_metadata_plugins()
|
||||
|
||||
initialize_plugins()
|
||||
|
||||
|
@ -5,30 +5,10 @@ __copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net>'
|
||||
import os, re, collections
|
||||
|
||||
from calibre.utils.config import prefs
|
||||
from calibre.ebooks.metadata.rtf import get_metadata as rtf_metadata
|
||||
from calibre.ebooks.metadata.fb2 import get_metadata as fb2_metadata
|
||||
from calibre.ebooks.lrf.meta import get_metadata as lrf_metadata
|
||||
from calibre.ebooks.metadata.pdf import get_metadata as pdf_metadata
|
||||
from calibre.ebooks.metadata.lit import get_metadata as lit_metadata
|
||||
from calibre.ebooks.metadata.imp import get_metadata as imp_metadata
|
||||
from calibre.ebooks.metadata.rb import get_metadata as rb_metadata
|
||||
from calibre.ebooks.metadata.epub import get_metadata as epub_metadata
|
||||
from calibre.ebooks.metadata.html import get_metadata as html_metadata
|
||||
from calibre.ebooks.mobi.reader import get_metadata as mobi_metadata
|
||||
from calibre.ebooks.metadata.odt import get_metadata as odt_metadata
|
||||
from calibre.ebooks.metadata.lrx import get_metadata as lrx_metadata
|
||||
|
||||
from calibre.ebooks.metadata.opf2 import OPF
|
||||
from calibre.ebooks.metadata.rtf import set_metadata as set_rtf_metadata
|
||||
from calibre.ebooks.lrf.meta import set_metadata as set_lrf_metadata
|
||||
from calibre.ebooks.metadata.epub import set_metadata as set_epub_metadata
|
||||
from calibre.ebooks.metadata.pdf import set_metadata as set_pdf_metadata
|
||||
try:
|
||||
from calibre.libunrar import extract_member as rar_extract_first
|
||||
except OSError:
|
||||
rar_extract_first = None
|
||||
|
||||
from calibre.libunzip import extract_member as zip_extract_first
|
||||
|
||||
from calibre.customize.ui import get_file_type_metadata, set_file_type_metadata
|
||||
from calibre.ebooks.metadata import MetaInformation
|
||||
|
||||
_METADATA_PRIORITIES = [
|
||||
@ -88,11 +68,7 @@ def get_metadata(stream, stream_type='lrf', use_libprs_metadata=False):
|
||||
|
||||
mi = MetaInformation(None, None)
|
||||
if prefs['read_file_metadata']:
|
||||
try:
|
||||
func = eval(stream_type + '_metadata')
|
||||
mi = func(stream)
|
||||
except NameError:
|
||||
pass
|
||||
mi = get_file_type_metadata(stream, stream_type)
|
||||
|
||||
name = os.path.basename(getattr(stream, 'name', ''))
|
||||
base = metadata_from_filename(name)
|
||||
@ -104,36 +80,13 @@ def get_metadata(stream, stream_type='lrf', use_libprs_metadata=False):
|
||||
if opf is not None:
|
||||
base.smart_update(opf)
|
||||
|
||||
if stream_type in ('cbr', 'cbz'):
|
||||
try:
|
||||
cdata = get_comic_cover(stream, stream_type)
|
||||
if cdata is not None:
|
||||
base.cover_data = cdata
|
||||
except:
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
pass
|
||||
|
||||
return base
|
||||
|
||||
def get_comic_cover(stream, type):
|
||||
extract_first = zip_extract_first if type.lower() == 'cbz' else rar_extract_first
|
||||
ret = extract_first(stream)
|
||||
if ret is not None:
|
||||
path, data = ret
|
||||
ext = os.path.splitext(path)[1][1:]
|
||||
return (ext.lower(), data)
|
||||
|
||||
def set_metadata(stream, mi, stream_type='lrf'):
|
||||
if stream_type: stream_type = stream_type.lower()
|
||||
if stream_type == 'lrf':
|
||||
set_lrf_metadata(stream, mi)
|
||||
elif stream_type == 'epub':
|
||||
set_epub_metadata(stream, mi)
|
||||
elif stream_type == 'rtf':
|
||||
set_rtf_metadata(stream, mi)
|
||||
#elif stream_type == 'pdf':
|
||||
# set_pdf_metadata(stream, mi)
|
||||
if stream_type:
|
||||
stream_type = stream_type.lower()
|
||||
set_file_type_metadata(stream, mi, stream_type)
|
||||
|
||||
|
||||
def metadata_from_filename(name, pat=None):
|
||||
name = os.path.splitext(name)[0]
|
||||
|
@ -103,7 +103,7 @@ class PluginModel(QAbstractItemModel):
|
||||
if role == Qt.DisplayRole:
|
||||
ver = '.'.join(map(str, plugin.version))
|
||||
desc = '\n'.join(textwrap.wrap(plugin.description, 50))
|
||||
ans='%s (%s) by %s\n%s'%(plugin.name, ver, plugin.author, desc)
|
||||
ans='%s (%s) %s %s\n%s'%(plugin.name, ver, _('by'), plugin.author, desc)
|
||||
c = plugin_customization(plugin)
|
||||
if c:
|
||||
ans += '\nCustomization: '+c
|
||||
|
@ -698,8 +698,6 @@ class Main(MainWindow, Ui_MainWindow):
|
||||
if d.exec_() == QDialog.Accepted:
|
||||
num = model.add_books(*duplicates, **dict(add_duplicates=True))[1]
|
||||
number_added += num
|
||||
#self.library_view.sortByColumn(3, Qt.DescendingOrder)
|
||||
#model.research()
|
||||
model.books_added(number_added)
|
||||
else:
|
||||
self.upload_books(paths, list(map(sanitize_file_name, names)), infos, on_card=on_card)
|
||||
|
Loading…
x
Reference in New Issue
Block a user