Coverage for src / rendercv / schema / models / locale / locale.py: 100%
18 statements
« prev ^ index » next coverage.py v7.13.4, created at 2026-03-25 13:49 +0000
« prev ^ index » next coverage.py v7.13.4, created at 2026-03-25 13:49 +0000
1from functools import reduce
2from operator import or_
3from pathlib import Path
4from typing import Annotated, get_args
6import pydantic
8from ...variant_pydantic_model_generator import create_variant_pydantic_model
9from ...yaml_reader import read_yaml
10from .english_locale import EnglishLocale
13def discover_other_locales() -> list[type[EnglishLocale]]:
14 """Auto-discover and load locale variant classes from other_locales/ directory.
16 Why:
17 Locales beyond English are defined as YAML files with translations
18 and format overrides. Dynamic discovery enables community-contributed
19 locales without core code changes.
21 Returns:
22 List of dynamically generated locale variant classes.
23 """
24 other_locales_dir = Path(__file__).parent / "other_locales"
25 discovered: list[type[EnglishLocale]] = []
27 for yaml_file in sorted(other_locales_dir.glob("*.yaml")):
28 locale_model = create_variant_pydantic_model(
29 variant_name=yaml_file.stem,
30 defaults=read_yaml(yaml_file)["locale"],
31 base_class=EnglishLocale,
32 discriminator_field="language",
33 class_name_suffix="Locale",
34 module_name="rendercv.schema.models.locale",
35 require_all_fields=True,
36 )
37 discovered.append(locale_model)
39 return discovered
42# Build discriminated union dynamically
43type Locale = Annotated[
44 reduce(or_, discover_other_locales(), EnglishLocale), # ty: ignore[invalid-type-form]
45 pydantic.Field(discriminator="language"),
46]
47available_locales = [
48 LocaleModel.model_fields["language"].default
49 for LocaleModel in get_args(get_args(Locale.__value__)[0])
50]
51locale_adapter = pydantic.TypeAdapter[Locale](Locale)