xref: /aosp_15_r20/external/bazelbuild-rules_python/sphinxdocs/private/sphinx_server.py (revision 60517a1edbc8ecf509223e9af94a7adec7d736b8)
1import contextlib
2import errno
3import os
4import sys
5import time
6from http import server
7
8
9def main(argv):
10    build_workspace_directory = os.environ["BUILD_WORKSPACE_DIRECTORY"]
11    docs_directory = argv[1]
12    serve_directory = os.path.join(build_workspace_directory, docs_directory)
13
14    class DirectoryHandler(server.SimpleHTTPRequestHandler):
15        def __init__(self, *args, **kwargs):
16            super().__init__(directory=serve_directory, *args, **kwargs)
17
18    address = ("0.0.0.0", 8000)
19    # with server.ThreadingHTTPServer(address, DirectoryHandler) as (ip, port, httpd):
20    with _start_server(DirectoryHandler, "0.0.0.0", 8000) as (ip, port, httpd):
21
22        def _print_server_info():
23            print(f"Serving...")
24            print(f"  Address: http://{ip}:{port}")
25            print(f"  Serving directory: {serve_directory}")
26            print(f"      url: file://{serve_directory}")
27            print(f"  Server CWD: {os.getcwd()}")
28            print()
29            print("*** You do not need to restart this server to see changes ***")
30            print("*** CTRL+C once to reprint this info ***")
31            print("*** CTRL+C twice to exit ***")
32            print()
33
34        while True:
35            _print_server_info()
36            try:
37                httpd.serve_forever()
38            except KeyboardInterrupt:
39                _print_server_info()
40                print(
41                    "*** KeyboardInterrupt received: CTRL+C again to terminate server ***"
42                )
43                try:
44                    time.sleep(1)
45                    print("Restarting serving ...")
46                except KeyboardInterrupt:
47                    break
48    return 0
49
50
51@contextlib.contextmanager
52def _start_server(handler, ip, start_port):
53    for port in range(start_port, start_port + 10):
54        try:
55            with server.ThreadingHTTPServer((ip, port), handler) as httpd:
56                yield ip, port, httpd
57                return
58        except OSError as e:
59            if e.errno == errno.EADDRINUSE:
60                pass
61            else:
62                raise
63    raise ValueError("Unable to find an available port")
64
65
66if __name__ == "__main__":
67    sys.exit(main(sys.argv))
68