Some more work on pecan serve --reload.

Now the app and config directories are monitored (instead of cwd()).
This commit is contained in:
Ryan Petrello
2012-03-19 12:53:10 -04:00
parent cf5c4e4998
commit 2e6e66e50a
3 changed files with 44 additions and 16 deletions

View File

@@ -38,9 +38,12 @@ class ServeCommand(BaseCommand):
stdout=sys.stdout, stderr=sys.stderr stdout=sys.stdout, stderr=sys.stderr
) )
def watch_and_spawn(self): def watch_and_spawn(self, conf):
from watchdog.observers import Observer from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler from watchdog.events import (
FileSystemEventHandler, FileSystemMovedEvent, FileModifiedEvent,
DirModifiedEvent
)
print 'Monitoring for changes...' print 'Monitoring for changes...'
self.create_subprocess() self.create_subprocess()
@@ -48,24 +51,31 @@ class ServeCommand(BaseCommand):
parent = self parent = self
class AggressiveEventHandler(FileSystemEventHandler): class AggressiveEventHandler(FileSystemEventHandler):
def should_reload(self, path): def should_reload(self, event):
extension = os.path.splitext(path)[1] for t in (
if extension in ( FileSystemMovedEvent, FileModifiedEvent, DirModifiedEvent
'.py', '.pyc', '.html', '.mak',
'.mako', '.xml'
): ):
return True if isinstance(event, t):
return True
return False return False
def on_modified(self, event): def on_modified(self, event):
if self.should_reload(getattr(event, 'src_path', '')): if self.should_reload(event):
parent.server_process.kill() parent.server_process.kill()
parent.create_subprocess() parent.create_subprocess()
# Determine a list of file paths to monitor
paths = self.paths_to_monitor(conf)
event_handler = AggressiveEventHandler() event_handler = AggressiveEventHandler()
observer = Observer() for path, recurse in paths:
observer.schedule(event_handler, path=os.getcwd(), recursive=True) observer = Observer()
observer.start() observer.schedule(
event_handler,
path=path,
recursive=recurse
)
observer.start()
try: try:
while True: while True:
@@ -73,6 +83,22 @@ class ServeCommand(BaseCommand):
except KeyboardInterrupt: except KeyboardInterrupt:
pass pass
def paths_to_monitor(self, conf):
paths = []
for package_name in getattr(conf.app, 'modules', []):
module = __import__(package_name, fromlist=['app'])
if hasattr(module, 'app') and hasattr(module.app, 'setup_app'):
paths.append((
os.path.dirname(module.__file__),
True
))
break
paths.append((os.path.dirname(conf.__file__), False))
return paths
def _serve(self, app, conf): def _serve(self, app, conf):
from wsgiref.simple_server import make_server from wsgiref.simple_server import make_server
@@ -100,7 +126,7 @@ class ServeCommand(BaseCommand):
if self.args.reload: if self.args.reload:
try: try:
self.watch_and_spawn() self.watch_and_spawn(conf)
except ImportError: except ImportError:
print('The `--reload` option requires `watchdog` to be ' print('The `--reload` option requires `watchdog` to be '
'installed.') 'installed.')

View File

@@ -161,7 +161,6 @@ def conf_from_dict(conf_dict):
:param conf_dict: The configuration dictionary. :param conf_dict: The configuration dictionary.
''' '''
conf = Config(filename=conf_dict.get('__file__', '')) conf = Config(filename=conf_dict.get('__file__', ''))
for k, v in conf_dict.iteritems(): for k, v in conf_dict.iteritems():
@@ -195,7 +194,10 @@ def set_config(config, overwrite=False):
_runtime_conf.empty() _runtime_conf.empty()
if isinstance(config, basestring): if isinstance(config, basestring):
_runtime_conf.update(conf_from_file(config)) config = conf_from_file(config)
_runtime_conf.update(config)
if config.__file__:
_runtime_conf.__file__ = config.__file__
elif isinstance(config, dict): elif isinstance(config, dict):
_runtime_conf.update(conf_from_dict(config)) _runtime_conf.update(conf_from_dict(config))
else: else:

View File

@@ -1,4 +1,3 @@
from configuration import _runtime_conf, set_config
from templating import RendererFactory from templating import RendererFactory
from routing import lookup_controller, NonCanonicalPath from routing import lookup_controller, NonCanonicalPath
from util import _cfg, encode_if_needed from util import _cfg, encode_if_needed
@@ -141,6 +140,7 @@ def load_app(config):
which represents a (relative) configuration filename. which represents a (relative) configuration filename.
:returns a pecan.Pecan object :returns a pecan.Pecan object
''' '''
from configuration import _runtime_conf, set_config
set_config(config, overwrite=True) set_config(config, overwrite=True)
for package_name in getattr(_runtime_conf.app, 'modules', []): for package_name in getattr(_runtime_conf.app, 'modules', []):