Download mathly2/tests/test_pooled.py from wzender/mathly: direct link, hf CLI and curl.
- Browser
- Download file 5.5 kB
-
https://huggingface.co/spaces/wzender/mathly/resolve/main/mathly2/tests/test_pooled.py
- Command line
-
hf download hf://spaces/wzender/mathly/mathly2/tests/test_pooled.py
-
curl -L -o test_pooled.py https://huggingface.co/spaces/wzender/mathly/resolve/main/mathly2/tests/test_pooled.py
5.5 kB
| """Reused connections to the database (fewer-database-calls 1.3), against a small local server.""" | |
| import json | |
| import threading | |
| import urllib.error | |
| from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer | |
| import pytest | |
| from mathly2 import pooled | |
| class Server: | |
| """A keep-alive HTTP/1.1 server that counts the connections it accepted and the requests it answered.""" | |
| def __init__(self, close_after: int | None = None, status: int = 200, body: bytes = b'[{"ok": true}]', delay: float = 0.0): | |
| outer = self | |
| self.connections = self.requests = 0 | |
| self.lock = threading.Lock() | |
| class Handler(BaseHTTPRequestHandler): | |
| protocol_version = "HTTP/1.1" | |
| def setup(self): | |
| super().setup() | |
| with outer.lock: | |
| outer.connections += 1 | |
| self.served = 0 | |
| def do_GET(self): | |
| self.answer() | |
| do_POST = do_GET | |
| def answer(self): | |
| length = int(self.headers.get("Content-Length") or 0) | |
| self.rfile.read(length) | |
| if delay: | |
| import time | |
| time.sleep(delay) | |
| self.served += 1 | |
| with outer.lock: | |
| outer.requests += 1 | |
| self.send_response(status) | |
| self.send_header("Content-Type", "application/json") | |
| self.send_header("Content-Length", str(len(body))) | |
| if close_after and self.served >= close_after: | |
| self.close_connection = True # hang up after this answer without saying so (an idle timeout) | |
| self.end_headers() | |
| self.wfile.write(body) | |
| def log_message(self, *a): | |
| pass | |
| self.httpd = ThreadingHTTPServer(("127.0.0.1", 0), Handler) | |
| self.url = f"http://127.0.0.1:{self.httpd.server_address[1]}" | |
| threading.Thread(target=self.httpd.serve_forever, daemon=True).start() | |
| def stop(self): | |
| self.httpd.shutdown() | |
| self.httpd.server_close() | |
| def server(): | |
| made = [] | |
| def make(**kw): | |
| made.append(Server(**kw)) | |
| return made[-1] | |
| yield make | |
| for s in made: | |
| s.stop() | |
| def test_several_calls_reuse_one_connection(server): | |
| s = server() | |
| for _ in range(5): | |
| status, body = pooled.request("GET", s.url + "/rest/v1/x?a=1") | |
| assert status == 200 and json.loads(body) == [{"ok": True}] | |
| assert s.requests == 5 and s.connections == 1 | |
| def test_a_write_sends_its_body_and_reuses_the_connection(server): | |
| s = server() | |
| pooled.request("GET", s.url + "/a") | |
| status, _ = pooled.request("POST", s.url + "/b", {"Content-Type": "application/json"}, b'{"x": 1}') | |
| assert status == 200 and s.connections == 1 | |
| def test_each_thread_has_its_own_connection(server): | |
| s = server() | |
| pooled.request("GET", s.url + "/a") | |
| done = [] | |
| threading.Thread(target=lambda: done.append(pooled.request("GET", s.url + "/b")[0])).start() | |
| for _ in range(100): | |
| if done: | |
| break | |
| threading.Event().wait(0.02) | |
| assert done == [200] and s.connections == 2 | |
| def test_a_connection_the_server_closed_is_replaced_once_and_the_call_still_works(server): | |
| s = server(close_after=1) # the server hangs up after every answer | |
| for _ in range(3): | |
| status, _ = pooled.request("GET", s.url + "/a") | |
| assert status == 200 | |
| assert s.requests == 3 and s.connections >= 2 | |
| def test_an_answer_of_400_or_more_raises_an_http_error_with_a_body_that_can_be_read(server): | |
| s = server(status=409, body=b'{"message": "duplicate key"}') | |
| with pytest.raises(urllib.error.HTTPError) as caught: | |
| pooled.request("POST", s.url + "/a", None, b"{}") | |
| assert caught.value.code == 409 and json.loads(caught.value.read())["message"] == "duplicate key" | |
| ok = server() # a failed answer leaves the client usable | |
| assert pooled.request("GET", ok.url + "/a")[0] == 200 | |
| def test_a_connection_that_fails_is_a_url_error_and_a_slow_server_a_timeout(server): | |
| with pytest.raises(urllib.error.URLError): | |
| pooled.request("GET", "http://127.0.0.1:1/never") | |
| slow = server(delay=1.0) | |
| with pytest.raises(TimeoutError): | |
| pooled.request("GET", slow.url + "/a", timeout=0.2) | |
| assert pooled.request("GET", slow.url + "/a", timeout=5)[0] == 200 # the broken connection was dropped; the next call works | |
| def test_the_store_and_the_authenticator_use_the_pooled_client(server): | |
| from mathly2.auth import SupabaseAuthenticator | |
| from mathly2.store import SupabaseStore | |
| s = server(body=b'[{"id": 1, "name": "A", "lessons": [], "teacher_email": null, "ai_enabled": false, "ai_daily_checks": 150, "created_by": "x", "created_at": "2026-11-01T00:00:00+00:00", "students": 0}]') | |
| store = SupabaseStore(s.url, "secret") | |
| for _ in range(3): | |
| store._request("GET", "m2_classes", {"select": "*"}) | |
| assert s.requests == 3 and s.connections == 1 | |
| user = server(body=b'{"id": "u1", "email": "a@school.test", "email_confirmed_at": "2026-01-01"}') | |
| auth = SupabaseAuthenticator(user.url, "key") | |
| assert auth.user("token-1") == {"id": "u1", "email": "a@school.test"} | |
| assert auth.user("token-2") == {"id": "u1", "email": "a@school.test"} and user.requests == 2 and user.connections == 1 | |