Skip to content

Alternative policies support #174

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

Closed
wants to merge 2 commits into from
Closed

Alternative policies support #174

wants to merge 2 commits into from

Conversation

Tinche
Copy link
Member

@Tinche Tinche commented Jun 28, 2020

Introduces code for handling custom event loop policies and tests for it.

Apologies for reformatting noise, I'm using black now.

@Tinche
Copy link
Member Author

Tinche commented Jun 28, 2020

The tests are failing atm because in the test scenario (and in the toy project I've created to test this) the event_loop fixture gets executed before the event_loop_policy fixture for the first test only. This could be because we inject the event_loop fixture into the list of fixtures as the first element. So maybe the logic there could be improved.

@Tinche
Copy link
Member Author

Tinche commented Jun 28, 2020

One fix is to override the event_loop fixture to depend on your event_loop_policy fixture explicitly:

@pytest.fixture(autouse=True, scope="session")
def event_loop_policy():
    asyncio.set_event_loop_policy(CustomSelectorLoopPolicy())
    yield
    asyncio.set_event_loop_policy(None)


@pytest.fixture()
def event_loop(event_loop_policy):
    return asyncio.new_event_loop()

This is boilerplate though, let's see if we can come up with something better.

@Tinche
Copy link
Member Author

Tinche commented Jun 28, 2020

Fun fact: the event_loop fixture being prepended instead of appended to the list of fixtures for asyncio tests was added recently in #154.

@Tinche
Copy link
Member Author

Tinche commented Jun 28, 2020

The solution I'm leaning towards is making event_loop_policy a magical fixture you should override if you want to install your own policy, like event_loop is a magical fixture.

@alblasco
Copy link
Contributor

alblasco commented Jun 28, 2020

Apologies for reformatting noise, I'm using black now.

I use black too (and prospector)

The solution I'm leaning towards is making event_loop_policy a magical fixture you should override if you want to install your own policy, like event_loop is a magical fixture.

This sounds good. What about the following, as an easy solution :

  • Option 1.a: Only one fixture. You have to include inside event_loop:
@pytest.fixture
def event_loop():
    """Create an instance of the default event loop for each test case."""
    asyncio.set_event_loop_policy(XXXLoopPolicy())
    loop = asyncio.get_event_loop_policy().new_event_loop()
    yield loop
    loop.close()
    asyncio.set_event_loop_policy(None)
  • Option 1.b: Two fixtures (in very special cases, if any, as normally it wouldn´t be needed). And then users have to make explicit dependencies:
@pytest.fixture
def event_loop_policy():
    """Create an instance of the default event loop for each test case."""
    asyncio.set_event_loop_policy(XXXLoopPolicy())
    yield loop
    asyncio.set_event_loop_policy(None)

@pytest.fixture
def event_loop(event_loop_policy):
    """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()
  • Option 2: Pytest-asyncio to provide always an empty event_loop_policy:,
@pytest.fixture
def event_loop_policy():
    pass

that could be overwritten by customer:

@pytest.fixture
def event_loop_policy():
    """Create an instance of the default event loop for each test case."""
    asyncio.set_event_loop_policy(XXXLoopPolicy())
    yield loop
    asyncio.set_event_loop_policy(None)

With this option you can force order:

    if "event_loop" in item.fixturenames:
        item.fixturenames.remove("event_loop")
    item.fixturenames.insert(0, "event_loop")
	
    if "event_loop_policy" in item.fixturenames:
        item.fixturenames.remove("event_loop_policy")
    item.fixturenames.insert(0, "event_loop_policy")

@Tinche
Copy link
Member Author

Tinche commented Jun 28, 2020

Hm actually the suggestion of having users override the policy in the loop fixture is simpler, but less obvious. That might be the way to go if we document it properly. Ideally you wouldn't need to override the policy, overriding the loop would be enough (although you might need to override the policy if the code you're testing deals with it directly).

@alblasco
Copy link
Contributor

So I understand that option 2 is the way to go. Fine, it sounds good to me.
Let me know if I can help in anyway.

@Tinche
Copy link
Member Author

Tinche commented Jun 29, 2020

@alblasco Actually I was going for 1.a. Seems the simplest, we just need to document it.

@alblasco
Copy link
Contributor

@alblasco Actually I was going for 1.a. Seems the simplest, we just need to document it.

Python ZEN: Simple is better than complex.

@seifertm
Copy link
Contributor

@Tinche pytest-asyncio no longer resets the current policy when creating a new event loop. That means users could set loop policies using regular pytest fixtures.

Can you think of another use case covered by this PR? Is this something we want to pursue?

@asvetlov
Copy link
Contributor

Agree with @seifertm

@Tinche Tinche closed this Jan 16, 2022
@Tinche
Copy link
Member Author

Tinche commented Jan 16, 2022

@seifertm agreed! thanks

@seifertm seifertm deleted the policies branch July 12, 2023 08:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants