Skip to content

Commit e004552

Browse files
fix: Enable email configuration for backends (issue #47) (#51)
This commit fixes issue #47 where email configuration was not working due to lambda syntax errors in backend factory registrations. Core Implementation Changes: - Fixed backend factory lambda syntax to accept email parameter - Added missing self.email = email in CrossValidatorBackend.__init__ - Implemented generic parameter filtering using inspect.signature() - Added get_supported_params() method to BackendRegistry - Updated config generation to only include supported parameters Test Infrastructure Improvements: - Added backend import to conftest.py for test-wide registration - Fixed temp config file fixture to flush content before yielding - Added registry state save/restore fixture for test isolation - Created comprehensive integration and unit tests for email config Files Modified: - src/aletheia_probe/backends/base.py: Parameter filtering logic - src/aletheia_probe/backends/cross_validator.py: Email attribute fix - src/aletheia_probe/config.py: Updated default config generation - tests/*: New tests and fixtures for email configuration All 239 tests passing with full quality checks (ruff, mypy, formatting). Fixes #47 Co-authored-by: florath-ai-assistant[bot] <Andreas.Florath@telekom.de>
1 parent 6899a18 commit e004552

File tree

8 files changed

+663
-3
lines changed

8 files changed

+663
-3
lines changed

src/aletheia_probe/backends/base.py

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
import asyncio
55
import hashlib
6+
import inspect
67
import time
78
from abc import ABC, abstractmethod
89
from collections.abc import Callable
@@ -351,8 +352,59 @@ def create_backend(self, name: str, **config: Any) -> Backend:
351352
# Merge provided config with defaults
352353
merged_config = {**self._default_configs[name], **config}
353354

355+
# Filter config parameters based on factory signature
356+
factory = self._factories[name]
357+
filtered_config = self._filter_config_params(factory, merged_config)
358+
354359
# Create backend instance using factory
355-
return self._factories[name](**merged_config)
360+
return factory(**filtered_config)
361+
362+
def _filter_config_params(
363+
self, factory: Callable[..., Backend], config: dict[str, Any]
364+
) -> dict[str, Any]:
365+
"""Filter config parameters based on factory function signature.
366+
367+
Args:
368+
factory: Backend factory function
369+
config: Configuration parameters to filter
370+
371+
Returns:
372+
Filtered configuration with only parameters the factory accepts
373+
"""
374+
try:
375+
sig = inspect.signature(factory)
376+
accepted_params = set(sig.parameters.keys())
377+
378+
# Filter config to only include parameters the factory accepts
379+
filtered_config = {
380+
key: value for key, value in config.items() if key in accepted_params
381+
}
382+
383+
return filtered_config
384+
except Exception:
385+
# If signature inspection fails, return original config
386+
# This ensures backward compatibility
387+
return config
388+
389+
def get_supported_params(self, name: str) -> set[str]:
390+
"""Get the set of parameters supported by a backend.
391+
392+
Args:
393+
name: Backend name
394+
395+
Returns:
396+
Set of parameter names the backend accepts
397+
"""
398+
if name not in self._factories:
399+
return set()
400+
401+
try:
402+
factory = self._factories[name]
403+
sig = inspect.signature(factory)
404+
return set(sig.parameters.keys())
405+
except Exception:
406+
# If signature inspection fails, return empty set
407+
return set()
356408

357409
def get_backend(self, name: str) -> Backend:
358410
"""Get a backend by name with default configuration."""

src/aletheia_probe/backends/cross_validator.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ def __init__(
2424
cache_ttl_hours: Cache TTL in hours
2525
"""
2626
super().__init__(cache_ttl_hours)
27+
self.email = email
2728
self.openalex_backend = OpenAlexAnalyzerBackend(email, cache_ttl_hours)
2829
self.crossref_backend = CrossrefAnalyzerBackend(email, cache_ttl_hours)
2930

src/aletheia_probe/config.py

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,10 @@ def __init__(self, config_path: Path | None = None):
9898
self.config_path = config_path or self._find_config_file()
9999
self._config: AppConfig | None = None
100100

101+
def _reset_cache(self) -> None:
102+
"""Reset cached configuration. Useful for testing."""
103+
self._config = None
104+
101105
def _find_config_file(self) -> Path | None:
102106
"""Find configuration file in standard locations."""
103107
search_paths = [
@@ -273,15 +277,22 @@ def get_default_config_with_all_backends(self) -> dict[str, Any]:
273277

274278
backends_config = {}
275279
for backend_name in backend_names:
276-
backends_config[backend_name] = {
280+
# Start with common config fields
281+
backend_config = {
277282
"name": backend_name,
278283
"enabled": True,
279284
"weight": DEFAULT_BACKEND_WEIGHT,
280285
"timeout": DEFAULT_BACKEND_TIMEOUT,
281-
"email": None, # Use backend default unless configured
282286
"config": {},
283287
}
284288

289+
# Only add parameters that this backend supports
290+
supported_params = backend_registry.get_supported_params(backend_name)
291+
if "email" in supported_params:
292+
backend_config["email"] = None # Use backend default unless configured
293+
294+
backends_config[backend_name] = backend_config
295+
285296
return {
286297
"backends": backends_config,
287298
"heuristics": {

tests/conftest.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
import pytest
77

8+
import aletheia_probe.backends # Import backends to register them
89
from aletheia_probe.models import BackendResult, BackendStatus, QueryInput
910

1011

0 commit comments

Comments
 (0)