aputils/docs/build.py
2022-11-21 20:29:39 -05:00

122 lines
2.7 KiB
Python
Executable file

#!/usr/bin/env python3
import subprocess
import sys
from datetime import datetime
from http.server import ThreadingHTTPServer, SimpleHTTPRequestHandler
from pathlib import Path
from watchdog.events import FileSystemEventHandler
from watchdog.observers.polling import PollingObserver
docpath = Path(__file__).resolve().parent
class DocWatcher(FileSystemEventHandler):
proc = None
last_restart = 0
def __init__(self, path):
self.path = str(path)
def on_any_event(self, event):
if event.event_type not in ['modified', 'created', 'deleted']:
return
path = Path(event.src_path)
directory = str(path.parent).replace(self.path, '')
if not path.suffix or not directory:
return
if directory.startswith('/docs/_') or str(path).endswith('/docs/build.py'):
return
if path.suffix[1:] not in {'py', 'rst', 'yml'}:
return
self.run_proc()
def run_proc(self):
timestamp = datetime.timestamp(datetime.now())
if not self.last_restart:
pass
elif timestamp - 3 < self.last_restart:
return
self.last_restart = timestamp
build_docs()
class ServerHandler(SimpleHTTPRequestHandler):
def send_response(self, code, message=None):
if any(map(self.path.endswith, ['/', '.html'])):
agent = self.headers.get('User-Agent', 'n/a')
sys.stdout.write(f'\n{self.address_string()} {self.path} {code} "{agent}"')
sys.stdout.flush()
self.send_response_only(code, message)
self.send_header('Server', self.version_string())
self.send_header('Date', self.date_time_string())
class Server(ThreadingHTTPServer):
def __init__(self, host, port, directory):
ThreadingHTTPServer.__init__(self, (host, port), SimpleHTTPRequestHandler)
self.directory = directory
def finish_request(self, request, client_address):
ServerHandler(request, client_address, self, directory=self.directory)
def run(self):
with self as httpd:
host, port = httpd.socket.getsockname()[:2]
print(f'Serving HTTP on {host} port {port} (http://{host}:{port}/)')
try:
httpd.serve_forever()
except KeyboardInterrupt:
print('\nKeyboard interrupt received, exiting.')
return 0
print('Bye! :3')
def build_docs():
sphinx('-M', 'html', str(docpath), docpath.joinpath('_build'))
def sphinx(*args):
return subprocess.run(['sphinx-build', *args])
def main():
if len(sys.argv) < 2:
print('Must include output type')
return 1
arg = sys.argv[1]
if arg == 'serve':
build_docs()
s = Server('0.0.0.0', 8080, docpath.joinpath('_build/html'))
watcher = PollingObserver()
watcher.schedule(DocWatcher(docpath.parent), docpath.parent, recursive=True)
watcher.start()
s.run()
watcher.stop()
return
return sphinx('-M', sys.argv[1], str(docpath), docpath.joinpath('_build'))
if __name__ == '__main__':
sys.exit(main())