13
13
14
14
15
15
class Server :
16
- def __init__ (self , app ):
16
+ def __init__ (
17
+ self , app , host = "0.0.0.0" , port = 5000 , log = None , debug = False , zeroconf = True
18
+ ):
17
19
self .app = app
18
20
# Find LabThing attached to app
19
21
self .labthing = current_labthing (app )
20
22
21
- def run (
22
- self ,
23
- host = "0.0.0.0" ,
24
- port = 5000 ,
25
- log = None ,
26
- debug = False ,
27
- stop_timeout = 1 ,
28
- zeroconf = True ,
29
- ):
30
- # Type checks
31
- port = int (port )
32
- host = str (host )
23
+ # Server properties
24
+ self .host = host
25
+ self .port = port
26
+ self .log = log
27
+ self .debug = debug
28
+ self .zeroconf = zeroconf
33
29
34
- # Unmodified version of app
35
- app_to_run = self .app
30
+ # Servers
31
+ self .wsgi_server = None
32
+ self .zeroconf_server = None
33
+ self .service_info = None
36
34
37
- # Handle zeroconf
38
- zeroconf_server = None
39
- if zeroconf and self .labthing :
40
- service_info = ServiceInfo (
35
+ # Events
36
+ self .started_event = gevent .event .Event ()
37
+
38
+ def register_zeroconf (self ):
39
+ if self .labthing :
40
+ self .service_info = ServiceInfo (
41
41
"_labthings._tcp.local." ,
42
- f"{ self .labthing .title } ._labthings._tcp.local." ,
43
- port = port ,
42
+ f"{ self .labthing .safe_title } ._labthings._tcp.local." ,
43
+ port = self . port ,
44
44
properties = {
45
45
"path" : self .labthing .url_prefix ,
46
46
"title" : self .labthing .title ,
@@ -55,43 +55,96 @@ def run(
55
55
]
56
56
),
57
57
)
58
- zeroconf_server = Zeroconf (ip_version = IPVersion .V4Only )
59
- zeroconf_server .register_service (service_info )
58
+ self .zeroconf_server = Zeroconf (ip_version = IPVersion .V4Only )
59
+ self .zeroconf_server .register_service (self .service_info )
60
+
61
+ def stop (self , timeout = 1 ):
62
+ # Unregister zeroconf service
63
+ if self .zeroconf_server :
64
+ self .zeroconf_server .unregister_service (self .service_info )
65
+ self .zeroconf_server .close ()
66
+ self .zeroconf_server = None
67
+ # Stop WSGI server with timeout
68
+ if self .wsgi_server :
69
+ self .wsgi_server .stop (timeout = timeout )
70
+ self .wsgi_server = None
71
+ # Clear started event
72
+ if self .started_event .is_set ():
73
+ self .started_event .clear ()
74
+
75
+ def start (self ):
76
+ # Unmodified version of app
77
+ app_to_run = self .app
78
+
79
+ # Handle zeroconf
80
+ if self .zeroconf :
81
+ self .register_zeroconf ()
60
82
61
83
# Handle logging
62
- if not log :
63
- log = logging .getLogger ()
84
+ if not self . log :
85
+ self . log = logging .getLogger ()
64
86
65
87
# Handle debug mode
66
- if debug :
67
- log .setLevel (logging .DEBUG )
88
+ if self . debug :
89
+ self . log .setLevel (logging .DEBUG )
68
90
app_to_run = DebuggedApplication (self .app )
69
91
logging .getLogger ("zeroconf" ).setLevel (logging .DEBUG )
70
92
71
93
# Slightly more useful logger output
72
- friendlyhost = "localhost" if host == "0.0.0.0" else host
94
+ friendlyhost = "localhost" if self . host == "0.0.0.0" else self . host
73
95
print ("Starting LabThings WSGI Server" )
74
- print (f"Debug mode: { debug } " )
75
- print (f"Running on http://{ friendlyhost } :{ port } (Press CTRL+C to quit)" )
96
+ print (f"Debug mode: { self . debug } " )
97
+ print (f"Running on http://{ friendlyhost } :{ self . port } (Press CTRL+C to quit)" )
76
98
77
99
# Create WSGIServer
78
- wsgi_server = gevent .pywsgi .WSGIServer (
79
- (host , port ), app_to_run , handler_class = WebSocketHandler , log = log
100
+ self .wsgi_server = gevent .pywsgi .WSGIServer (
101
+ (self .host , self .port ),
102
+ app_to_run ,
103
+ handler_class = WebSocketHandler ,
104
+ log = self .log ,
80
105
)
81
106
82
- def stop ():
83
- # Unregister zeroconf service
84
- if zeroconf_server :
85
- zeroconf_server .unregister_service (service_info )
86
- zeroconf_server .close ()
87
- # Stop WSGI server with timeout
88
- wsgi_server .stop (timeout = stop_timeout )
89
-
90
107
# Serve
91
- signal .signal (signal .SIGTERM , stop )
108
+ signal .signal (signal .SIGTERM , self . stop )
92
109
110
+ # Set started event
111
+ self .started_event .set ()
93
112
try :
94
- wsgi_server .serve_forever ()
95
- except (KeyboardInterrupt , SystemExit ):
96
- logging .warning ("Terminating by KeyboardInterrupt or SystemExit" )
97
- stop ()
113
+ self .wsgi_server .serve_forever ()
114
+ # Ignore the exit lines in coverage
115
+ # as I can't find a way to test a KeyboardInterrupt...
116
+ except (KeyboardInterrupt , SystemExit ): # pragma: no cover
117
+ logging .warning (
118
+ "Terminating by KeyboardInterrupt or SystemExit"
119
+ ) # pragma: no cover
120
+ self .stop () # pragma: no cover
121
+
122
+ def run (
123
+ self , host = None , port = None , log = None , debug = None , zeroconf = None ,
124
+ ):
125
+ """Starts the server allowing for runtime parameters. Designed to immitate
126
+ the old Flask app.run style of starting an app
127
+
128
+ Args:
129
+ host (string, optional): Host IP address. Defaults to None.
130
+ port (int, optional): Host port. Defaults to None.
131
+ log (optional): Logger to log to. Defaults to None.
132
+ debug (bool, optional): Enable server debug mode. Defaults to None.
133
+ zeroconf (bool, optional): Enable the zeroconf server. Defaults to None.
134
+ """
135
+ if port is not None :
136
+ self .port = int (port )
137
+
138
+ if host is not None :
139
+ self .host = str (host )
140
+
141
+ if log is not None :
142
+ self .log = log
143
+
144
+ if debug is not None :
145
+ self .debug = debug
146
+
147
+ if zeroconf is not None :
148
+ self .zeroconf = zeroconf
149
+
150
+ self .start ()
0 commit comments