Coverage for src/lexigram/features/backends/chained.py: 100%
18 statements
« prev ^ index » next coverage.py v7.15.4, created at 2026-08-26 02:04 +0800
« prev ^ index » next coverage.py v7.15.4, created at 2026-08-26 02:04 +0800
1"""Layered provider that queries multiple providers in order.
3The first provider that returns a non-*None* flag definition wins.
4This allows environment overrides to take precedence over code-defined
5defaults without modifying either provider.
6"""
8from __future__ import annotations
10from typing import TYPE_CHECKING
12from lexigram.features.backends.base import AbstractFlagProvider
14if TYPE_CHECKING:
15 from lexigram.features.types import Flag
18class ChainedProvider(AbstractFlagProvider):
19 """Layered provider that queries multiple providers in order.
21 The first provider that returns a non-*None* flag definition wins.
22 When merging all flags, earlier providers take precedence over later ones.
23 """
25 def __init__(self, providers: list[AbstractFlagProvider]) -> None:
26 self._providers = providers
28 # -- AbstractFlagProvider interface -------------------------------------
30 async def get_flag_definition(self, name: str) -> Flag | None:
31 """Return the first match across the provider chain, or *None*."""
32 for provider in self._providers:
33 flag = await provider.get_flag_definition(name)
34 if flag is not None:
35 return flag
36 return None
38 async def get_all_flags(self) -> dict[str, Flag]:
39 """Merge flags from all providers; earlier providers take precedence."""
40 merged: dict[str, Flag] = {}
41 # iterate in reverse so highest-priority providers overwrite
42 for provider in reversed(self._providers):
43 merged.update(await provider.get_all_flags())
44 return merged
47__all__ = ["ChainedProvider"]