Coverage for audoma/drf/fields.py: 37%

27 statements  

« prev     ^ index     » next       coverage.py v6.4.2, created at 2022-08-08 06:12 +0000

1""" 

2This module is an override for default drf's field module. 

3Most of those fields, are providing additional example functionality, 

4and also has defined schema type. 

5""" 

6 

7import sys 

8 

9import exrex 

10import phonenumbers 

11from djmoney.contrib.django_rest_framework import MoneyField 

12from drf_spectacular.types import OpenApiTypes 

13from drf_spectacular.utils import extend_schema_field 

14from phonenumber_field import serializerfields 

15from phonenumber_field.phonenumber import to_python 

16from rest_framework import fields 

17from rest_framework.fields import * # noqa: F403, F401 

18 

19from django.core import validators 

20 

21from audoma.example_generators import generate_lorem_ipsum 

22from audoma.mixins import ( 

23 ExampleMixin, 

24 NumericExampleMixin, 

25 RegexExampleMixin, 

26) 

27 

28 

29field_names = [ 

30 "BooleanField", 

31 "NullBooleanField", 

32 "EmailField", 

33 "SlugField", 

34 "URLField", 

35 "DateTimeField", 

36 "DurationField", 

37 "ChoiceField", 

38 "MultipleChoiceField", 

39 "FilePathField", 

40 "FileField", 

41 "ImageField", 

42 "ListField", 

43 "DictField", 

44 "HStoreField", 

45 "JSONField", 

46 "ReadOnlyField", 

47 "SerializerMethodField", 

48] # pragma: no cover 

49 

50 

51this = sys.modules[__name__] # pragma: no cover 

52 

53 

54for field_name in field_names: # pragma: no cover 

55 

56 setattr( 

57 this, 

58 field_name, 

59 type(field_name, (ExampleMixin, getattr(fields, field_name)), {}), 

60 ) 

61 

62 

63class DecimalField(NumericExampleMixin, fields.DecimalField): # pragma: no cover 

64 pass 

65 

66 

67@extend_schema_field(OpenApiTypes.UUID) # pragma: no cover 

68class UUIDField(ExampleMixin, fields.UUIDField): # pragma: no cover 

69 pass 

70 

71 

72class IntegerField(NumericExampleMixin, fields.IntegerField): # pragma: no cover 

73 pass 

74 

75 

76class FloatField(NumericExampleMixin, fields.FloatField): # pragma: no cover 

77 pass 

78 

79 

80class RegexField(RegexExampleMixin, fields.RegexField): # pragma: no cover 

81 pass 

82 

83 

84class MACAddressField(RegexExampleMixin, fields.CharField): # pragma: no cover 

85 def __init__(self, **kwargs) -> None: 

86 self.regex = "^([0-9A-F]{2}:){5}([0-9A-F]{2})|([0-9A-F]{2}-){5}([0-9A-F]{2})$" 

87 self.validators = [validators.RegexValidator(self.regex)] 

88 super().__init__(**kwargs) 

89 

90 

91@extend_schema_field(OpenApiTypes.DATE) # pragma: no cover 

92class DateField(ExampleMixin, fields.DateField): # pragma: no cover 

93 pass 

94 

95 

96@extend_schema_field(OpenApiTypes.TIME) # pragma: no cover 

97class TimeField(ExampleMixin, fields.TimeField): # pragma: no cover 

98 pass 

99 

100 

101@extend_schema_field( 

102 field={ 

103 "format": "ip-address", 

104 "example": str( 

105 exrex.getone( 

106 r"^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$" 

107 ) 

108 ), 

109 } 

110) # pragma: no cover 

111class IPAddressField(ExampleMixin, fields.IPAddressField): # pragma: no cover 

112 pass 

113 

114 

115@extend_schema_field(field={"format": "tel"}) # pragma: no cover 

116class PhoneNumberField(ExampleMixin, serializerfields.PhoneNumberField): 

117 def __init__(self, *args, **kwargs) -> None: 

118 example = kwargs.pop("example", None) 

119 if example is None: 

120 number = phonenumbers.example_number(None) 

121 example = str(to_python(number)) 

122 super().__init__(*args, example=example, **kwargs) 

123 

124 

125class CharField(ExampleMixin, fields.CharField): 

126 def __init__(self, *args, **kwargs) -> None: 

127 example = kwargs.pop("example", None) 

128 min_length = kwargs.get("min_length", 20) 

129 max_length = kwargs.get("max_length", 80) 

130 if not example: 

131 example = generate_lorem_ipsum(min_length=min_length, max_length=max_length) 

132 

133 super().__init__(*args, example=example, **kwargs) 

134 

135 

136class MoneyField(NumericExampleMixin, MoneyField): # pragma: no cover 

137 pass 

138 

139 

140class ChoiceField(ExampleMixin, fields.ChoiceField): 

141 def __init__(self, choices, **kwargs): 

142 if isinstance(choices, dict): 

143 self.original_choices = list(choices.items()) 

144 else: 

145 self.original_choices = choices 

146 super().__init__(choices, **kwargs)