-
Notifications
You must be signed in to change notification settings - Fork 114
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Added shutting down calls to the visualization server #241
Changes from all commits
f7474d9
a628c1c
1c09a99
a49c584
52a0bca
8b48732
d2d4940
e47906a
4dd240a
f77b84a
5d99580
63756c3
d2e91cd
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,36 +2,122 @@ | |
|
||
import os | ||
import sys | ||
import signal | ||
import socket | ||
import webbrowser | ||
|
||
# For python 2 and python 3 compatibility | ||
if sys.version_info < (3, 0): | ||
from SimpleHTTPServer import SimpleHTTPRequestHandler | ||
from BaseHTTPServer import HTTPServer | ||
else: | ||
from http.server import SimpleHTTPRequestHandler | ||
from http.server import HTTPServer | ||
raw_input = input | ||
|
||
__all__ = ['Server'] | ||
|
||
|
||
class StoppableHTTPServer(HTTPServer): | ||
""" | ||
Overrides BaseHTTPServer.HTTPServer to include a stop | ||
function. | ||
""" | ||
|
||
def server_bind(self): | ||
HTTPServer.server_bind(self) | ||
self.socket.settimeout(1) | ||
self.run = True | ||
|
||
def get_request(self): | ||
while self.run: | ||
try: | ||
sock, addr = self.socket.accept() | ||
sock.settimeout(None) | ||
return (sock, addr) | ||
except socket.timeout: | ||
pass | ||
|
||
def stop(self): | ||
self.run = False | ||
|
||
def serve(self): | ||
while self.run: | ||
try: | ||
self.handle_request() | ||
except TypeError: | ||
# When server is being closed, while loop can run once | ||
# after setting self.run = False depending on how it | ||
# is scheduled. | ||
pass | ||
|
||
|
||
class Server(object): | ||
""" | ||
Parameters | ||
---------- | ||
port : integer | ||
Defines the port on which the server will run. If this port is | ||
already bind, then it increment 1 until it finds a free port. | ||
scene_file : name of the scene_file generated for visualization | ||
A Valid PyDy generated scene file in 'directory' parameter. | ||
directory : absolute path of a directory | ||
Absolute path to the directory which contains scene_file with | ||
all other static files. | ||
|
||
Example | ||
------- | ||
>>> server = Server(scene_file=_scene_json_file) | ||
>>> server.run_server() | ||
|
||
__all__ = ['run_server'] | ||
""" | ||
def __init__(self, scene_file, directory="static/", port=8000): | ||
self.scene_file = scene_file | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. My suggestion in the previous commit was to have this call sig: def __init__(scene_file, directory=None, port=8000) The scene file should be required and the directory can default to the cwd if None is passed in. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I will add that in my new pr on static directory creation. Trying to make it atomic There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. But this is a whole new server code. It seems atomic to add this. |
||
self.port = port | ||
self.directory = directory | ||
|
||
def run_server(self): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What happens if port 8000 is taken? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It throws an error. This needs to be fixed. |
||
# Change dir to static first. | ||
os.chdir(self.directory) | ||
# Get a free port | ||
while self._check_port(self.port): | ||
self.port += 1 | ||
handler_class = SimpleHTTPRequestHandler | ||
server_class = StoppableHTTPServer | ||
protocol = "HTTP/1.0" | ||
server_address = ('127.0.0.1', self.port) | ||
handler_class.protocol_version = protocol | ||
self.httpd = server_class(server_address, handler_class) | ||
sa = self.httpd.socket.getsockname() | ||
print("Serving HTTP on", sa[0], "port", sa[1], "...") | ||
print("To view visualization, open:\n") | ||
url = "http://localhost:"+str(sa[1]) + "/index.html?load=" + \ | ||
self.scene_file | ||
print(url) | ||
webbrowser.open(url) | ||
print("Hit Ctrl+C to stop the server...") | ||
signal.signal(signal.SIGINT, self._stop_server) | ||
self.httpd.serve() | ||
|
||
def run_server(port=8000,scene_file="Null"): | ||
#change dir to static first. | ||
os.chdir("static/") | ||
HandlerClass = SimpleHTTPRequestHandler | ||
ServerClass = HTTPServer | ||
Protocol = "HTTP/1.0" | ||
server_address = ('127.0.0.1', port) | ||
HandlerClass.protocol_version = Protocol | ||
httpd = ServerClass(server_address, HandlerClass) | ||
sa = httpd.socket.getsockname() | ||
print("Serving HTTP on", sa[0], "port", sa[1], "...") | ||
print("hit ctrl+c to stop the server..") | ||
print("To view visualization, open:\n") | ||
url = "http://localhost:"+ str(sa[1]) + "/index.html?load=" + scene_file | ||
print(url) | ||
webbrowser.open(url) | ||
httpd.serve_forever() | ||
def _check_port(self, port): | ||
soc = socket.socket(socket.AF_INET, socket.SOCK_STREAM) | ||
result = soc.connect_ex(('127.0.0.1', port)) | ||
return result == 0 | ||
|
||
def _stop_server(self, signal, frame): | ||
""" | ||
Confirms and stops the visulisation server | ||
signal: | ||
Required by signal.signal | ||
frame: | ||
Required by signal.signal | ||
|
||
if __name__ == "__main__": | ||
run_server() | ||
""" | ||
res = raw_input("Shutdown this visualization server ([y]/n)? ") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This will fail in Python 3. Oliver had the fix for this in this file before this PR. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What are the options then, should I use There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Got it! |
||
res = res.lower()[0] | ||
if res == '' or res == 'y': | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This works even for strings like "Yes" |
||
print("Shutdown confirmed") | ||
print("Shutting down server...") | ||
self.httpd.stop() | ||
else: | ||
print("Resuming operations...") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This needs to stay in for Python 2/3 compat.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I totally missed that. Thanks
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe make a comment in your PR that says why that is there.