Coverage for /var/srv/projects/api.amasfac.comuna18.com/tmp/venv/lib/python3.9/site-packages/django/contrib/postgres/fields/hstore.py: 51%

74 statements  

« prev     ^ index     » next       coverage.py v6.4.4, created at 2023-07-17 14:22 -0600

1import json 

2 

3from django.contrib.postgres import forms, lookups 

4from django.contrib.postgres.fields.array import ArrayField 

5from django.core import exceptions 

6from django.db.models import Field, TextField, Transform 

7from django.db.models.fields.mixins import CheckFieldDefaultMixin 

8from django.utils.translation import gettext_lazy as _ 

9 

10__all__ = ["HStoreField"] 

11 

12 

13class HStoreField(CheckFieldDefaultMixin, Field): 

14 empty_strings_allowed = False 

15 description = _("Map of strings to strings/nulls") 

16 default_error_messages = { 

17 "not_a_string": _("The value of “%(key)s” is not a string or null."), 

18 } 

19 _default_hint = ("dict", "{}") 

20 

21 def db_type(self, connection): 

22 return "hstore" 

23 

24 def get_transform(self, name): 

25 transform = super().get_transform(name) 

26 if transform: 

27 return transform 

28 return KeyTransformFactory(name) 

29 

30 def validate(self, value, model_instance): 

31 super().validate(value, model_instance) 

32 for key, val in value.items(): 

33 if not isinstance(val, str) and val is not None: 

34 raise exceptions.ValidationError( 

35 self.error_messages["not_a_string"], 

36 code="not_a_string", 

37 params={"key": key}, 

38 ) 

39 

40 def to_python(self, value): 

41 if isinstance(value, str): 

42 value = json.loads(value) 

43 return value 

44 

45 def value_to_string(self, obj): 

46 return json.dumps(self.value_from_object(obj)) 

47 

48 def formfield(self, **kwargs): 

49 return super().formfield( 

50 **{ 

51 "form_class": forms.HStoreField, 

52 **kwargs, 

53 } 

54 ) 

55 

56 def get_prep_value(self, value): 

57 value = super().get_prep_value(value) 

58 

59 if isinstance(value, dict): 

60 prep_value = {} 

61 for key, val in value.items(): 

62 key = str(key) 

63 if val is not None: 

64 val = str(val) 

65 prep_value[key] = val 

66 value = prep_value 

67 

68 if isinstance(value, list): 

69 value = [str(item) for item in value] 

70 

71 return value 

72 

73 

74HStoreField.register_lookup(lookups.DataContains) 

75HStoreField.register_lookup(lookups.ContainedBy) 

76HStoreField.register_lookup(lookups.HasKey) 

77HStoreField.register_lookup(lookups.HasKeys) 

78HStoreField.register_lookup(lookups.HasAnyKeys) 

79 

80 

81class KeyTransform(Transform): 

82 output_field = TextField() 

83 

84 def __init__(self, key_name, *args, **kwargs): 

85 super().__init__(*args, **kwargs) 

86 self.key_name = key_name 

87 

88 def as_sql(self, compiler, connection): 

89 lhs, params = compiler.compile(self.lhs) 

90 return "(%s -> %%s)" % lhs, tuple(params) + (self.key_name,) 

91 

92 

93class KeyTransformFactory: 

94 def __init__(self, key_name): 

95 self.key_name = key_name 

96 

97 def __call__(self, *args, **kwargs): 

98 return KeyTransform(self.key_name, *args, **kwargs) 

99 

100 

101@HStoreField.register_lookup 

102class KeysTransform(Transform): 

103 lookup_name = "keys" 

104 function = "akeys" 

105 output_field = ArrayField(TextField()) 

106 

107 

108@HStoreField.register_lookup 

109class ValuesTransform(Transform): 

110 lookup_name = "values" 

111 function = "avals" 

112 output_field = ArrayField(TextField())