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 | Xuecong Liao | ||||||
| Zoltán Máté | Zoltán Máté | ||||||
| Roland Puntaier | Roland Puntaier | ||||||
|  | Allan Feldman | ||||||
|  |  | ||||||
|  | @ -24,6 +24,12 @@ from _pytest.compat import ( | ||||||
| from _pytest.outcomes import fail, TEST_OUTCOME | 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): | def pytest_sessionstart(session): | ||||||
|     import _pytest.python |     import _pytest.python | ||||||
|     import _pytest.nodes |     import _pytest.nodes | ||||||
|  | @ -440,10 +446,9 @@ class FixtureRequest(FuncargnamesCompatAttr): | ||||||
|                 fixturedef = self._getnextfixturedef(argname) |                 fixturedef = self._getnextfixturedef(argname) | ||||||
|             except FixtureLookupError: |             except FixtureLookupError: | ||||||
|                 if argname == "request": |                 if argname == "request": | ||||||
|                     class PseudoFixtureDef(object): |  | ||||||
|                     cached_result = (self, [0], None) |                     cached_result = (self, [0], None) | ||||||
|                     scope = "function" |                     scope = "function" | ||||||
|                     return PseudoFixtureDef |                     return PseudoFixtureDef(cached_result, scope) | ||||||
|                 raise |                 raise | ||||||
|         # remove indent to prevent the python3 exception |         # remove indent to prevent the python3 exception | ||||||
|         # from leaking into the call |         # 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 len(arg2fixturedefs) == 1 | ||||||
|         assert arg2fixturedefs['something'][0].argname == "something" |         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): |     def test_getfixturevalue_recursive(self, testdir): | ||||||
|         testdir.makeconftest(""" |         testdir.makeconftest(""" | ||||||
|             import pytest |             import pytest | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue