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

1"""PostProcessor for serving reveal.js HTML slideshows.""" 

2 

3# Copyright (c) Jupyter Development Team. 

4# Distributed under the terms of the Modified BSD License. 

5 

6 

7import os 

8import threading 

9import webbrowser 

10 

11from tornado import gen, httpserver, ioloop, log, web 

12from tornado.httpclient import AsyncHTTPClient 

13from traitlets import Bool, Int, Unicode 

14 

15from .base import PostProcessorBase 

16 

17 

18class ProxyHandler(web.RequestHandler): 

19 """handler the proxies requests from a local prefix to a CDN""" 

20 

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) 

27 

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) 

32 

33 

34class ServePostProcessor(PostProcessorBase): 

35 """Post processor designed to serve files 

36 

37 Proxies reveal.js requests to a CDN if no local reveal.js is present 

38 """ 

39 

40 open_in_browser = Bool(True, help="""Should the browser be opened automatically?""").tag( 

41 config=True 

42 ) 

43 

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) 

55 

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) 

62 

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 ] 

70 

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)) 

80 

81 app = web.Application( 

82 handlers, 

83 cdn=self.reveal_cdn, 

84 client=AsyncHTTPClient(), 

85 ) 

86 

87 # hook up tornado logging to our logger 

88 log.app_log = self.log 

89 

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 

103 

104 try: 

105 ioloop.IOLoop.instance().start() 

106 except KeyboardInterrupt: 

107 print("\nInterrupted") 

108 

109 

110def main(path): 

111 """allow running this module to serve the slides""" 

112 server = ServePostProcessor() 

113 server(path) 

114 

115 

116if __name__ == "__main__": 

117 import sys 

118 

119 main(sys.argv[1])