Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FIX #162 "attached to a different loop", and add a new test case #164

Merged
merged 8 commits into from
Jun 2, 2020
Merged

FIX #162 "attached to a different loop", and add a new test case #164

merged 8 commits into from
Jun 2, 2020

Commits on May 24, 2020

  1. 1) A new test case that fails with 0.12.0, and pass with this commit.

       test_async_fixtures_with_finalizer_scope.py:
    2) Main problem is due to side effects of asyncio.get_event_loop(). See:
       https://github.com/python/cpython/blob/3.8/Lib/asyncio/events.py#L636
       This method could either return an existing loop or create a new one.
    
       This commit replaces all asyncio.get_event_loop() with previous pytest-asyncio code (0.10.0), so plugin uses the loop provided by event_loop fixture (instead of calling asyncio.get_event_loop())
    
       Except following block, that has not been modified in this commit (as it behaves similar to 0.10.0)
       https://github.com/pytest-dev/pytest-asyncio/blob/v0.12.0/pytest_asyncio/plugin.py#L54-L66
    
    Changes are for using always the new loop provided by event_loop fixture.
       Instead of calling get_event_loop() that:
       - either returns global recorded loop (with set_event_loop()) in case there is one,
       - or otherwise creates and record a new one
    alblasco committed May 24, 2020
    Configuration menu
    Copy the full SHA
    b96c042 View commit details
    Browse the repository at this point in the history

Commits on May 25, 2020

  1. 1) Test case (test_async_fixtures_with_finalizer) refactoring to pass…

    … on python 3.6 & 3.5
    
    2) An additional test case (test_module_with_get_event_loop_finalizer).
       Refactoring previous test case I got to another potential issue: Finalizers using get_event_loop() instead of event_loop [on a module scope fixture]
       To be able to pass this new test case I needed some additional changes on next event_loop fixture block(  https://github.com/pytest-dev/pytest-asyncio/blob/v0.12.0/pytest_asyncio/plugin.py#L54-L66):
       - This block needs to apply on all event_loop fixture scopes (so I remove 'asyncio' in request.keywords, that only apply to function scope)
       - The get_event_loop() method inside this block has following side effects (See https://github.com/python/cpython/blob/3.8/Lib/asyncio/events.py#L636):
         - As no loop is still set, then L636 is executed, and so a new event_loop (let's call it L2) is first created and then set.
    	 - And then finalizer will restore L2 at the end of test. What has no sense, to restore L2 that wasn't before the test. And additionally this L2 is never closed.
    	 So it seeems that get_event_loop() should be removed, and so I see no reasons for any finalizer.
    
    3) DRY: New FixtureStripper to avoid repeating code
    alblasco committed May 25, 2020
    Configuration menu
    Copy the full SHA
    bf4538c View commit details
    Browse the repository at this point in the history
  2. To solve test cases that fail:

    Even_loop() fixture properly closes the loop (but as explained below this is not enough to reset behaviour):
    ```
    @pytest.fixture
    def event_loop(request):
        """Create an instance of the default event loop for each test case."""
        loop = asyncio.get_event_loop_policy().new_event_loop()
        yield loop
        loop.close()
    ```
    Subsequent calls to asyncio.get_event_loop() returns the previous closed loop, instead of providing a new loop.
    This is due to (https://github.com/python/cpython/blob/3.8/Lib/asyncio/events.py#L634) variable _set_called is True, and so even when loop is None, then no new_event_loop is created [I really don´t know the reason of this _set_called behaviour].
    
    The best solution I have found is to set_event_loop_policy(None). This completely resets global variable and so any subsequent call to asyncio.get_event_loop() provides a new event_loop.
    I have included this in the pytest hook (pytest_fixture_post_finalizer), that is called after fixture teardowns.
    
    Note: Same behaviour can be done modifying event_loop() fixture, but I have discarded it as this would force users that have overwritten even_loop fixture to modify its implementation:
    ```
    @pytest.fixture
    def event_loop(request):
        """Create an instance of the default event loop for each test case."""
        loop = asyncio.get_event_loop_policy().new_event_loop()
        yield loop
        loop.close()
    	asyncio.set_event_loop_policy(None)
    ```
    alblasco committed May 25, 2020
    Configuration menu
    Copy the full SHA
    a151a60 View commit details
    Browse the repository at this point in the history
  3. FIX new test_cases on python 3.5 & 3.6

    asyncio.create_task has been added in Python 3.7. The low-level asyncio.ensure_future() function can be used instead (works in all Python versions but is less readable).
    
    https://docs.python.org/3/library/asyncio-task.html#asyncio.create_task
    alblasco committed May 25, 2020
    Configuration menu
    Copy the full SHA
    341c369 View commit details
    Browse the repository at this point in the history

Commits on May 26, 2020

  1. Clarify names and comments, according to yanlend comments 26 May

    Angel Luis Blasco committed May 26, 2020
    Configuration menu
    Copy the full SHA
    f246a8c View commit details
    Browse the repository at this point in the history
  2. One import is not needed

    Angel Luis Blasco committed May 26, 2020
    Configuration menu
    Copy the full SHA
    882c11e View commit details
    Browse the repository at this point in the history

Commits on Jun 1, 2020

  1. A line is added to the changelog.

    Please review release date
    alblasco committed Jun 1, 2020
    Configuration menu
    Copy the full SHA
    81af289 View commit details
    Browse the repository at this point in the history
  2. Configuration menu
    Copy the full SHA
    1ee279e View commit details
    Browse the repository at this point in the history