Skip to content

capsys breaks sys.stdin.encoding #2375

@kpinc

Description

@kpinc

Hi,

Using capsys breaks the use of sys.stdin.encoding. (And probably does the same for sys.stdout.encoding and other file like object encoding attributes.)

Using sys.stdout.encoding is important when writing portable code that sometimes outputs stdout to the MS Windows console, which may use cp1252 encoding. If you don't explicitly do something to encode your unicode strings and handle encoding failures then printing sometimes crashes your program with a UnicodeEncodeError exception. But testing sys.stdout.encoding with capsys is awkward.

See the example.

$ venv/bin/pip list
DEPRECATION: The default format will switch to columns in the future. You can use --format=(legacy|columns) (or define a format=(legacy|columns) in your pip.conf under the [list] section) to disable this warning.
appdirs (1.4.3)
packaging (16.8)
pip (9.0.1)
py (1.4.33)
pyparsing (2.2.0)
pytest (3.0.7)
setuptools (35.0.1)
six (1.10.0)

Debian stable 8.7 (Jessie)
Python 2.7.9 (from Debian repo)
(You get the same output from Debian's Python 3.4.2.)
#src/test_capsys.py 
from __future__ import print_function

import sys


def func(text):
    print(text.encode(sys.stdout.encoding, 'replace'))


def test_func(capsys):
    func('sample text')
    (out, err) = capsys.readouterr()
    assert out
    assert err == ''
$ venv/bin/pytest 
============================= test session starts ==============================
platform linux2 -- Python 2.7.9, pytest-3.0.7, py-1.4.33, pluggy-0.4.0
rootdir: *REDACTED*, inifile:
collected 1 items 

src/test_capsys.py F

=================================== FAILURES ===================================
__________________________________ test_func ___________________________________

capsys = <_pytest.capture.CaptureFixture instance at 0x7f90ba65a8c0>

    def test_func(capsys):
>       func('sample text')

src/test_capsys.py:11: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

text = 'sample text'

    def func(text):
>       print(text.encode(sys.stdout.encoding, 'replace'))
E       TypeError: encode() argument 1 must be string, not None

src/test_capsys.py:7: TypeError
=========================== 1 failed in 0.40 seconds ===========================

EDIT: fixed formatting

Metadata

Metadata

Assignees

No one assigned

    Labels

    good first issueeasy issue that is friendly to new contributorplugin: capturerelated to the capture builtin plugin

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions