#!/usr/bin/env python3 """ Patch bbctrl Web.py so font files get the correct MIME type. Background ---------- The Onefinity controller (Pi 3B running Raspbian stretch) ships Python 3.5, whose ``mimetypes`` module does not recognize ``.woff``, ``.woff2`` or ``.ttf``. Tornado's ``StaticFileHandler`` therefore falls back to ``application/octet-stream`` for those, and Chromium 72 (the Pi's onboard kiosk browser) refuses to use such payloads as web fonts. The result is that every FontAwesome icon renders as an empty box on the kiosk display. This patch monkey-patches ``StaticFileHandler.get_content_type`` to emit the right MIME types. It is idempotent: running it twice is a no-op. Run with ``sudo`` so it can rewrite the egg's Web.py. Used by: scripts/deploy/hardware.sh """ from __future__ import print_function import os import sys def find_web_py(): """Return the absolute path to the bbctrl Web.py shipped in the egg.""" base = "/usr/local/lib" for entry in os.listdir(base): if not entry.startswith("python"): continue candidate_dir = os.path.join(base, entry, "dist-packages") if not os.path.isdir(candidate_dir): continue for sub in os.listdir(candidate_dir): if sub.startswith("bbctrl-") and sub.endswith(".egg"): p = os.path.join(candidate_dir, sub, "bbctrl", "Web.py") if os.path.isfile(p): return p return None OLD_BLOCK = ( "class StaticFileHandler(tornado.web.StaticFileHandler):\n" " def set_extra_headers(self, path):\n" " self.set_header('Cache-Control',\n" " 'no-store, no-cache, must-revalidate, max-age=0')" ) NEW_BLOCK = ( "class StaticFileHandler(tornado.web.StaticFileHandler):\n" " # FONT_MIME_FIX: Python 3.5's mimetypes module does not know\n" " # woff/woff2/ttf, so Tornado serves them as application/octet-\n" " # stream which Chromium 72 (the Pi's onboard kiosk browser)\n" " # refuses to use as web fonts. Set explicit types so the FA6\n" " # icon set actually renders on the kiosk display.\n" " def get_content_type(self):\n" " path = self.absolute_path or ''\n" " if path.endswith('.woff2'): return 'font/woff2'\n" " if path.endswith('.woff'): return 'font/woff'\n" " if path.endswith('.ttf'): return 'font/ttf'\n" " if path.endswith('.otf'): return 'font/otf'\n" " if path.endswith('.eot'): return 'application/vnd.ms-fontobject'\n" " return super().get_content_type()\n" "\n" " def set_extra_headers(self, path):\n" " self.set_header('Cache-Control',\n" " 'no-store, no-cache, must-revalidate, max-age=0')" ) def main(): target = find_web_py() if target is None: print("ERROR: could not locate bbctrl Web.py under /usr/local/lib", file=sys.stderr) return 1 with open(target) as f: src = f.read() if "FONT_MIME_FIX" in src: print("font mime: already patched ({})".format(target)) return 0 if OLD_BLOCK not in src: print("font mime: expected block not found in {} -- skipping".format(target), file=sys.stderr) # Don't fail the deploy; just log and continue. return 0 new_src = src.replace(OLD_BLOCK, NEW_BLOCK, 1) with open(target, "w") as f: f.write(new_src) print("font mime: patched {}".format(target)) return 0 if __name__ == "__main__": sys.exit(main())