Repository: stytchauth/stytch-python (language: python)

Issue:
how to use the Client in non-async scenarios?
after the update to 9.x, my code that previously used to work, now raises RuntimeError exceptions because it is not running in an async context.

For example,

```
    client = Client(
        project_id=settings.stytch_project_id,
        secret=settings.stytch_secret,
        environment=settings.stytch_environment,
    )
```

in a flask application (without async), the following is raised

```
  File "/home/.../lib/python3.12/site-packages/stytch/consumer/client.py", line 42, in __init__
    super().__init__(
  File "/home/.../lib/python3.12/site-packages/stytch/core/client_base.py", line 24, in __init__
    self.async_client = AsyncClient(project_id, secret, session=async_session)
                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/.../lib/python3.12/site-packages/stytch/core/http/client.py", line 99, in __init__
    self._session = session or aiohttp.ClientSession()
                               ^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/.../lib/python3.12/site-packages/aiohttp/client.py", line 279, in __init__
    loop = get_running_loop(loop)
           ^^^^^^^^^^^^^^^^^^^^^^
  File "/home/.../lib/python3.12/site-packages/aiohttp/helpers.py", line 300, in get_running_loop
    loop = asyncio.get_event_loop()
           ^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/.../lib/python3.12/asyncio/events.py", line 698, in get_event_loop
    raise RuntimeError('There is no current event loop in thread %r.'
RuntimeError: There is no current event loop in thread 'Dummy-2'.
2024-05-27T20:10:05Z {'REMOTE_ADDR': '127.0.0.1', 'REMOTE_PORT': '47724', 'HTTP_HOST': 'localhost:5000', (hidden keys: 33)} failed with RuntimeError
```

i downgraded to check if it worked in 8.7.0 and indeed it does.

The documentation here, for example, does not seem to work now in my flask app.

https://github.com/stytchauth/stytch-python?tab=readme-ov-file#example-usage

it does work, however if I just copy/pasta it into a test.py file and run that.

Any idea waht I'm missing here? or is this a bug?


Discussion / hints:

Fix patch:
diff --git a/stytch/core/http/client.py b/stytch/core/http/client.py
index aad771e..53e14aa 100644
--- a/stytch/core/http/client.py
+++ b/stytch/core/http/client.py
@@ -96,10 +96,16 @@ def __init__(
         super().__init__(project_id, secret)
         self.auth = aiohttp.BasicAuth(project_id, secret)
         self._external_session = session is not None
-        self._session = session or aiohttp.ClientSession()
+        self.__session = session
+
+    @property
+    def _session(self) -> aiohttp.ClientSession:
+        if self.__session is None:
+            self.__session = aiohttp.ClientSession()
+        return self.__session
 
     def __del__(self) -> None:
-        if self._external_session:
+        if self._external_session or self.__session is None:
             return
 
         # If we're responsible for the session, close it now
diff --git a/stytch/version.py b/stytch/version.py
index 0009b32..68afea6 100644
--- a/stytch/version.py
+++ b/stytch/version.py
@@ -1,1 +1,1 @@
-__version__ = "9.5.0"
+__version__ = "9.5.1"


Test patch:
diff --git a/stytch/core/http/test/__init__.py b/stytch/core/http/test/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/stytch/core/http/test/test_client.py b/stytch/core/http/test/test_client.py
new file mode 100644
index 0000000..7df2895
--- /dev/null
+++ b/stytch/core/http/test/test_client.py
@@ -0,0 +1,20 @@
+#!/usr/bin/env python3
+
+from __future__ import annotations
+
+import asyncio
+import unittest
+
+from stytch.core.http.client import AsyncClient
+
+
+class NoEventLoopPolicy(asyncio.DefaultEventLoopPolicy):
+    def get_event_loop(self):
+        raise RuntimeError("No event loop")
+
+
+class TestAsyncClient(unittest.TestCase):
+    def test_session_without_event_loop(self):
+        asyncio.set_event_loop_policy(NoEventLoopPolicy())
+        client = AsyncClient("project_id", "secret")
+        self.assertIsNotNone(client)