TestTableSchemaRepr::test_publishes - AttributeError: '_GeneratorContextManager' object has no attribute 'args'

I've been seeing this for a couple weeks.

Comment From: lithomas1

Can you paste the traceback?

Comment From: jbrockmendel

_________________________________________________________ TestTableSchemaRepr.test_publishes __________________________________________________________

self = <pandas.tests.io.formats.test_ipython_compat.TestTableSchemaRepr object at 0x12bb71890>
ip = <IPython.core.interactiveshell.InteractiveShell object at 0x2cc064e10>

    def test_publishes(self, ip):
        ipython = ip.instance(config=ip.config)
        df = DataFrame({"A": [1, 2]})
        objects = [df["A"], df]  # dataframe / series
        expected_keys = [
            {"text/plain", "application/vnd.dataresource+json"},
            {"text/plain", "text/html", "application/vnd.dataresource+json"},
        ]

        opt = cf.option_context("display.html.table_schema", True)
        last_obj = None
        for obj, expected in zip(objects, expected_keys):
            last_obj = obj
>           with opt:

pandas/tests/io/formats/test_ipython_compat.py:25: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <contextlib._GeneratorContextManager object at 0x2d15ac210>

    def __enter__(self):
        # do not keep args and kwds alive unnecessarily
        # they are only needed for recreation, which is not possible anymore
>       del self.args, self.kwds, self.func
E       AttributeError: '_GeneratorContextManager' object has no attribute 'args'

../../../.pyenv/versions/3.11.7/lib/python3.11/contextlib.py:135: AttributeError

Comment From: lithomas1

This diff fixes it for me, not sure why though.

Maybe it's an ipython bug?

(opt is cf.option_context("display.html.table_schema", True))

diff --git a/pandas/tests/io/formats/test_ipython_compat.py b/pandas/tests/io/formats/test_ipython_compat.py
index 8512f41396..67bb0fb9e3 100644
--- a/pandas/tests/io/formats/test_ipython_compat.py
+++ b/pandas/tests/io/formats/test_ipython_compat.py
@@ -22,7 +22,7 @@ class TestTableSchemaRepr:
         last_obj = None
         for obj, expected in zip(objects, expected_keys):
             last_obj = obj
-            with opt:
+            with cf.option_context("display.html.table_schema", True):
                 formatted = ipython.display_formatter.format(obj)
             assert set(formatted[0].keys()) == expected

Comment From: jbrockmendel

That fixes it for me too

Comment From: Aloqeely

Happens to me on Windows as well, and that fixes it for me My guess is that this context manager is not re-usable

Comment From: avm19

Happens to me on Windows as well, and that fixes it for me

I can confirm on Linux.

@lithomas1 :

Maybe it's an ipython bug?

I don't think so. See the example below.

My guess is that this context manager is not re-usable

Agree. Pandas is using this pattern, which reproduces precisely the same error:

from contextlib import contextmanager
@contextmanager
def cm_factory():
    yield

cm = cm_factory()
with cm: pass  # works
with cm: pass  # fails
# AttributeError: '_GeneratorContextManager' object has no attribute 'args'

According to Python 3 docs (emphasis is mine),

... it is generally advisable to create context managers directly in the header of the with statement where they are used ... ... Context managers created using contextmanager() are also single use context managers ...

To sum up: the source of the bug is clear, the proposed solution seems correct (just remember to also replace the second occurrence of opt). To me, the only question is why had this test code ever worked? I guess, previous Python versions had a slightly different implementation of contextmanager.

Comment From: lithomas1

I don't remember the context behind this anymore, sorry.

Feel free to open up a PR for more discussion.