Coverage for pyodmongo/models/db_field_info.py: 100%

46 statements  

« prev     ^ index     » next       coverage.py v7.7.1, created at 2025-03-27 14:31 +0000

1from typing import Any 

2from dataclasses import dataclass 

3from .query_operators import ComparisonOperator 

4from .id_model import Id 

5from .db_decimal import DbDecimal 

6from bson import ObjectId 

7from decimal import Decimal 

8from bson import Decimal128 

9from ..services.verify_subclasses import is_subclass 

10 

11 

12@dataclass 

13class DbField: 

14 """ 

15 Represents a field within a database model, containing metadata necessary for 

16 managing the serialization and deserialization of model fields, especially in 

17 contexts involving references to other documents or complex nested structures. 

18 

19 Attributes: 

20 field_name (str | None): The name of the field as defined in the database model. 

21 field_alias (str | None): The alias used for the field in database operations, 

22 which might differ from the field name. 

23 path_str (str | None): The string representation of the path to the field within 

24 nested structures or related models. 

25 field_type (Any | None): The data type of the field, which can be any valid Python 

26 type or a more complex custom type. 

27 by_reference (bool | None): Indicates whether the field is linked by reference 

28 to another document or model, rather than embedded. 

29 is_list (bool | None): Specifies if the field is expected to be a list of items, 

30 typically used for handling multiple relationships or 

31 collections of values. 

32 has_model_fields (bool | None): Indicates if the field itself contains sub-fields 

33 that are also modeled, suggesting a nested data 

34 structure that requires special handling. 

35 """ 

36 

37 field_name: str = None 

38 field_alias: str = None 

39 path_str: str = None 

40 field_type: Any = None 

41 by_reference: bool = None 

42 is_list: bool = None 

43 has_model_fields: bool = None 

44 

45 def comparison_operator(self, operator: str, value: Any) -> ComparisonOperator: 

46 type_of_value = type(value) 

47 if self.by_reference or self.field_type == Id: 

48 if type_of_value != list and value is not None: 

49 value = ObjectId(value) 

50 elif type_of_value == list: 

51 value = [ObjectId(v) for v in value] 

52 

53 elif ( 

54 self.field_type == Decimal or self.field_type == DbDecimal 

55 ) and value is not None: 

56 if type_of_value == list: 

57 value = [Decimal128(str(o)) for o in value] 

58 else: 

59 value = Decimal128(str(value)) 

60 

61 return ComparisonOperator( 

62 path_str=self.path_str, operator=operator, value=value 

63 ) 

64 

65 def __lt__(self, value: Any) -> ComparisonOperator: 

66 return self.comparison_operator(operator="$lt", value=value) 

67 

68 def __le__(self, value: Any) -> ComparisonOperator: 

69 return self.comparison_operator(operator="$lte", value=value) 

70 

71 def __eq__(self, value: Any) -> ComparisonOperator: 

72 if isinstance(value, DbField): 

73 return super().__eq__(value) 

74 return self.comparison_operator(operator="$eq", value=value) 

75 

76 def __ne__(self, value: Any) -> ComparisonOperator: 

77 if isinstance(value, DbField): 

78 return super().__ne__(value) 

79 return self.comparison_operator(operator="$ne", value=value) 

80 

81 def __gt__(self, value: Any) -> ComparisonOperator: 

82 return self.comparison_operator(operator="$gt", value=value) 

83 

84 def __ge__(self, value: Any) -> ComparisonOperator: 

85 return self.comparison_operator(operator="$gte", value=value)