diff --git a/CHANGELOG.md b/CHANGELOG.md index f4a94ac..824806a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # Changelog +## [unreleased] + +* Fixed devsever so it does not crash when the (re-)build fails anymore +* updated dependencies + ## [2.2.1] -- 2023-11-11 * fixed `suggests` to blag-doc diff --git a/blag/devserver.py b/blag/devserver.py index 4f3ec50..87df66e 100644 --- a/blag/devserver.py +++ b/blag/devserver.py @@ -52,7 +52,7 @@ def get_last_modified(dirs: list[str]) -> float: return last_mtime -def autoreload(args: argparse.Namespace) -> NoReturn: +def autoreload(args: argparse.Namespace, wait: int=1) -> NoReturn: """Start the autoreloader. This method monitors the given directories for changes (i.e. the @@ -66,6 +66,9 @@ def autoreload(args: argparse.Namespace) -> NoReturn: ---------- args contains the input-, template- and static dir + wait + number of seconds the devsever waits before checking for updated + content """ dirs = [args.input_dir, args.template_dir, args.static_dir] @@ -74,12 +77,18 @@ def autoreload(args: argparse.Namespace) -> NoReturn: # loop to avoid serving stale contents last_mtime = 0.0 while True: - mtime = get_last_modified(dirs) - if mtime > last_mtime: - last_mtime = mtime - logger.info("Change detected, rebuilding...") - blag.build(args) - time.sleep(1) + # make sure the devsever does not crash when the build fails with an + # exception + try: + mtime = get_last_modified(dirs) + if mtime > last_mtime: + last_mtime = mtime + logger.info("Change detected, rebuilding...") + blag.build(args) + time.sleep(wait) + except Exception: + logger.exception("Error occurred during rebuild:") + logger.info("Devserver did not crash, you may continue editing.") def serve(args: argparse.Namespace) -> None: diff --git a/tests/test_devserver.py b/tests/test_devserver.py index 3652f19..aab422b 100644 --- a/tests/test_devserver.py +++ b/tests/test_devserver.py @@ -8,10 +8,10 @@ import threading import time from argparse import Namespace -import pytest - from blag import devserver +WAITTIME = 0.1 + def test_get_last_modified(cleandir: str) -> None: """Test get_last_modified.""" @@ -19,13 +19,13 @@ def test_get_last_modified(cleandir: str) -> None: t1 = devserver.get_last_modified(["content"]) # wait a bit, create a file and measure again - time.sleep(0.1) + time.sleep(WAITTIME) with open("content/test", "w") as fh: fh.write("boo") t2 = devserver.get_last_modified(["content"]) # wait a bit and take time again - time.sleep(0.1) + time.sleep(WAITTIME) t3 = devserver.get_last_modified(["content"]) assert t2 > t1 @@ -40,14 +40,14 @@ def test_autoreload_builds_immediately(args: Namespace) -> None: t = threading.Thread( target=devserver.autoreload, - args=(args,), + args=(args, WAITTIME), daemon=True, ) t0 = devserver.get_last_modified(["build"]) t.start() # try for 5 seconds... for i in range(5): - time.sleep(1) + time.sleep(WAITTIME) t1 = devserver.get_last_modified(["build"]) print(t1) if t1 > t0: @@ -55,14 +55,11 @@ def test_autoreload_builds_immediately(args: Namespace) -> None: assert t1 > t0 -@pytest.mark.filterwarnings( - "ignore::pytest.PytestUnhandledThreadExceptionWarning" -) def test_autoreload(args: Namespace) -> None: """Test autoreload.""" t = threading.Thread( target=devserver.autoreload, - args=(args,), + args=(args, WAITTIME), daemon=True, ) t.start() @@ -75,8 +72,32 @@ def test_autoreload(args: Namespace) -> None: # try for 5 seconds to see if we rebuild once... for i in range(5): - time.sleep(1) + time.sleep(WAITTIME) t1 = devserver.get_last_modified(["build"]) if t1 > t0: break assert t1 > t0 + + +def test_autoreload_does_not_crash(args: Namespace) -> None: + """Test autoreload does not crash if build fails.""" + t = threading.Thread( + target=devserver.autoreload, + args=(args, WAITTIME), + daemon=True, + ) + t.start() + + t0 = devserver.get_last_modified(["build"]) + + # create a file that causes build to crash + with open("content/test.md", "w") as fh: + fh.write("date: ") + + # try for 5 seconds to see if we rebuild once... + for i in range(5): + time.sleep(WAITTIME) + t1 = devserver.get_last_modified(["build"]) + if t1 > t0: + break + assert t.is_alive()