fix: wire dry-run source state policy
This commit is contained in:
@@ -126,6 +126,7 @@ class PipelineRunner:
|
|||||||
:rtype: PipelineRunner
|
:rtype: PipelineRunner
|
||||||
"""
|
"""
|
||||||
effective_dry_run = settings.app.dry_run if dry_run is None else dry_run
|
effective_dry_run = settings.app.dry_run if dry_run is None else dry_run
|
||||||
|
persistence_enabled = not effective_dry_run
|
||||||
theoretical_provider = get_theoretical_provider(
|
theoretical_provider = get_theoretical_provider(
|
||||||
settings.app.theoretical_agenda_path,
|
settings.app.theoretical_agenda_path,
|
||||||
settings.app.school_holidays_path,
|
settings.app.school_holidays_path,
|
||||||
@@ -136,7 +137,9 @@ class PipelineRunner:
|
|||||||
AgendaComparator(theoretical_provider) if theoretical_provider is not None else None
|
AgendaComparator(theoretical_provider) if theoretical_provider is not None else None
|
||||||
)
|
)
|
||||||
blog_client = BlogRSSClient(settings.blog.rss_url) if settings.blog.enabled else None
|
blog_client = BlogRSSClient(settings.blog.rss_url) if settings.blog.enabled else None
|
||||||
blog_state = BlogRSSState() if settings.blog.enabled else None
|
blog_state = (
|
||||||
|
BlogRSSState(persistence_enabled=persistence_enabled) if settings.blog.enabled else None
|
||||||
|
)
|
||||||
return cls(
|
return cls(
|
||||||
settings=settings,
|
settings=settings,
|
||||||
pronote_fetcher=PronoteFetcher(
|
pronote_fetcher=PronoteFetcher(
|
||||||
@@ -144,7 +147,9 @@ class PipelineRunner:
|
|||||||
PronoteClient(
|
PronoteClient(
|
||||||
settings.pronote,
|
settings.pronote,
|
||||||
auth_state=(
|
auth_state=(
|
||||||
PronoteAuthState() if settings.pronote.auth_mode == "qr_token" else None
|
PronoteAuthState(persistence_enabled=persistence_enabled)
|
||||||
|
if settings.pronote.auth_mode == "qr_token"
|
||||||
|
else None
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -8,7 +8,13 @@ from typing import Any, cast
|
|||||||
import pytest
|
import pytest
|
||||||
from pydantic import SecretStr
|
from pydantic import SecretStr
|
||||||
|
|
||||||
from pronote_sync.config.settings import AISettings, AppSettings, PronoteSettings, Settings
|
from pronote_sync.config.settings import (
|
||||||
|
AISettings,
|
||||||
|
AppSettings,
|
||||||
|
BlogSettings,
|
||||||
|
PronoteSettings,
|
||||||
|
Settings,
|
||||||
|
)
|
||||||
from pronote_sync.errors import PipelineCriticalError, PipelineWarning, PronoteAuthRotationError
|
from pronote_sync.errors import PipelineCriticalError, PipelineWarning, PronoteAuthRotationError
|
||||||
from pronote_sync.models.agenda import Lesson, LessonStatus, SchoolEvent
|
from pronote_sync.models.agenda import Lesson, LessonStatus, SchoolEvent
|
||||||
from pronote_sync.models.blog import BlogArticle
|
from pronote_sync.models.blog import BlogArticle
|
||||||
@@ -449,6 +455,64 @@ def test_from_settings_qr_token_mode_passes_auth_state_instance(
|
|||||||
assert isinstance(constructed[0][1], PronoteAuthState)
|
assert isinstance(constructed[0][1], PronoteAuthState)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("dry_run", [False, True])
|
||||||
|
def test_from_settings_configures_source_state_persistence_for_dry_run(
|
||||||
|
monkeypatch: pytest.MonkeyPatch,
|
||||||
|
dry_run: bool,
|
||||||
|
) -> None:
|
||||||
|
"""Composition disables source-state persistence only in dry-run mode."""
|
||||||
|
import pronote_sync.pipeline.run as run_module
|
||||||
|
|
||||||
|
blog_persistence: list[bool] = []
|
||||||
|
auth_persistence: list[bool] = []
|
||||||
|
|
||||||
|
class RecordingBlogState:
|
||||||
|
"""Blog state factory recording its persistence configuration."""
|
||||||
|
|
||||||
|
def __init__(self, *, persistence_enabled: bool = True) -> None:
|
||||||
|
"""Record the requested persistence setting.
|
||||||
|
|
||||||
|
:param persistence_enabled: Whether disk writes are enabled.
|
||||||
|
"""
|
||||||
|
blog_persistence.append(persistence_enabled)
|
||||||
|
|
||||||
|
class RecordingAuthState:
|
||||||
|
"""Authentication state factory recording its persistence configuration."""
|
||||||
|
|
||||||
|
def __init__(self, *, persistence_enabled: bool = True) -> None:
|
||||||
|
"""Record the requested persistence setting.
|
||||||
|
|
||||||
|
:param persistence_enabled: Whether disk writes are enabled.
|
||||||
|
"""
|
||||||
|
auth_persistence.append(persistence_enabled)
|
||||||
|
|
||||||
|
class RecordingClient:
|
||||||
|
"""Pronote client constructor accepting the injected auth state."""
|
||||||
|
|
||||||
|
def __init__(self, settings: PronoteSettings, *, auth_state: object) -> None:
|
||||||
|
"""Accept the composition-root dependencies.
|
||||||
|
|
||||||
|
:param settings: Pronote settings.
|
||||||
|
:param auth_state: Injected authentication state.
|
||||||
|
"""
|
||||||
|
del settings, auth_state
|
||||||
|
|
||||||
|
monkeypatch.setattr(run_module, "BlogRSSState", RecordingBlogState)
|
||||||
|
monkeypatch.setattr(run_module, "PronoteAuthState", RecordingAuthState)
|
||||||
|
monkeypatch.setattr(run_module, "PronoteClient", RecordingClient)
|
||||||
|
|
||||||
|
PipelineRunner.from_settings(
|
||||||
|
Settings(
|
||||||
|
app=AppSettings(dry_run=dry_run),
|
||||||
|
blog=BlogSettings(enabled=True),
|
||||||
|
pronote=PronoteSettings(auth_mode="qr_token"),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
assert blog_persistence == [not dry_run]
|
||||||
|
assert auth_persistence == [not dry_run]
|
||||||
|
|
||||||
|
|
||||||
def test_runner_reuses_ical_download_and_parse_within_one_run(
|
def test_runner_reuses_ical_download_and_parse_within_one_run(
|
||||||
monkeypatch: pytest.MonkeyPatch,
|
monkeypatch: pytest.MonkeyPatch,
|
||||||
pipeline_inputs: tuple[Lesson, Homework],
|
pipeline_inputs: tuple[Lesson, Homework],
|
||||||
|
|||||||
Reference in New Issue
Block a user