Skip to content

Commit d4de35f

Browse files
Merge pull request #247 from phenobarbital/new-exports
adding support to parse ObjectId bson objects into string and binary
2 parents fe72f7d + c4a53d9 commit d4de35f

File tree

4 files changed

+46
-3
lines changed

4 files changed

+46
-3
lines changed

datamodel/converters.pyx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -662,6 +662,12 @@ cpdef object parse_basic(object T, object data, object encoder = None):
662662
raise ValueError(
663663
f"Error parsing type {T}, {e}"
664664
)
665+
except AttributeError as e:
666+
if data is None:
667+
return None
668+
raise AttributeError(
669+
f"Attribute Error for Encoder {encoder!s} for type {T}: {e}"
670+
) from e
665671
# Using the encoders for basic types:
666672
try:
667673
return encoders[T](data)

datamodel/parsers/json.pyx

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,13 @@ cdef inline bint is_subclassof(object obj, object cls):
6060
return False
6161
return res != 0
6262

63+
cdef inline bint is_objid(object obj):
64+
return (
65+
getattr(obj, "__class__", None) is not None and
66+
obj.__class__.__module__ == "bson.objectid" and
67+
obj.__class__.__name__ == "ObjectId"
68+
)
69+
6370

6471
ORJSON_DEFAULT_OPTIONS = (
6572
orjson.OPT_SERIALIZE_NUMPY |
@@ -122,6 +129,8 @@ cdef class JSONContent:
122129
return obj.name
123130
elif isinstance(obj, Binary): # Handle bytea column from PostgreSQL
124131
return str(obj) # Convert Binary object to string
132+
elif is_objid(obj):
133+
return str(obj)
125134
elif isinstance(obj, Field):
126135
if has_attribute(obj, 'to_dict'):
127136
return obj.to_dict()

datamodel/version.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
'simple library based on python +3.8 to use Dataclass-syntax'
77
'for interacting with Data'
88
)
9-
__version__ = '0.10.6'
9+
__version__ = '0.10.7'
1010
__copyright__ = 'Copyright (c) 2020-2024 Jesus Lara'
1111
__author__ = 'Jesus Lara'
1212
__author_email__ = '[email protected]'

examples/test_validations.py

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
from typing import Union, List
22
import uuid
3+
from bson import ObjectId
34
from datetime import datetime
4-
from datamodel import BaseModel, Column
5+
from datamodel import BaseModel, Column, Field
56
from datamodel.exceptions import ValidationError
67

78

9+
810
def auto_uuid(*args, **kwargs):
911
return uuid.uuid4()
1012

@@ -65,10 +67,21 @@ def __str__(self) -> str:
6567
]
6668
}
6769

70+
def to_objid(value):
71+
if isinstance(value, str):
72+
return ObjectId(value.encode('ascii'))
73+
return value
74+
75+
class Dataset(BaseModel):
76+
_id: ObjectId = Field(encoder=to_objid)
77+
name: str = Field(required=True)
78+
6879

6980
if __name__ == '__main__':
7081
user = Actor(**user)
71-
print(f"User: ID: {user.userid}, Name: {user.name}, age: {user.age}, accounts: {user.account!r}, created: {user.created_at}")
82+
print(
83+
f"User: ID: {user.userid}, Name: {user.name}, age: {user.age}, accounts: {user.account!r}, created: {user.created_at}"
84+
)
7285
print(f'Types: {type(user.created_at)}')
7386
try:
7487
# Test if name is required:
@@ -120,3 +133,18 @@ def __str__(self) -> str:
120133
print(
121134
f"ValidationError: {ex.payload}"
122135
)
136+
try:
137+
print('================================================================')
138+
dataset = Dataset(_id='123456789012', name="Test Dataset")
139+
print(dataset._id, dataset.name)
140+
print(' == Convert into JSON ===')
141+
data = dataset.to_json()
142+
print(data)
143+
print(' == Revert Back ===')
144+
d = Dataset(**dataset.to_dict())
145+
print(d._id, type(d._id))
146+
except ValidationError as ex:
147+
print(f"Error: {ex}", type(ex))
148+
print(f"ValidationError: {ex.payload}")
149+
except ValueError as ex:
150+
print(f"Error: {ex}", type(ex))

0 commit comments

Comments
 (0)