|
|
@ -1,6 +1,7 @@
|
|
|
|
# bureau
|
|
|
|
# bureau
|
|
|
|
import configparser
|
|
|
|
import configparser
|
|
|
|
import functools
|
|
|
|
import functools
|
|
|
|
|
|
|
|
import inspect
|
|
|
|
import json
|
|
|
|
import json
|
|
|
|
import os.path
|
|
|
|
import os.path
|
|
|
|
import subprocess
|
|
|
|
import subprocess
|
|
|
@ -65,6 +66,15 @@ class Bureau(object):
|
|
|
|
self.commands = {}
|
|
|
|
self.commands = {}
|
|
|
|
self.api = {}
|
|
|
|
self.api = {}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
modpath = os.path.dirname(__file__)
|
|
|
|
|
|
|
|
phantomjs = os.path.join(modpath, "..", "lib", "phantomjs", "bin",
|
|
|
|
|
|
|
|
"phantomjs")
|
|
|
|
|
|
|
|
renderer = os.path.join(modpath, "..", "lib", "rasterize.js")
|
|
|
|
|
|
|
|
self.phantomjs = os.path.abspath(phantomjs)
|
|
|
|
|
|
|
|
self.html2pdf = self.phantomjs + " " + os.path.abspath(renderer) + " "
|
|
|
|
|
|
|
|
mypath = inspect.getfile(self.__class__)
|
|
|
|
|
|
|
|
self.mdir = os.path.dirname(mypath)
|
|
|
|
|
|
|
|
|
|
|
|
basepath = os.path.expanduser("~/.screenless")
|
|
|
|
basepath = os.path.expanduser("~/.screenless")
|
|
|
|
if not os.path.exists(basepath):
|
|
|
|
if not os.path.exists(basepath):
|
|
|
|
os.mkdir(basepath)
|
|
|
|
os.mkdir(basepath)
|
|
|
@ -108,22 +118,20 @@ class Bureau(object):
|
|
|
|
sender = self.context.socket(zmq.REQ)
|
|
|
|
sender = self.context.socket(zmq.REQ)
|
|
|
|
sender.connect("ipc://" + recipient + ".ipc")
|
|
|
|
sender.connect("ipc://" + recipient + ".ipc")
|
|
|
|
sender.send_string(message)
|
|
|
|
sender.send_string(message)
|
|
|
|
# TODO: retry this a few times with a proper sleep/timeout
|
|
|
|
|
|
|
|
#time.sleep(0.5)
|
|
|
|
|
|
|
|
#try:
|
|
|
|
|
|
|
|
# ret = json.loads(sender.recv_string(flags=zmq.NOBLOCK))
|
|
|
|
|
|
|
|
# # TODO: deal with non-json replies
|
|
|
|
|
|
|
|
#except zmq.ZMQError:
|
|
|
|
|
|
|
|
# print("message sent but got no reply...")
|
|
|
|
|
|
|
|
# ret = None
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
events = sender.poll(timeout=10000)
|
|
|
|
events = sender.poll(timeout=10000)
|
|
|
|
if events is not 0:
|
|
|
|
if events is not 0:
|
|
|
|
ret = json.loads(sender.recv_string())
|
|
|
|
resp = sender.recv_string()
|
|
|
|
|
|
|
|
if len(resp) == 0:
|
|
|
|
|
|
|
|
return None
|
|
|
|
|
|
|
|
elif resp[0] == "0":
|
|
|
|
|
|
|
|
return json.loads(resp[1:])
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
|
|
|
# TODO: this may need some better error handling
|
|
|
|
|
|
|
|
return resp
|
|
|
|
else:
|
|
|
|
else:
|
|
|
|
print("message sent... timed out after 10 seconds.")
|
|
|
|
print("message sent... timed out after 10 seconds.")
|
|
|
|
ret = None
|
|
|
|
return None
|
|
|
|
return ret
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def _publish_methods(self):
|
|
|
|
def _publish_methods(self):
|
|
|
|
"""
|
|
|
|
"""
|
|
|
@ -133,7 +141,13 @@ class Bureau(object):
|
|
|
|
# register bureau with Inhuman Resources
|
|
|
|
# register bureau with Inhuman Resources
|
|
|
|
bureau_detail = {"name": self.name, "prefix": self.prefix,
|
|
|
|
bureau_detail = {"name": self.name, "prefix": self.prefix,
|
|
|
|
"desc": self.__doc__}
|
|
|
|
"desc": self.__doc__}
|
|
|
|
self.send("IR", "addbureau", bureau_detail)
|
|
|
|
|
|
|
|
|
|
|
|
# slight hack to avoid messy self-reference and chicken-egg waiting
|
|
|
|
|
|
|
|
if self.prefix == "IR":
|
|
|
|
|
|
|
|
method = getattr(self, "add_bureau")
|
|
|
|
|
|
|
|
method(bureau_detail)
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
|
|
|
self.send("IR", "addbureau", bureau_detail)
|
|
|
|
|
|
|
|
|
|
|
|
# find and store all published methods
|
|
|
|
# find and store all published methods
|
|
|
|
for member in dir(self):
|
|
|
|
for member in dir(self):
|
|
|
@ -148,14 +162,22 @@ class Bureau(object):
|
|
|
|
"prefix": self.prefix,
|
|
|
|
"prefix": self.prefix,
|
|
|
|
"cmd": method.command,
|
|
|
|
"cmd": method.command,
|
|
|
|
"desc": method.__doc__}
|
|
|
|
"desc": method.__doc__}
|
|
|
|
self.send("IR", "addcommand", cmd_detail)
|
|
|
|
if self.prefix == "IR":
|
|
|
|
|
|
|
|
method = getattr(self, "add_cmd")
|
|
|
|
|
|
|
|
method(cmd_detail)
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
|
|
|
self.send("IR", "addcommand", cmd_detail)
|
|
|
|
elif hasattr(method, "api"):
|
|
|
|
elif hasattr(method, "api"):
|
|
|
|
self.api[method.api] = method
|
|
|
|
self.api[method.api] = method
|
|
|
|
api_detail = {"apiname": method.name,
|
|
|
|
api_detail = {"apiname": method.name,
|
|
|
|
"prefix": self.prefix,
|
|
|
|
"prefix": self.prefix,
|
|
|
|
"api": method.api,
|
|
|
|
"api": method.api,
|
|
|
|
"desc": method.__doc__}
|
|
|
|
"desc": method.__doc__}
|
|
|
|
self.send("IR", "addapi", api_detail)
|
|
|
|
if self.prefix == "IR":
|
|
|
|
|
|
|
|
method = getattr(self, "add_api_method")
|
|
|
|
|
|
|
|
method(api_detail)
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
|
|
|
self.send("IR", "addapi", api_detail)
|
|
|
|
|
|
|
|
|
|
|
|
print("registered:")
|
|
|
|
print("registered:")
|
|
|
|
print(self.commands)
|
|
|
|
print(self.commands)
|
|
|
@ -163,22 +185,35 @@ class Bureau(object):
|
|
|
|
|
|
|
|
|
|
|
|
def print_full(self, template, **kwargs):
|
|
|
|
def print_full(self, template, **kwargs):
|
|
|
|
"""print a full page (A4) document """
|
|
|
|
"""print a full page (A4) document """
|
|
|
|
# TODO: look up the printer LPR name
|
|
|
|
# TODO: look up the printer LPR name / allow multiple printers/non-default
|
|
|
|
|
|
|
|
|
|
|
|
lpname = kwargs.get("printer", "default")
|
|
|
|
# lpname = kwargs.get("printer", "default")
|
|
|
|
templ = Template(filename=template)
|
|
|
|
|
|
|
|
|
|
|
|
htmlfile, htmlpath = tempfile.mkstemp(".html")
|
|
|
|
texfile, texfilepath = tempfile.mkstemp(".tex")
|
|
|
|
htmlfile = os.fdopen(htmlfile, "w")
|
|
|
|
texfile.write(templ.render_unicode(
|
|
|
|
# run template with kwargs
|
|
|
|
**kwargs).encode('utf-8', 'replace'))
|
|
|
|
templfile = os.path.join(self.mdir, template)
|
|
|
|
|
|
|
|
print("using template: ", templfile)
|
|
|
|
texdir = os.path.dirname(texfilepath)
|
|
|
|
templ = Template(filename=templfile)
|
|
|
|
|
|
|
|
htmlfile.write(templ.render_unicode(**kwargs))
|
|
|
|
subprocess.call("cd " + texdir + "; xelatex " + texfilepath)
|
|
|
|
htmlfile.close()
|
|
|
|
|
|
|
|
#.encode('utf-8',
|
|
|
|
pdffile = texfilepath[0:-4] + ".pdf"
|
|
|
|
# 'replace'))
|
|
|
|
|
|
|
|
|
|
|
|
subprocess.call("lpr -P " + lpname + " " + pdffile)
|
|
|
|
# texfile, texfilepath = tempfile.mkstemp(".tex")
|
|
|
|
|
|
|
|
# texfile.write(templ.render_unicode(
|
|
|
|
|
|
|
|
# **kwargs).encode('utf-8', 'replace'))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# texdir = os.path.dirname(texfilepath)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# subprocess.call("cd " + texdir + "; xelatex " + texfilepath)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# TODO: make paper size a config variable
|
|
|
|
|
|
|
|
pdfpath = tempfile.mkstemp(".pdf")[1]
|
|
|
|
|
|
|
|
print("rendering with: ", self.html2pdf + htmlpath + " " + pdfpath)
|
|
|
|
|
|
|
|
subprocess.call(self.html2pdf + htmlpath + " " + pdfpath +
|
|
|
|
|
|
|
|
" A4 1920px", shell=True)
|
|
|
|
|
|
|
|
#subprocess.call("lpr " + pdfpath, shell=True)
|
|
|
|
|
|
|
|
|
|
|
|
# TODO: make this asynchronous
|
|
|
|
# TODO: make this asynchronous
|
|
|
|
def print_small(self, text, printer="/dev/usb/lp0"):
|
|
|
|
def print_small(self, text, printer="/dev/usb/lp0"):
|
|
|
|