mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
...
This commit is contained in:
parent
c3e5c50f98
commit
a2187a86ac
@ -2,8 +2,14 @@ __license__ = 'GPL v3'
|
|||||||
__copyright__ = '2008, Kovid Goyal kovid@kovidgoyal.net'
|
__copyright__ = '2008, Kovid Goyal kovid@kovidgoyal.net'
|
||||||
__docformat__ = 'restructuredtext en'
|
__docformat__ = 'restructuredtext en'
|
||||||
__appname__ = 'calibre'
|
__appname__ = 'calibre'
|
||||||
__version__ = '0.5.14'
|
__version__ = '0.6.0b1'
|
||||||
__author__ = "Kovid Goyal <kovid@kovidgoyal.net>"
|
__author__ = "Kovid Goyal <kovid@kovidgoyal.net>"
|
||||||
|
|
||||||
|
import re
|
||||||
|
_ver = __version__.split('.')
|
||||||
|
_ver = [int(re.search(r'(\d+)', x).group(1)) for x in _ver]
|
||||||
|
numeric_version = tuple(_ver)
|
||||||
|
|
||||||
'''
|
'''
|
||||||
Various run time constants.
|
Various run time constants.
|
||||||
'''
|
'''
|
||||||
|
@ -5,58 +5,58 @@ __copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net>'
|
|||||||
import sys
|
import sys
|
||||||
|
|
||||||
from calibre.ptempfile import PersistentTemporaryFile
|
from calibre.ptempfile import PersistentTemporaryFile
|
||||||
from calibre.constants import __version__, __author__
|
from calibre.constants import numeric_version
|
||||||
|
|
||||||
class Plugin(object):
|
class Plugin(object):
|
||||||
'''
|
'''
|
||||||
A calibre plugin. Useful members include:
|
A calibre plugin. Useful members include:
|
||||||
|
|
||||||
* ``self.plugin_path``: Stores path to the zip file that contains
|
* ``self.plugin_path``: Stores path to the zip file that contains
|
||||||
this plugin or None if it is a builtin
|
this plugin or None if it is a builtin
|
||||||
plugin
|
plugin
|
||||||
* ``self.site_customization``: Stores a customization string entered
|
* ``self.site_customization``: Stores a customization string entered
|
||||||
by the user.
|
by the user.
|
||||||
|
|
||||||
Methods that should be overridden in sub classes:
|
Methods that should be overridden in sub classes:
|
||||||
|
|
||||||
* :meth:`initialize`
|
* :meth:`initialize`
|
||||||
* :meth:`customization_help`
|
* :meth:`customization_help`
|
||||||
|
|
||||||
Useful methods:
|
Useful methods:
|
||||||
|
|
||||||
* :meth:`temporary_file`
|
* :meth:`temporary_file`
|
||||||
|
|
||||||
'''
|
'''
|
||||||
#: List of platforms this plugin works on
|
#: List of platforms this plugin works on
|
||||||
#: For example: ``['windows', 'osx', 'linux']
|
#: For example: ``['windows', 'osx', 'linux']
|
||||||
supported_platforms = []
|
supported_platforms = []
|
||||||
|
|
||||||
#: The name of this plugin
|
#: The name of this plugin
|
||||||
name = 'Trivial Plugin'
|
name = 'Trivial Plugin'
|
||||||
|
|
||||||
#: The version of this plugin as a 3-tuple (major, minor, revision)
|
#: The version of this plugin as a 3-tuple (major, minor, revision)
|
||||||
version = (1, 0, 0)
|
version = (1, 0, 0)
|
||||||
|
|
||||||
#: A short string describing what this plugin does
|
#: A short string describing what this plugin does
|
||||||
description = _('Does absolutely nothing')
|
description = _('Does absolutely nothing')
|
||||||
|
|
||||||
#: The author of this plugin
|
#: The author of this plugin
|
||||||
author = _('Unknown')
|
author = _('Unknown')
|
||||||
|
|
||||||
#: When more than one plugin exists for a filetype,
|
#: When more than one plugin exists for a filetype,
|
||||||
#: the plugins are run in order of decreasing priority
|
#: the plugins are run in order of decreasing priority
|
||||||
#: i.e. plugins with higher priority will be run first.
|
#: i.e. plugins with higher priority will be run first.
|
||||||
#: The highest possible priority is ``sys.maxint``.
|
#: The highest possible priority is ``sys.maxint``.
|
||||||
#: Default pririty is 1.
|
#: Default pririty is 1.
|
||||||
priority = 1
|
priority = 1
|
||||||
|
|
||||||
#: The earliest version of calibre this plugin requires
|
#: The earliest version of calibre this plugin requires
|
||||||
minimum_calibre_version = (0, 4, 118)
|
minimum_calibre_version = (0, 4, 118)
|
||||||
|
|
||||||
#: If False, the user will not be able to disable this plugin. Use with
|
#: If False, the user will not be able to disable this plugin. Use with
|
||||||
#: care.
|
#: care.
|
||||||
can_be_disabled = True
|
can_be_disabled = True
|
||||||
|
|
||||||
#: The type of this plugin. Used for categorizing plugins in the
|
#: The type of this plugin. Used for categorizing plugins in the
|
||||||
#: GUI
|
#: GUI
|
||||||
type = _('Base')
|
type = _('Base')
|
||||||
@ -64,109 +64,109 @@ class Plugin(object):
|
|||||||
def __init__(self, plugin_path):
|
def __init__(self, plugin_path):
|
||||||
self.plugin_path = plugin_path
|
self.plugin_path = plugin_path
|
||||||
self.site_customization = None
|
self.site_customization = None
|
||||||
|
|
||||||
def initialize(self):
|
def initialize(self):
|
||||||
'''
|
'''
|
||||||
Called once when calibre plugins are initialized. Plugins are re-initialized
|
Called once when calibre plugins are initialized. Plugins are re-initialized
|
||||||
every time a new plugin is added.
|
every time a new plugin is added.
|
||||||
|
|
||||||
Perform any plugin specific initialization here, such as extracting
|
Perform any plugin specific initialization here, such as extracting
|
||||||
resources from the plugin zip file. The path to the zip file is
|
resources from the plugin zip file. The path to the zip file is
|
||||||
available as ``self.plugin_path``.
|
available as ``self.plugin_path``.
|
||||||
|
|
||||||
Note that ``self.site_customization`` is **not** available at this point.
|
Note that ``self.site_customization`` is **not** available at this point.
|
||||||
'''
|
'''
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def customization_help(self, gui=False):
|
def customization_help(self, gui=False):
|
||||||
'''
|
'''
|
||||||
Return a string giving help on how to customize this plugin.
|
Return a string giving help on how to customize this plugin.
|
||||||
By default raise a :class:`NotImplementedError`, which indicates that
|
By default raise a :class:`NotImplementedError`, which indicates that
|
||||||
the plugin does not require customization.
|
the plugin does not require customization.
|
||||||
|
|
||||||
If you re-implement this method in your subclass, the user will
|
If you re-implement this method in your subclass, the user will
|
||||||
be asked to enter a string as customization for this plugin.
|
be asked to enter a string as customization for this plugin.
|
||||||
The customization string will be available as
|
The customization string will be available as
|
||||||
``self.site_customization``.
|
``self.site_customization``.
|
||||||
|
|
||||||
Site customization could be anything, for example, the path to
|
Site customization could be anything, for example, the path to
|
||||||
a needed binary on the user's computer.
|
a needed binary on the user's computer.
|
||||||
|
|
||||||
:param gui: If True return HTML help, otherwise return plain text help.
|
:param gui: If True return HTML help, otherwise return plain text help.
|
||||||
|
|
||||||
'''
|
'''
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
def temporary_file(self, suffix):
|
def temporary_file(self, suffix):
|
||||||
'''
|
'''
|
||||||
Return a file-like object that is a temporary file on the file system.
|
Return a file-like object that is a temporary file on the file system.
|
||||||
This file will remain available even after being closed and will only
|
This file will remain available even after being closed and will only
|
||||||
be removed on interpreter shutdown. Use the ``name`` member of the
|
be removed on interpreter shutdown. Use the ``name`` member of the
|
||||||
returned object to access the full path to the created temporary file.
|
returned object to access the full path to the created temporary file.
|
||||||
|
|
||||||
:param suffix: The suffix that the temporary file will have.
|
:param suffix: The suffix that the temporary file will have.
|
||||||
'''
|
'''
|
||||||
return PersistentTemporaryFile(suffix)
|
return PersistentTemporaryFile(suffix)
|
||||||
|
|
||||||
def is_customizable(self):
|
def is_customizable(self):
|
||||||
try:
|
try:
|
||||||
self.customization_help()
|
self.customization_help()
|
||||||
return True
|
return True
|
||||||
except NotImplementedError:
|
except NotImplementedError:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def __enter__(self, *args):
|
def __enter__(self, *args):
|
||||||
if self.plugin_path is not None:
|
if self.plugin_path is not None:
|
||||||
sys.path.insert(0, self.plugin_path)
|
sys.path.insert(0, self.plugin_path)
|
||||||
|
|
||||||
def __exit__(self, *args):
|
def __exit__(self, *args):
|
||||||
if self.plugin_path in sys.path:
|
if self.plugin_path in sys.path:
|
||||||
sys.path.remove(self.plugin_path)
|
sys.path.remove(self.plugin_path)
|
||||||
|
|
||||||
|
|
||||||
class FileTypePlugin(Plugin):
|
class FileTypePlugin(Plugin):
|
||||||
'''
|
'''
|
||||||
A plugin that is associated with a particular set of file types.
|
A plugin that is associated with a particular set of file types.
|
||||||
'''
|
'''
|
||||||
|
|
||||||
#: Set 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'])``
|
#: For example: ``set(['lit', 'mobi', 'prc'])``
|
||||||
file_types = set([])
|
file_types = set([])
|
||||||
|
|
||||||
#: If True, this plugin is run when books are added
|
#: If True, this plugin is run when books are added
|
||||||
#: to the database
|
#: to the database
|
||||||
on_import = False
|
on_import = False
|
||||||
|
|
||||||
#: If True, this plugin is run whenever an any2* tool
|
#: If True, this plugin is run whenever an any2* tool
|
||||||
#: is used, on the file passed to the any2* tool.
|
#: is used, on the file passed to the any2* tool.
|
||||||
on_preprocess = False
|
on_preprocess = False
|
||||||
|
|
||||||
#: If True, this plugin is run after an any2* tool is
|
#: If True, this plugin is run after an any2* tool is
|
||||||
#: used, on the final file produced by the tool.
|
#: used, on the final file produced by the tool.
|
||||||
on_postprocess = False
|
on_postprocess = False
|
||||||
|
|
||||||
type = _('File type')
|
type = _('File type')
|
||||||
|
|
||||||
def run(self, path_to_ebook):
|
def run(self, path_to_ebook):
|
||||||
'''
|
'''
|
||||||
Run the plugin. Must be implemented in subclasses.
|
Run the plugin. Must be implemented in subclasses.
|
||||||
It should perform whatever modifications are required
|
It should perform whatever modifications are required
|
||||||
on the ebook and return the absolute path to the
|
on the ebook and return the absolute path to the
|
||||||
modified ebook. If no modifications are needed, it should
|
modified ebook. If no modifications are needed, it should
|
||||||
return the path to the original ebook. If an error is encountered
|
return the path to the original ebook. If an error is encountered
|
||||||
it should raise an Exception. The default implementation
|
it should raise an Exception. The default implementation
|
||||||
simply return the path to the original ebook.
|
simply return the path to the original ebook.
|
||||||
|
|
||||||
The modified ebook file should be created with the
|
The modified ebook file should be created with the
|
||||||
:meth:`temporary_file` method.
|
:meth:`temporary_file` method.
|
||||||
|
|
||||||
:param path_to_ebook: Absolute path to the ebook.
|
:param path_to_ebook: Absolute path to the ebook.
|
||||||
|
|
||||||
:return: Absolute path to the modified ebook.
|
:return: Absolute path to the modified ebook.
|
||||||
'''
|
'''
|
||||||
# Default implementation does nothing
|
# Default implementation does nothing
|
||||||
return path_to_ebook
|
return path_to_ebook
|
||||||
|
|
||||||
class MetadataReaderPlugin(Plugin):
|
class MetadataReaderPlugin(Plugin):
|
||||||
'''
|
'''
|
||||||
A plugin that implements reading metadata from a set of file types.
|
A plugin that implements reading metadata from a set of file types.
|
||||||
@ -174,26 +174,26 @@ class MetadataReaderPlugin(Plugin):
|
|||||||
#: Set 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'])``
|
#: For example: ``set(['lit', 'mobi', 'prc'])``
|
||||||
file_types = set([])
|
file_types = set([])
|
||||||
|
|
||||||
supported_platforms = ['windows', 'osx', 'linux']
|
supported_platforms = ['windows', 'osx', 'linux']
|
||||||
version = tuple(map(int, (__version__.split('.'))[:3]))
|
version = numeric_version
|
||||||
author = 'Kovid Goyal'
|
author = 'Kovid Goyal'
|
||||||
|
|
||||||
type = _('Metadata reader')
|
type = _('Metadata reader')
|
||||||
|
|
||||||
def get_metadata(self, stream, type):
|
def get_metadata(self, stream, type):
|
||||||
'''
|
'''
|
||||||
Return metadata for the file represented by stream (a file like object
|
Return metadata for the file represented by stream (a file like object
|
||||||
that supports reading). Raise an exception when there is an error
|
that supports reading). Raise an exception when there is an error
|
||||||
with the input data.
|
with the input data.
|
||||||
|
|
||||||
:param type: The type of file. Guaranteed to be one of the entries
|
:param type: The type of file. Guaranteed to be one of the entries
|
||||||
in :attr:`file_types`.
|
in :attr:`file_types`.
|
||||||
|
|
||||||
:return: A :class:`calibre.ebooks.metadata.MetaInformation` object
|
:return: A :class:`calibre.ebooks.metadata.MetaInformation` object
|
||||||
'''
|
'''
|
||||||
return None
|
return None
|
||||||
|
|
||||||
class MetadataWriterPlugin(Plugin):
|
class MetadataWriterPlugin(Plugin):
|
||||||
'''
|
'''
|
||||||
A plugin that implements reading metadata from a set of file types.
|
A plugin that implements reading metadata from a set of file types.
|
||||||
@ -201,24 +201,24 @@ class MetadataWriterPlugin(Plugin):
|
|||||||
#: Set 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'])``
|
#: For example: ``set(['lit', 'mobi', 'prc'])``
|
||||||
file_types = set([])
|
file_types = set([])
|
||||||
|
|
||||||
supported_platforms = ['windows', 'osx', 'linux']
|
supported_platforms = ['windows', 'osx', 'linux']
|
||||||
version = tuple(map(int, (__version__.split('.'))[:3]))
|
version = numeric_version
|
||||||
author = 'Kovid Goyal'
|
author = 'Kovid Goyal'
|
||||||
|
|
||||||
type = _('Metadata writer')
|
type = _('Metadata writer')
|
||||||
|
|
||||||
def set_metadata(self, stream, mi, type):
|
def set_metadata(self, stream, mi, type):
|
||||||
'''
|
'''
|
||||||
Set metadata for the file represented by stream (a file like object
|
Set metadata for the file represented by stream (a file like object
|
||||||
that supports reading). Raise an exception when there is an error
|
that supports reading). Raise an exception when there is an error
|
||||||
with the input data.
|
with the input data.
|
||||||
|
|
||||||
:param type: The type of file. Guaranteed to be one of the entries
|
:param type: The type of file. Guaranteed to be one of the entries
|
||||||
in :attr:`file_types`.
|
in :attr:`file_types`.
|
||||||
:param mi: A :class:`calibre.ebooks.metadata.MetaInformation` object
|
:param mi: A :class:`calibre.ebooks.metadata.MetaInformation` object
|
||||||
|
|
||||||
'''
|
'''
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@ import textwrap
|
|||||||
import os
|
import os
|
||||||
import glob
|
import glob
|
||||||
from calibre.customize import FileTypePlugin, MetadataReaderPlugin, MetadataWriterPlugin
|
from calibre.customize import FileTypePlugin, MetadataReaderPlugin, MetadataWriterPlugin
|
||||||
from calibre.constants import __version__
|
from calibre.constants import numeric_version
|
||||||
|
|
||||||
class HTML2ZIP(FileTypePlugin):
|
class HTML2ZIP(FileTypePlugin):
|
||||||
name = 'HTML to ZIP'
|
name = 'HTML to ZIP'
|
||||||
@ -15,7 +15,7 @@ Follow all local links in an HTML file and create a ZIP \
|
|||||||
file containing all linked files. This plugin is run \
|
file containing all linked files. This plugin is run \
|
||||||
every time you add an HTML file to the library.\
|
every time you add an HTML file to the library.\
|
||||||
'''))
|
'''))
|
||||||
version = tuple(map(int, (__version__.split('.'))[:3]))
|
version = numeric_version
|
||||||
file_types = set(['html', 'htm', 'xhtml', 'xhtm'])
|
file_types = set(['html', 'htm', 'xhtml', 'xhtm'])
|
||||||
supported_platforms = ['windows', 'osx', 'linux']
|
supported_platforms = ['windows', 'osx', 'linux']
|
||||||
on_import = True
|
on_import = True
|
||||||
|
@ -9,13 +9,12 @@ from calibre.customize import Plugin, FileTypePlugin, MetadataReaderPlugin, \
|
|||||||
from calibre.customize.conversion import InputFormatPlugin, OutputFormatPlugin
|
from calibre.customize.conversion import InputFormatPlugin, OutputFormatPlugin
|
||||||
from calibre.customize.profiles import InputProfile, OutputProfile
|
from calibre.customize.profiles import InputProfile, OutputProfile
|
||||||
from calibre.customize.builtins import plugins as builtin_plugins
|
from calibre.customize.builtins import plugins as builtin_plugins
|
||||||
from calibre.constants import __version__, iswindows, isosx
|
from calibre.constants import numeric_version as version, iswindows, isosx
|
||||||
from calibre.devices.interface import DevicePlugin
|
from calibre.devices.interface import DevicePlugin
|
||||||
from calibre.ebooks.metadata import MetaInformation
|
from calibre.ebooks.metadata import MetaInformation
|
||||||
from calibre.utils.config import make_config_dir, Config, ConfigProxy, \
|
from calibre.utils.config import make_config_dir, Config, ConfigProxy, \
|
||||||
plugin_dir, OptionParser
|
plugin_dir, OptionParser
|
||||||
|
|
||||||
version = tuple([int(x) for x in __version__.split('.')])
|
|
||||||
|
|
||||||
platform = 'linux'
|
platform = 'linux'
|
||||||
if iswindows:
|
if iswindows:
|
||||||
|
@ -653,8 +653,9 @@ class MobiWriter(object):
|
|||||||
def _generate_end_records(self):
|
def _generate_end_records(self):
|
||||||
self._flis_number = len(self._records)
|
self._flis_number = len(self._records)
|
||||||
self._records.append(
|
self._records.append(
|
||||||
'FLIS\0\0\0\x08\0\x41\0\0\0\0\0\0\xff\xff\xff\xff\0\x01\0\x03\0\0\0\x03\0\0\0\x01')
|
'FLIS\0\0\0\x08\0\x41\0\0\0\0\0\0\xff\xff\xff\xff\0\x01\0\x03\0\0\0\x03\0\0\0\x01'+
|
||||||
fcis = 'FCIS\x00\x00\x00\x14\x00\x00\x00\x10\x00\x00\x00\x00'
|
'\xff'*4)
|
||||||
|
fcis = 'FCIS\x00\x00\x00\x14\x00\x00\x00\x10\x00\x00\x00\x01\x00\x00\x00\x00'
|
||||||
fcis += pack('>I', self._text_length)
|
fcis += pack('>I', self._text_length)
|
||||||
fcis += '\x00\x00\x00\x00\x00\x00\x00\x20\x00\x00\x00\x08\x00\x01\x00\x01\x00\x00\x00\x00'
|
fcis += '\x00\x00\x00\x00\x00\x00\x00\x20\x00\x00\x00\x08\x00\x01\x00\x01\x00\x00\x00\x00'
|
||||||
self._fcis_number = len(self._records)
|
self._fcis_number = len(self._records)
|
||||||
|
10
upload.py
10
upload.py
@ -17,6 +17,7 @@ __appname__ = re.search(r'__appname__\s+=\s+[\'"]([^\'"]+)[\'"]', raw).group(1)
|
|||||||
|
|
||||||
PREFIX = "/var/www/calibre.kovidgoyal.net"
|
PREFIX = "/var/www/calibre.kovidgoyal.net"
|
||||||
DOWNLOADS = PREFIX+"/htdocs/downloads"
|
DOWNLOADS = PREFIX+"/htdocs/downloads"
|
||||||
|
BETAS = DOWNLOADS +'/betas'
|
||||||
DOCS = PREFIX+"/htdocs/apidocs"
|
DOCS = PREFIX+"/htdocs/apidocs"
|
||||||
USER_MANUAL = PREFIX+'/htdocs/user_manual'
|
USER_MANUAL = PREFIX+'/htdocs/user_manual'
|
||||||
HTML2LRF = "src/calibre/ebooks/lrf/html/demo"
|
HTML2LRF = "src/calibre/ebooks/lrf/html/demo"
|
||||||
@ -429,8 +430,9 @@ class upload_demo(OptionlessCommand):
|
|||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
check_call(
|
check_call(
|
||||||
'''html2lrf --title='Demonstration of html2lrf' --author='Kovid Goyal' '''
|
'''ebook-convert %s/demo.html /tmp/html2lrf.lrf '''
|
||||||
'''--header --output=/tmp/html2lrf.lrf %s/demo.html '''
|
'''--title='Demonstration of html2lrf' --author='Kovid Goyal' '''
|
||||||
|
'''--header '''
|
||||||
'''--serif-family "/usr/share/fonts/corefonts, Times New Roman" '''
|
'''--serif-family "/usr/share/fonts/corefonts, Times New Roman" '''
|
||||||
'''--mono-family "/usr/share/fonts/corefonts, Andale Mono" '''
|
'''--mono-family "/usr/share/fonts/corefonts, Andale Mono" '''
|
||||||
''''''%(HTML2LRF,), shell=True)
|
''''''%(HTML2LRF,), shell=True)
|
||||||
@ -442,8 +444,8 @@ class upload_demo(OptionlessCommand):
|
|||||||
check_call('scp /tmp/html-demo.zip divok:%s/'%(DOWNLOADS,), shell=True)
|
check_call('scp /tmp/html-demo.zip divok:%s/'%(DOWNLOADS,), shell=True)
|
||||||
|
|
||||||
check_call(
|
check_call(
|
||||||
'''txt2lrf -t 'Demonstration of txt2lrf' -a 'Kovid Goyal' '''
|
("ebook-convert %s/demo.txt /tmp/txt2lrf.lrf -t 'Demonstration of txt2lrf'"
|
||||||
'''--header -o /tmp/txt2lrf.lrf %s/demo.txt'''%(TXT2LRF,), shell=True)
|
"-a 'Kovid Goyal' --header ")%(TXT2LRF,), shell=True)
|
||||||
|
|
||||||
check_call('cd src/calibre/ebooks/lrf/txt/demo/ && '
|
check_call('cd src/calibre/ebooks/lrf/txt/demo/ && '
|
||||||
'zip -j /tmp/txt-demo.zip * /tmp/txt2lrf.lrf', shell=True)
|
'zip -j /tmp/txt-demo.zip * /tmp/txt2lrf.lrf', shell=True)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user