Skip to content

Migrate motor to pymongo#1705

Merged
JrooTJunior merged 26 commits intoaiogram:dev-3.xfrom
kievzenit:migrate-motor-to-pymongo
Aug 17, 2025
Merged

Migrate motor to pymongo#1705
JrooTJunior merged 26 commits intoaiogram:dev-3.xfrom
kievzenit:migrate-motor-to-pymongo

Conversation

@kievzenit
Copy link
Contributor

Description

Migrated MongoStorage from relying on deprecated motor package to using new async PyMongo. Also __init__.py file was changed in aiogram/storage/fsm to improve developer experience.

Fixes #1695

Type of change

  • Documentation (typos, code examples or any documentation update)
  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • This change requires a documentation update

How Has This Been Tested?

It was tested utilizing method that is provided in contributing guide: pytest --mongo mongodb://<user>:<password>@<host>:<port> tests

Test Configuration:

  • Operating System: Linux fedora 6.15.4-100.fc41.x86_64 x86_64 GNU/Linux
  • Python version: 3.13.5
  • MongoDB version: 6.0.22-ubi8

Checklist:

  • My code follows the style guidelines of this project
  • I have performed a self-review of my own code
  • I have made corresponding changes to the documentation
  • I have added tests that prove my fix is effective or that my feature works
  • New and existing unit tests pass locally with my changes

@github-actions github-actions bot added the 3.x Issue or PR for stable 3.x version label Jul 9, 2025
@github-actions
Copy link

github-actions bot commented Jul 9, 2025

✔️ Changelog found.

Thank you for adding a description of the changes

Copy link
Member

@JrooTJunior JrooTJunior left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a very small but critical change for developers using this type of storage, as it could break code until the developer rewrites other code that uses Mongo. Also, using multiple drivers for the same purposes can be too expensive.

So, the best way to update this storage is to mark the current implementation as deprecated and add a new storage implementation with a name like PyMongoStorage, and provide migration guidance in the changelog and documentation articles (storages section).

@kievzenit kievzenit requested a review from JrooTJunior July 21, 2025 16:27
@JrooTJunior JrooTJunior requested a review from Copilot August 9, 2025 16:20

This comment was marked as outdated.

This comment was marked as outdated.

@JrooTJunior JrooTJunior requested a review from Copilot August 11, 2025 17:19
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR migrates MongoDB storage from the deprecated motor package to the async PyMongo package, introducing a new PyMongoStorage class while deprecating the existing MongoStorage class.

  • Introduces new PyMongoStorage class as replacement for deprecated MongoStorage
  • Updates package dependencies to include pymongo>=4.9.12
  • Adds comprehensive test coverage for the new PyMongo storage implementation

Reviewed Changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
aiogram/fsm/storage/pymongo.py New PyMongoStorage class implementing async MongoDB storage using PyMongo
aiogram/fsm/storage/mongo.py Adds deprecation warning to existing MongoStorage class
tests/test_fsm/storage/test_pymongo.py Comprehensive test suite for PyMongoStorage functionality
tests/conftest.py Adds pymongo_storage fixture for testing
tests/test_fsm/storage/test_storages.py Includes pymongo_storage in storage tests
pyproject.toml Adds pymongo dependency
docs/dispatcher/finite_state_machine/storages.rst Documents new PyMongoStorage class
CHANGES/1705.misc.rst Release notes for the migration

projection={"_id": 0},
)
if not update_result:
await self._collection.delete_one({"_id": document_id})
Copy link

Copilot AI Aug 11, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The return value can be None when update_result is falsy, but the method signature expects Dict[str, Any]. This will cause a TypeError since None.get() will fail. Should return {} when update_result is falsy.

Suggested change
await self._collection.delete_one({"_id": document_id})
await self._collection.delete_one({"_id": document_id})
return {}

Copilot uses AI. Check for mistakes.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nothing returns in this branch, below, where actual value is returned, there is a fallback to {}

projection={"_id": 0},
)
if not update_result:
await self._collection.delete_one({"_id": document_id})
Copy link

Copilot AI Aug 11, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This condition will never be true because find_one_and_update with upsert=True will always return a document (either the existing one or the newly created one). The deletion logic is unreachable.

Suggested change
await self._collection.delete_one({"_id": document_id})

Copilot uses AI. Check for mistakes.
Copy link
Contributor Author

@kievzenit kievzenit Aug 11, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually it will be true. Because of projection={"_id": 0}. When there is no record in database and user tries to call update_data(key, data={}), update_result will be {}. So this condition will be true.

@codecov
Copy link

codecov bot commented Aug 11, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 100.00%. Comparing base (7a517f1) to head (cf2e472).
⚠️ Report is 4 commits behind head on dev-3.x.

Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff            @@
##           dev-3.x     #1705   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files          578       579    +1     
  Lines        13531     13593   +62     
=========================================
+ Hits         13531     13593   +62     
Flag Coverage Δ
unittests 100.00% <100.00%> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
aiogram/fsm/storage/mongo.py 100.00% <ø> (ø)
aiogram/fsm/storage/pymongo.py 100.00% <100.00%> (ø)
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@kievzenit
Copy link
Contributor Author

kievzenit commented Aug 11, 2025

Some of the tests fails are transient, they should go on tests rerun.

Copy link
Contributor

@Vadim-Khristenko Vadim-Khristenko left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Everything looks good — great work!

Just one suggestion: I recommend pinning the upper version of pymongo to <4.11 for now.

Why?

  • pymongo==4.10.1 still supports PyPy 3.9.
  • pymongo>=4.11 drops support for PyPy 3.9 entirely.

Since we currently run tests on pypy3.9, upgrading beyond 4.10.1 would break CI.

Suggestion:
Let’s create an issue to track this and automatically upgrade the upper bound when CPython 3.9 reaches EOL (October 2025).
This way, we’ll be ready to safely bump pymongo without breaking builds.

Ready for final review from @JrooTJunior before merge.

@JrooTJunior JrooTJunior merged commit 99fa246 into aiogram:dev-3.x Aug 17, 2025
23 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

3.x Issue or PR for stable 3.x version

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Migrate from Motor to PyMongo Async for MongoStorage

4 participants