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 + sys.stdout.buffer => AttributeError #1407

Closed
asottile opened this issue Feb 22, 2016 · 9 comments
Closed

capsys + sys.stdout.buffer => AttributeError #1407

asottile opened this issue Feb 22, 2016 · 9 comments

Comments

@asottile
Copy link
Member

Applicable versions where sys.stdout.buffer should exist and be a bytestream:

  • python3.x
import sys


def test(capsys):
    sys.stdout.buffer.write(b'hi\n')
    assert capsys.readouterr()[0] == 'hi\n'
$ py.test test.py
============================= test session starts ==============================
platform linux -- Python 3.4.3, pytest-2.8.7, py-1.4.31, pluggy-0.3.1
rootdir: /home/asottile/workspace/cheetah_lint, inifile: 
collected 1 items 

test.py F

=================================== FAILURES ===================================
_____________________________________ test _____________________________________

capsys = <_pytest.capture.CaptureFixture object at 0x7f15ca2cd320>

    def test(capsys):
>       sys.stdout.buffer.write(b'hi\n')
E       AttributeError: '_io.StringIO' object has no attribute 'buffer'

test.py:5: AttributeError
=========================== 1 failed in 0.01 seconds ===========================
@nicoddemus
Copy link
Member

Hmm I'm not sure how to solve this @asottile... after all io.StringIO doesn't have a buffer object anyway. Do you have any suggestion on how this could be fixed?

@asottile
Copy link
Member Author

Perhaps an object that looks something like this?

class FakeStdout(object):
    def __init__(self):
        self.buffer = io.BytesIO()

    def write(self, s):
        self.buffer.write(s.encode('UTF-8'))

    def _read_out(self):
        return self.buffer.getvalue().decode('UTF-8')

though that has at least 3 cases where I can see it not working :S

Maybe introduce a capsysbytes which handles this case and returns bytes instead of text (str PY3 / unicode PY2)?

@funkyfuture
Copy link

i also am in need of such functionality. any idea for a simple workaround for now?

propably i will capsys.close(), replace the capsys.captureclass with a subclass of SysCapture for bytes and capsys._start() at a test's start.

concerning the design of a native support for this, i have these considerations:

  • there should also be support for a binary capfd-like
  • should the data type be configurable per filedescriptor?
    • writing bytes to stdout and text to stderr is propably not uncommon

i'm not really fond of further, longer fixture names. though the idea of configuring the fixtures (e.g. with a set_mode method) per test also doesn't convince me.

@nicoddemus
Copy link
Member

should the data type be configurable per filedescriptor?

Good point.

i'm not really fond of further, longer fixture names. though the idea of configuring the fixtures (e.g. with a set_mode method) per test also doesn't convince me.

I think a capsys.set_mode('b', 'out') is not a bad idea actually (if we can change that after the fixture was created, that is). There are plenty of mechanisms that you can use so that you don't need to configure capsys for all tests which need it, from marks to autouse-fixtures.

Btw, I mention capsys.set_mode('b', 'out') instead of the arguably more natural capsys.set_mode('out', 'b') because we can have the second argument optional and mean "all streams" when not given.

@funkyfuture
Copy link

There are plenty of mechanisms that you can use so that you don't need to configure capsys for all tests which need it, from marks to autouse-fixtures.

okay, should be well documented.

your signature proposal looks good. the complement should be t (yeah, it's obvious).

when i'm responsible towards myself and my schedule, i will not implement that too soon. :-/ i certainly appreciate if someone else did it.

@nicoddemus
Copy link
Member

Yeah, a PR would be most welcome. 😁

@RonnyPfannschmidt
Copy link
Member

imho capture should NOT support buffer by default, only if its requested as encoded

@funkyfuture
Copy link

as far as i understood, no one is proposing a different default behavior. could you elaborate your point?

@nicoddemus
Copy link
Member

Fixed by #2266

This was referenced Mar 6, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants