Skip to content

Commit 8dd0496

Browse files
committed
Implement HTTP server in CLI
1 parent d830f12 commit 8dd0496

File tree

1 file changed

+63
-4
lines changed

1 file changed

+63
-4
lines changed

src/anisette/cli.py

Lines changed: 63 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@
77
import hashlib
88
import json
99
import logging
10-
from typing import TYPE_CHECKING, Annotated
10+
from http.server import SimpleHTTPRequestHandler, ThreadingHTTPServer
11+
from typing import TYPE_CHECKING, Annotated, Callable, override
1112

1213
import typer
1314
from rich.console import Console
@@ -118,8 +119,27 @@ def list(self) -> list[str]:
118119
return [path.stem for path in self.config_dir.glob("*.prov")]
119120

120121

122+
class _HttpRequestHandler(SimpleHTTPRequestHandler):
123+
def __init__(self, ani: Anisette, callback: Callable, *args, **kwargs) -> None: # noqa: ANN002, ANN003
124+
self._ani = ani
125+
self._callback = callback
126+
127+
super().__init__(*args, **kwargs)
128+
129+
@override
130+
def do_GET(self) -> None:
131+
data = self._ani.get_data()
132+
133+
self.send_response(200)
134+
self.send_header("Content-type", "application/json")
135+
self.end_headers()
136+
self.wfile.write(json.dumps(data).encode())
137+
138+
self._callback()
139+
140+
121141
@app.command()
122-
def new(name: Annotated[str, typer.Argument()] = "default") -> None:
142+
def new(name: Annotated[str, typer.Argument(help="The name of the new session")] = "default") -> None:
123143
"""Create a new Anisette session."""
124144
sessions = _SessionManager()
125145
if not sessions.can_save:
@@ -135,7 +155,7 @@ def new(name: Annotated[str, typer.Argument()] = "default") -> None:
135155

136156

137157
@app.command()
138-
def remove(name: Annotated[str, typer.Argument()] = "default") -> None:
158+
def remove(name: Annotated[str, typer.Argument(help="The name of the saved session to remove")] = "default") -> None:
139159
"""Remove a saved Anisette session."""
140160
sessions = _SessionManager()
141161
if not sessions.can_save:
@@ -151,7 +171,7 @@ def remove(name: Annotated[str, typer.Argument()] = "default") -> None:
151171

152172

153173
@app.command()
154-
def get(name: Annotated[str, typer.Argument()] = "default") -> None:
174+
def get(name: Annotated[str, typer.Argument(help="The name of the saved session")] = "default") -> None:
155175
"""Get Anisette data for a saved session."""
156176
sessions = _SessionManager()
157177
if not sessions.can_save:
@@ -184,5 +204,44 @@ def list_() -> None:
184204
console.print(table)
185205

186206

207+
@app.command()
208+
def serve(
209+
name: Annotated[str, typer.Argument(help="The name of the saved session")] = "default",
210+
host: Annotated[str, typer.Option(help="Host to run the server on")] = "localhost",
211+
port: Annotated[int, typer.Option(help="Port to run the server on")] = 6969,
212+
) -> None:
213+
"""Serve Anisette data for a saved session."""
214+
sessions = _SessionManager()
215+
if not sessions.can_save:
216+
print("Unable to figure out a config directory to retrieve sessions from")
217+
raise typer.Exit(code=1)
218+
219+
try:
220+
ani = sessions.get(name)
221+
except _AniError as e:
222+
print(str(e))
223+
raise typer.Abort from None
224+
225+
server = ThreadingHTTPServer(
226+
(host, port),
227+
lambda *args, **kwargs: _HttpRequestHandler(
228+
ani,
229+
(lambda: sessions.save(ani, name)),
230+
*args,
231+
**kwargs,
232+
),
233+
)
234+
235+
print(f"Starting server on {host}:{port}")
236+
print("Press CTRL+C to exit")
237+
print()
238+
239+
try:
240+
server.serve_forever()
241+
except KeyboardInterrupt:
242+
print()
243+
print("Stopping server")
244+
245+
187246
if __name__ == "__main__":
188247
app()

0 commit comments

Comments
 (0)