diff options
Diffstat (limited to 'nikola/plugins/command/auto')
| -rw-r--r-- | nikola/plugins/command/auto/__init__.py | 39 |
1 files changed, 24 insertions, 15 deletions
diff --git a/nikola/plugins/command/auto/__init__.py b/nikola/plugins/command/auto/__init__.py index 71f9624..a82dc3e 100644 --- a/nikola/plugins/command/auto/__init__.py +++ b/nikola/plugins/command/auto/__init__.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -# Copyright © 2012-2015 Roberto Alsina and others. +# Copyright © 2012-2016 Roberto Alsina and others. # Permission is hereby granted, free of charge, to any # person obtaining a copy of this software and associated @@ -43,6 +43,7 @@ except ImportError: import webbrowser from wsgiref.simple_server import make_server import wsgiref.util +import pkg_resources from blinker import signal try: @@ -61,9 +62,8 @@ except ImportError: FileSystemEventHandler = object PatternMatchingEventHandler = object - from nikola.plugin_categories import Command -from nikola.utils import req_missing, get_logger, get_theme_path, STDERR_HANDLER +from nikola.utils import dns_sd, req_missing, get_logger, get_theme_path, STDERR_HANDLER LRJS_PATH = os.path.join(os.path.dirname(__file__), 'livereload.js') error_signal = signal('error') refresh_signal = signal('refresh') @@ -79,13 +79,14 @@ ERROR {} class CommandAuto(Command): - """Automatic rebuilds for Nikola.""" name = "auto" logger = None has_server = True doc_purpose = "builds and serves a site; automatically detects site changes, rebuilds, and optionally refreshes a browser" + dns_sd = None + cmd_options = [ { 'name': 'port', @@ -101,7 +102,7 @@ class CommandAuto(Command): 'long': 'address', 'type': str, 'default': '127.0.0.1', - 'help': 'Address to bind (default: 127.0.0.1 – localhost)', + 'help': 'Address to bind (default: 127.0.0.1 -- localhost)', }, { 'name': 'browser', @@ -142,7 +143,7 @@ class CommandAuto(Command): self.cmd_arguments = ['nikola', 'build'] if self.site.configuration_filename != 'conf.py': - self.cmd_arguments = ['--conf=' + self.site.configuration_filename] + self.cmd_arguments + self.cmd_arguments.append('--conf=' + self.site.configuration_filename) # Run an initial build so we are up-to-date subprocess.call(self.cmd_arguments) @@ -156,7 +157,7 @@ class CommandAuto(Command): # Do not duplicate entries -- otherwise, multiple rebuilds are triggered watched = set([ - 'templates/', + 'templates/' ] + [get_theme_path(name) for name in self.site.THEMES]) for item in self.site.config['post_pages']: watched.add(os.path.dirname(item[0])) @@ -166,6 +167,10 @@ class CommandAuto(Command): watched.add(item) for item in self.site.config['LISTINGS_FOLDERS']: watched.add(item) + for item in self.site._plugin_places: + watched.add(item) + # Nikola itself (useful for developers) + watched.add(pkg_resources.resource_filename('nikola', '')) out_folder = self.site.config['OUTPUT_FOLDER'] if options and options.get('browser'): @@ -208,7 +213,6 @@ class CommandAuto(Command): parent = self class Mixed(WebSocketWSGIApplication): - """A class that supports WS and HTTP protocols on the same port.""" def __call__(self, environ, start_response): @@ -235,9 +239,12 @@ class CommandAuto(Command): webbrowser.open('http://{0}:{1}'.format(host, port)) try: + self.dns_sd = dns_sd(port, (options['ipv6'] or '::' in host)) ws.serve_forever() except KeyboardInterrupt: self.logger.info("Server is shutting down.") + if self.dns_sd: + self.dns_sd.Reset() # This is a hack, but something is locking up in a futex # and exit() doesn't work. os.kill(os.getpid(), 15) @@ -262,6 +269,8 @@ class CommandAuto(Command): fname = os.path.basename(event_path) if (fname.endswith('~') or fname.startswith('.') or + '__pycache__' in event_path or + event_path.endswith(('.pyc', '.pyo', '.pyd')) or os.path.isdir(event_path)): # Skip on folders, these are usually duplicates return self.logger.info('REBUILDING SITE (from {0})'.format(event_path)) @@ -293,18 +302,21 @@ class CommandAuto(Command): mimetype = 'text/html' if uri.endswith('/') else mimetypes.guess_type(uri)[0] or 'application/octet-stream' if os.path.isdir(f_path): - if not f_path.endswith('/'): # Redirect to avoid breakage - start_response('301 Redirect', [('Location', p_uri.path + '/')]) + if not p_uri.path.endswith('/'): # Redirect to avoid breakage + start_response('301 Moved Permanently', [('Location', p_uri.path + '/')]) return [] f_path = os.path.join(f_path, self.site.config['INDEX_FILE']) mimetype = 'text/html' if p_uri.path == '/robots.txt': - start_response('200 OK', [('Content-type', 'text/plain')]) + start_response('200 OK', [('Content-type', 'text/plain; charset=UTF-8')]) return ['User-Agent: *\nDisallow: /\n'.encode('utf-8')] elif os.path.isfile(f_path): with open(f_path, 'rb') as fd: - start_response('200 OK', [('Content-type', mimetype)]) + if mimetype.startswith('text/') or mimetype.endswith('+xml'): + start_response('200 OK', [('Content-type', "{0}; charset=UTF-8".format(mimetype))]) + else: + start_response('200 OK', [('Content-type', mimetype)]) return [self.file_filter(mimetype, fd.read())] elif p_uri.path == '/livereload.js': with open(LRJS_PATH, 'rb') as fd: @@ -337,7 +349,6 @@ pending = [] class LRSocket(WebSocket): - """Speak Livereload protocol.""" def __init__(self, *a, **kw): @@ -410,7 +421,6 @@ class LRSocket(WebSocket): class OurWatchHandler(FileSystemEventHandler): - """A Nikola-specific handler for Watchdog.""" def __init__(self, function): @@ -424,7 +434,6 @@ class OurWatchHandler(FileSystemEventHandler): class ConfigWatchHandler(FileSystemEventHandler): - """A Nikola-specific handler for Watchdog that handles the config file (as a workaround).""" def __init__(self, configuration_filename, function): |
