mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-08-07 09:01:38 -04:00
Allow importing calibre extension modules using import statements
from calibre_extensions import speedup
This commit is contained in:
parent
cc665e1ce5
commit
6690187e0a
@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
# vim:fileencoding=utf-8
|
# vim:fileencoding=utf-8
|
||||||
# License: GPLv3 Copyright: 2015, Kovid Goyal <kovid at kovidgoyal.net>
|
# License: GPLv3 Copyright: 2015, Kovid Goyal <kovid at kovidgoyal.net>
|
||||||
from polyglot.builtins import map, unicode_type, environ_item, hasenv, getenv, as_unicode, native_string_type
|
from polyglot.builtins import map, unicode_type, environ_item, hasenv, getenv
|
||||||
import sys, locale, codecs, os, importlib, collections
|
import sys, locale, codecs, os, importlib, collections
|
||||||
|
|
||||||
__appname__ = 'calibre'
|
__appname__ = 'calibre'
|
||||||
@ -177,76 +177,32 @@ plugins_loc = sys.extensions_location
|
|||||||
|
|
||||||
class Plugins(collections.Mapping):
|
class Plugins(collections.Mapping):
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
self._plugins = {}
|
|
||||||
plugins = [
|
|
||||||
'pictureflow',
|
|
||||||
'lzx',
|
|
||||||
'msdes',
|
|
||||||
'podofo',
|
|
||||||
'cPalmdoc',
|
|
||||||
'progress_indicator',
|
|
||||||
'icu',
|
|
||||||
'speedup',
|
|
||||||
'html_as_json',
|
|
||||||
'unicode_names',
|
|
||||||
'html_syntax_highlighter',
|
|
||||||
'hyphen',
|
|
||||||
'freetype',
|
|
||||||
'imageops',
|
|
||||||
'hunspell',
|
|
||||||
'_patiencediff_c',
|
|
||||||
'bzzdec',
|
|
||||||
'matcher',
|
|
||||||
'tokenizer',
|
|
||||||
'certgen',
|
|
||||||
]
|
|
||||||
if iswindows:
|
|
||||||
plugins.extend(['winutil', 'wpd', 'winfonts'])
|
|
||||||
if ismacos:
|
|
||||||
plugins.append('usbobserver')
|
|
||||||
plugins.append('cocoa')
|
|
||||||
if isfreebsd or ishaiku or islinux or ismacos:
|
|
||||||
plugins.append('libusb')
|
|
||||||
plugins.append('libmtp')
|
|
||||||
self.plugins = frozenset(plugins)
|
|
||||||
|
|
||||||
def load_plugin(self, name):
|
|
||||||
if name in self._plugins:
|
|
||||||
return
|
|
||||||
if not isfrozen:
|
|
||||||
sys.path.insert(0, plugins_loc)
|
|
||||||
try:
|
|
||||||
del sys.modules[name]
|
|
||||||
except KeyError:
|
|
||||||
pass
|
|
||||||
plugin_err = ''
|
|
||||||
try:
|
|
||||||
p = importlib.import_module(name)
|
|
||||||
except Exception as err:
|
|
||||||
p = None
|
|
||||||
try:
|
|
||||||
plugin_err = unicode_type(err)
|
|
||||||
except Exception:
|
|
||||||
plugin_err = as_unicode(native_string_type(err), encoding=preferred_encoding, errors='replace')
|
|
||||||
self._plugins[name] = p, plugin_err
|
|
||||||
if not isfrozen:
|
|
||||||
sys.path.remove(plugins_loc)
|
|
||||||
|
|
||||||
def __iter__(self):
|
def __iter__(self):
|
||||||
return iter(self.plugins)
|
from importlib.resources import contents
|
||||||
|
return contents('calibre_extensions')
|
||||||
|
|
||||||
def __len__(self):
|
def __len__(self):
|
||||||
return len(self.plugins)
|
from importlib.resources import contents
|
||||||
|
ans = 0
|
||||||
|
for x in contents('calibre_extensions'):
|
||||||
|
ans += 1
|
||||||
|
return ans
|
||||||
|
|
||||||
def __contains__(self, name):
|
def __contains__(self, name):
|
||||||
return name in self.plugins
|
from importlib.resources import contents
|
||||||
|
for x in contents('calibre_extensions'):
|
||||||
|
if x == name:
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
def __getitem__(self, name):
|
def __getitem__(self, name):
|
||||||
if name not in self.plugins:
|
from importlib import import_module
|
||||||
|
try:
|
||||||
|
return import_module('calibre_extensions.' + name), None
|
||||||
|
except ModuleNotFoundError:
|
||||||
raise KeyError('No plugin named %r'%name)
|
raise KeyError('No plugin named %r'%name)
|
||||||
self.load_plugin(name)
|
except Exception as err:
|
||||||
return self._plugins[name]
|
return None, str(err)
|
||||||
|
|
||||||
|
|
||||||
plugins = None
|
plugins = None
|
||||||
|
@ -21,7 +21,7 @@ builtins.__dict__['__'] = lambda s: s
|
|||||||
builtins.__dict__['dynamic_property'] = lambda func: func(None)
|
builtins.__dict__['dynamic_property'] = lambda func: func(None)
|
||||||
|
|
||||||
|
|
||||||
from calibre.constants import iswindows, preferred_encoding, plugins, ismacos, islinux, DEBUG, isfreebsd
|
from calibre.constants import iswindows, preferred_encoding, plugins, ismacos, islinux, ishaiku, DEBUG, isfreebsd, plugins_loc
|
||||||
|
|
||||||
_run_once = False
|
_run_once = False
|
||||||
winutil = winutilerror = None
|
winutil = winutilerror = None
|
||||||
@ -49,7 +49,7 @@ def get_debug_executable():
|
|||||||
|
|
||||||
if not _run_once:
|
if not _run_once:
|
||||||
_run_once = True
|
_run_once = True
|
||||||
from importlib.machinery import ModuleSpec
|
from importlib.machinery import ModuleSpec, EXTENSION_SUFFIXES, ExtensionFileLoader
|
||||||
from importlib.util import find_spec
|
from importlib.util import find_spec
|
||||||
from importlib import import_module
|
from importlib import import_module
|
||||||
|
|
||||||
@ -81,6 +81,89 @@ if not _run_once:
|
|||||||
|
|
||||||
sys.meta_path.insert(0, DeVendor())
|
sys.meta_path.insert(0, DeVendor())
|
||||||
|
|
||||||
|
class ExtensionsPackageLoader:
|
||||||
|
|
||||||
|
def __init__(self, calibre_extensions):
|
||||||
|
self.calibre_extensions = calibre_extensions
|
||||||
|
|
||||||
|
def is_package(self, fullname=None):
|
||||||
|
return True
|
||||||
|
|
||||||
|
def get_resource_reader(self, fullname=None):
|
||||||
|
return self
|
||||||
|
|
||||||
|
def get_source(self, fullname=None):
|
||||||
|
return ''
|
||||||
|
|
||||||
|
def contents(self):
|
||||||
|
return iter(self.calibre_extensions)
|
||||||
|
|
||||||
|
def create_module(self, spec):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def exec_module(self, spec):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class ExtensionsImporter:
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
extensions = (
|
||||||
|
'pictureflow',
|
||||||
|
'lzx',
|
||||||
|
'msdes',
|
||||||
|
'podofo',
|
||||||
|
'cPalmdoc',
|
||||||
|
'progress_indicator',
|
||||||
|
'icu',
|
||||||
|
'speedup',
|
||||||
|
'html_as_json',
|
||||||
|
'unicode_names',
|
||||||
|
'html_syntax_highlighter',
|
||||||
|
'hyphen',
|
||||||
|
'freetype',
|
||||||
|
'imageops',
|
||||||
|
'hunspell',
|
||||||
|
'_patiencediff_c',
|
||||||
|
'bzzdec',
|
||||||
|
'matcher',
|
||||||
|
'tokenizer',
|
||||||
|
'certgen',
|
||||||
|
)
|
||||||
|
if iswindows:
|
||||||
|
extra = ('winutil', 'wpd', 'winfonts')
|
||||||
|
elif ismacos:
|
||||||
|
extra = ('usbobserver', 'cocoa')
|
||||||
|
elif isfreebsd or ishaiku or islinux or ismacos:
|
||||||
|
extra = ('libusb', 'libmtp')
|
||||||
|
else:
|
||||||
|
extra = ()
|
||||||
|
self.calibre_extensions = frozenset(extensions + extra)
|
||||||
|
|
||||||
|
def find_spec(self, fullname, path=None, target=None):
|
||||||
|
if not fullname.startswith('calibre_extensions'):
|
||||||
|
return
|
||||||
|
parts = fullname.split('.')
|
||||||
|
if parts[0] != 'calibre_extensions':
|
||||||
|
return
|
||||||
|
if len(parts) > 2:
|
||||||
|
return
|
||||||
|
is_package = len(parts) == 1
|
||||||
|
extension_name = None if is_package else parts[1]
|
||||||
|
path = os.path.join(plugins_loc, '__init__.py')
|
||||||
|
if extension_name:
|
||||||
|
if extension_name not in self.calibre_extensions:
|
||||||
|
return
|
||||||
|
for suffix in EXTENSION_SUFFIXES:
|
||||||
|
path = os.path.join(plugins_loc, extension_name + suffix)
|
||||||
|
if os.path.exists(path):
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
return
|
||||||
|
return ModuleSpec(fullname, ExtensionFileLoader(fullname, path), is_package=is_package, origin=path)
|
||||||
|
return ModuleSpec(fullname, ExtensionsPackageLoader(self.calibre_extensions), is_package=is_package, origin=path)
|
||||||
|
|
||||||
|
sys.meta_path.append(ExtensionsImporter())
|
||||||
|
|
||||||
# Ensure that all temp files/dirs are created under a calibre tmp dir
|
# Ensure that all temp files/dirs are created under a calibre tmp dir
|
||||||
from calibre.ptempfile import base_dir
|
from calibre.ptempfile import base_dir
|
||||||
try:
|
try:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user