1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133
|
# -*- coding: utf-8 -*-
import locale
import os
import sys
from DisplayCAL.encoding import get_encodings
original_codepage = None
enc, fs_enc = get_encodings()
_conwidth = None
def _get_console_width():
global _conwidth
if _conwidth is None:
_conwidth = 80
try:
if sys.platform == "win32":
from ctypes import windll, create_string_buffer
import struct
# Use stderr handle so that pipes don't affect the reported size
stderr_handle = windll.kernel32.GetStdHandle(-12)
buf = create_string_buffer(22)
consinfo = windll.kernel32.GetConsoleScreenBufferInfo(
stderr_handle, buf
)
if consinfo:
_conwidth = struct.unpack("hhhhHhhhhhh", buf.raw)[0]
else:
_conwidth = int(os.getenv("COLUMNS"))
except Exception:
pass
return _conwidth
class SafePrinter:
def __init__(
self,
pad=False,
padchar=" ",
sep=" ",
end="\n",
file_=sys.stdout,
fn=None,
encoding=None,
):
"""Write safely, avoiding any UnicodeDe-/EncodingErrors on strings and
converting all other objects to safe string representations.
sprint = SafePrinter(pad=False, padchar=' ', sep=' ', end='\\n',
file=sys.stdout, fn=None)
sprint(value, ..., pad=False, padchar=' ', sep=' ', end='\\n',
file=sys.stdout, fn=None)
Writes the values to a stream (default sys.stdout), honoring its encoding and
replacing characters not present in the encoding with question marks silently.
Optional keyword arguments:
pad: pad the lines to n chars, or os.getenv('COLUMNS') if True.
padchar: character to use for padding, default a space.
sep: string inserted between values, default a space.
end: string appended after the last value, default a newline.
file: a file-like object (stream); defaults to the sys.stdout.
fn: a function to execute instead of printing.
"""
self.pad = pad
self.padchar = padchar
self.sep = sep
self.end = end
self.file = file_
self.fn = fn
self.encoding = "utf-8"
def __call__(self, *args, **kwargs):
# TODO: Why calling the instance writes it, this is not a good practice.
self.write(*args, **kwargs)
def flush(self):
self.file and self.file.flush()
def write(self, *args, **kwargs):
pad = kwargs.get("pad", self.pad)
padchar = kwargs.get("padchar", self.padchar)
sep = kwargs.get("sep", self.sep)
end = kwargs.get("end", self.end)
file_ = kwargs.get("file_", self.file)
fn = kwargs.get("fn", self.fn)
encoding = self.encoding
# convert everything to bytes
if isinstance(padchar, str):
padchar = padchar.encode(self.encoding)
if isinstance(sep, str):
sep = sep.encode(self.encoding)
if isinstance(end, str):
end = end.encode(self.encoding)
strargs = []
for arg in args:
if not isinstance(arg, bytes):
arg = bytes(arg, encoding, "asciize")
strargs.append(arg)
line = sep.join(strargs).rstrip(end)
if pad is not False:
if pad is True:
width = _get_console_width()
else:
width = int(pad)
line = line.ljust(width, padchar)
if fn:
fn(line)
else:
try:
if "b" not in file_.mode:
line = line.decode(self.encoding)
if end:
end = end.decode(self.encoding)
file_.write(line)
if end:
file_.write(end)
except IOError:
pass
safe_print = SafePrinter()
if __name__ == "__main__":
for arg in sys.argv[1:]:
print(arg)
|