Skip to content

Commit

Permalink
print_: coverage; make it take any kind of object like print()
Browse files Browse the repository at this point in the history
  • Loading branch information
lazka committed Aug 20, 2016
1 parent 1354523 commit 0538d35
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 11 deletions.
41 changes: 30 additions & 11 deletions senf/_print.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,18 +26,19 @@ def print_(*objects, **kwargs):
"""print_(*objects, sep=None, end=None, file=None, flush=False)
Arguments:
objects: none or more `bytes` or `text`
sep (fsnative): Object separator to use, defaults to ``" "``
end (fsnative): Trailing string to use, defaults to ``"\\n"``.
objects (object): zero or more objects to print
sep (str): Object separator to use, defaults to ``" "``
end (str): Trailing string to use, defaults to ``"\\n"``.
If end is ``"\\n"`` then `os.linesep` is used.
file (object): A file-like object, defaults to `sys.stdout`
flush (bool): If the file stream should be flushed
A print which supports printing bytes under Unix + Python 3 and Unicode
under Windows + Python 2.
Like print(), but:
In addition it interprets ANSI escape sequences on platforms which
don't support them.
* Supports printing filenames under Unix + Python 3 and Windows + Python 2
* Emulates ANSI escape sequence support under Windows
* Never fails due to encoding/decoding errors. Tries hard to get everything
on screen as is, but will fall back to "?" if all fails.
"""

sep = kwargs.get("sep", " ")
Expand All @@ -64,20 +65,31 @@ def _print_default(objects, sep, end, file, flush):

if isinstance(sep, text_type):
sep = sep.encode(encoding, "replace")
if not isinstance(sep, bytes):
raise TypeError

if isinstance(end, text_type):
end = end.encode(encoding, "replace")
if not isinstance(end, bytes):
raise TypeError

parts = []
for obj in objects:
if not isinstance(obj, text_type) and not isinstance(obj, bytes):
obj = text_type(obj)
if isinstance(obj, text_type):
if PY2:
obj = obj.encode(encoding, "replace")
else:
obj = obj.encode(encoding, "surrogateescape")
try:
obj = obj.encode(encoding, "surrogateescape")
except UnicodeEncodeError:
obj = obj.encode(encoding, "replace")
assert isinstance(obj, bytes)
parts.append(obj)

data = sep.join(parts) + end
assert isinstance(data, bytes)

file = getattr(file, "buffer", file)

Expand Down Expand Up @@ -134,8 +146,15 @@ def _print_windows(objects, sep, end, file, flush):
obj = text_type(obj)
parts.append(obj)

sep = path2fsn(sep)
end = path2fsn(end)
if isinstance(sep, bytes):
sep = sep.decode(encoding, "replace")
if not isinstance(sep, text_type):
raise TypeError

if isinstance(end, bytes):
end = end.decode(encoding, "replace")
if not isinstance(end, text_type):
raise TypeError

text = sep.join(parts) + end
assert isinstance(text, text_type)
Expand Down Expand Up @@ -164,7 +183,7 @@ def _print_windows(objects, sep, end, file, flush):
def input_(prompt=None):
"""
Args:
prompt (`bytes` or `text`): Prints the passed text to stdout without
prompt (object): Prints the passed text to stdout without
a trailing newline
Returns:
`fsnative`
Expand Down
30 changes: 30 additions & 0 deletions tests/test_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,36 @@ def test_print():
print_(u"foo", file=f, flush=True)


def test_print_ansi():
for i in range(1, 110):
print_("\033[%dm" % i, end="")
other = ["\033[A", "\033[B", "\033[C", "\033[D", "\033[s", "\033[u",
"\033[H", "\033[f"]
for c in other:
print_(c, end="")


def test_print_anything():
with capture_output():
print_(u"\u1234")

with capture_output() as (out, err):
print_(5, end="")
assert out.getvalue() == b"5"

with capture_output() as (out, err):
print_([], end="")
assert out.getvalue() == b"[]"


def test_print_error():
with pytest.raises(TypeError):
print_(end=4)

with pytest.raises(TypeError):
print_(sep=4)


@pytest.mark.skipif(os.name == "nt" or PY2, reason="unix+py3 only")
def test_print_strict_strio():
f = StringIO()
Expand Down

0 comments on commit 0538d35

Please sign in to comment.