vinissimus / async-asgi-testclient

@@ -25,6 +25,7 @@
Loading
25 25
        self.cookies = cookies
26 26
        self.input_queue: asyncio.Queue[dict] = asyncio.Queue()
27 27
        self.output_queue: asyncio.Queue[dict] = asyncio.Queue()
28 +
        self._app_task = None  # Necessary to keep a hard reference to running task
28 29
29 30
    async def __aenter__(self):
30 31
        await self.connect()
@@ -32,6 +33,7 @@
Loading
32 33
33 34
    async def __aexit__(self, exc_type, exc, tb):
34 35
        await self.close()
36 +
        self._app_task = None
35 37
36 38
    async def close(self, code: int = 1000):
37 39
        await self._send({"type": "websocket.disconnect", "code": code})
@@ -120,7 +122,7 @@
Loading
120 122
            "subprotocols": [],
121 123
        }
122 124
123 -
        create_monitored_task(
125 +
        self._app_task = create_monitored_task(
124 126
            app(scope, self.input_queue.get, self.output_queue.put),
125 127
            self.output_queue.put_nowait,
126 128
        )

@@ -75,9 +75,10 @@
Loading
75 75
        self._scope = scope or {}
76 76
        self._lifespan_input_queue: asyncio.Queue[dict] = asyncio.Queue()
77 77
        self._lifespan_output_queue: asyncio.Queue[dict] = asyncio.Queue()
78 +
        self._lifespan_task = None  # Must keep hard reference to prevent gc
78 79
79 80
    async def __aenter__(self):
80 -
        create_monitored_task(
81 +
        self._lifespan_task = create_monitored_task(
81 82
            self.application(
82 83
                {"type": "lifespan", "asgi": {"version": "3.0"}},
83 84
                self._lifespan_input_queue.get,
@@ -91,6 +92,7 @@
Loading
91 92
92 93
    async def __aexit__(self, exc_type, exc, tb):
93 94
        await self.send_lifespan("shutdown")
95 +
        self._lifespan_task = None
94 96
95 97
    async def send_lifespan(self, action):
96 98
        await self._lifespan_input_queue.put({"type": f"lifespan.{action}"})
@@ -233,7 +235,7 @@
Loading
233 235
        }
234 236
        scope.update(self._scope)
235 237
236 -
        create_monitored_task(
238 +
        running_task = create_monitored_task(
237 239
            self.application(scope, input_queue.get, output_queue.put),
238 240
            output_queue.put_nowait,
239 241
        )
@@ -280,6 +282,9 @@
Loading
280 282
            response.cookies.update(cookies)
281 283
            cookie_jar.update(cookies)
282 284
285 +
        # We need to keep a hard reference to running task to prevent gc
286 +
        assert running_task  # Useless assert to prevent unused variable warnings
287 +
283 288
        if allow_redirects and response.is_redirect:
284 289
            path = response.headers["location"]
285 290
            return await self.get(path)
Files Coverage
async_asgi_testclient 87.41%
Project Totals (6 files) 87.41%
Notifications are pending CI completion. Periodically Codecov will check the CI state, when complete notifications will be submitted. Push notifications now.
191.2
TRAVIS_PYTHON_VERSION=3.7
TRAVIS_OS_NAME=linux
191.1
TRAVIS_PYTHON_VERSION=3.6
TRAVIS_OS_NAME=linux
191.3
TRAVIS_PYTHON_VERSION=3.8
TRAVIS_OS_NAME=linux
191.4
TRAVIS_PYTHON_VERSION=3.9
TRAVIS_OS_NAME=linux

No yaml found.

Create your codecov.yml to customize your Codecov experience

Sunburst
The inner-most circle is the entire project, moving away from the center are folders then, finally, a single file. The size and color of each slice is representing the number of statements and the coverage, respectively.
Icicle
The top section represents the entire project. Proceeding with folders and finally individual files. The size and color of each slice is representing the number of statements and the coverage, respectively.
Grid
Each block represents a single file in the project. The size and color of each block is represented by the number of statements and the coverage, respectively.
Loading