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

1from functools import reduce 

2from operator import or_ 

3from pathlib import Path 

4from typing import Annotated, get_args 

5 

6import pydantic 

7 

8from ...variant_pydantic_model_generator import create_variant_pydantic_model 

9from ...yaml_reader import read_yaml 

10from .english_locale import EnglishLocale 

11 

12 

13def discover_other_locales() -> list[type[EnglishLocale]]: 

14 """Auto-discover and load locale variant classes from other_locales/ directory. 

15 

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. 

20 

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]] = [] 

26 

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) 

38 

39 return discovered 

40 

41 

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)