polish: env_for hardening per code review (M1-M3)
- env_for validates theme against THEMES whitelist (defense in depth) - degraded single-path envs are no longer cached - tests: unknown-theme rejection, real macro shadowing semantics, degraded branch path + no-cache Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
@@ -54,3 +54,40 @@ def test_env_for_is_cached_per_theme():
|
||||
def test_env_for_pro_template_loads_unprefixed():
|
||||
from app import theme_pro
|
||||
assert theme_pro.env_for('industrial').get_template('pro.html') is not None
|
||||
|
||||
def test_env_for_rejects_unknown_theme():
|
||||
import pytest
|
||||
from app import theme_pro
|
||||
with pytest.raises(ValueError):
|
||||
theme_pro.env_for('../../etc')
|
||||
with pytest.raises(ValueError):
|
||||
theme_pro.env_for('no-such-theme')
|
||||
|
||||
def test_env_for_theme_macro_shadows_shared_root(tmp_path, monkeypatch):
|
||||
# The core mechanism: a theme-local _professional_components.html wins over
|
||||
# the shared one at themes/ root.
|
||||
from app import theme_pro
|
||||
themes = tmp_path / 'themes'
|
||||
for sub, marker in (('industrial', 'theme-local'), ('_root_macros', None)):
|
||||
d = themes / sub
|
||||
d.mkdir(parents=True)
|
||||
(themes / '_professional_components.html').write_text('SHARED', encoding='utf-8')
|
||||
(themes / 'industrial' / '_professional_components.html').write_text('THEME-LOCAL', encoding='utf-8')
|
||||
monkeypatch.setattr(theme_pro, 'ROOT', tmp_path)
|
||||
monkeypatch.setattr(theme_pro, '_ENVS', {})
|
||||
tpl = theme_pro.env_for('industrial').get_template('_professional_components.html')
|
||||
assert tpl.render().strip() == 'THEME-LOCAL'
|
||||
|
||||
def test_env_for_degraded_branch_not_cached_and_single_path(tmp_path, monkeypatch):
|
||||
from app import theme_pro
|
||||
themes = tmp_path / 'themes'
|
||||
themes.mkdir(parents=True)
|
||||
monkeypatch.setattr(theme_pro, 'ROOT', tmp_path)
|
||||
monkeypatch.setattr(theme_pro, '_ENVS', {})
|
||||
core.THEMES = ('industrial',) # whitelist a theme whose dir does not exist
|
||||
try:
|
||||
env = theme_pro.env_for('industrial')
|
||||
assert [str(p) for p in env.loader.searchpath] == [str(themes)]
|
||||
assert 'industrial' not in theme_pro._ENVS
|
||||
finally:
|
||||
core.THEMES = core.discover_themes()
|
||||
|
||||
Reference in New Issue
Block a user