Add a typing-compatible mechanism for ad-hoc attributes on various objects
pytest has several instances where plugins set their own attributes on objects they receive in hooks, like nodes and config. Since plugins are detached from these object's definition by design, this causes a problem for type checking because these attributes are not defined and mypy complains. Fix this by giving these objects a "store" which can be used by plugins in a type-safe manner. Currently this mechanism is private. We can consider exposing it at a later point.
This commit is contained in:
@@ -1,7 +1,12 @@
|
||||
""" submit failure or test session information to a pastebin service. """
|
||||
import tempfile
|
||||
from typing import IO
|
||||
|
||||
import pytest
|
||||
from _pytest.store import StoreKey
|
||||
|
||||
|
||||
pastebinfile_key = StoreKey[IO[bytes]]()
|
||||
|
||||
|
||||
def pytest_addoption(parser):
|
||||
@@ -26,25 +31,26 @@ def pytest_configure(config):
|
||||
# when using pytest-xdist, for example
|
||||
if tr is not None:
|
||||
# pastebin file will be utf-8 encoded binary file
|
||||
config._pastebinfile = tempfile.TemporaryFile("w+b")
|
||||
config._store[pastebinfile_key] = tempfile.TemporaryFile("w+b")
|
||||
oldwrite = tr._tw.write
|
||||
|
||||
def tee_write(s, **kwargs):
|
||||
oldwrite(s, **kwargs)
|
||||
if isinstance(s, str):
|
||||
s = s.encode("utf-8")
|
||||
config._pastebinfile.write(s)
|
||||
config._store[pastebinfile_key].write(s)
|
||||
|
||||
tr._tw.write = tee_write
|
||||
|
||||
|
||||
def pytest_unconfigure(config):
|
||||
if hasattr(config, "_pastebinfile"):
|
||||
if pastebinfile_key in config._store:
|
||||
pastebinfile = config._store[pastebinfile_key]
|
||||
# get terminal contents and delete file
|
||||
config._pastebinfile.seek(0)
|
||||
sessionlog = config._pastebinfile.read()
|
||||
config._pastebinfile.close()
|
||||
del config._pastebinfile
|
||||
pastebinfile.seek(0)
|
||||
sessionlog = pastebinfile.read()
|
||||
pastebinfile.close()
|
||||
del config._store[pastebinfile_key]
|
||||
# undo our patching in the terminal reporter
|
||||
tr = config.pluginmanager.getplugin("terminalreporter")
|
||||
del tr._tw.__dict__["write"]
|
||||
|
||||
Reference in New Issue
Block a user