77import functools
88import gc
99import os
10+ import sys
1011import time
1112import warnings
1213from pathlib import Path
1314
1415import numpy as np
1516import pyvista
1617import sphinx .util .logging
18+ from refleak .testing import assert_no_instances
1719from sphinx .errors import ExtensionError
1820
1921import mne
20- from mne .utils import (
21- _assert_no_instances ,
22- _get_extra_data_path ,
23- sizeof_fmt ,
24- )
22+ from mne .utils import Bunch , _get_extra_data_path , sizeof_fmt
2523from mne .viz import Brain
2624
2725sphinx_logger = sphinx .util .logging .getLogger ("mne" )
@@ -177,6 +175,18 @@ def reset_modules(gallery_conf, fname, when):
177175 neo .io .stimfitio .STFIO_ERR = None
178176 except Exception :
179177 pass
178+ # IPython.core.completer does `import __main__` at import time, permanently
179+ # capturing whatever sys.modules['__main__'] was at that moment. Since SG
180+ # temporarily swaps sys.modules['__main__'] to each example's throwaway
181+ # namespace while it runs, if that import happens to fire during one of
182+ # those windows, it pins that example's globals (and anything reachable
183+ # from them) alive for the rest of the process.
184+ try :
185+ import IPython .core .completer
186+
187+ IPython .core .completer .__main__ = sys .modules ["__main__" ]
188+ except Exception :
189+ pass
180190 gc .collect ()
181191
182192 # Agg does not call close_event so let's clean up on our own :(
@@ -192,19 +202,21 @@ def reset_modules(gallery_conf, fname, when):
192202 # to just test MNEQtBrowser
193203 skips = os .getenv ("MNE_SKIP_INSTANCE_ASSERTIONS" , "" ).lower ()
194204 prefix = ""
205+ request = Bunch () # just give it something to say "we have done GC already"
206+ request .node = Bunch ()
195207 if skips not in ("true" , "1" , "all" ):
196208 prefix = "Clean "
197209 skips = skips .split ("," )
198210 if "brain" not in skips :
199- _assert_no_instances (Brain , when ) # calls gc.collect( )
211+ assert_no_instances (Brain , when = when , request = request )
200212 if Plotter is not None and "plotter" not in skips :
201- _assert_no_instances (Plotter , when )
213+ assert_no_instances (Plotter , when = when , request = request )
202214 if BackgroundPlotter is not None and "backgroundplotter" not in skips :
203- _assert_no_instances (BackgroundPlotter , when )
215+ assert_no_instances (BackgroundPlotter , when = when , request = request )
204216 if vtkPolyData is not None and "vtkpolydata" not in skips :
205- _assert_no_instances (vtkPolyData , when )
217+ assert_no_instances (vtkPolyData , when = when , request = request )
206218 if "_renderer" not in skips :
207- _assert_no_instances (_Renderer , when )
219+ assert_no_instances (_Renderer , when = when , request = request )
208220 if MNEQtBrowser is not None and "mneqtbrowser" not in skips :
209221 # Ensure any manual fig.close() events get properly handled
210222 from mne_qt_browser ._pg_figure import QApplication
@@ -213,7 +225,7 @@ def reset_modules(gallery_conf, fname, when):
213225 if inst is not None :
214226 for _ in range (2 ):
215227 inst .processEvents ()
216- _assert_no_instances (MNEQtBrowser , when )
228+ assert_no_instances (MNEQtBrowser , when = when , request = request )
217229 # This will overwrite some Sphinx printing but it's useful
218230 # for memory timestamps
219231 if os .getenv ("SG_STAMP_STARTS" , "" ).lower () == "true" :
0 commit comments