"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "modules/web/pymolhttpd.py" between
pymol-v1.8.6.0.tar.bz2 and pymol-v2.1.0.tar.bz2

About: PyMOL is a Python-enhanced molecular graphics tool. It excels at 3D visualization of proteins, small molecules, density, surfaces, and trajectories. It also includes molecular editing, ray tracing, and movies. Open Source version.

pymolhttpd.py  (pymol-v1.8.6.0.tar.bz2):pymolhttpd.py  (pymol-v2.1.0.tar.bz2)
# Copyright (C) Schrodinger, LLC. # Copyright (C) Schrodinger, LLC.
# All Rights Reserved # All Rights Reserved
# #
# For more information, see LICENSE in PyMOL's home directory. # For more information, see LICENSE in PyMOL's home directory.
# #
# pymolhttpd.py # pymolhttpd.py
# #
# web server interface for controlling PyMOL # web server interface for controlling PyMOL
from __future__ import print_function from __future__ import print_function
from __future__ import absolute_import
# we make extensive use of Python's build-in in web infrastructure # we make extensive use of Python's build-in in web infrastructure
import BaseHTTPServer, cgi, urlparse import sys
import StringIO, socket
_PY3 = sys.version_info[0] > 2
if _PY3:
import http.server as BaseHTTPServer
import io as StringIO
import urllib.parse as urlparse
from urllib.request import urlopen
else:
import BaseHTTPServer
import StringIO
import urlparse
from urllib import urlopen
import cgi
import socket
# we also rely upon Python's json infrastructure # we also rely upon Python's json infrastructure
try: try:
import simplejson as json import simplejson as json
except: except:
import json import json
# standard Python dependencies # standard Python dependencies
skipping to change at line 46 skipping to change at line 62
_json_mime_types = [ 'text/json', 'application/json' ] _json_mime_types = [ 'text/json', 'application/json' ]
class _PymolHTTPRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler): class _PymolHTTPRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):
# for now, we're using a single-threaded server # for now, we're using a single-threaded server
# our actual HTTP server class is private for the time being # our actual HTTP server class is private for the time being
# if we need to, then we'll change this # if we need to, then we'll change this
def wfile_write(self, s):
if _PY3 and not isinstance(s, bytes):
s = s.encode('utf-8')
self.wfile.write(s)
def do_GET(self): def do_GET(self):
self.process_request() self.process_request()
def do_POST(self): def do_POST(self):
self.process_request() self.process_request()
def log_message(self, format, *args): def log_message(self, format, *args):
if self.server.pymol_logging: if self.server.pymol_logging:
BaseHTTPServer.BaseHTTPRequestHandler.log_message(self,format, BaseHTTPServer.BaseHTTPRequestHandler.log_message(self,format,
*args) *args)
skipping to change at line 135 skipping to change at line 156
self.echo_args(parts[2]) self.echo_args(parts[2])
else: # simple file retrieval else: # simple file retrieval
self.send_doc() self.send_doc()
def pymol_getattr(self, attr): def pymol_getattr(self, attr):
""" """
apply the repr method to the requested attr, but only for apply the repr method to the requested attr, but only for
allowed attributes - those stored in the session dictionary allowed attributes - those stored in the session dictionary
""" """
key = '/getattr/' + attr; key = '/getattr/' + attr;
if self.session.has_key(key): if key in self.session:
try: try:
result = repr(self.session[key]) result = repr(self.session[key])
self.send_json_result(result) self.send_json_result(result)
except: except:
self.send_error(500,"Unable to get attribute.") self.send_error(500,"Unable to get attribute.")
self.wfile.write(" %s\n" % attr) self.wfile_write(" %s\n" % attr)
traceback.print_exc(file=self.wfile) traceback.print_exc(file=self.wfile)
else: else:
self.send_error(404,"Not a recognized attribute") self.send_error(404,"Not a recognized attribute")
self.wfile.write(" %s is not a recognized attribute\n" % attr) self.wfile_write(" %s is not a recognized attribute\n" % attr)
def wrap_return(self, result, status="OK", indent=None): def wrap_return(self, result, status="OK", indent=None):
r = { 'status' : status, 'result' : result } r = { 'status' : status, 'result' : result }
if self.server.wrap_natives==1: if self.server.wrap_natives==1:
return json.dumps(r,indent) return json.dumps(r, indent=indent)
else: else:
return json.dumps(result,indent) return json.dumps(result, indent=indent)
def send_json_result(self, result): def send_json_result(self, result):
""" """
send the mime header and result body. requests that came from send the mime header and result body. requests that came from
XMLHTTPRequest have specified they will accept (expect) json XMLHTTPRequest have specified they will accept (expect) json
formatted results. other requests will have come from formatted results. other requests will have come from
ordinary GET or POST requests via links or forms ordinary GET or POST requests via links or forms
""" """
if self.callback != None: if self.callback != None:
self.send_resp_header(200,'text/javascript') self.send_resp_header(200,'text/javascript')
self.wfile.write("%s(%s)"%(self.callback,self.wrap_return(result))) self.wfile_write("%s(%s)"%(self.callback,self.wrap_return(result)))
else: else:
accept_mime = self.headers.getheader('Accept') accept_mime = self.headers.get('Accept')
if accept_mime in _json_mime_types: if accept_mime in _json_mime_types:
self.send_resp_header(200,accept_mime) self.send_resp_header(200,accept_mime)
self.wfile.write(self.wrap_return(result)) self.wfile_write(self.wrap_return(result))
else: else:
self.send_resp_header(200,'text/html') self.send_resp_header(200,'text/html')
self.wfile.write("PyMOL's JSON response: <pre>") self.wfile_write("PyMOL's JSON response: <pre>")
self.wfile.write(self.wrap_return(result,indent=4)) self.wfile_write(self.wrap_return(result,indent=4))
self.wfile.write("</pre>") self.wfile_write("</pre>")
def send_json_error(self, code, message): def send_json_error(self, code, message):
if self.callback != None: if self.callback != None:
self.send_resp_header(code,'text/javascript') self.send_resp_header(code,'text/javascript')
self.wfile.write("%s(%s)"%(self.callback,self.wrap_return(message,"E RROR"))) self.wfile_write("%s(%s)"%(self.callback,self.wrap_return(message,"E RROR")))
else: else:
accept_mime = self.headers.getheader('Accept') accept_mime = self.headers.get('Accept')
if accept_mime in _json_mime_types: if accept_mime in _json_mime_types:
self.send_resp_header(code,accept_mime) self.send_resp_header(code,accept_mime)
self.wfile.write(self.wrap_return(message,"ERROR")) self.wfile_write(self.wrap_return(message,"ERROR"))
else: else:
self.send_resp_header(code,'text/html') self.send_resp_header(code,'text/html')
self.wfile.write("PyMOL's JSON response: <pre>") self.wfile_write("PyMOL's JSON response: <pre>")
self.wfile.write(self.wrap_return(message,"ERROR",indent=4)) self.wfile_write(self.wrap_return(message,"ERROR",indent=4))
self.wfile.write("</pre>") self.wfile_write("</pre>")
def send_exception_json(self, code, message): def send_exception_json(self, code, message):
fp = StringIO.StringIO() fp = StringIO.StringIO()
traceback.print_exc(file=fp) traceback.print_exc(file=fp)
tb = fp.getvalue() tb = fp.getvalue()
message = message + tb.split('\n') message = message + tb.split('\n')
response = json.dumps(message) response = json.dumps(message)
if self.callback != None: if self.callback != None:
self.send_resp_header(code, 'text/javascript') self.send_resp_header(code, 'text/javascript')
self.wfile.write("%s(%s)"%(self.callback,response)) self.wfile_write("%s(%s)"%(self.callback,response))
else: else:
accept_mime = self.headers.getheader('Accept') accept_mime = self.headers.get('Accept')
if accept_mime in _json_mime_types: if accept_mime in _json_mime_types:
self.send_resp_header(code,accept_mime) self.send_resp_header(code,accept_mime)
self.wfile.write(response) self.wfile_write(response)
else: else:
self.send_resp_header(code,'text/html') self.send_resp_header(code,'text/html')
self.wfile.write("PyMOL's JSON response: <pre>") self.wfile_write("PyMOL's JSON response: <pre>")
self.wfile.write(json.dumps(json.loads(response),indent=4)) self.wfile_write(json.dumps(json.loads(response),indent=4))
self.wfile.write("</pre>") self.wfile_write("</pre>")
def pymol_apply(self,method): def pymol_apply(self,method):
""" """
apply the appropriate method held in the session dictionary. apply the appropriate method held in the session dictionary.
supply the method arguements in the form of key/value supply the method arguements in the form of key/value
""" """
args = None args = None
kwds = None kwds = None
query_kwds = {} query_kwds = {}
send_multi_result_list = False send_multi_result_list = False
skipping to change at line 244 skipping to change at line 265
method = json.loads(self.fs.getfirst(k)) method = json.loads(self.fs.getfirst(k))
elif k == '_args': # tentative, not in spec -- may disappear elif k == '_args': # tentative, not in spec -- may disappear
args = json.loads(self.fs.getfirst(k)) args = json.loads(self.fs.getfirst(k))
elif k == '_kwds': # tentative, not in spec -- may disappear elif k == '_kwds': # tentative, not in spec -- may disappear
kwds = json.loads(self.fs.getfirst(k)) kwds = json.loads(self.fs.getfirst(k))
# other underscore arguments are ignored (not passed on) # other underscore arguments are ignored (not passed on)
elif k[0:1] != '_': elif k[0:1] != '_':
query_kwds[k] = self.fs.getfirst(k) query_kwds[k] = self.fs.getfirst(k)
blocks = [] blocks = []
if isinstance(method,types.StringType): if isinstance(method, str):
# method is merely a string # method is merely a string
if kwds == None: if kwds == None:
kwds = query_kwds kwds = query_kwds
if args == None: if args == None:
args = () args = ()
if len(method): if len(method):
blocks = [ [ method, args, kwds ] ] blocks = [ [ method, args, kwds ] ]
elif isinstance(method,types.ListType) and len(method): elif isinstance(method, list) and len(method):
# method is a list # method is a list
if not isinstance(method[0],types.ListType): if not isinstance(method[0], list):
blocks = [ method ] # contains just [name, args, kwds] blocks = [ method ] # contains just [name, args, kwds]
else: else:
blocks = method blocks = method
# contains [ [name, arg, kwds], [name, args, kwds], ... ] # contains [ [name, arg, kwds], [name, args, kwds], ... ]
send_multi_result_list = False # only return final result send_multi_result_list = False # only return final result
else: else:
self.send_json_error(500,[ "Unable to apply method:", str(method)]) self.send_json_error(500,[ "Unable to apply method:", str(method)])
return return
result = [] result = []
skipping to change at line 298 skipping to change at line 319
"Args: " + str(args) , "Args: " + str(args) ,
"Kwds: " + str(kwds)]) "Kwds: " + str(kwds)])
return return
else: else:
self.send_json_error(500,[ "Method not found:", self.send_json_error(500,[ "Method not found:",
str(block) ]) str(block) ])
return return
if block[0] == '_quit': # special quit behavior if block[0] == '_quit': # special quit behavior
self.send_resp_header() self.send_resp_header()
self.wfile.write("<html>") self.wfile_write("<html>")
href = None href = None
if kwds.has_key("href"): if "href" in kwds:
href = str(kwds['href']) href = str(kwds['href'])
elif len(args): elif len(args):
href = str(args[1]) href = str(args[1])
if href == None: if href == None:
self.wfile.write("<body>") self.wfile_write("<body>")
elif not len(href): # simply elif not len(href): # simply
self.wfile.write("<body onload=\"window.close()\">") self.wfile_write("<body onload=\"window.close()\">")
else: else:
self.wfile.write( self.wfile_write(
"<body onload=\"document.location.replace('"+ "<body onload=\"document.location.replace('"+
kwds['href']+"')\">") kwds['href']+"')\">")
self.wfile.write("<p>PyMOL-HTTPd: Shutting down...</p>") self.wfile_write("<p>PyMOL-HTTPd: Shutting down...</p>")
self.wfile.write("<p><i>Please close this window.</i></p>") self.wfile_write("<p><i>Please close this window.</i></p>")
self.wfile.write("</body></html>") self.wfile_write("</body></html>")
self.wfile.flush() self.wfile.flush()
self.server.pymol_cmd.quit() self.server.pymol_cmd.quit()
return return
if send_multi_result_list: if send_multi_result_list:
self.send_json_result(result) self.send_json_result(result)
elif len(result): elif len(result):
self.send_json_result(result[-1]) self.send_json_result(result[-1])
else: else:
self.send_json_result(None) self.send_json_result(None)
return return
def send_doc(self): def send_doc(self):
""" """
send a document (file) in the current directory or any sub-directory send a document (file) in the current directory or any sub-directory
""" """
path_list = self.path.split('/')[1:] path_list = self.path.split('/')[1:]
if '..' in path_list: # prevent access to parent directories if '..' in path_list: # prevent access to parent directories
self.send_error(404,"Illegal path.") self.send_error(404,"Illegal path.")
self.wfile.write(": %s" % self.path) self.wfile_write(": %s" % self.path)
elif self.server.pymol_root == None: elif self.server.pymol_root == None:
self.send_error(404,"No content root specified.") self.send_error(404,"No content root specified.")
else: else:
try: try:
full_path = os.path.join(*[self.server.pymol_root] + full_path = os.path.join(*[self.server.pymol_root] +
list(path_list)) list(path_list))
if os.path.isdir(full_path): if os.path.isdir(full_path):
full_path = full_path + "/index.html" full_path = full_path + "/index.html"
fp = open(full_path,"rb") fp = open(full_path,"rb")
self.send_resp_header(200,self.guess_mime(full_path)) self.send_resp_header(200,self.guess_mime(full_path))
self.wfile.write(fp.read()) self.wfile_write(fp.read())
fp.close() fp.close()
except: except:
self.send_error(404,"Unable to locate document.") self.send_error(404,"Unable to locate document.")
self.wfile.write(": %s" % self.path) self.wfile_write(": %s" % self.path)
self.wfile.write(str(sys.exc_info())) self.wfile_write(str(sys.exc_info()))
# exc_info() is thread safe # exc_info() is thread safe
# self.wfile.write(sys.exc_value) # exc_value not thread safe # self.wfile.write(sys.exc_value) # exc_value not thread safe
def guess_mime(self,path): def guess_mime(self,path):
""" """
guess the mime type based on the file extension guess the mime type based on the file extension
""" """
if path.endswith('.html'): if path.endswith('.html'):
return 'text/html' return 'text/html'
elif path.endswith('.js'): elif path.endswith('.js'):
skipping to change at line 384 skipping to change at line 405
else: else:
return 'text/plain' return 'text/plain'
def send_error(self,errcode,errmsg): def send_error(self,errcode,errmsg):
self.send_response(errcode) self.send_response(errcode)
self.send_header('Content-type', 'text/plain') self.send_header('Content-type', 'text/plain')
self.send_header('Pragma','no-cache') self.send_header('Pragma','no-cache')
self.send_header('Cache-Control','no-cache, must-revalidate') self.send_header('Cache-Control','no-cache, must-revalidate')
self.send_header('Expires','Sat, 10 Jan 2008 01:00:00 GMT') self.send_header('Expires','Sat, 10 Jan 2008 01:00:00 GMT')
self.end_headers() self.end_headers()
self.wfile.write("PyMOL-HTTPd-Error: "+errmsg+"\n") self.wfile_write("PyMOL-HTTPd-Error: "+errmsg+"\n")
def send_resp_header(self, code=200, mime='text/html'): def send_resp_header(self, code=200, mime='text/html'):
self.send_response(code) self.send_response(code)
self.send_header('Content-type', mime) self.send_header('Content-type', mime)
self.send_header('Pragma','no-cache') self.send_header('Pragma','no-cache')
self.send_header('Cache-Control','no-cache, must-revalidate') self.send_header('Cache-Control','no-cache, must-revalidate')
self.send_header('Expires','Sat, 10 Jan 2008 01:00:00 GMT') self.send_header('Expires','Sat, 10 Jan 2008 01:00:00 GMT')
self.end_headers() self.end_headers()
def echo_args(self): def echo_args(self):
""" """
for debugging requests for debugging requests
""" """
self.wfile.write("%s\n" % self.command) self.wfile_write("%s\n" % self.command)
if (self.fs): if (self.fs):
for k in self.fs.keys(): for k in self.fs.keys():
self.wfile.write("%s = " % k) self.wfile_write("%s = " % k)
# key can have multiple values, as with checkboxes, # key can have multiple values, as with checkboxes,
# but also arbitrarily # but also arbitrarily
if (isinstance(self.fs[k], types.ListType)): if (isinstance(self.fs[k], list)):
self.wfile.write("%s\n" % self.fs.getlist(k)) self.wfile_write("%s\n" % self.fs.getlist(k))
else: else:
# key can be uploaded file # key can be uploaded file
if (self.fs[k].filename): if (self.fs[k].filename):
self.wfile.write("%s\n" % self.fs[k].filename) self.wfile_write("%s\n" % self.fs[k].filename)
fp = self.fs[k].file fp = self.fs[k].file
#self.wfile.write("FILE %s" % cgi.escape(repr(fp))) #self.wfile.write("FILE %s" % cgi.escape(repr(fp)))
#self.wfile.write("%s\n" % fp.name) #self.wfile.write("%s\n" % fp.name)
# fails for StringIO instances # fails for StringIO instances
self.wfile.write("%s\n" % repr(fp)) self.wfile_write("%s\n" % repr(fp))
# two ways to get file contents # two ways to get file contents
#file_contents = self.fs.getvalue(k) #file_contents = self.fs.getvalue(k)
#file_contents = fp.read() #file_contents = fp.read()
#self.wfile.write("%s" % file_contents) #self.wfile.write("%s" % file_contents)
else: else:
#plain-old key/value #plain-old key/value
self.wfile.write("%s\n" % self.fs.getvalue(k)) self.wfile_write("%s\n" % self.fs.getvalue(k))
else: else:
self.wfile.write("No args\n") self.wfile_write("No args\n")
# this is the public class we're exposing to PyMOL consortium members # this is the public class we're exposing to PyMOL consortium members
class PymolHttpd: class PymolHttpd:
def __init__(self, port=8080, root=None, logging=1, wrap_natives=0, self_cmd =None): def __init__(self, port=8080, root=None, logging=1, wrap_natives=0, self_cmd =None):
if self_cmd == None: if self_cmd == None:
# fallback on the global singleton PyMOL API # fallback on the global singleton PyMOL API
try: try:
from pymol import cmd from pymol import cmd
skipping to change at line 487 skipping to change at line 508
self.port ) self.port )
t = threading.Thread(target=self._server_thread) t = threading.Thread(target=self._server_thread)
t.setDaemon(1) t.setDaemon(1)
self.stop_event.clear() self.stop_event.clear()
t.start() t.start()
def stop(self): def stop(self):
if not self.stop_event.isSet(): if not self.stop_event.isSet():
self.stop_event.set() self.stop_event.set()
try: # create a request in order to release the handler try: # create a request in order to release the handler
import urllib urlopen("http://localhost:%d" % self.port)
urllib.urlopen("http://localhost:%d" % self.port)
except: except:
pass pass
self.server.socket.close() self.server.socket.close()
def quit(self): def quit(self):
self.stop_event.set() self.stop_event.set()
def expose(self, name, value): def expose(self, name, value):
''' '''
exposes a Python method or symbol to the web services interface exposes a Python method or symbol to the web services interface
 End of changes. 41 change blocks. 
51 lines changed or deleted 71 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)