microsoftgraph / msgraph-sdk-python

MIT License
359 stars 49 forks source link

RuntimeError: Event loop is closed while using Pytest #798

Open MarcinBinkowski opened 2 months ago

MarcinBinkowski commented 2 months ago

Describe the bug

When running multiple tests that are using GraphServiceClient every second test is failing with "RuntimeError: Event loop is closed". When changing scope of test to "module" tests are working properly.

Expected behavior

GraphServiceClient can be used in pytest tests with test scope=="function".

How to reproduce

import pytest
from azure.identity import AzureCliCredential
from msgraph import GraphServiceClient

@pytest.mark.asyncio()
async def test_1():
    with AzureCliCredential() as credential:
        client = GraphServiceClient(credential)
        me = await client.me.get()

@pytest.mark.asyncio()
async def test_2():
    with AzureCliCredential() as credential:
        client = GraphServiceClient(credential)
        me = await client.me.get()

SDK Version

1.4.0

Latest version known to work for scenario above?

Tried 1.0.0. Issue still exists.

Known Workarounds

No response

Debug output

Click to expand log ``` platform darwin -- Python 3.9.6, pytest-8.2.2, pluggy-1.5.0 rootdir: /Users/marcin/Desktop/msgraphbug/pythonProject plugins: time-machine-2.14.2, asyncio-0.23.7, anyio-4.4.0 asyncio: mode=strict collected 2 items test.py .F [100%] ============================================================================ FAILURES ============================================================================ _____________________________________________________________________________ test_2 _____________________________________________________________________________ @pytest.mark.asyncio() async def test_2(): with AzureCliCredential() as credential: client = GraphServiceClient(credential) > me = await client.me.get() test.py:15: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ .venv/lib/python3.9/site-packages/msgraph/generated/users/item/user_item_request_builder.py:160: in get return await self.request_adapter.send_async(request_info, User, error_mapping) .venv/lib/python3.9/site-packages/kiota_http/httpx_request_adapter.py:178: in send_async response = await self.get_http_response_message(request_info, parent_span) .venv/lib/python3.9/site-packages/kiota_http/httpx_request_adapter.py:530: in get_http_response_message resp = await self._http_client.send(request) .venv/lib/python3.9/site-packages/httpx/_client.py:1661: in send response = await self._send_handling_auth( .venv/lib/python3.9/site-packages/httpx/_client.py:1689: in _send_handling_auth response = await self._send_handling_redirects( .venv/lib/python3.9/site-packages/httpx/_client.py:1726: in _send_handling_redirects response = await self._send_single_request(request) .venv/lib/python3.9/site-packages/httpx/_client.py:1763: in _send_single_request response = await transport.handle_async_request(request) .venv/lib/python3.9/site-packages/msgraph_core/middleware/async_graph_transport.py:21: in handle_async_request response = await self.pipeline.send(request) .venv/lib/python3.9/site-packages/kiota_http/middleware/middleware.py:38: in send return await self._first_middleware.send(request, self._transport) .venv/lib/python3.9/site-packages/kiota_http/middleware/redirect_handler.py:77: in send response = await super().send(request, transport) .venv/lib/python3.9/site-packages/kiota_http/middleware/middleware.py:65: in send return await self.next.send(request, transport) .venv/lib/python3.9/site-packages/kiota_http/middleware/retry_handler.py:84: in send response = await super().send(request, transport) .venv/lib/python3.9/site-packages/kiota_http/middleware/middleware.py:65: in send return await self.next.send(request, transport) .venv/lib/python3.9/site-packages/kiota_http/middleware/parameters_name_decoding_handler.py:62: in send response = await super().send(request, transport) .venv/lib/python3.9/site-packages/kiota_http/middleware/middleware.py:65: in send return await self.next.send(request, transport) .venv/lib/python3.9/site-packages/kiota_http/middleware/url_replace_handler.py:44: in send response = await super().send(request, transport) .venv/lib/python3.9/site-packages/kiota_http/middleware/middleware.py:65: in send return await self.next.send(request, transport) .venv/lib/python3.9/site-packages/kiota_http/middleware/user_agent_handler.py:30: in send return await super().send(request, transport) .venv/lib/python3.9/site-packages/kiota_http/middleware/middleware.py:65: in send return await self.next.send(request, transport) .venv/lib/python3.9/site-packages/kiota_http/middleware/headers_inspection_handler.py:54: in send response = await super().send(request, transport) .venv/lib/python3.9/site-packages/kiota_http/middleware/middleware.py:65: in send return await self.next.send(request, transport) .venv/lib/python3.9/site-packages/msgraph_core/middleware/telemetry.py:48: in send response = await super().send(request, transport) .venv/lib/python3.9/site-packages/kiota_http/middleware/middleware.py:62: in send response = await transport.handle_async_request(request) .venv/lib/python3.9/site-packages/msgraph_core/middleware/async_graph_transport.py:24: in handle_async_request response = await self.transport.handle_async_request(request) .venv/lib/python3.9/site-packages/httpx/_transports/default.py:373: in handle_async_request resp = await self._pool.handle_async_request(req) .venv/lib/python3.9/site-packages/httpcore/_async/connection_pool.py:216: in handle_async_request raise exc from None .venv/lib/python3.9/site-packages/httpcore/_async/connection_pool.py:196: in handle_async_request response = await connection.handle_async_request( .venv/lib/python3.9/site-packages/httpcore/_async/connection.py:101: in handle_async_request return await self._connection.handle_async_request(request) .venv/lib/python3.9/site-packages/httpcore/_async/http2.py:185: in handle_async_request raise exc .venv/lib/python3.9/site-packages/httpcore/_async/http2.py:148: in handle_async_request status, headers = await self._receive_response( .venv/lib/python3.9/site-packages/httpcore/_async/http2.py:292: in _receive_response event = await self._receive_stream_event(request, stream_id) .venv/lib/python3.9/site-packages/httpcore/_async/http2.py:333: in _receive_stream_event await self._receive_events(request, stream_id) .venv/lib/python3.9/site-packages/httpcore/_async/http2.py:361: in _receive_events events = await self._read_incoming_data(request) .venv/lib/python3.9/site-packages/httpcore/_async/http2.py:452: in _read_incoming_data raise exc .venv/lib/python3.9/site-packages/httpcore/_async/http2.py:438: in _read_incoming_data data = await self._network_stream.read(self.READ_NUM_BYTES, timeout) .venv/lib/python3.9/site-packages/httpcore/_backends/anyio.py:35: in read return await self._stream.receive(max_bytes=max_bytes) .venv/lib/python3.9/site-packages/anyio/streams/tls.py:205: in receive data = await self._call_sslobject_method(self._ssl_object.read, max_bytes) .venv/lib/python3.9/site-packages/anyio/streams/tls.py:147: in _call_sslobject_method data = await self.transport_stream.receive() .venv/lib/python3.9/site-packages/anyio/_backends/_asyncio.py:1141: in receive self._transport.resume_reading() /Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/asyncio/selector_events.py:808: in resume_reading self._add_reader(self._sock_fd, self._read_ready) /Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/asyncio/selector_events.py:754: in _add_reader self._loop._add_reader(fd, callback, *args) /Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/asyncio/selector_events.py:258: in _add_reader self._check_closed() _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = <_UnixSelectorEventLoop running=False closed=True debug=False> def _check_closed(self): if self._closed: > raise RuntimeError('Event loop is closed') E RuntimeError: Event loop is closed /Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/asyncio/base_events.py:510: RuntimeError ======================================================================== warnings summary ======================================================================== .venv/lib/python3.9/site-packages/urllib3/__init__.py:35 /Users/marcin/Desktop/msgraphbug/pythonProject/.venv/lib/python3.9/site-packages/urllib3/__init__.py:35: NotOpenSSLWarning: urllib3 v2 only supports OpenSSL 1.1.1+, currently the 'ssl' module is compiled with 'LibreSSL 2.8.3'. See: https://github.com/urllib3/urllib3/issues/3020 warnings.warn( test.py::test_1 /Users/marcin/Desktop/msgraphbug/pythonProject/.venv/lib/python3.9/site-packages/kiota_abstractions/default_query_parameters.py:23: DeprecationWarning: GetQueryParameters is deprecated. Use QueryParameters instead. warn("GetQueryParameters is deprecated. Use QueryParameters instead.", DeprecationWarning) test.py::test_1 /Users/marcin/Desktop/msgraphbug/pythonProject/.venv/lib/python3.9/site-packages/msgraph/generated/users/item/user_item_request_builder.py:910: DeprecationWarning: This class is deprecated. Please use the generic RequestConfiguration class generated by the generator. warn("This class is deprecated. Please use the generic RequestConfiguration class generated by the generator.", DeprecationWarning) test.py::test_1 /Users/marcin/Desktop/msgraphbug/pythonProject/.venv/lib/python3.9/site-packages/msgraph/generated/users/item/user_item_request_builder.py:943: DeprecationWarning: This class is deprecated. Please use the generic RequestConfiguration class generated by the generator. warn("This class is deprecated. Please use the generic RequestConfiguration class generated by the generator.", DeprecationWarning) test.py::test_1 /Users/marcin/Desktop/msgraphbug/pythonProject/.venv/lib/python3.9/site-packages/msgraph/generated/users/item/user_item_request_builder.py:950: DeprecationWarning: This class is deprecated. Please use the generic RequestConfiguration class generated by the generator. warn("This class is deprecated. Please use the generic RequestConfiguration class generated by the generator.", DeprecationWarning) -- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html ==================================================================== short test summary info ===================================================================== FAILED test.py::test_2 - RuntimeError: Event loop is closed ============================================================ 1 failed, 1 passed, 5 warnings in 2.13s ============================================================= ```

Configuration

Other information

In my opinion it is connected to GraphRequestAdapter and GraphClientFactory.create_with_default_middleware - After I've modified client parameters to be None by default and then creating clients if needed within the function body it started working properly.

olsgaard commented 3 weeks ago

An option for non-async API calls would be highly appreciated.