mirror of
https://github.com/gryf/ebook-converter.git
synced 2026-03-06 01:05:52 +01:00
Removed prints and extract function from init module
This commit is contained in:
@@ -14,9 +14,7 @@ from ebook_converter.constants_old import islinux, isfrozen, \
|
|||||||
isbsd, __appname__, __version__, __author__, \
|
isbsd, __appname__, __version__, __author__, \
|
||||||
config_dir
|
config_dir
|
||||||
from ebook_converter.ebooks.html_entities import html5_entities
|
from ebook_converter.ebooks.html_entities import html5_entities
|
||||||
from ebook_converter.libunzip import extract as zipextract
|
|
||||||
from ebook_converter.startup import winutil, winutilerror
|
from ebook_converter.startup import winutil, winutilerror
|
||||||
from ebook_converter.utils.unrar import extract as rarextract
|
|
||||||
|
|
||||||
|
|
||||||
if False:
|
if False:
|
||||||
@@ -72,45 +70,6 @@ def sanitize_file_name(name, substitute='_'):
|
|||||||
return one
|
return one
|
||||||
|
|
||||||
|
|
||||||
def prints(*args, **kwargs):
|
|
||||||
"""
|
|
||||||
Print unicode arguments safely by encoding them to preferred_encoding
|
|
||||||
Has the same signature as the print function from Python 3, except for the
|
|
||||||
additional keyword argument safe_encode, which if set to True will cause
|
|
||||||
the function to use repr when encoding fails.
|
|
||||||
|
|
||||||
Returns the number of bytes written.
|
|
||||||
"""
|
|
||||||
fobj = kwargs.get('file', sys.stdout)
|
|
||||||
enc = ('utf-8' if os.getenv('CALIBRE_WORKER')
|
|
||||||
else constants_old.preferred_encoding)
|
|
||||||
sep = kwargs.get('sep', ' ')
|
|
||||||
if isinstance(sep, bytes):
|
|
||||||
sep = sep.decode(enc)
|
|
||||||
end = kwargs.get('end', '\n')
|
|
||||||
if isinstance(end, bytes):
|
|
||||||
end = end.decode(enc)
|
|
||||||
count = 0
|
|
||||||
|
|
||||||
for i, arg in enumerate(args):
|
|
||||||
if isinstance(arg, bytes):
|
|
||||||
arg = arg.decode(enc)
|
|
||||||
arg = repr(arg)
|
|
||||||
try:
|
|
||||||
fobj.write(arg)
|
|
||||||
count += len(arg)
|
|
||||||
except Exception:
|
|
||||||
arg = repr(arg)
|
|
||||||
fobj.write(arg)
|
|
||||||
count += len(arg)
|
|
||||||
if i != len(args)-1:
|
|
||||||
fobj.write(sep)
|
|
||||||
count += len(sep)
|
|
||||||
fobj.write(end)
|
|
||||||
count += len(end)
|
|
||||||
return count
|
|
||||||
|
|
||||||
|
|
||||||
def setup_cli_handlers(logger, level):
|
def setup_cli_handlers(logger, level):
|
||||||
if os.getenv('CALIBRE_WORKER') and logger.handlers:
|
if os.getenv('CALIBRE_WORKER') and logger.handlers:
|
||||||
return
|
return
|
||||||
@@ -132,27 +91,6 @@ def setup_cli_handlers(logger, level):
|
|||||||
logger.addHandler(handler)
|
logger.addHandler(handler)
|
||||||
|
|
||||||
|
|
||||||
def extract(path, dir):
|
|
||||||
extractor = None
|
|
||||||
# First use the file header to identify its type
|
|
||||||
with open(path, 'rb') as f:
|
|
||||||
id_ = f.read(3)
|
|
||||||
if id_ == b'Rar':
|
|
||||||
extractor = rarextract
|
|
||||||
elif id_.startswith(b'PK'):
|
|
||||||
extractor = zipextract
|
|
||||||
if extractor is None:
|
|
||||||
# Fallback to file extension
|
|
||||||
ext = os.path.splitext(path)[1][1:].lower()
|
|
||||||
if ext in ['zip', 'cbz', 'epub', 'oebzip']:
|
|
||||||
extractor = zipextract
|
|
||||||
elif ext in ['cbr', 'rar']:
|
|
||||||
extractor = rarextract
|
|
||||||
if extractor is None:
|
|
||||||
raise Exception('Unknown archive type')
|
|
||||||
extractor(path, dir)
|
|
||||||
|
|
||||||
|
|
||||||
def fit_image(width, height, pwidth, pheight):
|
def fit_image(width, height, pwidth, pheight):
|
||||||
"""
|
"""
|
||||||
Fit image in box of width pwidth and height pheight.
|
Fit image in box of width pwidth and height pheight.
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ from ebook_converter.customize import profiles
|
|||||||
from ebook_converter.customize import builtins
|
from ebook_converter.customize import builtins
|
||||||
from ebook_converter.ebooks import metadata
|
from ebook_converter.ebooks import metadata
|
||||||
from ebook_converter.utils import config as cfg
|
from ebook_converter.utils import config as cfg
|
||||||
from ebook_converter import prints
|
|
||||||
|
|
||||||
|
|
||||||
builtin_names = frozenset(p.name for p in builtins.plugins)
|
builtin_names = frozenset(p.name for p in builtins.plugins)
|
||||||
@@ -349,9 +348,8 @@ def set_file_type_metadata(stream, mi, ftype, report_error=None):
|
|||||||
break
|
break
|
||||||
except Exception:
|
except Exception:
|
||||||
if report_error is None:
|
if report_error is None:
|
||||||
prints('Failed to set metadata for the', ftype.upper(),
|
print('Failed to set metadata for the', ftype.upper(),
|
||||||
'format of:', getattr(mi, 'title', ''),
|
'format of:', getattr(mi, 'title', ''))
|
||||||
file=sys.stderr)
|
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
else:
|
else:
|
||||||
report_error(mi, ftype, traceback.format_exc())
|
report_error(mi, ftype, traceback.format_exc())
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import os
|
import os
|
||||||
from collections import namedtuple
|
from collections import namedtuple
|
||||||
|
|
||||||
from ebook_converter import prints
|
|
||||||
from ebook_converter.customize import Plugin
|
from ebook_converter.customize import Plugin
|
||||||
|
|
||||||
|
|
||||||
@@ -170,7 +169,7 @@ class DevicePlugin(Plugin):
|
|||||||
cbcd = self.BCD
|
cbcd = self.BCD
|
||||||
if self.test_bcd(bcd, cbcd):
|
if self.test_bcd(bcd, cbcd):
|
||||||
if debug:
|
if debug:
|
||||||
prints(dev)
|
print(dev)
|
||||||
if ch(dev, debug=debug):
|
if ch(dev, debug=debug):
|
||||||
return True, dev
|
return True, dev
|
||||||
return False, None
|
return False, None
|
||||||
|
|||||||
@@ -5,11 +5,9 @@ from various formats.
|
|||||||
import numbers
|
import numbers
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
import sys
|
|
||||||
|
|
||||||
from lxml import etree
|
from lxml import etree
|
||||||
|
|
||||||
from ebook_converter import prints
|
|
||||||
from ebook_converter.ebooks.chardet import xml_to_unicode
|
from ebook_converter.ebooks.chardet import xml_to_unicode
|
||||||
|
|
||||||
|
|
||||||
@@ -123,13 +121,14 @@ def render_html_data(path_to_html, width, height):
|
|||||||
result = {}
|
result = {}
|
||||||
|
|
||||||
def report_error(text=''):
|
def report_error(text=''):
|
||||||
prints('Failed to render', path_to_html, 'with errors:',
|
__import__('pdb').set_trace()
|
||||||
file=sys.stderr)
|
print(f'Failed to render {path_to_html}')
|
||||||
|
# file=sys.stderr)
|
||||||
if text:
|
if text:
|
||||||
prints(text, file=sys.stderr)
|
print(text) # , file=sys.stderr)
|
||||||
if result and result['stdout_stderr']:
|
if result and result['stdout_stderr']:
|
||||||
with open(result['stdout_stderr'], 'rb') as f:
|
with open(result['stdout_stderr'], 'rb') as f:
|
||||||
prints(f.read(), file=sys.stderr)
|
print(f.read()) # , file=sys.stderr)
|
||||||
|
|
||||||
with TemporaryDirectory('-render-html') as tdir:
|
with TemporaryDirectory('-render-html') as tdir:
|
||||||
try:
|
try:
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ from ebook_converter.ebooks.conversion.preprocess import HTMLPreProcessor
|
|||||||
from ebook_converter.ptempfile import PersistentTemporaryDirectory
|
from ebook_converter.ptempfile import PersistentTemporaryDirectory
|
||||||
from ebook_converter.utils.date import parse_date
|
from ebook_converter.utils.date import parse_date
|
||||||
from ebook_converter.utils.zipfile import ZipFile
|
from ebook_converter.utils.zipfile import ZipFile
|
||||||
from ebook_converter import extract, walk
|
|
||||||
from ebook_converter import constants
|
from ebook_converter import constants
|
||||||
from ebook_converter.constants_old import filesystem_encoding
|
from ebook_converter.constants_old import filesystem_encoding
|
||||||
|
|
||||||
@@ -694,11 +693,6 @@ OptionRecommendation(name='search_replace',
|
|||||||
input_fmt = 'epub'
|
input_fmt = 'epub'
|
||||||
self.archive_input_tdir = None
|
self.archive_input_tdir = None
|
||||||
self.changed_options = set()
|
self.changed_options = set()
|
||||||
if input_fmt in ARCHIVE_FMTS:
|
|
||||||
self.log('Processing archive...')
|
|
||||||
tdir = PersistentTemporaryDirectory('_pl_arc')
|
|
||||||
self.input, input_fmt = self.unarchive(self.input, tdir)
|
|
||||||
self.archive_input_tdir = tdir
|
|
||||||
if os.access(self.input, os.R_OK):
|
if os.access(self.input, os.R_OK):
|
||||||
nfp = run_plugins_on_preprocess(self.input, input_fmt)
|
nfp = run_plugins_on_preprocess(self.input, input_fmt)
|
||||||
if nfp != self.input:
|
if nfp != self.input:
|
||||||
@@ -761,25 +755,6 @@ OptionRecommendation(name='search_replace',
|
|||||||
if merge_plugin_recs:
|
if merge_plugin_recs:
|
||||||
self.merge_plugin_recommendations()
|
self.merge_plugin_recommendations()
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def unarchive(self, path, tdir):
|
|
||||||
extract(path, tdir)
|
|
||||||
files = list(walk(tdir))
|
|
||||||
files = [f if isinstance(f, str) else f.decode(filesystem_encoding)
|
|
||||||
for f in files]
|
|
||||||
from ebook_converter.customize.ui import available_input_formats
|
|
||||||
fmts = set(available_input_formats())
|
|
||||||
fmts -= {'htm', 'html', 'xhtm', 'xhtml'}
|
|
||||||
fmts -= set(ARCHIVE_FMTS)
|
|
||||||
|
|
||||||
for ext in fmts:
|
|
||||||
for f in files:
|
|
||||||
if f.lower().endswith('.'+ext):
|
|
||||||
if ext in ['txt', 'rtf'] and os.stat(f).st_size < 2048:
|
|
||||||
continue
|
|
||||||
return f, ext
|
|
||||||
return self.find_html_index(files)
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def find_html_index(self, files):
|
def find_html_index(self, files):
|
||||||
'''
|
'''
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import sys
|
|||||||
import urllib.parse
|
import urllib.parse
|
||||||
|
|
||||||
from ebook_converter.ebooks.chardet import detect_xml_encoding
|
from ebook_converter.ebooks.chardet import detect_xml_encoding
|
||||||
from ebook_converter import unicode_path, replace_entities
|
from ebook_converter import replace_entities
|
||||||
|
|
||||||
|
|
||||||
class Link(object):
|
class Link(object):
|
||||||
|
|||||||
@@ -24,7 +24,6 @@ class HTML2ZIP(FileTypePlugin):
|
|||||||
|
|
||||||
def run(self, htmlfile):
|
def run(self, htmlfile):
|
||||||
import codecs
|
import codecs
|
||||||
from ebook_converter import prints
|
|
||||||
from ebook_converter.ptempfile import TemporaryDirectory
|
from ebook_converter.ptempfile import TemporaryDirectory
|
||||||
from ebook_converter.gui2.convert.gui_conversion import gui_convert
|
from ebook_converter.gui2.convert.gui_conversion import gui_convert
|
||||||
from ebook_converter.customize.conversion import OptionRecommendation
|
from ebook_converter.customize.conversion import OptionRecommendation
|
||||||
@@ -40,7 +39,8 @@ class HTML2ZIP(FileTypePlugin):
|
|||||||
try:
|
try:
|
||||||
codecs.lookup(enc)
|
codecs.lookup(enc)
|
||||||
except Exception:
|
except Exception:
|
||||||
prints('Ignoring invalid input encoding for HTML:', enc)
|
print('Ignoring invalid input encoding for HTML: %s',
|
||||||
|
enc)
|
||||||
else:
|
else:
|
||||||
recs.append(['input_encoding', enc, OptionRecommendation.HIGH])
|
recs.append(['input_encoding', enc, OptionRecommendation.HIGH])
|
||||||
if bf == 'bf':
|
if bf == 'bf':
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import re
|
|||||||
import sys
|
import sys
|
||||||
import urllib.parse
|
import urllib.parse
|
||||||
|
|
||||||
from ebook_converter import prints, force_unicode
|
from ebook_converter import force_unicode
|
||||||
from ebook_converter.utils.config_base import tweaks
|
from ebook_converter.utils.config_base import tweaks
|
||||||
from ebook_converter.polyglot.urllib import unquote
|
from ebook_converter.polyglot.urllib import unquote
|
||||||
|
|
||||||
@@ -16,8 +16,8 @@ from ebook_converter.polyglot.urllib import unquote
|
|||||||
try:
|
try:
|
||||||
_author_pat = re.compile(tweaks['authors_split_regex'])
|
_author_pat = re.compile(tweaks['authors_split_regex'])
|
||||||
except Exception:
|
except Exception:
|
||||||
prints('Author split regexp:', tweaks['authors_split_regex'],
|
print(f"Author split regexp: {tweaks['authors_split_regex']}, is invalid, "
|
||||||
'is invalid, using default')
|
f"using default")
|
||||||
_author_pat = re.compile(r'(?i),?\s+(and|with)\s+')
|
_author_pat = re.compile(r'(?i),?\s+(and|with)\s+')
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import copy, traceback
|
import copy, traceback
|
||||||
|
|
||||||
from ebook_converter import prints
|
|
||||||
from ebook_converter.constants_old import DEBUG
|
from ebook_converter.constants_old import DEBUG
|
||||||
from ebook_converter.ebooks.metadata.book import (SC_COPYABLE_FIELDS,
|
from ebook_converter.ebooks.metadata.book import (SC_COPYABLE_FIELDS,
|
||||||
SC_FIELDS_COPY_NOT_NULL, STANDARD_METADATA_FIELDS,
|
SC_FIELDS_COPY_NOT_NULL, STANDARD_METADATA_FIELDS,
|
||||||
@@ -453,12 +452,12 @@ class Metadata(object):
|
|||||||
# Old Metadata API {{{
|
# Old Metadata API {{{
|
||||||
def print_all_attributes(self):
|
def print_all_attributes(self):
|
||||||
for x in STANDARD_METADATA_FIELDS:
|
for x in STANDARD_METADATA_FIELDS:
|
||||||
prints('%s:'%x, getattr(self, x, 'None'))
|
print('%s:' % x, getattr(self, x, 'None'))
|
||||||
for x in self.custom_field_keys():
|
for x in self.custom_field_keys():
|
||||||
meta = self.get_user_metadata(x, make_copy=False)
|
meta = self.get_user_metadata(x, make_copy=False)
|
||||||
if meta is not None:
|
if meta is not None:
|
||||||
prints(x, meta)
|
print(x, meta)
|
||||||
prints('--------------')
|
print('--------------')
|
||||||
|
|
||||||
def smart_update(self, other, replace_metadata=False):
|
def smart_update(self, other, replace_metadata=False):
|
||||||
'''
|
'''
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ from lxml import etree
|
|||||||
from ebook_converter.utils.date import parse_only_date
|
from ebook_converter.utils.date import parse_only_date
|
||||||
from ebook_converter.utils.img import save_cover_data_to
|
from ebook_converter.utils.img import save_cover_data_to
|
||||||
from ebook_converter.utils.imghdr import identify
|
from ebook_converter.utils.imghdr import identify
|
||||||
from ebook_converter import prints, force_unicode
|
from ebook_converter import force_unicode
|
||||||
from ebook_converter.ebooks.metadata import MetaInformation, check_isbn
|
from ebook_converter.ebooks.metadata import MetaInformation, check_isbn
|
||||||
from ebook_converter.ebooks.chardet import xml_to_unicode
|
from ebook_converter.ebooks.chardet import xml_to_unicode
|
||||||
from ebook_converter.polyglot.binary import as_base64_unicode
|
from ebook_converter.polyglot.binary import as_base64_unicode
|
||||||
@@ -237,8 +237,8 @@ def _parse_cover_data(root, imgid, mi, ctx):
|
|||||||
fmt = identify(cdata)[0]
|
fmt = identify(cdata)[0]
|
||||||
mi.cover_data = (fmt, cdata)
|
mi.cover_data = (fmt, cdata)
|
||||||
else:
|
else:
|
||||||
prints("WARNING: Unsupported coverpage mime-type '%s' (id=#%s)" %
|
print(f"WARNING: Unsupported coverpage mime-type '{mimetype}' "
|
||||||
(mimetype, imgid))
|
f"(id=#{imgid})")
|
||||||
|
|
||||||
|
|
||||||
def _parse_tags(root, mi, ctx):
|
def _parse_tags(root, mi, ctx):
|
||||||
|
|||||||
@@ -32,7 +32,6 @@ from ebook_converter.ebooks.metadata import string_to_authors, \
|
|||||||
from ebook_converter.ebooks.metadata.book.base import Metadata
|
from ebook_converter.ebooks.metadata.book.base import Metadata
|
||||||
from ebook_converter.utils.date import parse_date, isoformat
|
from ebook_converter.utils.date import parse_date, isoformat
|
||||||
from ebook_converter.utils.localization import get_lang, canonicalize_lang
|
from ebook_converter.utils.localization import get_lang, canonicalize_lang
|
||||||
from ebook_converter import prints
|
|
||||||
from ebook_converter.utils.cleantext import clean_ascii_chars, clean_xml_chars
|
from ebook_converter.utils.cleantext import clean_ascii_chars, clean_xml_chars
|
||||||
from ebook_converter.utils.config import tweaks
|
from ebook_converter.utils.config import tweaks
|
||||||
from ebook_converter.polyglot.urllib import unquote
|
from ebook_converter.polyglot.urllib import unquote
|
||||||
@@ -516,7 +515,7 @@ def serialize_user_metadata(metadata_elem, all_user_metadata,
|
|||||||
fm = object_to_unicode(fm)
|
fm = object_to_unicode(fm)
|
||||||
fm = json.dumps(fm, default=to_json, ensure_ascii=False)
|
fm = json.dumps(fm, default=to_json, ensure_ascii=False)
|
||||||
except Exception:
|
except Exception:
|
||||||
prints('Failed to write user metadata:', name)
|
print('Failed to write user metadata: {name}')
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
continue
|
continue
|
||||||
meta = metadata_elem.makeelement('meta')
|
meta = metadata_elem.makeelement('meta')
|
||||||
@@ -671,7 +670,7 @@ class OPF(object): # {{{
|
|||||||
decode_is_multiple(fm)
|
decode_is_multiple(fm)
|
||||||
temp.set_user_metadata(name, fm)
|
temp.set_user_metadata(name, fm)
|
||||||
except Exception:
|
except Exception:
|
||||||
prints('Failed to read user metadata:', name)
|
print('Failed to read user metadata: {name}')
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
continue
|
continue
|
||||||
self._user_metadata_ = temp.get_all_user_metadata(True)
|
self._user_metadata_ = temp.get_all_user_metadata(True)
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import re
|
|||||||
from lxml import etree
|
from lxml import etree
|
||||||
|
|
||||||
from ebook_converter import constants as const
|
from ebook_converter import constants as const
|
||||||
from ebook_converter import prints
|
|
||||||
from ebook_converter.ebooks.metadata import authors_to_string
|
from ebook_converter.ebooks.metadata import authors_to_string
|
||||||
from ebook_converter.ebooks.metadata import check_isbn
|
from ebook_converter.ebooks.metadata import check_isbn
|
||||||
from ebook_converter.ebooks.metadata import string_to_authors
|
from ebook_converter.ebooks.metadata import string_to_authors
|
||||||
@@ -923,7 +922,7 @@ def read_user_metadata2(root, remove_tags=False):
|
|||||||
decode_is_multiple(fm)
|
decode_is_multiple(fm)
|
||||||
ans[name] = fm
|
ans[name] = fm
|
||||||
except Exception:
|
except Exception:
|
||||||
prints('Failed to read user metadata:', name)
|
print('Failed to read user metadata: {name}')
|
||||||
import traceback
|
import traceback
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
continue
|
continue
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ Read meta information from PDF files
|
|||||||
import os, subprocess, shutil, re
|
import os, subprocess, shutil, re
|
||||||
from functools import partial
|
from functools import partial
|
||||||
|
|
||||||
from ebook_converter import prints
|
|
||||||
from ebook_converter.ptempfile import TemporaryDirectory
|
from ebook_converter.ptempfile import TemporaryDirectory
|
||||||
from ebook_converter.ebooks.metadata import (
|
from ebook_converter.ebooks.metadata import (
|
||||||
MetaInformation, string_to_authors, check_isbn, check_doi)
|
MetaInformation, string_to_authors, check_isbn, check_doi)
|
||||||
@@ -39,12 +38,12 @@ def read_info(outputdir, get_cover):
|
|||||||
raw = subprocess.check_output([pdfinfo, '-enc', 'UTF-8', '-isodates',
|
raw = subprocess.check_output([pdfinfo, '-enc', 'UTF-8', '-isodates',
|
||||||
source_file])
|
source_file])
|
||||||
except subprocess.CalledProcessError as e:
|
except subprocess.CalledProcessError as e:
|
||||||
prints('pdfinfo errored out with return code: %d'%e.returncode)
|
print(f'pdfinfo errored out with return code: {e.returncode}')
|
||||||
return None
|
return None
|
||||||
try:
|
try:
|
||||||
info_raw = raw.decode('utf-8')
|
info_raw = raw.decode('utf-8')
|
||||||
except UnicodeDecodeError:
|
except UnicodeDecodeError:
|
||||||
prints('pdfinfo returned no UTF-8 data')
|
print('pdfinfo returned no UTF-8 data')
|
||||||
return None
|
return None
|
||||||
|
|
||||||
for line in info_raw.splitlines():
|
for line in info_raw.splitlines():
|
||||||
@@ -63,7 +62,8 @@ def read_info(outputdir, get_cover):
|
|||||||
try:
|
try:
|
||||||
raw = subprocess.check_output([pdfinfo, '-meta', source_file]).strip()
|
raw = subprocess.check_output([pdfinfo, '-meta', source_file]).strip()
|
||||||
except subprocess.CalledProcessError as e:
|
except subprocess.CalledProcessError as e:
|
||||||
prints('pdfinfo failed to read XML metadata with return code: %d'%e.returncode)
|
print('pdfinfo failed to read XML metadata with return code: '
|
||||||
|
f'{e.returncode}')
|
||||||
else:
|
else:
|
||||||
parts = re.split(br'^Metadata:', raw, 1, flags=re.MULTILINE)
|
parts = re.split(br'^Metadata:', raw, 1, flags=re.MULTILINE)
|
||||||
if len(parts) > 1:
|
if len(parts) > 1:
|
||||||
@@ -77,7 +77,7 @@ def read_info(outputdir, get_cover):
|
|||||||
subprocess.check_call([pdftoppm, '-singlefile', '-jpeg',
|
subprocess.check_call([pdftoppm, '-singlefile', '-jpeg',
|
||||||
'-cropbox', source_file, cover_file])
|
'-cropbox', source_file, cover_file])
|
||||||
except subprocess.CalledProcessError as e:
|
except subprocess.CalledProcessError as e:
|
||||||
prints('pdftoppm errored out with return code: %d'%e.returncode)
|
print('pdftoppm errored out with return code: {e.returncode}')
|
||||||
|
|
||||||
return ans
|
return ans
|
||||||
|
|
||||||
|
|||||||
@@ -4,11 +4,11 @@ import itertools
|
|||||||
import json
|
import json
|
||||||
import re
|
import re
|
||||||
import sys
|
import sys
|
||||||
|
import traceback
|
||||||
|
|
||||||
from lxml import etree
|
from lxml import etree
|
||||||
from lxml.builder import ElementMaker
|
from lxml.builder import ElementMaker
|
||||||
|
|
||||||
from ebook_converter import prints
|
|
||||||
from ebook_converter.ebooks.metadata import check_isbn, check_doi
|
from ebook_converter.ebooks.metadata import check_isbn, check_doi
|
||||||
from ebook_converter.ebooks.metadata.book.base import Metadata
|
from ebook_converter.ebooks.metadata.book.base import Metadata
|
||||||
from ebook_converter.ebooks.metadata.opf2 import dump_dict
|
from ebook_converter.ebooks.metadata.opf2 import dump_dict
|
||||||
@@ -192,7 +192,7 @@ def read_user_metadata(mi, root):
|
|||||||
mi.set_user_metadata(name, fm)
|
mi.set_user_metadata(name, fm)
|
||||||
fields.add(name)
|
fields.add(name)
|
||||||
except Exception:
|
except Exception:
|
||||||
prints('Failed to read user metadata:', name)
|
print(f'Failed to read user metadata: {name}')
|
||||||
import traceback
|
import traceback
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
|
|
||||||
@@ -467,8 +467,7 @@ def create_user_metadata(calibre, all_user_metadata):
|
|||||||
fm = object_to_unicode(fm)
|
fm = object_to_unicode(fm)
|
||||||
fm = json.dumps(fm, default=to_json, ensure_ascii=False)
|
fm = json.dumps(fm, default=to_json, ensure_ascii=False)
|
||||||
except Exception:
|
except Exception:
|
||||||
prints('Failed to write user metadata:', name)
|
print('Failed to write user metadata: {name}')
|
||||||
import traceback
|
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
continue
|
continue
|
||||||
li = bag.makeelement(expand('rdf:li'))
|
li = bag.makeelement(expand('rdf:li'))
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import sys
|
|||||||
|
|
||||||
from lxml import etree
|
from lxml import etree
|
||||||
|
|
||||||
from ebook_converter import CurrentDir, xml_replace_entities, prints
|
from ebook_converter import CurrentDir, xml_replace_entities
|
||||||
from ebook_converter.constants_old import isbsd, islinux, isosx
|
from ebook_converter.constants_old import isbsd, islinux, isosx
|
||||||
from ebook_converter.ebooks import ConversionError, DRMError
|
from ebook_converter.ebooks import ConversionError, DRMError
|
||||||
from ebook_converter.ebooks.chardet import xml_to_unicode
|
from ebook_converter.ebooks.chardet import xml_to_unicode
|
||||||
@@ -78,8 +78,8 @@ def pdftohtml(output_dir, pdf_path, no_images, as_xml=False):
|
|||||||
raise ConversionError('pdftohtml failed with return code: '
|
raise ConversionError('pdftohtml failed with return code: '
|
||||||
'%d\n%s' % (ret, out))
|
'%d\n%s' % (ret, out))
|
||||||
if out:
|
if out:
|
||||||
prints("pdftohtml log:")
|
print("pdftohtml log:")
|
||||||
prints(out)
|
print(out)
|
||||||
if not os.path.exists(index) or os.stat(index).st_size < 100:
|
if not os.path.exists(index) or os.stat(index).st_size < 100:
|
||||||
raise DRMError()
|
raise DRMError()
|
||||||
|
|
||||||
|
|||||||
@@ -5,13 +5,11 @@ meaning as possible.
|
|||||||
import errno
|
import errno
|
||||||
import os
|
import os
|
||||||
import shutil
|
import shutil
|
||||||
import time
|
|
||||||
from math import ceil
|
from math import ceil
|
||||||
|
|
||||||
from ebook_converter import force_unicode, prints, sanitize_file_name
|
from ebook_converter import force_unicode, sanitize_file_name
|
||||||
from ebook_converter.constants_old import (
|
from ebook_converter.constants_old import (filesystem_encoding,
|
||||||
filesystem_encoding, plugins, preferred_encoding, isosx
|
preferred_encoding)
|
||||||
)
|
|
||||||
from ebook_converter.utils.localization import get_udc
|
from ebook_converter.utils.localization import get_udc
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import os
|
|||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
from threading import Thread
|
from threading import Thread
|
||||||
|
|
||||||
from ebook_converter import walk, prints
|
from ebook_converter import walk
|
||||||
from ebook_converter.constants_old import isosx
|
from ebook_converter.constants_old import isosx
|
||||||
from ebook_converter.constants_old import plugins, DEBUG
|
from ebook_converter.constants_old import plugins, DEBUG
|
||||||
from ebook_converter.constants_old import filesystem_encoding
|
from ebook_converter.constants_old import filesystem_encoding
|
||||||
@@ -67,7 +67,7 @@ def fc_list():
|
|||||||
try:
|
try:
|
||||||
ans.append(d.decode(filesystem_encoding))
|
ans.append(d.decode(filesystem_encoding))
|
||||||
except ValueError:
|
except ValueError:
|
||||||
prints('Ignoring undecodeable font path: %r' % d)
|
print(f'Ignoring undecodeable font path: {d}')
|
||||||
continue
|
continue
|
||||||
end(str_list)
|
end(str_list)
|
||||||
if len(ans) < 3:
|
if len(ans) < 3:
|
||||||
@@ -309,7 +309,7 @@ class FontScanner(Thread):
|
|||||||
files = tuple(walk(folder))
|
files = tuple(walk(folder))
|
||||||
except EnvironmentError as e:
|
except EnvironmentError as e:
|
||||||
if DEBUG:
|
if DEBUG:
|
||||||
prints('Failed to walk font folder:', folder, str(e))
|
print(f'Failed to walk font folder: {folder}, {e}')
|
||||||
continue
|
continue
|
||||||
for candidate in files:
|
for candidate in files:
|
||||||
if (candidate.rpartition('.')[-1].lower() not in
|
if (candidate.rpartition('.')[-1].lower() not in
|
||||||
@@ -332,8 +332,8 @@ class FontScanner(Thread):
|
|||||||
self.read_font_metadata(candidate, fileid)
|
self.read_font_metadata(candidate, fileid)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
if DEBUG:
|
if DEBUG:
|
||||||
prints('Failed to read metadata from font file:',
|
print(f'Failed to read metadata from font file '
|
||||||
candidate, str(e))
|
f'{candidate}: {e}')
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if frozenset(cached_fonts) != frozenset(self.cached_fonts):
|
if frozenset(cached_fonts) != frozenset(self.cached_fonts):
|
||||||
@@ -369,18 +369,18 @@ class FontScanner(Thread):
|
|||||||
def dump_fonts(self):
|
def dump_fonts(self):
|
||||||
self.join()
|
self.join()
|
||||||
for family in self.font_families:
|
for family in self.font_families:
|
||||||
prints(family)
|
print(family)
|
||||||
for font in self.fonts_for_family(family):
|
for font in self.fonts_for_family(family):
|
||||||
prints('\t%s: %s' % (font['full_name'], font['path']))
|
print('\t%s: %s' % (font['full_name'], font['path']))
|
||||||
prints(end='\t')
|
print(end='\t')
|
||||||
for key in ('font-stretch', 'font-weight', 'font-style'):
|
for key in ('font-stretch', 'font-weight', 'font-style'):
|
||||||
prints('%s: %s' % (key, font[key]), end=' ')
|
print('%s: %s' % (key, font[key]))
|
||||||
prints()
|
print()
|
||||||
prints('\tSub-family:', font['wws_subfamily_name'] or
|
print('\tSub-family: %s' % (font['wws_subfamily_name'] or
|
||||||
font['preferred_subfamily_name'] or
|
font['preferred_subfamily_name']
|
||||||
font['subfamily_name'])
|
or font['subfamily_name']))
|
||||||
prints()
|
print()
|
||||||
prints()
|
print()
|
||||||
|
|
||||||
|
|
||||||
font_scanner = FontScanner()
|
font_scanner = FontScanner()
|
||||||
|
|||||||
@@ -204,15 +204,13 @@ def option_parser():
|
|||||||
|
|
||||||
|
|
||||||
def print_stats(old_stats, new_stats):
|
def print_stats(old_stats, new_stats):
|
||||||
from ebook_converter import prints
|
print('========= Table comparison (original vs. subset) =========')
|
||||||
prints('========= Table comparison (original vs. subset) =========')
|
print('Table Size Percent New Size New Percent')
|
||||||
prints('Table', ' ', '%10s'%'Size', ' ', 'Percent', ' ', '%10s'%'New Size',
|
print('='*80)
|
||||||
' New Percent')
|
|
||||||
prints('='*80)
|
|
||||||
old_total = sum(old_stats.values())
|
old_total = sum(old_stats.values())
|
||||||
new_total = sum(new_stats.values())
|
new_total = sum(new_stats.values())
|
||||||
tables = sorted(old_stats, key=lambda x:old_stats[x],
|
tables = sorted(old_stats, key=lambda x: old_stats[x],
|
||||||
reverse=True)
|
reverse=True)
|
||||||
for table in tables:
|
for table in tables:
|
||||||
osz = old_stats[table]
|
osz = old_stats[table]
|
||||||
op = osz/old_total * 100
|
op = osz/old_total * 100
|
||||||
@@ -220,15 +218,14 @@ def print_stats(old_stats, new_stats):
|
|||||||
np = nsz/new_total * 100
|
np = nsz/new_total * 100
|
||||||
suffix = ' | same size'
|
suffix = ' | same size'
|
||||||
if nsz != osz:
|
if nsz != osz:
|
||||||
suffix = ' | reduced to %.1f %%'%(nsz/osz * 100)
|
suffix = ' | reduced to %.1f %%' % (nsz/osz * 100)
|
||||||
prints('%4s'%table, ' ', '%10s'%osz, ' ', '%5.1f %%'%op, ' ',
|
print('%4s %10s %5.1f %% %10s %5.1f %% %s' %
|
||||||
'%10s'%nsz, ' ', '%5.1f %%'%np, suffix)
|
(table, osz, op, nsz, np, suffix))
|
||||||
prints('='*80)
|
print('='*80)
|
||||||
|
|
||||||
|
|
||||||
def main(args):
|
def main(args):
|
||||||
import sys, time
|
import sys, time
|
||||||
from ebook_converter import prints
|
|
||||||
parser = option_parser()
|
parser = option_parser()
|
||||||
opts, args = parser.parse_args(args)
|
opts, args = parser.parse_args(args)
|
||||||
if len(args) < 4 or len(args) > 4:
|
if len(args) < 4 or len(args) > 4:
|
||||||
@@ -243,7 +240,7 @@ def main(args):
|
|||||||
|
|
||||||
def not_single(c):
|
def not_single(c):
|
||||||
if len(c) > 1:
|
if len(c) > 1:
|
||||||
prints(c, 'is not a single character', file=sys.stderr)
|
print(f'{c}is not a single character')
|
||||||
raise SystemExit(1)
|
raise SystemExit(1)
|
||||||
|
|
||||||
def conv_code(c):
|
def conv_code(c):
|
||||||
@@ -255,7 +252,7 @@ def main(args):
|
|||||||
if '-' in c:
|
if '-' in c:
|
||||||
parts = [x.strip() for x in c.split('-')]
|
parts = [x.strip() for x in c.split('-')]
|
||||||
if len(parts) != 2:
|
if len(parts) != 2:
|
||||||
prints('Invalid range:', c, file=sys.stderr)
|
print(f'Invalid range: {c}')
|
||||||
raise SystemExit(1)
|
raise SystemExit(1)
|
||||||
if opts.codes:
|
if opts.codes:
|
||||||
parts = tuple(map(conv_code, parts))
|
parts = tuple(map(conv_code, parts))
|
||||||
@@ -272,13 +269,14 @@ def main(args):
|
|||||||
reduced = (len(sf)/len(orig)) * 100
|
reduced = (len(sf)/len(orig)) * 100
|
||||||
|
|
||||||
def sz(x):
|
def sz(x):
|
||||||
return '%gKB'%(len(x)/1024.)
|
return '%gKB' % (len(x)/1024.)
|
||||||
print_stats(old_stats, new_stats)
|
print_stats(old_stats, new_stats)
|
||||||
prints('Original size:', sz(orig), 'Subset size:', sz(sf), 'Reduced to: %g%%'%(reduced))
|
print('Original size:', sz(orig), 'Subset size:', sz(sf),
|
||||||
prints('Subsetting took %g seconds'%taken)
|
'Reduced to: %g%%' % (reduced))
|
||||||
|
print('Subsetting took %g seconds' % taken)
|
||||||
with open(off, 'wb') as f:
|
with open(off, 'wb') as f:
|
||||||
f.write(sf)
|
f.write(sf)
|
||||||
prints('Subset font written to:', off)
|
print('Subset font written to:', off)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ Created on 23 Sep 2010
|
|||||||
"""
|
"""
|
||||||
import re, string, traceback, numbers
|
import re, string, traceback, numbers
|
||||||
|
|
||||||
from ebook_converter import prints
|
|
||||||
from ebook_converter.constants_old import DEBUG
|
from ebook_converter.constants_old import DEBUG
|
||||||
from ebook_converter.utils.formatter_functions import formatter_functions
|
from ebook_converter.utils.formatter_functions import formatter_functions
|
||||||
|
|
||||||
@@ -373,7 +372,7 @@ class TemplateFormatter(string.Formatter):
|
|||||||
if DEBUG: # and getattr(e, 'is_locking_error', False):
|
if DEBUG: # and getattr(e, 'is_locking_error', False):
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
if column_name:
|
if column_name:
|
||||||
prints('Error evaluating column named:', column_name)
|
print('Error evaluating column named: {column_name}')
|
||||||
ans = error_value + ' ' + str(e)
|
ans = error_value + ' ' + str(e)
|
||||||
return ans
|
return ans
|
||||||
|
|
||||||
|
|||||||
@@ -4,10 +4,10 @@ A simplified logging system
|
|||||||
import sys
|
import sys
|
||||||
import traceback
|
import traceback
|
||||||
import io
|
import io
|
||||||
|
import os
|
||||||
from functools import partial
|
from functools import partial
|
||||||
from threading import Lock
|
|
||||||
|
|
||||||
from ebook_converter import force_unicode, prints
|
from ebook_converter import constants_old
|
||||||
|
|
||||||
|
|
||||||
DEBUG = 0
|
DEBUG = 0
|
||||||
@@ -22,13 +22,13 @@ class Stream(object):
|
|||||||
if stream is None:
|
if stream is None:
|
||||||
stream = io.BytesIO()
|
stream = io.BytesIO()
|
||||||
self.stream = getattr(stream, 'buffer', stream)
|
self.stream = getattr(stream, 'buffer', stream)
|
||||||
self._prints = partial(prints, safe_encode=True, file=stream)
|
# self._prints = partial(prints, safe_encode=True, file=stream)
|
||||||
|
|
||||||
def flush(self):
|
def flush(self):
|
||||||
self.stream.flush()
|
self.stream.flush()
|
||||||
|
|
||||||
def prints(self, level, *args, **kwargs):
|
def prints(self, level, *args, **kwargs):
|
||||||
self._prints(*args, **kwargs)
|
raise NotImplementedError()
|
||||||
|
|
||||||
|
|
||||||
class ANSIStream(Stream):
|
class ANSIStream(Stream):
|
||||||
@@ -43,97 +43,34 @@ class ANSIStream(Stream):
|
|||||||
}
|
}
|
||||||
|
|
||||||
def prints(self, level, *args, **kwargs):
|
def prints(self, level, *args, **kwargs):
|
||||||
from ebook_converter.utils.terminal import ColoredStream
|
fobj = kwargs.get('file', sys.stdout)
|
||||||
with ColoredStream(self.stream, self.color[level]):
|
|
||||||
self._prints(*args, **kwargs)
|
|
||||||
|
|
||||||
def flush(self):
|
|
||||||
self.stream.flush()
|
|
||||||
|
|
||||||
|
|
||||||
class FileStream(Stream):
|
|
||||||
|
|
||||||
def __init__(self, stream=None):
|
|
||||||
Stream.__init__(self, stream)
|
|
||||||
|
|
||||||
def prints(self, level, *args, **kwargs):
|
|
||||||
self._prints(*args, **kwargs)
|
|
||||||
|
|
||||||
|
|
||||||
class HTMLStream(Stream):
|
|
||||||
|
|
||||||
color = {DEBUG: b'<span style="color:green">',
|
|
||||||
INFO: b'<span>',
|
|
||||||
WARN: b'<span style="color:blue">',
|
|
||||||
ERROR: b'<span style="color:red">'}
|
|
||||||
normal = b'</span>'
|
|
||||||
|
|
||||||
def __init__(self, stream=sys.stdout):
|
|
||||||
Stream.__init__(self, stream)
|
|
||||||
|
|
||||||
def prints(self, level, *args, **kwargs):
|
|
||||||
self.stream.write(self.color[level])
|
|
||||||
kwargs['file'] = self.stream
|
|
||||||
self._prints(*args, **kwargs)
|
|
||||||
self.stream.write(self.normal)
|
|
||||||
|
|
||||||
def flush(self):
|
|
||||||
self.stream.flush()
|
|
||||||
|
|
||||||
|
|
||||||
class UnicodeHTMLStream(HTMLStream):
|
|
||||||
|
|
||||||
color = {k: v.decode('ascii') for k, v in HTMLStream.color.items()}
|
|
||||||
normal = HTMLStream.normal.decode('ascii')
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
self.clear()
|
|
||||||
|
|
||||||
def flush(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def prints(self, level, *args, **kwargs):
|
|
||||||
col = self.color[level]
|
|
||||||
if col != self.last_col:
|
|
||||||
if self.data:
|
|
||||||
self.data.append(self.normal)
|
|
||||||
self.data.append(col)
|
|
||||||
self.last_col = col
|
|
||||||
|
|
||||||
sep = kwargs.get('sep', ' ')
|
sep = kwargs.get('sep', ' ')
|
||||||
|
enc = ('utf-8' if os.getenv('CALIBRE_WORKER')
|
||||||
|
else constants_old.preferred_encoding)
|
||||||
|
if isinstance(sep, bytes):
|
||||||
|
sep = sep.decode(enc)
|
||||||
end = kwargs.get('end', '\n')
|
end = kwargs.get('end', '\n')
|
||||||
|
if isinstance(end, bytes):
|
||||||
for arg in args:
|
end = end.decode(enc)
|
||||||
|
count = 0
|
||||||
|
for i, arg in enumerate(args):
|
||||||
if isinstance(arg, bytes):
|
if isinstance(arg, bytes):
|
||||||
arg = force_unicode(arg)
|
arg = arg.decode(enc)
|
||||||
elif not isinstance(arg, str):
|
arg = repr(arg)
|
||||||
arg = str(arg)
|
try:
|
||||||
self.data.append(arg+sep)
|
fobj.write(arg)
|
||||||
self.plain_text.append(arg+sep)
|
count += len(arg)
|
||||||
self.data.append(end)
|
except Exception:
|
||||||
self.plain_text.append(end)
|
arg = repr(arg)
|
||||||
|
fobj.write(arg)
|
||||||
|
count += len(arg)
|
||||||
|
if i != len(args)-1:
|
||||||
|
fobj.write(sep)
|
||||||
|
count += len(sep)
|
||||||
|
count += len(end)
|
||||||
|
|
||||||
def clear(self):
|
def flush(self):
|
||||||
self.data = []
|
self.stream.flush()
|
||||||
self.plain_text = []
|
|
||||||
self.last_col = self.color[INFO]
|
|
||||||
|
|
||||||
@property
|
|
||||||
def html(self):
|
|
||||||
end = self.normal if self.data else ''
|
|
||||||
return ''.join(self.data) + end
|
|
||||||
|
|
||||||
def dump(self):
|
|
||||||
return [self.data, self.plain_text, self.last_col]
|
|
||||||
|
|
||||||
def load(self, dump):
|
|
||||||
self.data, self.plain_text, self.last_col = dump
|
|
||||||
|
|
||||||
def append_dump(self, dump):
|
|
||||||
d, p, lc = dump
|
|
||||||
self.data.extend(d)
|
|
||||||
self.plain_text.extend(p)
|
|
||||||
self.last_col = lc
|
|
||||||
|
|
||||||
|
|
||||||
class Log(object):
|
class Log(object):
|
||||||
@@ -192,80 +129,4 @@ class Log(object):
|
|||||||
o.close()
|
o.close()
|
||||||
|
|
||||||
|
|
||||||
class DevNull(Log):
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
Log.__init__(self, level=Log.ERROR)
|
|
||||||
self.outputs = []
|
|
||||||
|
|
||||||
|
|
||||||
class ThreadSafeLog(Log):
|
|
||||||
exception_traceback_level = Log.DEBUG
|
|
||||||
|
|
||||||
def __init__(self, level=Log.INFO):
|
|
||||||
Log.__init__(self, level=level)
|
|
||||||
self._lock = Lock()
|
|
||||||
|
|
||||||
def prints(self, *args, **kwargs):
|
|
||||||
with self._lock:
|
|
||||||
Log.prints(self, *args, **kwargs)
|
|
||||||
|
|
||||||
def print_with_flush(self, *args, **kwargs):
|
|
||||||
with self._lock:
|
|
||||||
Log.print_with_flush(self, *args, **kwargs)
|
|
||||||
|
|
||||||
def exception(self, *args, **kwargs):
|
|
||||||
limit = kwargs.pop('limit', None)
|
|
||||||
with self._lock:
|
|
||||||
Log.print_with_flush(self, ERROR, *args, **kwargs)
|
|
||||||
Log.print_with_flush(self, self.exception_traceback_level,
|
|
||||||
traceback.format_exc(limit))
|
|
||||||
|
|
||||||
|
|
||||||
class ThreadSafeWrapper(Log):
|
|
||||||
|
|
||||||
def __init__(self, other_log):
|
|
||||||
Log.__init__(self, level=other_log.filter_level)
|
|
||||||
self.outputs = list(other_log.outputs)
|
|
||||||
self._lock = Lock()
|
|
||||||
|
|
||||||
def prints(self, *args, **kwargs):
|
|
||||||
with self._lock:
|
|
||||||
Log.prints(self, *args, **kwargs)
|
|
||||||
|
|
||||||
def print_with_flush(self, *args, **kwargs):
|
|
||||||
with self._lock:
|
|
||||||
Log.print_with_flush(self, *args, **kwargs)
|
|
||||||
|
|
||||||
|
|
||||||
class GUILog(ThreadSafeLog):
|
|
||||||
"""
|
|
||||||
Logs in HTML and plain text as unicode. Ideal for display in a GUI context.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
ThreadSafeLog.__init__(self, level=self.DEBUG)
|
|
||||||
self.outputs = [UnicodeHTMLStream()]
|
|
||||||
|
|
||||||
def clear(self):
|
|
||||||
self.outputs[0].clear()
|
|
||||||
|
|
||||||
@property
|
|
||||||
def html(self):
|
|
||||||
return self.outputs[0].html
|
|
||||||
|
|
||||||
@property
|
|
||||||
def plain_text(self):
|
|
||||||
return u''.join(self.outputs[0].plain_text)
|
|
||||||
|
|
||||||
def dump(self):
|
|
||||||
return self.outputs[0].dump()
|
|
||||||
|
|
||||||
def load(self, dump):
|
|
||||||
return self.outputs[0].load(dump)
|
|
||||||
|
|
||||||
def append_dump(self, dump):
|
|
||||||
return self.outputs[0].append_dump(dump)
|
|
||||||
|
|
||||||
|
|
||||||
default_log = Log()
|
default_log = Log()
|
||||||
|
|||||||
Reference in New Issue
Block a user