Merge pull request #1 from venthur/devserver

Devserver
This commit is contained in:
Bastian Venthur
2021-03-19 11:30:55 +01:00
committed by GitHub
4 changed files with 126 additions and 2 deletions

View File

@@ -14,6 +14,7 @@ blag is named after [the blag of the webcomic xkcd][blagxkcd].
* Theming support using [Jinja2][] templates
* Generation of Atom feeds for blog content
* Fenced code blocks and syntax highlighting using [Pygments][]
* Integrated devserver
blag runs on Linux, Mac and Windows and requires Python >= 3.8

View File

@@ -19,6 +19,7 @@ from jinja2 import Environment, ChoiceLoader, FileSystemLoader, PackageLoader
import feedgenerator
from blag.markdown import markdown_factory, convert_markdown
from blag.devserver import serve
logger = logging.getLogger(__name__)
logging.basicConfig(
@@ -50,7 +51,10 @@ def parse_args(args=None):
commands = parser.add_subparsers(dest='command')
commands.required = True
build_parser = commands.add_parser('build')
build_parser = commands.add_parser(
'build',
help='Build website.',
)
build_parser.set_defaults(func=build)
build_parser.add_argument(
'-i', '--input-dir',
@@ -73,9 +77,38 @@ def parse_args(args=None):
help='Static directory (default: static)',
)
quickstart_parser = commands.add_parser('quickstart')
quickstart_parser = commands.add_parser(
'quickstart',
help="Quickstart blag, creating necessary configuration.",
)
quickstart_parser.set_defaults(func=quickstart)
serve_parser = commands.add_parser(
'serve',
help="Start development server.",
)
serve_parser.set_defaults(func=serve)
serve_parser.add_argument(
'-i', '--input-dir',
default='content',
help='Input directory (default: content)',
)
serve_parser.add_argument(
'-o', '--output-dir',
default='build',
help='Ouptut directory (default: build)',
)
serve_parser.add_argument(
'-t', '--template-dir',
default='templates',
help='Template directory (default: templates)',
)
serve_parser.add_argument(
'-s', '--static-dir',
default='static',
help='Static directory (default: static)',
)
return parser.parse_args(args)

60
blag/devserver.py Normal file
View File

@@ -0,0 +1,60 @@
import os
import logging
import time
import multiprocessing
from http.server import SimpleHTTPRequestHandler, HTTPServer
from functools import partial
from blag import blag
logger = logging.getLogger(__name__)
def get_last_modified(dirs):
"""Get the last modified time.
This method recursively goes through `dirs` and returns the most
recent modification time time found.
Parameters
----------
dirs : list[str]
list of directories to search
Returns
-------
int : most recent modification time found in `dirs`
"""
last_mtime = 0
for dir in dirs:
for root, dirs, files in os.walk(dir):
for f in files:
mtime = os.stat(os.path.join(root, f)).st_mtime
if mtime > last_mtime:
last_mtime = mtime
return last_mtime
def autoreload(args):
dirs = [args.input_dir, args.template_dir, args.static_dir]
logger.info(f'Monitoring {dirs} for changes...')
last_mtime = get_last_modified(dirs)
while True:
mtime = get_last_modified(dirs)
if mtime > last_mtime:
last_mtime = mtime
logger.debug('Change detected, rebuilding...')
blag.build(args)
time.sleep(1)
def serve(args):
httpd = HTTPServer(('', 8000), partial(SimpleHTTPRequestHandler,
directory=args.output_dir))
proc = multiprocessing.Process(target=autoreload, args=(args,))
proc.start()
httpd.serve_forever()

30
tests/test_devserver.py Normal file
View File

@@ -0,0 +1,30 @@
import time
import pytest
from tempfile import TemporaryDirectory
from blag import devserver
@pytest.fixture
def tempdir():
with TemporaryDirectory() as dir:
yield dir
def test_get_last_modified(tempdir):
# take initial time
t1 = devserver.get_last_modified([tempdir])
# wait a bit, create a file and measure again
time.sleep(0.1)
with open(f'{tempdir}/test', 'w') as fh:
fh.write('boo')
t2 = devserver.get_last_modified([tempdir])
# wait a bit and take time again
time.sleep(0.1)
t3 = devserver.get_last_modified([tempdir])
assert t2 > t1
assert t2 == t3