7
7
import hashlib
8
8
import json
9
9
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
11
12
12
13
import typer
13
14
from rich .console import Console
@@ -118,8 +119,27 @@ def list(self) -> list[str]:
118
119
return [path .stem for path in self .config_dir .glob ("*.prov" )]
119
120
120
121
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
+
121
141
@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 :
123
143
"""Create a new Anisette session."""
124
144
sessions = _SessionManager ()
125
145
if not sessions .can_save :
@@ -135,7 +155,7 @@ def new(name: Annotated[str, typer.Argument()] = "default") -> None:
135
155
136
156
137
157
@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 :
139
159
"""Remove a saved Anisette session."""
140
160
sessions = _SessionManager ()
141
161
if not sessions .can_save :
@@ -151,7 +171,7 @@ def remove(name: Annotated[str, typer.Argument()] = "default") -> None:
151
171
152
172
153
173
@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 :
155
175
"""Get Anisette data for a saved session."""
156
176
sessions = _SessionManager ()
157
177
if not sessions .can_save :
@@ -184,5 +204,44 @@ def list_() -> None:
184
204
console .print (table )
185
205
186
206
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
+
187
246
if __name__ == "__main__" :
188
247
app ()
0 commit comments