Private
Public Access
0
0

refactor(markdown_helper): remove top-level src.markdown_table import; use _require_warmed

Phase 5C of startup_speedup_20260606 track.

src/markdown_helper.py imported src.markdown_table at module level:
  from src.markdown_table import parse_tables, render_table

Both parse_tables and render_table are only used inside
MarkdownRenderer.render(). Removed the top-level import; the
MarkdownRenderer.render() method now does:
  markdown_table = _require_warmed('src.markdown_table')
  parse_tables = markdown_table.parse_tables
  render_table = markdown_table.render_table

at the top of its body, before any other logic.

TESTS:
- tests/test_markdown_helper_no_top_level_table.py: 3/3 PASS (all RED -> GREEN)
- tests/test_markdown_table*.py (5 files) + test_markdown_helper_bullets.py +
  test_markdown_render_robust.py: 24/24 PASS (no breakage)

EFFECTIVENESS: import src.markdown_helper no longer triggers src.markdown_table
(~250ms). For renderers that never hit a GFM table, the import is never
paid. For renderers that do, the warmup pre-loads it on _io_pool and the
render() lookup is O(1).

NEXT: Phase 5D - bulk refactor of src/gui_2.py feature-gated imports via
scripts/audit_gui2_imports.py.
This commit is contained in:
2026-06-06 16:58:32 -04:00
parent cbc3b075a0
commit 48c9649951
2 changed files with 104 additions and 1 deletions
+13 -1
View File
@@ -12,7 +12,14 @@ from typing import Optional, Dict, Callable
from src import theme_2
from src.markdown_table import parse_tables, render_table
from src.module_loader import _require_warmed
# NOTE: src.markdown_table is NOT imported at module level. The GFM table
# rendering branch is feature-gated (startup_speedup_20260606 Phase 5C);
# the lookup happens inside MarkdownRenderer.render() via _require_warmed.
# If you need parse_tables/render_table elsewhere in this file, do the
# lookup there too. The warmup on AppController's _io_pool pre-loads
# src.markdown_table so the first render() call is O(1).
def _get_language_id(name: str):
@@ -121,6 +128,11 @@ class MarkdownRenderer:
Render Markdown text with code block interception and GFM table substitution.
[C: src/theme_2.py:render_post_fx, tests/test_theme_nerv_alert.py:test_alert_pulsing_render_active, tests/test_theme_nerv_alert.py:test_alert_pulsing_render_inactive, tests/test_theme_nerv_fx.py:TestThemeNervFx.test_alert_pulsing_render, tests/test_theme_nerv_fx.py:TestThemeNervFx.test_crt_filter_disabled, tests/test_theme_nerv_fx.py:TestThemeNervFx.test_crt_filter_render]
"""
# Lazy lookup of src.markdown_table (Phase 5C). Warmup has already loaded
# it on AppController's _io_pool, so this is an O(1) sys.modules get.
markdown_table = _require_warmed("src.markdown_table")
parse_tables = markdown_table.parse_tables
render_table = markdown_table.render_table
if not text: return
text = self._normalize_bullet_delimiters(text)
text = self._normalize_nested_list_endings(text)
@@ -0,0 +1,91 @@
"""Tests that src/markdown_helper.py has NO top-level src.markdown_table import.
Per spec.md:2.2 Layer 1, the main thread's import chain must not include
heavy feature-gated modules. src.markdown_table (~250ms) is warmed on
AppController's _io_pool and accessed via _require_warmed at use sites.
The GFM table-rendering branch is optional (default markdown rendering
falls through to imgui_md).
src/markdown_helper.py uses src.markdown_table only inside the
MarkdownRenderer.render() method (parse_tables at the top, render_table
in a nested code block). The lookup is deferred to the render() call.
"""
import subprocess
import sys
import textwrap
from pathlib import Path
ROOT = Path(__file__).resolve().parent.parent
def _run_in_subprocess(snippet: str) -> subprocess.CompletedProcess:
script = textwrap.dedent(snippet)
return subprocess.run(
[sys.executable, "-c", script],
capture_output=True,
text=True,
cwd=str(ROOT),
timeout=30,
)
def test_markdown_helper_does_not_import_markdown_table_at_module_level() -> None:
res = _run_in_subprocess("""
import sys
import src.markdown_helper
print('src.markdown_table' in sys.modules)
""")
assert res.returncode == 0, f"stderr: {res.stderr}"
assert res.stdout.strip() == "False", f"markdown_helper triggered src.markdown_table import: {res.stdout}"
def test_markdown_helper_render_method_lazy_lookups() -> None:
"""The render() method should resolve parse_tables and render_table
via _require_warmed at call time, not at module load."""
res = _run_in_subprocess("""
import ast
from pathlib import Path
root = Path('.').resolve()
helper_path = root / 'src' / 'markdown_helper.py'
tree = ast.parse(helper_path.read_text(encoding='utf-8'))
# Look for any top-level ImportFrom that imports parse_tables or render_table
has_top_level_table_import = False
for node in tree.body:
if isinstance(node, ast.ImportFrom):
for alias in node.names:
if alias.name in ('parse_tables', 'render_table'):
has_top_level_table_import = True
print('HAS_TOP_LEVEL_TABLE_IMPORT:', has_top_level_table_import)
""")
assert res.returncode == 0, f"stderr: {res.stderr}"
assert "HAS_TOP_LEVEL_TABLE_IMPORT: False" in res.stdout
def test_audit_main_thread_imports_sees_no_new_violation_from_markdown_helper() -> None:
"""Run the static audit and check that src/markdown_helper.py contributes no
new markdown_table violations.
"""
res = _run_in_subprocess("""
import ast
from pathlib import Path
root = Path('.').resolve()
helper_path = root / 'src' / 'markdown_helper.py'
tree = ast.parse(helper_path.read_text(encoding='utf-8'))
heavy = ['src.markdown_table', 'markdown_table']
for node in tree.body:
if isinstance(node, ast.Import):
for alias in node.names:
for h in heavy:
if alias.name == h or alias.name.startswith(h + '.'):
print('VIOLATION:', alias.name)
elif isinstance(node, ast.ImportFrom):
if node.module:
for h in heavy:
if node.module == h or node.module.startswith(h + '.'):
print('VIOLATION:', node.module)
print('OK')
""")
assert res.returncode == 0, f"stderr: {res.stderr}"
assert "OK" in res.stdout
assert "VIOLATION" not in res.stdout