Coverage for tests/factories.py: 100%

29 statements  

« prev     ^ index     » next       coverage.py v7.10.3, created at 2026-09-13 18:40 +0000

1"""Polyfactory factories for the public data model. 

2 

3They keep property style tests honest: instead of hand writing a handful of settings objects we let 

4polyfactory build many of them, with the ranges narrowed to values that make sense for a parser. 

5""" 

6 

7import random 

8import typing 

9 

10from polyfactory.factories import dataclass_factory 

11 

12from meta_tags_parser import structs 

13 

14 

15FACTORY_RANDOM_SEED: typing.Final = 20260818 

16MAX_GENERATED_LIMIT_CHARS: typing.Final = 8192 

17MIN_GENERATED_LIMIT_CHARS: typing.Final = 16 

18SHARED_RANDOM_SOURCE: typing.Final = random.Random(FACTORY_RANDOM_SEED) 

19KNOWN_BOUNDARY_TAG_PAIRS: typing.Final[tuple[tuple[str, str], ...]] = ( 

20 ("</head>", "<body"), 

21 ("</HEAD>", "<BODY"), 

22 ("</head>", "<article"), 

23 ("</title>", "<body"), 

24) 

25 

26 

27@typing.final 

28class SettingsFromUserFactory(dataclass_factory.DataclassFactory[structs.SettingsFromUser]): 

29 """Build settings objects covering every combination of what_to_parse and slicing limits.""" 

30 

31 __model__ = structs.SettingsFromUser 

32 __random__ = SHARED_RANDOM_SOURCE 

33 

34 @classmethod 

35 def what_to_parse(cls) -> tuple[structs.WhatToParse, ...]: # noqa: COP009, COP007 

36 possible_parts: typing.Final[list[structs.WhatToParse]] = list(structs.WhatToParse) 

37 return tuple(cls.__random__.sample(possible_parts, k=cls.__random__.randint(1, len(possible_parts)))) 

38 

39 @classmethod 

40 def boundary_tags(cls) -> tuple[str, str]: # noqa: COP009, COP007 

41 return cls.__random__.choice(KNOWN_BOUNDARY_TAG_PAIRS) 

42 

43 @classmethod 

44 def fallback_limit_chars(cls) -> int: # noqa: COP009, COP007 

45 return cls.__random__.randint(MIN_GENERATED_LIMIT_CHARS, MAX_GENERATED_LIMIT_CHARS) 

46 

47 @classmethod 

48 def max_scan_chars(cls) -> int: # noqa: COP009, COP007 

49 return cls.__random__.randint(MIN_GENERATED_LIMIT_CHARS, MAX_GENERATED_LIMIT_CHARS) 

50 

51 @classmethod 

52 def hard_limit_chars(cls) -> int | None: # noqa: COP009, COP007 

53 return cls.__random__.choice( 

54 (None, cls.__random__.randint(MIN_GENERATED_LIMIT_CHARS, MAX_GENERATED_LIMIT_CHARS)) 

55 )