Migration Guide

Step-by-step guides for upgrading between major versions of kurigram-addons.

v0.4.x → v0.5.0

Summary: v0.5.0 fixes many concurrency bugs, adds new features (broadcast, DI, i18n, health, SQLiteStorage, testing, per-handler middleware), and changes a few APIs. Most v0.4 code works without changes, but review the breaking items below.

Breaking Changes

ChangeBefore (v0.4)After (v0.5)
PatchHelper.dataAsync property (broken — returned coroutine)await helper.get_data() method
ConversationContext.dataProperty (raised AttributeError)await ctx.get_data(model=None)
get_statistics()Returns Dict[str, Any]Returns PoolStatistics frozen dataclass (use .active_helpers not ["active_helpers"])
Custom storage backendsMust implement new increment(id, amount, *, ttl) abstract method
RateLimitMiddlewareCAS-based counters (broken — always read 0)Rewritten to use storage.increment()

New Deprecations in v0.5

DeprecatedReplacementRemoval
patch() / unpatch()Use KurigramClientv1.0.0
get_circuit_breaker(name)Instantiate AsyncCircuitBreaker directlyv1.0.0

Recommended Middleware Update

v0.5 introduces MiddlewareContext — a single structured object that replaces positional parameter name sniffing. Both conventions work, but the new form is preferred for IDE support:

Before (v0.4)
async def my_middleware(update, client, patch_helper):
    data = await patch_helper.get_data()
    ...
⬇️ becomes ⬇️
After (v0.5 — preferred)
from kurigram_addons import MiddlewareContext

async def my_middleware(ctx: MiddlewareContext):
    data = await ctx.helper.get_data()
    ...

New Features to Adopt

  • SQLiteStorage — persistent FSM without Redis. pip install kurigram-addons[sqlite]
  • DIContainer — register providers, handlers get deps injected by type annotation
  • broadcast() — bulk send to user list with FloodWait handling
  • I18nMiddleware — auto-detect language, inject _() translator
  • HealthServer — pass health_port=8080 to KurigramClient for GET /health
  • @use_middleware() — attach guards to individual handlers instead of globally
  • CallbackData — strongly-typed callback data with pack() / unpack() / filter()
  • Testing moduleMockClient, make_message(), ConversationTester for unit tests
  • State.filter() — replaces StateFilter("Registration:name") with Registration.name.filter()
  • FSM historypush_history() / get_history() state transition audit trail
  • Conversation.timeout — class-level inactivity timeout auto-expires FSM state
  • Router.on_callback_data(pattern) — regex capture groups injected as handler kwargs

v0.3.x → v0.4.x

Import Changes

Everything is now available from a single package:

Before (v0.3.x)
# Keyboards — separate pykeyboard package
from pykeyboard import InlineKeyboard, InlineButton
from pykeyboard import ReplyKeyboard, ReplyButton

# Routing — separate pyrogram_patch package
from pyrogram_patch.router import Router
from pyrogram_patch import patch, StopPropagation

# FSM & Storage — deep imports
from pyrogram_patch.fsm import StateItem, StatesGroup
from pyrogram_patch.fsm.storages import MemoryStorage
from pyrogram_patch.fsm.storages import RedisStorage
⬇️ becomes ⬇️
After (v0.4.x+)
# Everything from one package
from kurigram_addons import (
    # Client
    KurigramClient,

    # Keyboards
    InlineKeyboard, InlineButton,
    ReplyKeyboard, ReplyButton,

    # Routing & FSM
    Router, State, StatesGroup,
    MemoryStorage, RedisStorage,

    # Utilities
    Conversation, ConversationState,
    Menu, parse_command, RateLimit, Depends,
)

Client Setup

The patch() function is replaced by KurigramClient:

Before (v0.3.x)
from pyrogram import Client
from pyrogram_patch import patch

app = Client("my_bot")
patched = patch(app)
⬇️ becomes ⬇️
After (v0.4.x+)
from kurigram_addons import KurigramClient, MemoryStorage

app = KurigramClient(
    "my_bot",
    bot_token="...",
    storage=MemoryStorage(),
    auto_flood_wait=True,
)
app.run()

Breaking Changes in v0.4.1

ChangeBeforeAfter
parse_commandReturns empty dict on missing argsRaises CommandParseError
Menu._registryStrong references (leaks)WeakValueDictionary (auto-cleanup)
RateLimit bucketsUnbounded defaultdictBounded OrderedDict (max 10k, LRU)

Backward Compatibility

The old from pykeyboard import ... and from pyrogram_patch import ... paths still work. However, we recommend migrating to from kurigram_addons import ... for:

  • Simpler imports — one package instead of three
  • Consistent API — access to new features like KurigramClient, lifecycle hooks, and Conversation
  • Future-proof — legacy import paths will be removed in v1.0.0