# coding=utf8
import sys
isPython3 = sys.version_info >= (3,0,0)
import cgi
import json
import os
import threading
import time
import webbrowser
if isPython3:
import http.server as BaseHTTPServer
else:
import BaseHTTPServer
if isPython3:
import queue as Queue
else:
import Queue
if isPython3:
import urllib.request as urllib
import urllib.parse as urlparse
else:
import urllib2 as urllib
import urlparse
[docs]class QueueTimeout(Queue.Queue):
"""from http://stackoverflow.com/questions/1564501/add-timeout-argument-to-pythons-queue-join
by Lukáš Lalinský
"""
[docs] class NotFinished(Exception):
pass
[docs] def join_with_timeout(self, timeout):
self.all_tasks_done.acquire()
try:
endtime = time.time() + timeout
while self.unfinished_tasks:
remaining = endtime - time.time()
if remaining <= 0.0:
raise self.NotFinished
self.all_tasks_done.wait(remaining)
finally:
self.all_tasks_done.release()
[docs]class PyGeoTag(object):
def __init__(self, callback=None, synchronous=False):
self.basedir = os.path.dirname(__file__)
self.synchronous = synchronous
if callback is not None:
self.callback = callback
if synchronous:
self.callback = self._store
self.server_thread = None
self.running = False
self.address = ''
self.port = 8008
self.request_queue = QueueTimeout()
self.data = None
self.syncWait = threading.Condition()
self.server = self.init_server()
# def stop_server(self):
# self.current_server_thread = -1
# time.sleep(self.timeout+1) # wait for server to exit
[docs] def start_server(self):
if False and self.synchronous:
pass
else:
self.running = True
self.server_thread = threading.Thread(target=self._run_server)
self.server_thread.start()
def _run_server(self):
while self.running:
self.server.handle_request()
[docs] def init_server(self):
class _handler(GeoTagRequestHandler):
owner = self
server_class = BaseHTTPServer.HTTPServer
handler_class = _handler
server_address = (self.address, self.port)
httpd = server_class(server_address, handler_class)
httpd.timeout = 2
return httpd
[docs] def stop_server(self):
# make an attempt to empty the queue
for i in range(self.request_queue.qsize()):
try:
self.request_queue.get_nowait()
except Queue.Empty:
pass
self.request_queue.put({'__msg_type':'shutdown'})
time.sleep(2) # wait for the msg to be picked up
self.running = False
[docs] def open_server_page(self):
webbrowser.open_new("http://%s:%d/" %
(self.address or "127.0.0.1", self.port))
[docs] def callback(self, data):
print(data)
def _store(self, data):
self.data = data
[docs] def show_position(self, data={}):
print('SHOWING',data)
data["__msg_type"] = "show_position"
self.request_queue.put(data)
[docs] def request_position(self, data={}):
print('REQUESTING',data)
data["__msg_type"] = "request_position"
self.request_queue.put(data)
[docs] def get_position(self, data={}):
if not self.synchronous:
self.running = False
raise Exception("Can't call get_position in asynchronous mode")
if not self.running:
raise Exception("Server is not running")
if data:
self.request_position(data)
while True:
try:
self.request_queue.join_with_timeout(2)
except QueueTimeout.NotFinished:
if self.running:
continue
break
return self.data
[docs]class GeoTagRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):
staticMap = {
"": "template.html",
"jquery.js": "jquery.js",
"map.js": "map.js",
"jquery.json-2.2.min.js": "jquery.json-2.2.min.js",
}
[docs] def log_message(*args):
return
[docs] def do_GET(self):
if self.path.startswith("/QUIT"):
self.send_response(200)
self.send_header('Content-type', 'text/plain')
self.end_headers()
self.wfile.write("TERMINATING SERVER".encode('utf-8'))
# threading.Timer(2,self.server.shutdown).start()
self.owner.stop_server()
return
path = self.path.strip('/').split('/')
if len(path) == 1 and path[0] in self.staticMap:
self.send_response(200)
self.send_header('Content-type', 'text/html')
self.end_headers()
self.wfile.write(open(
os.path.join(self.owner.basedir,self.staticMap[path[0]])).read().encode('utf-8'))
return
if self.path.startswith("/sendPos?"):
self.send_response(200)
self.send_header('Content-type', 'text/plain')
self.end_headers()
data = urlparse.parse_qs(urlparse.urlparse(self.path).query)['data'][0]
data = json.loads(data)
was_requested = False
if "__msg_type" in data:
del data["__msg_type"]
was_requested = True
self.owner.callback(data)
if was_requested:
self.owner.request_queue.task_done()
return
if self.path.startswith("/getMessage"):
self.send_response(200)
self.send_header('Content-type', 'text/plain')
self.end_headers()
#data = urlparse.parse_qs(urlparse.urlparse(self.path).query)['data'][0]
#print(repr(json.loads(data)))
try:
data = self.owner.request_queue.get_nowait()
except Queue.Empty:
data = {}
self.wfile.write(json.dumps(data).encode('utf-8'))
return
if __name__ == '__main__':
pgt = PyGeoTag(synchronous=True)
pgt.start_server()
time.sleep(1)
pgt.open_server_page()
f = pgt.get_position
f({"description": "Turtles"})
f({"description": "Frogs", 'secret':7})
f({"description": "Otters"})
print("DONE")
if pgt.synchronous:
pgt.stop_server()