From 801c61f768626d604a7d73830d8fd20bfebf749a Mon Sep 17 00:00:00 2001 From: Pierce Freeman Date: Fri, 22 Nov 2024 07:35:05 -0800 Subject: [PATCH] Wait for reload --- mountaineer/__tests__/test_hotreload.py | 61 +++++++++++-------------- 1 file changed, 26 insertions(+), 35 deletions(-) diff --git a/mountaineer/__tests__/test_hotreload.py b/mountaineer/__tests__/test_hotreload.py index 5e661028..7fbae887 100644 --- a/mountaineer/__tests__/test_hotreload.py +++ b/mountaineer/__tests__/test_hotreload.py @@ -57,6 +57,18 @@ def get_child_value(self): return pkg_dir, pkg_name +def immediate_flush_to_disk(path: Path): + """ + Help deal with test unreliability when we reload a file + that has changed via python but hasn't yet been flushed to + the filesystem. reload seems to do a full filesystem pull and bipass + Python's write caching logic. + + """ + # Seems to be the only consistent approach + time.sleep(1) + + def test_initial_dependency_tracking(test_package_dir: tuple[Path, str]): """ Test initial dependency tracking on load. @@ -153,10 +165,6 @@ def __init__(self): ) ) - # Import modules - importlib.import_module(f"{pkg_name}.module_b") - importlib.import_module(f"{pkg_name}.module_a") - # Initialize HotReloader hot_reloader = HotReloader(pkg_name, pkg_dir, entrypoint=f"{pkg_name}.module_a") @@ -171,10 +179,6 @@ def test_partial_reload_failure(test_package_dir: tuple[Path, str]): """ pkg_dir, pkg_name = test_package_dir - # Import base and child - importlib.import_module(f"{pkg_name}.base") - importlib.import_module(f"{pkg_name}.child") - # Initialize HotReloader hot_reloader = HotReloader(pkg_name, pkg_dir, entrypoint=f"{pkg_name}.child") @@ -233,11 +237,6 @@ def get_child_value(self): ) ) - # Import necessary modules - importlib.import_module(f"{pkg_name}.base") - importlib.import_module(f"{pkg_name}.mixin") - importlib.import_module(f"{pkg_name}.child") - # Initialize HotReloader hot_reloader = HotReloader(pkg_name, pkg_dir, entrypoint=f"{pkg_name}.child") @@ -287,9 +286,6 @@ def get_status(self): ) ) - # Import modules - importlib.import_module(f"{pkg_name}.status") - # Initialize HotReloader hot_reloader = HotReloader(pkg_name, pkg_dir, entrypoint=f"{pkg_name}.document") @@ -348,7 +344,6 @@ def get_model_value(): ) # Import modules - importlib.import_module(f"{pkg_name}.models") main_module = importlib.import_module(f"{pkg_name}.main") # Initialize HotReloader @@ -432,7 +427,6 @@ def get_model_value(): ) # Import and verify initial state - importlib.import_module(f"{pkg_name}.models") main_module = importlib.import_module(f"{pkg_name}.main") hot_reloader = HotReloader(pkg_name, pkg_dir, entrypoint=f"{pkg_name}.main") @@ -520,7 +514,6 @@ def get_model_value(): ) # Import and verify initial state - importlib.import_module(f"{pkg_name}.models") main_module = importlib.import_module(f"{pkg_name}.main") hot_reloader = HotReloader(pkg_name, pkg_dir, entrypoint=f"{pkg_name}.main") @@ -594,7 +587,6 @@ class SubNestedInit: ) ) - # Import modules importlib.import_module(f"{pkg_name}.nested") importlib.import_module(f"{pkg_name}.nested.module") importlib.import_module(f"{pkg_name}.nested.subnested") @@ -653,11 +645,6 @@ class LeafClass(MiddleClass): ) ) - # Import modules - importlib.import_module(f"{pkg_name}.base") - importlib.import_module(f"{pkg_name}.middle") - importlib.import_module(f"{pkg_name}.leaf") - # Initialize HotReloader hot_reloader = HotReloader(pkg_name, pkg_dir, entrypoint=f"{pkg_name}.leaf") @@ -721,10 +708,6 @@ class DynamicClass(BaseClass): ) ) - # Import modules - importlib.import_module(f"{pkg_name}.base") - importlib.import_module(f"{pkg_name}.dynamic") - # Initialize HotReloader hot_reloader = HotReloader(pkg_name, pkg_dir, entrypoint=f"{pkg_name}.dynamic") @@ -760,7 +743,6 @@ def test_new_file_reload(test_package_dir: tuple[Path, str]): pkg_dir, pkg_name = test_package_dir # Import initial modules - importlib.import_module(f"{pkg_name}.base") hot_reloader = HotReloader(pkg_name, pkg_dir, entrypoint=f"{pkg_name}.base") # Create new file that imports base @@ -776,17 +758,25 @@ def get_special_value(self): ) ) - # Verify dependency tracking - new_deps = hot_reloader.get_module_dependencies(f"{pkg_name}.new_module") - base_deps = hot_reloader.get_module_dependencies(f"{pkg_name}.base") + immediate_flush_to_disk(pkg_dir / "new_module.py") + # Calling this should also start tracking the new file + new_deps = hot_reloader.get_module_dependencies(f"{pkg_name}.new_module") assert new_deps + + # Verify we have also updated the old file bidirectionally + base_deps = hot_reloader.get_module_dependencies(f"{pkg_name}.base") assert base_deps assert f"{pkg_name}.base" in new_deps.imports assert new_deps.superclasses == {"NewClass": {"BaseClass"}} assert "NewClass" in base_deps.subclasses["BaseClass"] + # Verify that the new module was reloaded + new_module = sys.modules[f"{pkg_name}.new_module"] + obj = new_module.NewClass() + assert obj.get_special_value() == 20 + # Modify the base module (pkg_dir / "base.py").write_text( textwrap.dedent( @@ -800,7 +790,8 @@ def get_value(self): ) ) - time.sleep(0.1) + immediate_flush_to_disk(pkg_dir / "base.py") + success, reloaded = hot_reloader.reload_module(f"{pkg_name}.base") assert success assert reloaded == [f"{pkg_name}.base", f"{pkg_name}.new_module"] @@ -808,7 +799,7 @@ def get_value(self): # Verify that the new module was reloaded new_module = sys.modules[f"{pkg_name}.new_module"] obj = new_module.NewClass() - assert obj.get_special_value() == 20 + assert obj.get_special_value() == 40 #