I've been trying to craft a small "mongodb orm" on top of pymongo with attrs. For this I've found that there's not a way for me to keep a consistent structure through the whole app since pymongo is very permissive by default. Trying to build what I think would add consistency I found a wall that I'm eager to break but don't think is a trivial task at first glance.
Let's say I have define this class:
from attrs import define
@define(slots=True)
class User:
@define()
class UserDetails:
status: UserStatus = UserStatus.ALIVE
address: str = None
user_id: CustomTypeId = None
details: UserDetails = UserDetails()
And this class works great for handling defaults in my app. But when I want to do a query, instead of making:
db[UserCollection].find({'user_id': 'newid', 'details.status': 'ALIVE'})
I want to make
db[UserCollection].find({User.user_id: 'newid', User.details.status: 'ALIVE' })
# or from a class method
db[UserCollection].find({cls.user_id: 'newid', cls.details.status: 'ALIVE' })
However accessing this properties in the class level hasn't been trivial and it gets ugly real fast using external methods. With all of this being said, If I'm breaking a fundamental design of pymongo/python and there's a way to turn this around using a more conventional path, more glad to hear it. Thanks for reading and for your help!
I' the author of cattrs and an attrs maintainer, and I've previously built a Mongo library using these libraries and Pymongo (not open source though) so I can share some tips.
You can use attrs.fields(User).user_id
instead of User.user_id
. (You can do from attrs import fields as f
to keep it less verbose.) Due to recent changes in Mypy, this approach can have much better static type safety, if done right.