pytest assumes stdout implements isatty()

Created on 20 Jun 2019  路  14Comments  路  Source: pytest-dev/pytest

Hello there,

TerminalWriter assumes that the sys.stdout object has a isatty() method.

I have read https://github.com/pytest-dev/pytest/issues/1447, and I'm not sure that the point about io.IOBase is always true. According to the sys.stdout documentation:

stdout and stderr needn鈥檛 be built-in file objects: any object is acceptable as long as it has a write() method that takes a string argument.

In my case, the sys.stdout object isn't under my control, it's provided by a DCC application (Maya), and it doesn't have that method at all. It's a C object so python doesn't even let me add a method to it.

Here's the traceback I get:

# INTERNALERROR> Traceback (most recent call last):
# INTERNALERROR>   File "/rel/lang/python/packages/pytest/4.6.2/python-2.7/python/_pytest/main.py", line 202, in wrap_session
# INTERNALERROR>     config._do_configure()
# INTERNALERROR>   File "/rel/lang/python/packages/pytest/4.6.2/python-2.7/python/_pytest/config/__init__.py", line 671, in _do_configure
# INTERNALERROR>     self.hook.pytest_configure.call_historic(kwargs=dict(config=self))
# INTERNALERROR>   File "/rel/lang/python/packages/pluggy/0.12.0/python-2.7/python/pluggy/hooks.py", line 311, in call_historic
# INTERNALERROR>     res = self._hookexec(self, self.get_hookimpls(), kwargs)
# INTERNALERROR>   File "/rel/lang/python/packages/pluggy/0.12.0/python-2.7/python/pluggy/manager.py", line 87, in _hookexec
# INTERNALERROR>     return self._inner_hookexec(hook, methods, kwargs)
# INTERNALERROR>   File "/rel/lang/python/packages/pluggy/0.12.0/python-2.7/python/pluggy/manager.py", line 81, in <lambda>
# INTERNALERROR>     firstresult=hook.spec.opts.get("firstresult") if hook.spec else False,
# INTERNALERROR>   File "/rel/lang/python/packages/pluggy/0.12.0/python-2.7/python/pluggy/callers.py", line 208, in _multicall
# INTERNALERROR>     return outcome.get_result()
# INTERNALERROR>   File "/rel/lang/python/packages/pluggy/0.12.0/python-2.7/python/pluggy/callers.py", line 81, in get_result
# INTERNALERROR>     _reraise(*ex)  # noqa
# INTERNALERROR>   File "/rel/lang/python/packages/pluggy/0.12.0/python-2.7/python/pluggy/callers.py", line 187, in _multicall
# INTERNALERROR>     res = hook_impl.function(*args)
# INTERNALERROR>   File "/rel/lang/python/packages/pytest/4.6.2/python-2.7/python/_pytest/terminal.py", line 151, in pytest_configure
# INTERNALERROR>     reporter = TerminalReporter(config, sys.stdout)
# INTERNALERROR>   File "/rel/lang/python/packages/pytest/4.6.2/python-2.7/python/_pytest/terminal.py", line 248, in __init__
# INTERNALERROR>     self.isatty = file.isatty()
# INTERNALERROR> AttributeError: 'maya.Output' object has no attribute 'isatty'

Right now I'm forced to monkey patch the DCC object.

Thanks!
Bernard

python 2 only bug

Most helpful comment

PR is done, so itom is working with pytest now.
@asottile I would not say that it's lying about what's correct,
because if it does not have the feature "isatty", it's obviously not a tty (in terms of doesn't implement its interface).
But you are very right in saying that this is not an error on pytest side, so it's not up to you to fix it.
Thank you anyway very much for the hint with the standard streams...

All 14 comments

I'm not sure maya's behaviour is valid, that line has been stricken from the python 3 documentation: https://docs.python.org/3/library/sys.html#sys.stdout

Is pytest 4.6 supported on python 2?

it is, but given it was removed from the python3 docs I'm not sure it's important to fix for python2 either

Well, Maya 2018 is python 2 and afaik its implementation of stdout meets the requirements of python 2.
Now, the version of Maya that will support python 3 has not been announced yet, but I have a hunch it won't be before the last quarter of 2020. So up to you.

@bernardlebel would you like to contribute a patch? I would love to review and merge this fix into the 4.6-maintenance branch.

Hello there,
i am having the same problem, but i'm forced to using itom(another python-console include project) which does connect the python interpreter as a stream/socket object.

As a quick fix i changed the lines 248 in _pytest\terminal.py
from
self.isatty = file.isatty()
to:

try:
    self.isatty = file.isatty()
except:
    self.isatty = False

I can use pytest now(without the capture things, because fds 0,1,2 are not openable on this software...)

Would this be an appropriate fix for pytest module?

P.S. i'm using python3 here, so i think this bug is not only related to python2...

The bug is in itom, it should implement isatty when monkeypatching standard streams

Yeah.
But I think falling back to False would be nice - although it should only catch AttributeError likely.

I disagree, I don't think we should intentionally enable broken code -- if itom would have dogfood tested with pytest they would have found this and fixed it

@blueyed Yes, you're right. catching AttributeError only is the better approach.
@asottile thanks for the hint with the streams at first, i will check this.
But i think it's a little unfair to blame the itom devs, as maya obviously(and maybe other programs too) would benefit from this feature.
I think it is still pretty clear what the writer intends with this try/catch thing.
You would help me bringing pytest to the realms of itom, so at least i don't have to go with plain unittests anymore...

@OliverSchwanke it's not about intention, it's about enabling broken code

say I was developing such a thing, I would want to know that I'm implementing a stream incorrectly and if my test runner is _lying to me about what's correct_ I'd be pretty peeved with my test runner

I'd much rather send a PR to itom to fix their monkeypatch

I'd much rather send a PR to itom to fix their monkeypatch

@OliverSchwanke
That should be done regardless.

PR is done, so itom is working with pytest now.
@asottile I would not say that it's lying about what's correct,
because if it does not have the feature "isatty", it's obviously not a tty (in terms of doesn't implement its interface).
But you are very right in saying that this is not an error on pytest side, so it's not up to you to fix it.
Thank you anyway very much for the hint with the standard streams...

hello, first off thank you for the issue!

python 2.x support has ended for pytest core.

we've decided in #7296 to close the python-2-specific issues to free up some space in our backlog. however, in accordance to our python 2.7 and 3.4 support community patches will still be accepted to the 4.6 series to fix bugs for python 2. (so if this issue is important to you and you have a patch to fix it, feel free to make a PR targeting the 4.6.x branch despite this ticket being closed).

Was this page helpful?
0 / 5 - 0 ratings