Install & Compatibility
Where this runs
tested against v1.3.0 · pip install
no network on importno background threads
Install × environment matrix
Each cell = how many times install + import succeeded across repeated harness runs. Partial = flaky.
glibc = Debian/Ubuntu slim · musl = Alpine Linux
muslpy 3.10–3.920 runs
installs and imports cleanly · install 0.0s · import 0.940s · 38MB
glibcpy 3.10–3.920 runs
installs and imports cleanly · install 4.5s · import 0.857s · 39MB
38MB installed
● package 38MB
Code
Verified usage
Verified import paths — ran on the pinned version, not inferred.
Document
✓ from bunnet import Document
init_bunnet
✓ from bunnet import init_bunnet
Indexed
✓ from bunnet import Indexed
MongoClient
✓ from pymongo import MongoClient
BaseModel
✓ from pydantic import BaseModel
✗ from bunnet import BaseModel
BaseModel should be imported from pydantic for nested models, not directly from bunnet.
This quickstart demonstrates how to connect to MongoDB, define a Bunnet Document, insert data, and perform basic queries and updates. It uses Pydantic for defining nested data structures and `pymongo.MongoClient` for the underlying database connection. Remember to replace `mongodb://localhost:27017` and `your_db_name` with your actual MongoDB connection string and database name.
from typing import Optional
from pymongo import MongoClient
from pydantic import BaseModel
from bunnet import Document, Indexed, init_bunnet
import os
# Define a Pydantic model for a nested object
class Category(BaseModel):
name: str
description: str
# Define a Bunnet Document model
class Product(Document):
name: str
description: Optional[str] = None
price: Indexed(float)
category: Category
# Optional: Configure collection name and other settings
class Settings:
name = "products_collection"
async def main():
# Connect to MongoDB (replace with your connection string)
# Use os.environ.get for secure credentials in production
MONGO_DETAILS = os.environ.get('MONGO_URI', 'mongodb://localhost:27017')
client = MongoClient(MONGO_DETAILS)
# Initialize Bunnet with the database and document models
# Ensure 'your_db_name' exists or will be created upon first write
init_bunnet(database=client.get_database('your_db_name'), document_models=[Product])
# Create a category instance
chocolate_category = Category(name="Chocolate", description="A preparation of roasted and ground cacao seeds.")
# Create a product instance
tonybar = Product(name="Tony's Chocolonely", price=5.95, category=chocolate_category)
# Insert the document into the database
inserted_product = tonybar.insert()
print(f"Inserted product: {inserted_product.name}")
# Find a document using Pythonic syntax
found_product = Product.find_one(Product.price < 10).run()
if found_product:
print(f"Found product: {found_product.name}")
# Update a document
updated_product = found_product.set({Product.name: "Gold Bar"})
print(f"Updated product to: {updated_product.name}")
if __name__ == "__main__":
# Bunnet is synchronous, so no asyncio.run() needed directly for document operations.
# The main function is defined as async only for consistency if a project mixed sync/async components
# For this quickstart, you would typically run the synchronous operations directly.
# However, to simulate an async context often seen in examples for its counterpart (Beanie),
# we wrap it here. For a purely synchronous application, you'd call main() directly and remove 'async/await'.
main()
Debug
Known issues
gotchaBunnet is the synchronous version of Beanie ODM. Methods in Bunnet do not use `await` and attempts to call `async` methods (like `find_one_async`) will result in `AttributeError` or `TypeError`.fixUse synchronous methods provided by Bunnet (e.g., `find_one().run()`) and ensure your application context is synchronous. If an async context is required, consider using BeanieODM instead.
affects: All versions
breakingPydantic V2 introduced significant internal changes. While Bunnet aims for compatibility, developers migrating from Pydantic V1-based applications might encounter validation or serialization issues, especially with custom types or complex data structures.fixRefer to Pydantic's official migration guide. If issues persist, check Bunnet's GitHub discussions or issues for specific Pydantic V2 related workarounds or bug fixes.
affects: Bunnet versions built against Pydantic V2 (post-Pydantic V2 release)
gotchaThe `replace_one` method in Bunnet (and Beanie) does not natively support `upsert=True` as a direct parameter in the same way `update_one` does in PyMongo. Attempting to use it for an upsert might not behave as expected.fixFor upsert functionality with `replace_one`, you might need to implement a check-then-insert/replace logic or use `save()` on a new or existing document instance. For more complex scenarios, consider using `update_one` with `upsert=True` or a custom bulk write operation. Raising a feature request/PR to the Bunnet maintainers might also be an option.
affects: All versions
gotchaInitialization with `init_bunnet` requires a PyMongo `database` object, not the client. Passing the client directly will raise an error or lead to incorrect behavior.fixAlways pass the `database` object obtained from the client (e.g., `client.get_database('your_db_name')`) to `init_bunnet`. affects: All versions
Errors
Common errors & fixes
AttributeError: 'Product' object has no attribute 'find_one_async'
Attempting to use an asynchronous method from BeanieODM (the async counterpart) on a Bunnet Document model.
fixBunnet is synchronous. Use `find_one().run()` instead of `find_one_async()`. All operations are synchronous and do not require `await`.
pymongo.errors.CollectionInvalid: collection name cannot be empty
The `init_bunnet` function was called without a valid `database` object or `document_models` list, preventing proper collection initialization.
fixEnsure `init_bunnet(database=client.get_database('your_db_name'), document_models=[YourDocumentClass])` is called with both a valid `pymongo.database.Database` instance and a list of your Document classes. TypeError: Document.save() missing 1 required positional argument: 'self'
Trying to call an instance method (`.save()`, `.insert()`, `.update()`) on the `Document` class itself, rather than on an instantiated document object.
fixFirst create an instance of your document (e.g., `my_product = Product(...)`), then call the method on the instance (`my_product.save()`).
TypeError: 'Collection' object is not callable
Attempting to access a database collection property (e.g., `Product.Collection`) which was a pattern in older Beanie versions but is now deprecated or unsupported in Bunnet, replaced by `Settings`.
fixAccess collection-level settings via `Product.Settings` or define `class Settings:` within your `Document` class to configure collection options like `name`. Do not use `Document.Collection` directly.
Upgrade
Version history
1.3.0latest on PyPI · released Feb 28, 2024
Audit
Dependencies
pymongorequiredBunnet uses Pymongo client under the hood for MongoDB interaction.
pydanticrequiredData models in Bunnet are based on Pydantic models for validation and serialization.