While developing the Dashboard module I had problems to display charts generated with Pygal. Charts can only be saved as SVG format (they can be saved as PNG files but I haven’t found any portable library to use easily in Windows).
The first solution I came up with was to create an HTML file and then point to the SVG file but WebKit doesn’t allow to do that if you aren’t using a Webserver (it is all about security policies).
So the next step was to implement a tiny webserver based on Python 3 core standard library. After a few research looking for simple implementations I found one very simple. At first, it worked but then Basico became unstable:
– After stopping Basico, the next execution returns errors due to the webserver isn’t stopped successfully and the port remains binded.
– Another issue: you can’t run the webserver and GTK application in the same thread because then the application freezes.
After a little bit more of research I was able to rewrite the module to overcome these problems and keep the compatibility in both platforms, Linux and Windows.
Finally, I was able to load my webpage from my tiny and simple webserver and embed it into my GTK application using WebKit:
The code used to do this:
#!/usr/bin/python # -*- coding: utf-8 -*- # File: webserver.py # Author: Tomás Vírseda # License: GPL v3 # Description: Simple and tiny WebServer service for Basico import os import time import threading from http.server import HTTPServer, SimpleHTTPRequestHandler import socketserver from .service import Service from .env import LPATH # FIXME: make PORT dynamic via configuration PORT = 8763 # Custom Port. Could be any above 1024. WEBROOT = LPATH['WWW'] class LoggingRequestHandler(SimpleHTTPRequestHandler): '''Custom class based on SimpleHTTPRequestHandler which disables logging ''' def log_message(self, format, *args): return class WebServer(Service): def initialize(self): os.chdir(WEBROOT) self.webserver = HTTPServer(('localhost', PORT), LoggingRequestHandler) def run(self): self.thread = threading.Thread(target = self.webserver.serve_forever) self.thread.daemon = True self.thread.start() self.log.debug("Basico WebServer Document Root: %s" % WEBROOT) self.log.debug('Basico WebServer listening on port: {}'.format(self.webserver.server_port)) def halt(self): self.webserver.shutdown() self.thread.join() def finalize(self): self.halt()
The HTML code:
<html> <head></head> <body> <h1>SAP Components</h1> <h3>Number of SAP Notes for each SAP Component in your database</h3> <object id="svg1" data="chart.svg" type="image/svg+xml"></object> </body> </html>