Merge pull request #3249 from a-feld/request-fixture-reference-cycle
Fix PseudoFixtureDef reference cycle.
This commit is contained in:
		
						commit
						bedceaacc4
					
				
							
								
								
									
										1
									
								
								AUTHORS
								
								
								
								
							
							
						
						
									
										1
									
								
								AUTHORS
								
								
								
								
							|  | @ -197,3 +197,4 @@ Xuan Luong | |||
| Xuecong Liao | ||||
| Zoltán Máté | ||||
| Roland Puntaier | ||||
| Allan Feldman | ||||
|  |  | |||
|  | @ -24,6 +24,12 @@ from _pytest.compat import ( | |||
| from _pytest.outcomes import fail, TEST_OUTCOME | ||||
| 
 | ||||
| 
 | ||||
| @attr.s(frozen=True) | ||||
| class PseudoFixtureDef(object): | ||||
|     cached_result = attr.ib() | ||||
|     scope = attr.ib() | ||||
| 
 | ||||
| 
 | ||||
| def pytest_sessionstart(session): | ||||
|     import _pytest.python | ||||
|     import _pytest.nodes | ||||
|  | @ -440,10 +446,9 @@ class FixtureRequest(FuncargnamesCompatAttr): | |||
|                 fixturedef = self._getnextfixturedef(argname) | ||||
|             except FixtureLookupError: | ||||
|                 if argname == "request": | ||||
|                     class PseudoFixtureDef(object): | ||||
|                     cached_result = (self, [0], None) | ||||
|                     scope = "function" | ||||
|                     return PseudoFixtureDef | ||||
|                     return PseudoFixtureDef(cached_result, scope) | ||||
|                 raise | ||||
|         # remove indent to prevent the python3 exception | ||||
|         # from leaking into the call | ||||
|  |  | |||
|  | @ -0,0 +1 @@ | |||
| Fix reference cycle generated when using the ``request`` fixture. | ||||
|  | @ -519,6 +519,41 @@ class TestRequestBasic(object): | |||
|         assert len(arg2fixturedefs) == 1 | ||||
|         assert arg2fixturedefs['something'][0].argname == "something" | ||||
| 
 | ||||
|     def test_request_garbage(self, testdir): | ||||
|         testdir.makepyfile(""" | ||||
|             import sys | ||||
|             import pytest | ||||
|             import gc | ||||
| 
 | ||||
|             @pytest.fixture(autouse=True) | ||||
|             def something(request): | ||||
|                 # this method of test doesn't work on pypy | ||||
|                 if hasattr(sys, "pypy_version_info"): | ||||
|                     yield | ||||
|                 else: | ||||
|                     original = gc.get_debug() | ||||
|                     gc.set_debug(gc.DEBUG_SAVEALL) | ||||
|                     gc.collect() | ||||
| 
 | ||||
|                     yield | ||||
| 
 | ||||
|                     gc.collect() | ||||
|                     leaked_types = sum(1 for _ in gc.garbage | ||||
|                                     if 'PseudoFixtureDef' in str(_)) | ||||
| 
 | ||||
|                     gc.garbage[:] = [] | ||||
| 
 | ||||
|                     try: | ||||
|                         assert leaked_types == 0 | ||||
|                     finally: | ||||
|                         gc.set_debug(original) | ||||
| 
 | ||||
|             def test_func(): | ||||
|                 pass | ||||
|         """) | ||||
|         reprec = testdir.inline_run() | ||||
|         reprec.assertoutcome(passed=1) | ||||
| 
 | ||||
|     def test_getfixturevalue_recursive(self, testdir): | ||||
|         testdir.makeconftest(""" | ||||
|             import pytest | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue