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

pytest assumes stdout implements isatty() #5462

Closed
bernardlebel opened this issue Jun 19, 2019 · 15 comments
Closed

pytest assumes stdout implements isatty() #5462

bernardlebel opened this issue Jun 19, 2019 · 15 comments
Labels
type: bug problem that needs to be addressed

Comments

@bernardlebel
Copy link

Hello there,

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

I have read #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’t 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

@asottile
Copy link
Member

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

@bernardlebel
Copy link
Author

Is pytest 4.6 supported on python 2?

@asottile
Copy link
Member

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

@bernardlebel
Copy link
Author

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.

@Zac-HD Zac-HD added platform: python 2 only type: bug problem that needs to be addressed labels Jul 9, 2019
@nicoddemus
Copy link
Member

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

@binbs
Copy link

binbs commented Aug 6, 2019

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...

@asottile
Copy link
Member

asottile commented Aug 6, 2019

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

@blueyed
Copy link
Contributor

blueyed commented Aug 6, 2019

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

@asottile
Copy link
Member

asottile commented Aug 6, 2019

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

@binbs
Copy link

binbs commented Aug 7, 2019

@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...

@asottile
Copy link
Member

asottile commented Aug 7, 2019

@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

@blueyed
Copy link
Contributor

blueyed commented Aug 7, 2019

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

@OliverSchwanke
That should be done regardless.

@binbs
Copy link

binbs commented Aug 12, 2019

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...

@asottile
Copy link
Member

asottile commented Jun 2, 2020

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).

@asottile asottile closed this as completed Jun 2, 2020
@asztalosdani
Copy link

For anyone stumbling upon this looking for a workaround, I ended up writing a small wrapper for sys.stdout.

import sys

class StdOutWrapper:
    
    def __init__(self, stdout):
        self._stdout = stdout

    def __getattr__(self, item):
        if item == "isatty":
            return self.isatty
        else:
            return getattr(self._stdout, item)

    def isatty(self):
        return False


sys.stdout = StdOutWrapper(sys.stdout)

sys.stdout._stdout

gabrieljreed added a commit to DeRemerJD/Rig.Sys that referenced this issue Oct 26, 2023
gabrieljreed added a commit to DeRemerJD/Rig.Sys that referenced this issue Oct 26, 2023
* Create python code module

* Add python code module to example character

* Unit testing for python code module

* Fix test runner to handle this weird error.
pytest-dev/pytest#5462
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: bug problem that needs to be addressed
Projects
None yet
Development

No branches or pull requests

7 participants