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