Coverage for tests/random_model.py: 79%

75 statements  

« prev     ^ index     » next       coverage.py v7.6.2, created at 2024-10-10 03:02 +0300

1import datetime 

2import random 

3import string 

4from enum import Enum 

5from types import NoneType 

6from typing import Any, get_args 

7from uuid import UUID, uuid4 

8 

9from bson import ObjectId 

10from pydantic import BaseModel, EmailStr 

11from pydantic_extra_types.phone_numbers import PhoneNumber 

12from sotrans_models.models._base import BaseIdModel 

13from sotrans_models.utils.type_checks import ( 

14 is_list_type, 

15 is_not_generic_alias, 

16 is_union, 

17) 

18 

19 

20def generate_random_string(length): 

21 return "".join( 

22 random.choices(string.ascii_letters + string.digits + " ", k=length) 

23 ) 

24 

25 

26def primitive_types(field_type): 

27 if field_type == int: 

28 random_value = random.randint(0, 100) 

29 elif field_type == float: 

30 random_value = random.uniform(0, 1) 

31 elif field_type == str: 31 ↛ 34line 31 didn't jump to line 34 because the condition on line 31 was always true

32 random_value = generate_random_string(10) 

33 else: 

34 random_value = random.choice([True, False]) 

35 return random_value 

36 

37 

38def generate_random_model_dict(model: type[BaseModel]) -> dict[str, Any]: 

39 result = {} 

40 

41 for field_name, field_info in model.model_fields.items(): 

42 field_type = field_info.annotation 

43 if field_name == "inn": 43 ↛ 44line 43 didn't jump to line 44 because the condition on line 43 was never true

44 result[field_name] = "1234567890" 

45 continue 

46 

47 if is_union(field_type): 

48 args = get_args(field_type) 

49 field_type = random.choice(args) 

50 

51 if is_list_type(field_type): 

52 random_value: Any = [] 

53 elif is_not_generic_alias(field_type): 53 ↛ 83line 53 didn't jump to line 83 because the condition on line 53 was always true

54 if field_type in (int, float, str, bool): 

55 random_value = primitive_types(field_type) 

56 elif field_type == dict: 56 ↛ 57line 56 didn't jump to line 57 because the condition on line 56 was never true

57 random_value = {} 

58 elif issubclass(field_type, ObjectId): 58 ↛ 59line 58 didn't jump to line 59 because the condition on line 58 was never true

59 random_value = ObjectId() 

60 elif issubclass(field_type, UUID): 60 ↛ 61line 60 didn't jump to line 61 because the condition on line 60 was never true

61 random_value = uuid4() 

62 elif field_type == datetime.date: 62 ↛ 63line 62 didn't jump to line 63 because the condition on line 62 was never true

63 random_value = datetime.date.today() 

64 elif field_type == datetime.datetime: 

65 random_value = datetime.datetime.now() 

66 elif issubclass(field_type, Enum): 

67 random_value = random.choice(list(field_type)) 

68 elif field_type == PhoneNumber: 68 ↛ 69line 68 didn't jump to line 69 because the condition on line 68 was never true

69 random_value = f"+7999{random.randint(1_000_000, 9_999_999)}" 

70 elif field_type == EmailStr: 70 ↛ 71line 70 didn't jump to line 71

71 random_value = ( 

72 f"{generate_random_string(16).replace(' ', '')}@ya.ru" 

73 ) 

74 elif issubclass(field_type, BaseModel): 

75 random_value = generate_random_model_dict(field_type) 

76 elif field_type == NoneType: 76 ↛ 79line 76 didn't jump to line 79 because the condition on line 76 was always true

77 random_value = None 

78 else: 

79 raise TypeError( 

80 f"Random value for type {field_type} is not supported" 

81 ) 

82 else: 

83 random_value = None 

84 

85 # Set the random value in the object dictionary 

86 field_alias = ( 

87 model.model_fields[field_name].validation_alias 

88 or model.model_fields[field_name].alias 

89 ) 

90 field_name = field_alias if field_alias else field_name 

91 result[field_name] = random_value 

92 

93 return result 

94 

95 

96def generate_random_model(model: type[BaseModel]) -> BaseModel: 

97 return model(**generate_random_model_dict(model)) 

98 

99 

100def generate_models_json( 

101 model: type[BaseModel], specific: dict | None = None 

102) -> dict[str, Any]: 

103 if specific is None: 103 ↛ 105line 103 didn't jump to line 105 because the condition on line 103 was always true

104 specific = {} 

105 model_dict = generate_random_model_dict(model) 

106 to_construct = {**model_dict, **specific} 

107 params: dict[str, Any] = dict(mode="json") 

108 if issubclass(model, BaseIdModel): 108 ↛ 109line 108 didn't jump to line 109 because the condition on line 108 was never true

109 params.update({"format_ids": False}) 

110 return model(**to_construct).model_dump(**params)