https://github.com/sbdchd/mongo-types
:fallen_leaf: Type stubs for mongoengine, pymongo, and bson
https://github.com/sbdchd/mongo-types
mongoengine mypy mypy-stubs stubs type-stubs
Last synced: about 2 months ago
JSON representation
:fallen_leaf: Type stubs for mongoengine, pymongo, and bson
- Host: GitHub
- URL: https://github.com/sbdchd/mongo-types
- Owner: sbdchd
- License: apache-2.0
- Created: 2020-11-16T01:06:45.000Z (over 4 years ago)
- Default Branch: main
- Last Pushed: 2023-11-24T23:16:31.000Z (over 1 year ago)
- Last Synced: 2025-03-29T05:22:40.491Z (2 months ago)
- Topics: mongoengine, mypy, mypy-stubs, stubs, type-stubs
- Language: Python
- Homepage:
- Size: 133 KB
- Stars: 20
- Watchers: 3
- Forks: 8
- Open Issues: 10
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# mongo-types [](https://pypi.org/project/mongo-types/)
Type stubs for [`mongoengine`][0].
Allows for autocomplete and static typing.
## install
```shell
pip install mongo-types
```Monkey patch mongoengine's `QuerySet` so we can type it with a generic
argument at runtime:```python
import types
from mongoengine.queryset.queryset import QuerySetdef no_op(self, x):
return selfQuerySet.__class_getitem__ = types.MethodType(no_op, QuerySet)
```## usage
After installing and monkey patching, the types should work for the most
part,
but you'll probably need to change how you write some things.### getting `objects` to work
By default, the base document is typed to not have an `objects` property so
that each document can type it properly.Here's a helper class that's useful for simple cases which don't modify the
`QuerySet`.```python
from typing import Generic, Type, TypeVar
from mongoengine import QuerySet, DocumentU = TypeVar("U", bound=Document)
class QuerySetManager(Generic[U]):
def __get__(self, instance: object, cls: Type[U]) -> QuerySet[U]:
return QuerySet(cls, cls._get_collection())class Page(Document):
meta = {
"collection": "pages",
}objects = QuerySetManager["Page"]()
organization = fields.StringField()
```### replacing usages of `queryset_class`
before:
```python
from typing import Type
from mongoengine import QuerySet, Documentclass PostQuerySet(QuerySet):
def for_org(self, *, org: str) -> QuerySet:
return self.filter(organization=org)def exists(self) -> bool:
return self.count() > 0class Post(Document):
meta = {
"collection": "posts",
"queryset_class": SMSLogQuerySet,
}organization = fields.StringField()
# --snip--
```after:
```python
from typing import Type
from mongoengine import QuerySet, Documentclass PostQuerySet(QuerySet["Post"]):
def for_org(self, *, org: str) -> QuerySet["Post"]:
return self.filter(organization=org)def exists(self) -> bool:
return self.count() > 0class QuerySetManager:
def __get__(self, instance: object, cls: Type[Post]) -> PostQuerySet:
return PostQuerySet(cls, cls._get_collection())class Post(Document):
meta = {
"collection": "posts",
}objects = QuerySetManager()
organization = fields.StringField()
# --snip--
```### replicating `@queryset_manager` behavior
before:
```python
from mongoengine import Document, QuerySet, queryset_manager, fieldsclass UserQuerySet(QuerySet):
def for_org(self, *, org: str) -> QuerySet:
return self.filter(organization=org)class User(Document):
meta = {
"collection": "users",
"queryset_class": UserQuerySet,
}is_active = fields.BooleanField()
# --snip--
@queryset_manager
def objects(self, queryset: QuerySet) -> QuerySet:
return queryset.filter(is_active=True)@queryset_manager
def all_objects(self, queryset: QuerySet) -> QuerySet:
return querysetmaybe_user = User.all_objects.first()
```after:
```python
from __future__ import annotations
from typing import Type
from mongoengine import QuerySet, Documentclass UserQuerySet(QuerySet["User"]):
def for_org(self, *, org: str) -> UserQuerySet:
return self.filter(organization=org)class QuerySetManager:
def __get__(self, instance: object, cls: Type[User]) -> UserQuerySet:
return UserQuerySet(cls, cls._get_collection()).filter(is_active=True)class User(Document):
meta = {
"collection": "users",
}is_active = fields.BooleanField()
# --snip--
objects = QuerySetManager()
@classmethod
def all_objects(cls) -> UserQuerySet:
return UserQuerySet(cls, cls._get_collection())maybe_user = User.all_objects().first()
```### fixing "Model" has no attribute "id"
Mongoengine will define an `id` field for you automatically.
Mongo-types require you specify your `id` explicitly so that
the types can be more strict.```python
class User(Document):
meta = {
"collection": "users",
}# becomes
class User(Document):
meta = {
"collection": "users",
}
id = fields.StringField(db_field="_id", primary_key=True, default=default_id)# or if you prefer ObjectIds
class User(Document):
meta = {
"collection": "users",
}
id = fields.ObjectIdField(db_field="_id", primary_key=True, default=ObjectId)
```## dev
```shell
poetry install# run formatting, linting, and typechecking
s/lint# build
poetry build -f wheel# build and publish
poetry publish --build
```[0]: https://github.com/MongoEngine/mongoengine
## related
-
-
-
-