Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

capsys breaks sys.stdin.encoding #2375

Closed
kpinc opened this issue Apr 20, 2017 · 4 comments · Fixed by #2578
Closed

capsys breaks sys.stdin.encoding #2375

kpinc opened this issue Apr 20, 2017 · 4 comments · Fixed by #2578
Labels
good first issue easy issue that is friendly to new contributor plugin: capture related to the capture builtin plugin

Comments

@kpinc
Copy link
Contributor

kpinc commented Apr 20, 2017

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

@nicoddemus
Copy link
Member

Thanks for the report!

It seems it should be just a matter of copying the encoding attribute from the original stream.

@nicoddemus nicoddemus added plugin: capture related to the capture builtin plugin good first issue easy issue that is friendly to new contributor labels Apr 20, 2017
@kpinc
Copy link
Contributor Author

kpinc commented Apr 20, 2017 via email

@kpinc
Copy link
Contributor Author

kpinc commented Apr 20, 2017 via email

@maiksensi
Copy link
Contributor

maiksensi commented Jul 15, 2017

I could only reproduce this for py27 running it via: tox -e py27,py34,py36,py35 -- testcases/test_capsys.py.

ERROR:   py27: commands failed
  py34: commands succeeded
  py36: commands succeeded
  py35: commands succeeded

The py27 outout is:

testcases/test_capsys.py F
==================================================================================================== short test summary info =====================================================================================================
FAIL testcases/test_capsys.py::test_func

============================================================================================================ FAILURES ============================================================================================================
___________________________________________________________________________________________________________ test_func ____________________________________________________________________________________________________________

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

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

testcases/test_capsys.py:12: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

text = 'sample text'

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

testcases/test_capsys.py:8: TypeError
==================================================================================================== 1 failed in 0.05 seconds ====================================================================================================
ERROR: InvocationError: '/home/maiksen/repos/pytest/.tox/py27/bin/pytest --lsof -rfsxX testcases/test_capsys.py'

I am on the latest py3.4 available and on ubuntu 16.04.

This doesnt probably change the suggestions on what to change to fix the issue.

Llandy3d added a commit to Llandy3d/pytest that referenced this issue Jul 15, 2017
Fixes patching sys.stdout.encoding when using Capsys fixture on Python 2.

Fix pytest-dev#2375
Llandy3d added a commit to Llandy3d/pytest that referenced this issue Jul 15, 2017
Removed py.io dependency for CaptureIO.

Fix pytest-dev#2375
Llandy3d added a commit to Llandy3d/pytest that referenced this issue Jul 16, 2017
Llandy3d added a commit to Llandy3d/pytest that referenced this issue Jul 16, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
good first issue easy issue that is friendly to new contributor plugin: capture related to the capture builtin plugin
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants