codex-bot 0.2.1__tar.gz → 0.3.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {codex_bot-0.2.1 → codex_bot-0.3.0}/.gitignore +3 -2
- {codex_bot-0.2.1 → codex_bot-0.3.0}/CHANGELOG.md +11 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/PKG-INFO +6 -6
- {codex_bot-0.2.1 → codex_bot-0.3.0}/pyproject.toml +3 -3
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/engine/middlewares/i18n.py +1 -1
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/project/root/pyproject.toml.j2 +2 -2
- codex_bot-0.3.0/tests/engine/middlewares/test_i18n.py +91 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/uv.lock +56 -14
- {codex_bot-0.2.1 → codex_bot-0.3.0}/.github/workflows/ci.yml +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/.github/workflows/docs.yml +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/.github/workflows/publish.yml +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/.pre-commit-config.yaml +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/.python-version +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/.secrets.baseline +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/LICENSE +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/NOTICE +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/README.md +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/DOCUMENTATION_STANDARD.md +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/README.md +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/api/README.md +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/api/animation.md +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/api/base.md +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/api/director.md +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/api/discovery.md +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/api/factory.md +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/api/fsm.md +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/api/helper.md +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/api/http.md +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/api/i18n.md +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/api/middlewares.md +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/api/redis.md +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/api/router_builder.md +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/api/sender.md +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/api/url_signer.md +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/changelog.md +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/en_EN/README.md +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/en_EN/architecture/README.md +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/en_EN/architecture/cli/README.md +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/en_EN/architecture/engine/README.md +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/en_EN/architecture/engine/container.md +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/en_EN/architecture/engine/discovery.md +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/en_EN/architecture/engine/factory.md +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/en_EN/architecture/engine/http_db.md +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/en_EN/architecture/engine/i18n.md +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/en_EN/architecture/engine/middlewares.md +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/en_EN/architecture/services/animation/README.md +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/en_EN/architecture/services/base/README.md +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/en_EN/architecture/services/director/README.md +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/en_EN/architecture/services/fsm/README.md +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/en_EN/architecture/services/helper/README.md +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/en_EN/architecture/services/helper/url_signer.md +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/en_EN/architecture/services/redis/README.md +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/en_EN/architecture/services/view_sender/README.md +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/en_EN/guide/getting_started.md +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/en_EN/roadmap.md +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/en_EN/tasks/001_high_integrated_debug_system.md +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/en_EN/tasks/002_med_docker_infrastructure.md +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/en_EN/tasks/003_high_in_bot_guide_system.md +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/en_EN/tasks/004_high_redis_fsm_integration.md +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/en_EN/tasks/005_med_header_driven_navigation.md +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/en_EN/tasks/006_med_redis_stream_contract.md +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/en_EN/tasks/007_med_sqlalchemy_sender_storage.md +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/en_EN/tasks/008_high_multi_broker_support.md +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/en_EN/tasks/009_high_webhook_server.md +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/en_EN/tasks/ARCHIVE.md +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/en_EN/tasks/backlog.md +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/ru_RU/README.md +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/ru_RU/architecture/README.md +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/ru_RU/architecture/cli/README.md +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/ru_RU/architecture/engine/README.md +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/ru_RU/architecture/engine/container.md +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/ru_RU/architecture/engine/discovery.md +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/ru_RU/architecture/engine/factory.md +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/ru_RU/architecture/engine/http_db.md +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/ru_RU/architecture/engine/i18n.md +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/ru_RU/architecture/engine/middlewares.md +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/ru_RU/architecture/services/README.md +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/ru_RU/architecture/services/animation/README.md +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/ru_RU/architecture/services/base/README.md +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/ru_RU/architecture/services/director/README.md +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/ru_RU/architecture/services/fsm/README.md +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/ru_RU/architecture/services/helper/README.md +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/ru_RU/architecture/services/helper/url_signer.md +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/ru_RU/architecture/services/redis/README.md +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/ru_RU/architecture/services/view_sender/README.md +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/ru_RU/guide/getting_started.md +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/ru_RU/roadmap.md +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/ru_RU/tasks/001_high_integrated_debug_system.md +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/ru_RU/tasks/002_med_docker_infrastructure.md +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/ru_RU/tasks/003_high_in_bot_guide_system.md +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/ru_RU/tasks/004_high_redis_fsm_integration.md +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/ru_RU/tasks/005_med_header_driven_navigation.md +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/ru_RU/tasks/006_med_redis_stream_contract.md +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/ru_RU/tasks/007_med_sqlalchemy_sender_storage.md +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/ru_RU/tasks/008_high_multi_broker_support.md +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/ru_RU/tasks/009_high_webhook_server.md +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/ru_RU/tasks/ARCHIVE.md +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/ru_RU/tasks/backlog.md +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/mkdocs.yml +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/project_structure.txt +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/__init__.py +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/animation/__init__.py +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/animation/animation_service.py +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/base/__init__.py +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/base/base_orchestrator.py +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/base/context_dto.py +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/base/view_dto.py +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/cli/__init__.py +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/cli/commands/create_feature.py +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/cli/commands/migrations.py +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/cli/commands/startproject.py +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/cli/commands/utils.py +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/cli/main.py +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/cli/management.py +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/cli/templating.py +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/director/__init__.py +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/director/director.py +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/director/protocols.py +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/engine/__init__.py +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/engine/container.py +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/engine/database/__init__.py +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/engine/database/engine.py +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/engine/database/models.py +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/engine/database/repository.py +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/engine/discovery/__init__.py +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/engine/discovery/service.py +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/engine/factory/__init__.py +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/engine/factory/bot_builder.py +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/engine/http/__init__.py +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/engine/http/api_client.py +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/engine/i18n/__init__.py +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/engine/i18n/locales_compiler.py +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/engine/middlewares/__init__.py +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/engine/middlewares/container.py +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/engine/middlewares/database.py +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/engine/middlewares/director_middleware.py +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/engine/middlewares/throttling.py +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/engine/middlewares/user_validation.py +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/engine/protocols.py +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/engine/router_builder/__init__.py +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/engine/router_builder/router_builder.py +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/engine/runner.py +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/features/__init__.py +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/features/errors/__init__.py +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/features/errors/default_errors.py +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/features/errors/handlers.py +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/features/errors/orchestrator.py +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/features/errors/ui.py +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/fsm/__init__.py +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/fsm/common_fsm_handlers.py +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/fsm/garbage_collector.py +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/fsm/state_helper.py +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/fsm/state_manager.py +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/helper/__init__.py +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/helper/context_helper.py +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/helper/id_inspector.py +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/py.typed +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/redis/__init__.py +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/redis/dispatcher.py +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/redis/router.py +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/redis/stream_processor.py +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/sender/__init__.py +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/sender/memory_storage.py +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/sender/protocols.py +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/sender/redis_storage.py +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/sender/sender_keys.py +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/sender/sender_manager.py +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/sender/view_sender.py +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/stream/__init__.py +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/stream/dispatcher.py +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/stream/router.py +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/feature/redis/__init__.py +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/feature/redis/feature_setting.py.j2 +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/feature/redis/handlers/__init__.py.j2 +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/feature/redis/handlers/handlers.py.j2 +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/feature/redis/logic/__init__.py +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/feature/redis/logic/orchestrator.py.j2 +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/feature/redis/resources/__init__.py.j2 +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/feature/redis/resources/callbacks.py.j2 +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/feature/redis/resources/dto.py.j2 +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/feature/redis/resources/keyboards.py.j2 +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/feature/redis/resources/texts.py.j2 +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/feature/telegram/__init__.py +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/feature/telegram/contracts/contract.py.j2 +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/feature/telegram/feature_setting.py.j2 +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/feature/telegram/handlers/__init__.py.j2 +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/feature/telegram/handlers/handlers.py.j2 +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/feature/telegram/logic/orchestrator.py.j2 +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/feature/telegram/logic/state_manager.py.j2 +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/feature/telegram/resources/callbacks.py.j2 +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/feature/telegram/resources/dto.py.j2 +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/feature/telegram/resources/formatters.py.j2 +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/feature/telegram/resources/keyboards.py.j2 +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/feature/telegram/resources/texts.py.j2 +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/feature/telegram/ui/ui.py.j2 +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/project/root/.env.example.j2 +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/project/root/.env.j2 +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/project/root/.gitignore.j2 +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/project/root/.python-version.j2 +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/project/root/README.md.j2 +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/project/root/docs/architecture_cheat_sheet.md.j2 +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/project/root/docs/message_flow.md.j2 +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/project/root/manage.py.j2 +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/project/src/alembic.ini.j2 +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/project/src/core/config.py.j2 +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/project/src/core/container.py.j2 +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/project/src/core/errors.py.j2 +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/project/src/core/factory.py.j2 +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/project/src/core/logging.py.j2 +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/project/src/core/settings.py.j2 +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/project/src/features/telegram/bot_menu/__init__.py.j2 +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/project/src/features/telegram/bot_menu/contracts/__init__.py.j2 +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/project/src/features/telegram/bot_menu/contracts/menu_contract.py.j2 +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/project/src/features/telegram/bot_menu/feature_setting.py.j2 +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/project/src/features/telegram/bot_menu/handlers/__init__.py.j2 +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/project/src/features/telegram/bot_menu/handlers/handlers.py.j2 +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/project/src/features/telegram/bot_menu/logic/__init__.py.j2 +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/project/src/features/telegram/bot_menu/logic/orchestrator.py.j2 +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/project/src/features/telegram/bot_menu/orchestrator.py.j2 +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/project/src/features/telegram/bot_menu/resources/__init__.py.j2 +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/project/src/features/telegram/bot_menu/resources/callbacks.py.j2 +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/project/src/features/telegram/bot_menu/resources/dto.py.j2 +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/project/src/features/telegram/bot_menu/resources/keyboards.py.j2 +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/project/src/features/telegram/bot_menu/resources/texts.py.j2 +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/project/src/features/telegram/bot_menu/ui/__init__.py.j2 +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/project/src/features/telegram/bot_menu/ui/menu_ui.py.j2 +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/project/src/features/telegram/bot_menu/ui/ui.py.j2 +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/project/src/features/telegram/commands/__init__.py.j2 +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/project/src/features/telegram/commands/contracts/__init__.py.j2 +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/project/src/features/telegram/commands/contracts/auth_contract.py.j2 +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/project/src/features/telegram/commands/contracts/contract.py.j2 +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/project/src/features/telegram/commands/feature_setting.py.j2 +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/project/src/features/telegram/commands/handlers/__init__.py.j2 +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/project/src/features/telegram/commands/handlers/handlers.py.j2 +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/project/src/features/telegram/commands/logic/__init__.py.j2 +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/project/src/features/telegram/commands/logic/orchestrator.py.j2 +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/project/src/features/telegram/commands/resources/__init__.py.j2 +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/project/src/features/telegram/commands/resources/callbacks.py.j2 +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/project/src/features/telegram/commands/resources/formatters.py.j2 +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/project/src/features/telegram/commands/resources/keyboards.py.j2 +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/project/src/features/telegram/commands/resources/texts.py.j2 +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/project/src/features/telegram/commands/ui/__init__.py.j2 +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/project/src/features/telegram/commands/ui/commands_ui.py.j2 +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/project/src/infrastructure/database/__init__.py.j2 +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/project/src/infrastructure/database/migrations/env.py.j2 +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/project/src/infrastructure/database/migrations/script.py.mako.j2 +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/project/src/infrastructure/migrations/env.py.j2 +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/project/src/infrastructure/models/base.py.j2 +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/project/src/infrastructure/redis/container.py.j2 +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/project/src/infrastructure/repositories/base.py.j2 +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/project/src/launcher.py.j2 +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/project/src/resources/locales/en/messages.ftl.j2 +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/project/src/resources/locales/ru/messages.ftl.j2 +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/project/src/shared/schemas/user.py.j2 +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/url_signer/__init__.py +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/url_signer/service.py +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/tests/animation/test_animation_service.py +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/tests/base/test_base_orchestrator.py +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/tests/base/test_view_dto.py +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/tests/conftest.py +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/tests/director/test_director.py +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/tests/engine/factory/test_bot_builder.py +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/tests/engine/http/test_api_client.py +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/tests/engine/middlewares/test_throttling.py +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/tests/fsm/test_garbage_collector.py +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/tests/fsm/test_state_manager.py +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/tests/helper/test_context_helper.py +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/tests/integration/test_templates_e2e.py +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/tests/redis/__init__.py +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/tests/redis/test_dispatcher.py +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/tests/redis/test_router.py +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/tests/sender/test_sender_keys.py +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/tests/test_template_consistency.py +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/tests/test_templates.py +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/tests/url_signer/test_url_signer.py +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/tools/__init__.py +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/tools/dev/__init__.py +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/tools/dev/check.py +0 -0
- {codex_bot-0.2.1 → codex_bot-0.3.0}/tools/dev/generate_project_tree.py +0 -0
|
@@ -5,6 +5,17 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [0.3.0] - 2026-04-23
|
|
9
|
+
|
|
10
|
+
### Changed
|
|
11
|
+
|
|
12
|
+
- **Aiogram Stack**: Raised the core `aiogram` dependency contract to `>=3.27.0,<4.0` and the optional i18n extra to `aiogram-i18n[runtime]>=1.5,<2.0`.
|
|
13
|
+
- **Project Templates**: Updated generated project dependencies to use the same modern aiogram and aiogram-i18n ranges.
|
|
14
|
+
|
|
15
|
+
### Fixed
|
|
16
|
+
|
|
17
|
+
- **I18n Manager Initialization**: Updated `FSMContextI18nManager` to initialize `aiogram-i18n`'s `BaseManager`, restoring `locale_getter` and `locale_setter` for `I18nMiddleware`.
|
|
18
|
+
|
|
8
19
|
## [0.2.1] - 2026-04-18
|
|
9
20
|
|
|
10
21
|
### Fixed
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: codex-bot
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.0
|
|
4
4
|
Summary: Feature-based Aiogram framework library — reusable infrastructure for Telegram bots
|
|
5
5
|
Project-URL: Homepage, https://github.com/codexdlc/codex-bot
|
|
6
6
|
Project-URL: Documentation, https://codexdlc.github.io/codex-bot/
|
|
@@ -21,7 +21,7 @@ Classifier: Programming Language :: Python :: 3.13
|
|
|
21
21
|
Classifier: Topic :: Communications :: Chat
|
|
22
22
|
Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
|
|
23
23
|
Requires-Python: >=3.12
|
|
24
|
-
Requires-Dist: aiogram<4.0,>=3.
|
|
24
|
+
Requires-Dist: aiogram<4.0,>=3.27.0
|
|
25
25
|
Requires-Dist: aiohttp>=3.13.4
|
|
26
26
|
Requires-Dist: jinja2>=3.1.0
|
|
27
27
|
Requires-Dist: pydantic-settings>=2.0
|
|
@@ -29,7 +29,7 @@ Requires-Dist: pydantic<3.0,>=2.0
|
|
|
29
29
|
Requires-Dist: python-dotenv>=1.0.0
|
|
30
30
|
Requires-Dist: questionary>=2.0.0
|
|
31
31
|
Provides-Extra: all
|
|
32
|
-
Requires-Dist: aiogram-i18n
|
|
32
|
+
Requires-Dist: aiogram-i18n[runtime]<2.0,>=1.5; extra == 'all'
|
|
33
33
|
Requires-Dist: aiosqlite>=0.19.0; extra == 'all'
|
|
34
34
|
Requires-Dist: alembic>=1.13.0; extra == 'all'
|
|
35
35
|
Requires-Dist: arq>=0.25; extra == 'all'
|
|
@@ -49,7 +49,7 @@ Requires-Dist: alembic>=1.13.0; extra == 'db'
|
|
|
49
49
|
Requires-Dist: asyncpg>=0.29.0; extra == 'db'
|
|
50
50
|
Requires-Dist: sqlalchemy>=2.0; extra == 'db'
|
|
51
51
|
Provides-Extra: dev
|
|
52
|
-
Requires-Dist: aiogram-i18n
|
|
52
|
+
Requires-Dist: aiogram-i18n[runtime]<2.0,>=1.5; extra == 'dev'
|
|
53
53
|
Requires-Dist: aiosqlite>=0.19.0; extra == 'dev'
|
|
54
54
|
Requires-Dist: alembic>=1.13.0; extra == 'dev'
|
|
55
55
|
Requires-Dist: arq>=0.25; extra == 'dev'
|
|
@@ -62,7 +62,7 @@ Requires-Dist: loguru>=0.7.0; extra == 'dev'
|
|
|
62
62
|
Requires-Dist: mypy>=1.10; extra == 'dev'
|
|
63
63
|
Requires-Dist: pip-audit>=2.7; extra == 'dev'
|
|
64
64
|
Requires-Dist: pre-commit>=3.0; extra == 'dev'
|
|
65
|
-
Requires-Dist: pygments
|
|
65
|
+
Requires-Dist: pygments==2.19.1; extra == 'dev'
|
|
66
66
|
Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
|
|
67
67
|
Requires-Dist: pytest-cov; extra == 'dev'
|
|
68
68
|
Requires-Dist: pytest>=9.0.3; extra == 'dev'
|
|
@@ -78,7 +78,7 @@ Requires-Dist: mkdocstrings[python]>=0.24; extra == 'docs'
|
|
|
78
78
|
Provides-Extra: http
|
|
79
79
|
Requires-Dist: httpx<1.0,>=0.27; extra == 'http'
|
|
80
80
|
Provides-Extra: i18n
|
|
81
|
-
Requires-Dist: aiogram-i18n
|
|
81
|
+
Requires-Dist: aiogram-i18n[runtime]<2.0,>=1.5; extra == 'i18n'
|
|
82
82
|
Provides-Extra: postgres
|
|
83
83
|
Requires-Dist: asyncpg>=0.29.0; extra == 'postgres'
|
|
84
84
|
Provides-Extra: redis
|
|
@@ -22,7 +22,7 @@ classifiers = [
|
|
|
22
22
|
"Topic :: Software Development :: Libraries :: Application Frameworks",
|
|
23
23
|
]
|
|
24
24
|
dependencies = [
|
|
25
|
-
"aiogram>=3.
|
|
25
|
+
"aiogram>=3.27.0,<4.0",
|
|
26
26
|
"aiohttp>=3.13.4",
|
|
27
27
|
"pydantic>=2.0,<3.0",
|
|
28
28
|
"pydantic-settings>=2.0",
|
|
@@ -47,7 +47,7 @@ redis = [
|
|
|
47
47
|
"codex-platform",
|
|
48
48
|
]
|
|
49
49
|
arq = ["arq>=0.25"]
|
|
50
|
-
i18n = ["aiogram-i18n>=1.
|
|
50
|
+
i18n = ["aiogram-i18n[runtime]>=1.5,<2.0"]
|
|
51
51
|
http = ["httpx>=0.27,<1.0"]
|
|
52
52
|
sqlite = ["aiosqlite>=0.19.0"]
|
|
53
53
|
postgres = ["asyncpg>=0.29.0"]
|
|
@@ -58,7 +58,7 @@ all = [
|
|
|
58
58
|
dev = [
|
|
59
59
|
"codex-bot[all]",
|
|
60
60
|
"pytest>=9.0.3",
|
|
61
|
-
"pygments
|
|
61
|
+
"pygments==2.19.1",
|
|
62
62
|
"pytest-asyncio>=0.23",
|
|
63
63
|
"pytest-cov",
|
|
64
64
|
"ruff>=0.4",
|
|
@@ -51,8 +51,8 @@ class FSMContextI18nManager(BaseManager):
|
|
|
51
51
|
allowed_locales: list[str] | None = None,
|
|
52
52
|
default_locale: str = "en",
|
|
53
53
|
) -> None:
|
|
54
|
+
super().__init__(default_locale=default_locale)
|
|
54
55
|
self.allowed_locales: list[str] = allowed_locales or []
|
|
55
|
-
self.default_locale: str = default_locale
|
|
56
56
|
|
|
57
57
|
async def get_locale(self, event_from_user: User | None = None, **kwargs: Any) -> str:
|
|
58
58
|
"""
|
|
@@ -9,14 +9,14 @@ description = "Telegram Bot generated via codex-bot"
|
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.12"
|
|
11
11
|
dependencies = [
|
|
12
|
-
"aiogram>=3.4",
|
|
12
|
+
"aiogram>=3.27.0,<4.0",
|
|
13
13
|
"pydantic-settings>=2.0",
|
|
14
14
|
"codex-bot",
|
|
15
15
|
{% if use_loguru %}
|
|
16
16
|
"loguru>=0.7.0",
|
|
17
17
|
{% endif %}
|
|
18
18
|
{% if use_i18n %}
|
|
19
|
-
"aiogram-i18n>=1.
|
|
19
|
+
"aiogram-i18n[runtime]>=1.5,<2.0",
|
|
20
20
|
{% endif %}
|
|
21
21
|
{% if use_redis %}
|
|
22
22
|
"redis[asyncio]>=5.0",
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
from unittest.mock import AsyncMock
|
|
3
|
+
|
|
4
|
+
import pytest
|
|
5
|
+
from aiogram.types import TelegramObject, User
|
|
6
|
+
|
|
7
|
+
from codex_bot.engine.middlewares.i18n import FSMContextI18nManager
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
@pytest.fixture
|
|
11
|
+
def state():
|
|
12
|
+
fsm_state = AsyncMock()
|
|
13
|
+
fsm_state.get_data = AsyncMock(return_value={})
|
|
14
|
+
fsm_state.set_data = AsyncMock()
|
|
15
|
+
return fsm_state
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def test_manager_initialization():
|
|
19
|
+
manager = FSMContextI18nManager(default_locale="de")
|
|
20
|
+
|
|
21
|
+
assert hasattr(manager, "locale_getter") is True
|
|
22
|
+
assert hasattr(manager, "locale_setter") is True
|
|
23
|
+
assert manager.default_locale == "de"
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
async def test_get_locale_prefers_fsm_locale(state):
|
|
27
|
+
state.get_data.return_value = {"locale": "ru"}
|
|
28
|
+
manager = FSMContextI18nManager(allowed_locales=["de"], default_locale="de")
|
|
29
|
+
|
|
30
|
+
locale = await manager.get_locale(state=state)
|
|
31
|
+
|
|
32
|
+
assert locale == "ru"
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
async def test_get_locale_uses_allowed_telegram_language(state):
|
|
36
|
+
user = User(id=1, is_bot=False, first_name="Test", language_code="ru")
|
|
37
|
+
manager = FSMContextI18nManager(allowed_locales=["ru", "de"], default_locale="de")
|
|
38
|
+
|
|
39
|
+
locale = await manager.get_locale(event_from_user=user, state=state)
|
|
40
|
+
|
|
41
|
+
assert locale == "ru"
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
async def test_get_locale_falls_back_for_disallowed_language(state):
|
|
45
|
+
user = User(id=1, is_bot=False, first_name="Test", language_code="en")
|
|
46
|
+
manager = FSMContextI18nManager(allowed_locales=["ru", "de"], default_locale="de")
|
|
47
|
+
|
|
48
|
+
locale = await manager.get_locale(event_from_user=user, state=state)
|
|
49
|
+
|
|
50
|
+
assert locale == "de"
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
async def test_get_locale_uses_default_without_state_or_user():
|
|
54
|
+
manager = FSMContextI18nManager(default_locale="de")
|
|
55
|
+
|
|
56
|
+
locale = await manager.get_locale()
|
|
57
|
+
|
|
58
|
+
assert locale == "de"
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
async def test_set_locale_writes_to_fsm_storage(state):
|
|
62
|
+
state.get_data.return_value = {}
|
|
63
|
+
manager = FSMContextI18nManager(default_locale="de")
|
|
64
|
+
|
|
65
|
+
await manager.set_locale("ru", state=state)
|
|
66
|
+
|
|
67
|
+
state.set_data.assert_called_once_with({"locale": "ru"})
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
async def test_aiogram_i18n_middleware_uses_manager_locale_getter(tmp_path: Path, state):
|
|
71
|
+
from aiogram_i18n import I18nMiddleware
|
|
72
|
+
from aiogram_i18n.cores import FluentRuntimeCore
|
|
73
|
+
|
|
74
|
+
locale_dir = tmp_path / "de"
|
|
75
|
+
locale_dir.mkdir()
|
|
76
|
+
(locale_dir / "messages.ftl").write_text("hello = Hallo\n", encoding="utf-8")
|
|
77
|
+
|
|
78
|
+
manager = FSMContextI18nManager(default_locale="de")
|
|
79
|
+
middleware = I18nMiddleware(
|
|
80
|
+
core=FluentRuntimeCore(path=tmp_path / "{locale}"),
|
|
81
|
+
manager=manager,
|
|
82
|
+
default_locale="de",
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
event = TelegramObject()
|
|
86
|
+
handler = AsyncMock(return_value="ok")
|
|
87
|
+
|
|
88
|
+
result = await middleware(handler, event, {"state": state})
|
|
89
|
+
|
|
90
|
+
assert result == "ok"
|
|
91
|
+
handler.assert_awaited_once()
|
|
@@ -13,7 +13,7 @@ wheels = [
|
|
|
13
13
|
|
|
14
14
|
[[package]]
|
|
15
15
|
name = "aiogram"
|
|
16
|
-
version = "3.
|
|
16
|
+
version = "3.27.0"
|
|
17
17
|
source = { registry = "https://pypi.org/simple" }
|
|
18
18
|
dependencies = [
|
|
19
19
|
{ name = "aiofiles" },
|
|
@@ -23,9 +23,9 @@ dependencies = [
|
|
|
23
23
|
{ name = "pydantic" },
|
|
24
24
|
{ name = "typing-extensions" },
|
|
25
25
|
]
|
|
26
|
-
sdist = { url = "https://files.pythonhosted.org/packages/
|
|
26
|
+
sdist = { url = "https://files.pythonhosted.org/packages/b5/09/4bfeb0314b4d78739fc7c3cdcaa77eacaeb089312d9c16f3eb538d0f0f97/aiogram-3.27.0.tar.gz", hash = "sha256:ed5fd6b40d80a6cdb215ab162c9bd9d9b7892fb2710b45e3b762a98c21119297", size = 1753647, upload-time = "2026-04-03T22:57:00.39Z" }
|
|
27
27
|
wheels = [
|
|
28
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
28
|
+
{ url = "https://files.pythonhosted.org/packages/aa/1f/64c4a9428d15ccea5aa7b204fd53061b94407640d6b075cd61c38899dd53/aiogram-3.27.0-py3-none-any.whl", hash = "sha256:26a091b6266d87db514e02703072035e7c17feebef480f927083bcfb22f634a3", size = 727326, upload-time = "2026-04-03T22:56:58.427Z" },
|
|
29
29
|
]
|
|
30
30
|
|
|
31
31
|
[[package]]
|
|
@@ -41,6 +41,11 @@ wheels = [
|
|
|
41
41
|
{ url = "https://files.pythonhosted.org/packages/d4/09/a5ffedd5fca4e623a3e59ca39e88efe3671415eaaf9189b932d7b43b92d4/aiogram_i18n-1.5-py3-none-any.whl", hash = "sha256:6ce55978d32c8d1008d59f029c300506c6de48a18c8c346de3f666bd78013779", size = 33851, upload-time = "2026-03-07T23:36:16.374Z" },
|
|
42
42
|
]
|
|
43
43
|
|
|
44
|
+
[package.optional-dependencies]
|
|
45
|
+
runtime = [
|
|
46
|
+
{ name = "fluent-runtime" },
|
|
47
|
+
]
|
|
48
|
+
|
|
44
49
|
[[package]]
|
|
45
50
|
name = "aiohappyeyeballs"
|
|
46
51
|
version = "2.6.1"
|
|
@@ -447,7 +452,7 @@ dependencies = [
|
|
|
447
452
|
|
|
448
453
|
[package.optional-dependencies]
|
|
449
454
|
all = [
|
|
450
|
-
{ name = "aiogram-i18n" },
|
|
455
|
+
{ name = "aiogram-i18n", extra = ["runtime"] },
|
|
451
456
|
{ name = "aiosqlite" },
|
|
452
457
|
{ name = "alembic" },
|
|
453
458
|
{ name = "arq" },
|
|
@@ -471,7 +476,7 @@ db = [
|
|
|
471
476
|
{ name = "sqlalchemy" },
|
|
472
477
|
]
|
|
473
478
|
dev = [
|
|
474
|
-
{ name = "aiogram-i18n" },
|
|
479
|
+
{ name = "aiogram-i18n", extra = ["runtime"] },
|
|
475
480
|
{ name = "aiosqlite" },
|
|
476
481
|
{ name = "alembic" },
|
|
477
482
|
{ name = "arq" },
|
|
@@ -503,7 +508,7 @@ http = [
|
|
|
503
508
|
{ name = "httpx" },
|
|
504
509
|
]
|
|
505
510
|
i18n = [
|
|
506
|
-
{ name = "aiogram-i18n" },
|
|
511
|
+
{ name = "aiogram-i18n", extra = ["runtime"] },
|
|
507
512
|
]
|
|
508
513
|
postgres = [
|
|
509
514
|
{ name = "asyncpg" },
|
|
@@ -518,10 +523,10 @@ sqlite = [
|
|
|
518
523
|
|
|
519
524
|
[package.metadata]
|
|
520
525
|
requires-dist = [
|
|
521
|
-
{ name = "aiogram", specifier = ">=3.
|
|
522
|
-
{ name = "aiogram-i18n", marker = "extra == 'all'", specifier = ">=1.
|
|
523
|
-
{ name = "aiogram-i18n", marker = "extra == 'dev'", specifier = ">=1.
|
|
524
|
-
{ name = "aiogram-i18n", marker = "extra == 'i18n'", specifier = ">=1.
|
|
526
|
+
{ name = "aiogram", specifier = ">=3.27.0,<4.0" },
|
|
527
|
+
{ name = "aiogram-i18n", extras = ["runtime"], marker = "extra == 'all'", specifier = ">=1.5,<2.0" },
|
|
528
|
+
{ name = "aiogram-i18n", extras = ["runtime"], marker = "extra == 'dev'", specifier = ">=1.5,<2.0" },
|
|
529
|
+
{ name = "aiogram-i18n", extras = ["runtime"], marker = "extra == 'i18n'", specifier = ">=1.5,<2.0" },
|
|
525
530
|
{ name = "aiohttp", specifier = ">=3.13.4" },
|
|
526
531
|
{ name = "aiosqlite", marker = "extra == 'all'", specifier = ">=0.19.0" },
|
|
527
532
|
{ name = "aiosqlite", marker = "extra == 'db'", specifier = ">=0.19.0" },
|
|
@@ -559,7 +564,7 @@ requires-dist = [
|
|
|
559
564
|
{ name = "pre-commit", marker = "extra == 'dev'", specifier = ">=3.0" },
|
|
560
565
|
{ name = "pydantic", specifier = ">=2.0,<3.0" },
|
|
561
566
|
{ name = "pydantic-settings", specifier = ">=2.0" },
|
|
562
|
-
{ name = "pygments", marker = "extra == 'dev'", specifier = "
|
|
567
|
+
{ name = "pygments", marker = "extra == 'dev'", specifier = "==2.19.1" },
|
|
563
568
|
{ name = "pytest", marker = "extra == 'dev'", specifier = ">=9.0.3" },
|
|
564
569
|
{ name = "pytest-asyncio", marker = "extra == 'dev'", specifier = ">=0.23" },
|
|
565
570
|
{ name = "pytest-cov", marker = "extra == 'dev'" },
|
|
@@ -750,6 +755,34 @@ wheels = [
|
|
|
750
755
|
{ url = "https://files.pythonhosted.org/packages/a4/a5/842ae8f0c08b61d6484b52f99a03510a3a72d23141942d216ebe81fefbce/filelock-3.25.2-py3-none-any.whl", hash = "sha256:ca8afb0da15f229774c9ad1b455ed96e85a81373065fb10446672f64444ddf70", size = 26759, upload-time = "2026-03-11T20:45:37.437Z" },
|
|
751
756
|
]
|
|
752
757
|
|
|
758
|
+
[[package]]
|
|
759
|
+
name = "fluent-runtime"
|
|
760
|
+
version = "0.4.0"
|
|
761
|
+
source = { registry = "https://pypi.org/simple" }
|
|
762
|
+
dependencies = [
|
|
763
|
+
{ name = "attrs" },
|
|
764
|
+
{ name = "babel" },
|
|
765
|
+
{ name = "fluent-syntax" },
|
|
766
|
+
{ name = "pytz" },
|
|
767
|
+
{ name = "typing-extensions" },
|
|
768
|
+
]
|
|
769
|
+
sdist = { url = "https://files.pythonhosted.org/packages/dc/54/94bbd857443565a5776027165fe1e2634d836681d7d9c8992a2fd0ce8302/fluent.runtime-0.4.0.tar.gz", hash = "sha256:cb5ef96a58a3f67acaaca046d1201d202a1ebf2823e5e664370f359bae20574d", size = 17591, upload-time = "2023-03-16T11:10:35.165Z" }
|
|
770
|
+
wheels = [
|
|
771
|
+
{ url = "https://files.pythonhosted.org/packages/e5/89/a19b0bdfc74977b44aca2ad2e0600fd89c778184fcbb7fc44ba1002cc7b5/fluent.runtime-0.4.0-py2.py3-none-any.whl", hash = "sha256:51fd02582c2363e1106d7051642967a1b7f406dd9c317bd4600a73ede40c5146", size = 15627, upload-time = "2023-03-16T11:10:33.43Z" },
|
|
772
|
+
]
|
|
773
|
+
|
|
774
|
+
[[package]]
|
|
775
|
+
name = "fluent-syntax"
|
|
776
|
+
version = "0.19.0"
|
|
777
|
+
source = { registry = "https://pypi.org/simple" }
|
|
778
|
+
dependencies = [
|
|
779
|
+
{ name = "typing-extensions" },
|
|
780
|
+
]
|
|
781
|
+
sdist = { url = "https://files.pythonhosted.org/packages/51/52/de75f2faf499ed5a089acff2ab8bda5fc3b8db8a3f1615428ef9ccbf1917/fluent.syntax-0.19.0.tar.gz", hash = "sha256:920326d7f46864b9758f0044e9968e3112198bc826acee16ddd8f11d359004fd", size = 15039, upload-time = "2023-03-16T11:03:24.023Z" }
|
|
782
|
+
wheels = [
|
|
783
|
+
{ url = "https://files.pythonhosted.org/packages/54/28/475734afb670bf7932caa1828183a4687cac51111950b9fb633c4f976afc/fluent.syntax-0.19.0-py2.py3-none-any.whl", hash = "sha256:b352b3475fac6c6ed5f06527921f432aac073d764445508ee5218aeccc7cc5c4", size = 16432, upload-time = "2023-03-16T11:03:21.934Z" },
|
|
784
|
+
]
|
|
785
|
+
|
|
753
786
|
[[package]]
|
|
754
787
|
name = "frozenlist"
|
|
755
788
|
version = "1.8.0"
|
|
@@ -1921,11 +1954,11 @@ wheels = [
|
|
|
1921
1954
|
|
|
1922
1955
|
[[package]]
|
|
1923
1956
|
name = "pygments"
|
|
1924
|
-
version = "2.
|
|
1957
|
+
version = "2.19.1"
|
|
1925
1958
|
source = { registry = "https://pypi.org/simple" }
|
|
1926
|
-
sdist = { url = "https://files.pythonhosted.org/packages/
|
|
1959
|
+
sdist = { url = "https://files.pythonhosted.org/packages/7c/2d/c3338d48ea6cc0feb8446d8e6937e1408088a72a39937982cc6111d17f84/pygments-2.19.1.tar.gz", hash = "sha256:61c16d2a8576dc0649d9f39e089b5f02bcd27fba10d8fb4dcc28173f7a45151f", size = 4968581, upload-time = "2025-01-06T17:26:30.443Z" }
|
|
1927
1960
|
wheels = [
|
|
1928
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
1961
|
+
{ url = "https://files.pythonhosted.org/packages/8a/0b/9fcc47d19c48b59121088dd6da2488a49d5f72dacf8262e2790a1d2c7d15/pygments-2.19.1-py3-none-any.whl", hash = "sha256:9ea1544ad55cecf4b8242fab6dd35a93bbce657034b0611ee383099054ab6d8c", size = 1225293, upload-time = "2025-01-06T17:26:25.553Z" },
|
|
1929
1962
|
]
|
|
1930
1963
|
|
|
1931
1964
|
[[package]]
|
|
@@ -2036,6 +2069,15 @@ wheels = [
|
|
|
2036
2069
|
{ url = "https://files.pythonhosted.org/packages/0b/d7/1959b9648791274998a9c3526f6d0ec8fd2233e4d4acce81bbae76b44b2a/python_dotenv-1.2.2-py3-none-any.whl", hash = "sha256:1d8214789a24de455a8b8bd8ae6fe3c6b69a5e3d64aa8a8e5d68e694bbcb285a", size = 22101, upload-time = "2026-03-01T16:00:25.09Z" },
|
|
2037
2070
|
]
|
|
2038
2071
|
|
|
2072
|
+
[[package]]
|
|
2073
|
+
name = "pytz"
|
|
2074
|
+
version = "2026.1.post1"
|
|
2075
|
+
source = { registry = "https://pypi.org/simple" }
|
|
2076
|
+
sdist = { url = "https://files.pythonhosted.org/packages/56/db/b8721d71d945e6a8ac63c0fc900b2067181dbb50805958d4d4661cf7d277/pytz-2026.1.post1.tar.gz", hash = "sha256:3378dde6a0c3d26719182142c56e60c7f9af7e968076f31aae569d72a0358ee1", size = 321088, upload-time = "2026-03-03T07:47:50.683Z" }
|
|
2077
|
+
wheels = [
|
|
2078
|
+
{ url = "https://files.pythonhosted.org/packages/10/99/781fe0c827be2742bcc775efefccb3b048a3a9c6ce9aec0cbf4a101677e5/pytz-2026.1.post1-py2.py3-none-any.whl", hash = "sha256:f2fd16142fda348286a75e1a524be810bb05d444e5a081f37f7affc635035f7a", size = 510489, upload-time = "2026-03-03T07:47:49.167Z" },
|
|
2079
|
+
]
|
|
2080
|
+
|
|
2039
2081
|
[[package]]
|
|
2040
2082
|
name = "pyyaml"
|
|
2041
2083
|
version = "6.0.3"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|