From e1fdbd398232ab80380a7f0dd1b3be9b4eb73ec5 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Fri, 13 Dec 2019 18:01:55 +0530 Subject: [PATCH] Restore prints and use it instead of polyglot write --- src/calibre/__init__.py | 2 +- src/calibre/prints.py | 31 ++++++++++++++++++++++++++ src/calibre/srv/tests/loop.py | 1 - src/calibre/srv/utils.py | 25 +++++---------------- src/calibre/utils/logging.py | 41 ++++++++++++++--------------------- src/calibre/utils/terminal.py | 10 ++------- 6 files changed, 55 insertions(+), 55 deletions(-) create mode 100644 src/calibre/prints.py diff --git a/src/calibre/__init__.py b/src/calibre/__init__.py index 9b78feb4bc..25a13ffac1 100644 --- a/src/calibre/__init__.py +++ b/src/calibre/__init__.py @@ -22,6 +22,7 @@ from calibre.constants import (iswindows, isosx, islinux, isfrozen, filesystem_encoding, plugins, config_dir) from calibre.startup import winutil, winutilerror from calibre.utils.icu import safe_chr +from calibre.prints import prints if False: # Prevent pyflakes from complaining @@ -138,7 +139,6 @@ def sanitize_file_name(name, substitute='_'): sanitize_file_name2 = sanitize_file_name_unicode = sanitize_file_name -prints = print class CommandLineError(Exception): diff --git a/src/calibre/prints.py b/src/calibre/prints.py new file mode 100644 index 0000000000..dba67df599 --- /dev/null +++ b/src/calibre/prints.py @@ -0,0 +1,31 @@ +#!/usr/bin/env python +# vim:fileencoding=utf-8 +# License: GPL v3 Copyright: 2019, Kovid Goyal + +import io +import sys + +from polyglot.builtins import as_bytes, as_unicode + + +def is_binary(stream): + mode = getattr(stream, 'mode', None) + if mode: + return 'b' in mode + return not isinstance(stream, io.TextIOBase) + + +def prints(*a, **kw): + ' Print either unicode or bytes to either binary or text mode streams ' + stream = kw.get('file', sys.stdout) + if is_binary(stream): + encoding = getattr(stream, 'encoding', None) or 'utf-8' + a = tuple(as_bytes(x, encoding=encoding) for x in a) + kw['sep'] = as_bytes(kw.get('sep', b' ')) + kw['end'] = as_bytes(kw.get('end', b'\n')) + else: + a = tuple(as_unicode(x, errors='replace') for x in a) + kw['sep'] = as_unicode(kw.get('sep', ' ')) + kw['end'] = as_unicode(kw.get('end', '\n')) + + return print(*a, **kw) diff --git a/src/calibre/srv/tests/loop.py b/src/calibre/srv/tests/loop.py index b0ca60e498..f80cd44cac 100644 --- a/src/calibre/srv/tests/loop.py +++ b/src/calibre/srv/tests/loop.py @@ -36,7 +36,6 @@ class LoopTest(BaseTest): def log_size(): ssize = l.outputs[0].stream.tell() - self.ae(ssize, l.outputs[0].current_pos) self.ae(ssize, os.path.getsize(fname)) return ssize diff --git a/src/calibre/srv/utils.py b/src/calibre/srv/utils.py index 08ab8ac98c..6a7243598c 100644 --- a/src/calibre/srv/utils.py +++ b/src/calibre/srv/utils.py @@ -12,7 +12,6 @@ from operator import itemgetter from calibre import prints from calibre.constants import iswindows -from calibre.utils.terminal import polyglot_write from calibre.srv.errors import HTTPNotFound from calibre.utils.localization import get_translator from calibre.utils.socket_inheritance import set_socket_inherit @@ -314,36 +313,22 @@ class RotatingStream(object): def set_output(self): if iswindows: - self.stream = share_open(self.filename, 'ab') + self.stream = share_open(self.filename, 'a') else: # see https://bugs.python.org/issue27805 - self.stream = open(os.open(self.filename, os.O_WRONLY|os.O_APPEND|os.O_CREAT|os.O_CLOEXEC), 'wb') + self.stream = open(os.open(self.filename, os.O_WRONLY|os.O_APPEND|os.O_CREAT|os.O_CLOEXEC), 'w') try: - self.current_pos = self.stream.tell() + self.stream.tell() except EnvironmentError: # Happens if filename is /dev/stdout for example - self.current_pos = 0 self.max_size = None def flush(self): self.stream.flush() - def write(self, x): - return polyglot_write(self.stream, True, 'utf-8', x) - def prints(self, level, *args, **kwargs): - kwargs['file'] = self + kwargs['file'] = self.stream prints(*args, **kwargs) - try: - self.current_pos = self.stream.tell() - except EnvironmentError: - self.current_pos = 0 - # line bufferring only works with text mode streams - end = kwargs.get('end', b'\n') - if isinstance(end, unicode_type): - end = end.encode('utf-8') - if b'\n' in end: - self.flush() self.rollover() def rename(self, src, dest): @@ -361,7 +346,7 @@ class RotatingStream(object): raise def rollover(self): - if not self.max_size or self.current_pos <= self.max_size or self.filename in ('/dev/stdout', '/dev/stderr'): + if not self.max_size or self.stream.tell() <= self.max_size: return self.stream.close() for i in range(self.history - 1, 0, -1): diff --git a/src/calibre/utils/logging.py b/src/calibre/utils/logging.py index 182d54235d..6ba30840db 100644 --- a/src/calibre/utils/logging.py +++ b/src/calibre/utils/logging.py @@ -15,9 +15,8 @@ import traceback from functools import partial from threading import Lock -from calibre import as_unicode, force_unicode, isbytestring -from calibre.utils.terminal import is_binary, polyglot_write -from polyglot.builtins import iteritems, unicode_type +from calibre.prints import prints +from polyglot.builtins import as_unicode class Stream(object): @@ -26,12 +25,11 @@ class Stream(object): if stream is None: stream = io.StringIO() self.stream = stream - self.is_binary = is_binary(self.stream) self.encoding = getattr(self.stream, 'encoding', None) or 'utf-8' - self._prints = partial(print, file=self) + self._prints = partial(prints, file=self.stream) def write(self, text): - return polyglot_write(self.stream, self.is_binary, self.encoding, text) + self._prints(text, end='') def flush(self): self.stream.flush() @@ -72,21 +70,20 @@ class FileStream(Stream): class HTMLStream(Stream): color = { - DEBUG: b'', - INFO: b'', - WARN: b'', - ERROR: b'' + DEBUG: '', + INFO: '', + WARN: '', + ERROR: '' } - normal = b'' + normal = '' 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(self.color[level], end='') self._prints(*args, **kwargs) - self.stream.write(self.normal) + self._prints(self.normal, end='') def flush(self): self.stream.flush() @@ -94,9 +91,6 @@ class HTMLStream(Stream): class UnicodeHTMLStream(HTMLStream): - color = {k: v.decode('ascii') for k, v in iteritems(HTMLStream.color)} - normal = HTMLStream.normal.decode('ascii') - def __init__(self): self.clear() @@ -111,14 +105,11 @@ class UnicodeHTMLStream(HTMLStream): self.data.append(col) self.last_col = col - sep = kwargs.get(u'sep', u' ') - end = kwargs.get(u'end', u'\n') + sep = kwargs.get('sep', ' ') + end = kwargs.get('end', '\n') for arg in args: - if isbytestring(arg): - arg = force_unicode(arg) - elif not isinstance(arg, unicode_type): - arg = as_unicode(arg) + arg = as_unicode(arg) self.data.append(arg+sep) self.plain_text.append(arg+sep) self.data.append(end) @@ -131,8 +122,8 @@ class UnicodeHTMLStream(HTMLStream): @property def html(self): - end = self.normal if self.data else u'' - return u''.join(self.data) + end + end = self.normal if self.data else '' + return ''.join(self.data) + end def dump(self): return [self.data, self.plain_text, self.last_col] diff --git a/src/calibre/utils/terminal.py b/src/calibre/utils/terminal.py index 47232974d3..817f3bc6ea 100644 --- a/src/calibre/utils/terminal.py +++ b/src/calibre/utils/terminal.py @@ -5,8 +5,9 @@ __license__ = 'GPL v3' __copyright__ = '2012, Kovid Goyal ' __docformat__ = 'restructuredtext en' -import os, sys, re, io +import os, sys, re +from calibre.prints import is_binary from calibre.constants import iswindows from polyglot.builtins import iteritems, range, zip @@ -101,13 +102,6 @@ def colored(text, fg=None, bg=None, bold=False): return prefix + text + suffix -def is_binary(stream): - mode = getattr(stream, 'mode', None) - if mode: - return 'b' in mode - return not isinstance(stream, io.TextIOBase) - - class Detect(object): def __init__(self, stream):