Source code for server
import os
import threading
import SimpleHTTPServer
import BaseHTTPServer
from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler
[docs]class EventHandler(FileSystemEventHandler):
"""Watches all files except those that are hidden or are in
the hidden directory.
"""
def __init__(self, project_dir, new_changes_event):
"""
:param project_dir: project directory being watched
:param new_changes_event: event to be set when changes occur
:type new_changes_event: :class:`threading.Event`
"""
self._project_dir = project_dir
self._new_changes_event = new_changes_event
super(EventHandler, self).__init__()
def on_any_event(self, event):
path = os.path.realpath(event.src_path)
rel_path = os.path.relpath(path, self._project_dir)
rest = rel_path
while rest:
rest, head = os.path.split(rest)
if head.startswith('.'):
return
self._new_changes_event.set()
[docs]class Shutdowner(threading.Thread):
"""Daemon thread that waits for the changes and then
shuts down the server.
"""
def __init__(self, http_server, new_changes_event):
"""
:param http_server: server to be shut down
:type http_server: :class:`BaseHTTPServer.HTTPServer`
:param new_changes_event: event to be listened to
:type new_changes_event: :class:`threading.Event`
"""
super(Shutdowner, self).__init__()
self.daemon = True
self._http_server = http_server
self._new_changes_event = new_changes_event
def run(self):
while True:
self._new_changes_event.wait()
self._http_server.shutdown()
self._new_changes_event.clear()
[docs]def serve(host='localhost', port=8000):
"""Runs the development server at given `host` and `port`,
watches the changes and regenerates the site.
"""
http_server = BaseHTTPServer.HTTPServer(
(host, port), SimpleHTTPServer.SimpleHTTPRequestHandler)
# Event to be set when the project has changes and needs to be rebuilt
new_changes_event = threading.Event()
# Both `shutdowner` and `observer` are daemon threads
shutdowner = Shutdowner(http_server, new_changes_event)
shutdowner.start()
observer = Observer()
observer.start()
project_dir = os.getcwd()
www_dir = os.path.join(project_dir, 'www')
event_handler = EventHandler(project_dir, new_changes_event)
observer.schedule(event_handler, path=project_dir, recursive=True)
from carcade.cli import build # To resolve a circular import
while True:
os.chdir(project_dir)
build(to=www_dir, atomically=True)
if not os.path.exists(www_dir):
return 1
os.chdir(www_dir)
http_server.serve_forever()