Coverage for mongodb_odm / types.py: 93%
43 statements
« prev ^ index » next coverage.py v7.12.0, created at 2025-12-07 08:37 +0000
« prev ^ index » next coverage.py v7.12.0, created at 2025-12-07 08:37 +0000
1from collections.abc import Mapping, Sequence 1fabcde
2from typing import Any, TypeVar, Union 1fabcde
4from bson import ObjectId 1fabcde
5from pydantic import GetCoreSchemaHandler 1fabcde
6from pydantic_core import core_schema 1fabcde
7from pymongo.operations import ( 1fabcde
8 DeleteMany,
9 DeleteOne,
10 InsertOne,
11 ReplaceOne,
12 UpdateMany,
13 UpdateOne,
14)
16# Common types
17DICT_TYPE = dict[str, Any] 1fabcde
18SORT_TYPE = Union[str, Sequence[tuple[str, Union[int, str, Mapping[str, Any]]]]] 1fabcde
20DocumentType = TypeVar("DocumentType", bound=Mapping[str, Any]) 1fabcde
22WriteOp = Union[ 1fabcde
23 InsertOne[DocumentType],
24 DeleteOne,
25 DeleteMany,
26 ReplaceOne[DocumentType],
27 UpdateOne,
28 UpdateMany,
29]
32class ODMObjectId(ObjectId): 1fabcde
33 @classmethod 1fabcde
34 def __get_pydantic_core_schema__( 1fabcde
35 cls, _source_type: Any, _handler: Any
36 ) -> core_schema.CoreSchema:
37 return core_schema.json_or_python_schema( 1fabcde
38 json_schema=core_schema.chain_schema(
39 [
40 core_schema.str_schema(),
41 core_schema.no_info_plain_validator_function(cls.validate),
42 ]
43 ),
44 python_schema=core_schema.chain_schema(
45 [
46 core_schema.union_schema(
47 [
48 core_schema.is_instance_schema(ObjectId),
49 core_schema.str_schema(),
50 ]
51 ),
52 core_schema.no_info_plain_validator_function(cls.validate),
53 ]
54 ),
55 serialization=core_schema.plain_serializer_function_ser_schema(
56 lambda x: ObjectId(x)
57 ),
58 )
60 @classmethod 1fabcde
61 def validate(cls, v: Union[str, ObjectId]) -> ObjectId: 1fabcde
62 if isinstance(v, ObjectId): 1fabcde
63 """No conversion needed if type are already ObjectId""" 1abcde
64 return v 1fabcde
65 try: 1fabcde
66 return ObjectId(v) 1fabcde
67 except Exception as e: 1fabcde
68 raise ValueError("Invalid data. ObjectId required") from e 1fabcde
71class ObjectIdStr(str): 1fabcde
72 _example_object_id = str(ObjectId()) 1fabcde
74 @classmethod 1fabcde
75 def __get_pydantic_core_schema__( 1fabcde
76 cls, _source_type: Any, handler: GetCoreSchemaHandler
77 ) -> core_schema.CoreSchema:
78 return core_schema.json_or_python_schema( 1fabcde
79 json_schema=core_schema.chain_schema(
80 [
81 core_schema.str_schema(),
82 core_schema.no_info_plain_validator_function(cls.validate),
83 ]
84 ),
85 python_schema=core_schema.chain_schema(
86 [
87 core_schema.union_schema(
88 [
89 core_schema.is_instance_schema(ObjectId),
90 core_schema.str_schema(),
91 ]
92 ),
93 core_schema.no_info_plain_validator_function(cls.validate),
94 ]
95 ),
96 serialization=core_schema.plain_serializer_function_ser_schema(
97 lambda x: str(x), # Always serialize as string
98 return_schema=core_schema.str_schema(),
99 ),
100 )
102 @classmethod 1fabcde
103 def validate(cls, v: Union[str, ObjectId]) -> str: 1fabcde
104 if isinstance(v, ObjectId): 1fabcde
105 return cls(str(v)) 1fabcde
106 elif isinstance(v, str): 1fabcde
107 try: 1fabcde
108 return cls(str(ObjectId(v))) 1fabcde
109 except Exception as e: 1fabcde
110 raise ValueError("Invalid ObjectId") from e 1fabcde
112 raise ValueError("Invalid data. ObjectId required") 1fabcde
114 @classmethod 1fabcde
115 def __get_pydantic_json_schema__( 1fabcde
116 cls, schema: core_schema.CoreSchema, handler: GetCoreSchemaHandler
117 ) -> Any:
118 """Provide OpenAPI/JSON Schema metadata."""
119 json_schema: Any = handler(schema)
120 json_schema.update(
121 type="string",
122 format="objectid",
123 example=cls._example_object_id,
124 )
125 return json_schema