Skip to content

Commit

Permalink
Merge 7b5337c into a6f9bd5
Browse files Browse the repository at this point in the history
  • Loading branch information
d0ugal committed May 9, 2015
2 parents a6f9bd5 + 7b5337c commit 134db38
Show file tree
Hide file tree
Showing 5 changed files with 109 additions and 72 deletions.
14 changes: 9 additions & 5 deletions mkdocs/cli.py
Expand Up @@ -15,17 +15,17 @@
log = logging.getLogger(__name__)


def configure_logging(is_verbose=False):
def configure_logging(log_name='mkdocs', verbose=False):
'''When a --verbose flag is passed, increase the verbosity of mkdocs'''

logger = logging.getLogger('mkdocs')
logger = logging.getLogger(log_name)
logger.propagate = False
stream = logging.StreamHandler()
formatter = logging.Formatter("%(levelname)-7s - %(message)s ")
stream.setFormatter(formatter)
logger.addHandler(stream)

if is_verbose:
if verbose:
logger.setLevel(logging.DEBUG)
else:
logger.setLevel(logging.INFO)
Expand All @@ -40,6 +40,7 @@ def configure_logging(is_verbose=False):
theme_help = "The theme to use when building your documentation."
theme_choices = utils.get_theme_names()
site_dir_help = "The directory to output the result of the documentation build."
reload_help = "Enable and disable the live reloading in the development server."


@click.group()
Expand All @@ -49,21 +50,24 @@ def cli(verbose):
"""
MkDocs - Project documentation with Markdown.
"""
configure_logging(verbose)
configure_logging(verbose=verbose)


@cli.command(name="serve")
@click.option('--config-file', type=click.File('rb'), help=config_file_help)
@click.option('--dev-addr', help=dev_addr_help, metavar='<IP:PORT>')
@click.option('--strict', is_flag=True, help=strict_help)
@click.option('--theme', type=click.Choice(theme_choices), help=theme_help)
def serve_command(dev_addr, config_file, strict, theme):
@click.option('--livereload/--no-livereload', default=True, help=reload_help)
def serve_command(dev_addr, config_file, strict, theme, livereload):
"""Run the builtin development server"""
configure_logging('tornado')
serve.serve(
config_file=config_file,
dev_addr=dev_addr,
strict=strict,
theme=theme,
livereload=livereload,
)


Expand Down
75 changes: 61 additions & 14 deletions mkdocs/serve.py
@@ -1,19 +1,68 @@
import logging
import shutil
import tempfile

from livereload import Server

from mkdocs.build import build
from mkdocs.config import load_config

log = logging.getLogger(__name__)


def _livereload(host, port, config, builder, site_dir):

# We are importing here for anyone that has issues with livereload. Even if
# this fails, the --no-livereload alternative should still work.
from livereload import Server

server = Server()

# Watch the documentation files, the config file and the theme files.
server.watch(config['docs_dir'], builder)
server.watch(config['config_file_path'], builder)

for d in config['theme_dir']:
server.watch(d, builder)

server.serve(root=site_dir, host=host, port=int(port), restart_delay=0)


def _static_server(host, port, site_dir):

def serve(config_file=None, dev_addr=None, strict=None, theme=None):
# Importing here to seperate the code paths from the --livereload
# alternative.
from tornado import ioloop
from tornado import web

application = web.Application([
(r"/(.*)", web.StaticFileHandler, {
"path": site_dir,
"default_filename": "index.html"
}),
])
application.listen(port=port, address=host)

log.info('Running at: http://%s:%s/', host, port)
log.info('Hold ctrl+c to quit.')
try:
ioloop.IOLoop.instance().start()
except KeyboardInterrupt:
log.info('Stopping server...')


def serve(config_file=None, dev_addr=None, strict=None, theme=None,
livereload=True):
"""
Start the devserver, and rebuild the docs whenever any changes take effect.
Start the MkDocs development server
By default it will serve the documentation on http://localhost:8000/ and
it will rebuild the documentation and refresh the page automatically
whenever a file is edited.
"""
# Create a temporary build directory, and set some options to serve it
tempdir = tempfile.mkdtemp()

def builder():
log.info("Rebuilding documentation...")
config = load_config(
config_file=config_file,
dev_addr=dev_addr,
Expand All @@ -27,14 +76,12 @@ def builder():
# Perform the initial build
config = builder()

server = Server()

# Watch the documentation files, the config file and the theme files.
server.watch(config['docs_dir'], builder)
server.watch(config['config_file_path'], builder)

for d in config['theme_dir']:
server.watch(d, builder)

host, port = config['dev_addr'].split(':', 1)
server.serve(root=tempdir, host=host, port=int(port), restart_delay=0)

try:
if livereload:
_livereload(host, port, config, builder, tempdir)
else:
_static_server(host, port, tempdir)
finally:
shutil.rmtree(tempdir)
90 changes: 37 additions & 53 deletions mkdocs/tests/integration.py
Expand Up @@ -16,93 +16,77 @@

from __future__ import print_function

import os
import click
import contextlib
import logging
import os
import sys

from six.moves import cStringIO

from mkdocs import cli, config, serve, build, utils
from mkdocs import cli, config, build, utils

MKDOCS_CONFIG = os.path.join(os.path.dirname(__file__), '../../mkdocs.yml')
DIR = os.path.dirname(__file__)
MKDOCS_CONFIG = os.path.abspath(os.path.join(DIR, '../../mkdocs.yml'))
MKDOCS_THEMES = utils.get_theme_names()


@contextlib.contextmanager
def capture_stdout():
oldout, olderr = sys.stdout, sys.stderr
try:
out = [cStringIO(), cStringIO()]
sys.stdout, sys.stderr = out
yield out
finally:
sys.stdout, sys.stderr = oldout, olderr
out[0] = out[0].getvalue()
out[1] = out[1].getvalue()
def silence_logging(is_verbose=False):
'''When a --verbose flag is passed, increase the verbosity of mkdocs'''

logger = logging.getLogger('mkdocs')
logger.setLevel(logging.WARNING)


def run_build(theme_name, output=None, config_file=None, quiet=False):
def run_build(theme_name, output, config_file, quiet):
"""
Given a theme name and output directory use the configuration
for the MkDocs documentation and overwrite the site_dir and
theme. If no output is provided, serve the documentation on
each theme, one at a time.
"""

should_serve = output is None
options = {}

if not serve:
if not os.path.exists(output):
os.makedirs(output)
options['site_dir'] = os.path.join(output, theme_name)
options = {
'theme': theme_name,
}

if config_file is None:
config_file = open(MKDOCS_CONFIG, 'rb')

if not quiet:
print("Using config: {0}".format(config_file))

cli.configure_logging()
conf = config.load_config(config_file=config_file, theme=theme_name)

if should_serve:
if not quiet:
print("Serving {0}".format(theme_name))
try:
serve.serve(conf)
except KeyboardInterrupt:
return
else:
if not quiet:
print("Building {0}".format(theme_name))
print("Using config: {0}".format(config_file.name))

try:
with capture_stdout() as out:
build.build(conf)
build.build(conf, dump_json=True)
except Exception:
print("Failed building {0}".format(theme_name), file=sys.stderr)
raise
if not os.path.exists(output):
os.makedirs(output)
options['site_dir'] = os.path.join(output, theme_name)

if not quiet:
print(''.join(out))
if not quiet:
print("Building {0}".format(theme_name))

try:
conf = config.load_config(config_file=config_file, **options)
config_file.close()
build.build(conf)
build.build(conf, dump_json=True)
except Exception:
print("Error building: {0}".format(theme_name), file=sys.stderr)
raise


@click.command()
@click.option('--output',
help="The output directory to use when building themes",
type=click.Path(file_okay=False, writable=True))
@click.option('--config',
@click.option('--config-file',
help="The MkDocs project config to use.",
type=click.File('rb'))
@click.option('--quiet', is_flag=True)
def main(output=None, config=None, quiet=False):
def main(output=None, config_file=None, quiet=False):

if quiet:
silence_logging()
else:
cli.configure_logging()

for theme in sorted(MKDOCS_THEMES):

run_build(theme, output, config, quiet)
run_build(theme, output, config_file, quiet)

print("The theme builds are available in {0}".format(output))

Expand Down
1 change: 1 addition & 0 deletions requirements/project.txt
Expand Up @@ -5,3 +5,4 @@ livereload>=2.3.2
Markdown>=2.5
PyYAML>=3.10
six>=1.9.0
tornado>=4.1
1 change: 1 addition & 0 deletions setup.py
Expand Up @@ -81,6 +81,7 @@ def get_package_data(package):
'Markdown>=2.3.1,<2.5' if PY26 else 'Markdown>=2.3.1',
'PyYAML>=3.10',
'six>=1.9.0',
'tornado>=4.1',
],
entry_points={
'console_scripts': [
Expand Down

0 comments on commit 134db38

Please sign in to comment.