Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/nbconvert/postprocessors/serve.py: 34%
58 statements
« prev ^ index » next coverage.py v7.2.7, created at 2023-07-01 06:54 +0000
« prev ^ index » next coverage.py v7.2.7, created at 2023-07-01 06:54 +0000
1"""PostProcessor for serving reveal.js HTML slideshows."""
3# Copyright (c) Jupyter Development Team.
4# Distributed under the terms of the Modified BSD License.
7import os
8import threading
9import webbrowser
11from tornado import gen, httpserver, ioloop, log, web
12from tornado.httpclient import AsyncHTTPClient
13from traitlets import Bool, Int, Unicode
15from .base import PostProcessorBase
18class ProxyHandler(web.RequestHandler):
19 """handler the proxies requests from a local prefix to a CDN"""
21 @gen.coroutine
22 def get(self, prefix, url):
23 """proxy a request to a CDN"""
24 proxy_url = "/".join([self.settings["cdn"], url])
25 client = self.settings["client"]
26 response = yield client.fetch(proxy_url)
28 for header in ["Content-Type", "Cache-Control", "Date", "Last-Modified", "Expires"]:
29 if header in response.headers:
30 self.set_header(header, response.headers[header])
31 self.finish(response.body)
34class ServePostProcessor(PostProcessorBase):
35 """Post processor designed to serve files
37 Proxies reveal.js requests to a CDN if no local reveal.js is present
38 """
40 open_in_browser = Bool(True, help="""Should the browser be opened automatically?""").tag(
41 config=True
42 )
44 browser = Unicode(
45 "",
46 help="""Specify what browser should be used to open slides. See
47 https://docs.python.org/3/library/webbrowser.html#webbrowser.register
48 to see how keys are mapped to browser executables. If
49 not specified, the default browser will be determined
50 by the `webbrowser`
51 standard library module, which allows setting of the BROWSER
52 environment variable to override it.
53 """,
54 ).tag(config=True)
56 reveal_cdn = Unicode(
57 "https://cdnjs.cloudflare.com/ajax/libs/reveal.js/3.5.0", help="""URL for reveal.js CDN."""
58 ).tag(config=True)
59 reveal_prefix = Unicode("reveal.js", help="URL prefix for reveal.js").tag(config=True)
60 ip = Unicode("127.0.0.1", help="The IP address to listen on.").tag(config=True)
61 port = Int(8000, help="port for the server to listen on.").tag(config=True)
63 def postprocess(self, input): # noqa
64 """Serve the build directory with a webserver."""
65 dirname, filename = os.path.split(input)
66 handlers: list = [
67 (r"/(.+)", web.StaticFileHandler, {"path": dirname}),
68 (r"/", web.RedirectHandler, {"url": "/%s" % filename}),
69 ]
71 if "://" in self.reveal_prefix or self.reveal_prefix.startswith("//"):
72 # reveal specifically from CDN, nothing to do
73 pass
74 elif os.path.isdir(os.path.join(dirname, self.reveal_prefix)):
75 # reveal prefix exists
76 self.log.info("Serving local %s", self.reveal_prefix)
77 else:
78 self.log.info("Redirecting %s requests to %s", self.reveal_prefix, self.reveal_cdn)
79 handlers.insert(0, (r"/(%s)/(.*)" % self.reveal_prefix, ProxyHandler))
81 app = web.Application(
82 handlers,
83 cdn=self.reveal_cdn,
84 client=AsyncHTTPClient(),
85 )
87 # hook up tornado logging to our logger
88 log.app_log = self.log
90 http_server = httpserver.HTTPServer(app)
91 http_server.listen(self.port, address=self.ip)
92 url = "http://%s:%i/%s" % (self.ip, self.port, filename)
93 print("Serving your slides at %s" % url)
94 print("Use Control-C to stop this server")
95 if self.open_in_browser:
96 try:
97 browser = webbrowser.get(self.browser or None)
98 b = lambda: browser.open(url, new=2) # noqa
99 threading.Thread(target=b).start()
100 except webbrowser.Error as e:
101 self.log.warning("No web browser found: %s." % e)
102 browser = None
104 try:
105 ioloop.IOLoop.instance().start()
106 except KeyboardInterrupt:
107 print("\nInterrupted")
110def main(path):
111 """allow running this module to serve the slides"""
112 server = ServePostProcessor()
113 server(path)
116if __name__ == "__main__":
117 import sys
119 main(sys.argv[1])