Code-Society-Lab / Code-Society-Lab/matrixpy

Command Overload

Open
#94 0 comments 0 reactions 0 assignees View on GitHub
feature
Dominant language
Python
Stars
14
Forks
7
Avg merge
8d 19h
Merged PRs (30d)
5

Description

There is currently no way to register multiple implementations of the same command. Users who want to vary behaviour based on the number of arguments or their types must branch manually inside a single handler.

The idea is to introduce an `@bot.overload()` decorator that registers an alternate signature for an existing command. Rather than a separate structure, `_commands` itself would become two-level: `Dict[str, Dict[Signature + TypeHints, Command]]`. At dispatch time the bot looks up by name, then walks the inner dict to find the entry whose signature (parameter count and declared types) best matches the parsed arguments.

**Proposed API**
```python
@bot.command()
async def greet(ctx, name: str):
await ctx.reply(f"Hello {name}!")

@bot.overload()
async def greet(ctx):
await ctx.reply("Hello World!")
```

```python
@bot.command("roman")
async def roman_converter(ctx, number: str):
result = roman_to_decimal(number)
await ctx.reply(f"Roman -> Decimal: {result}!")

@bot.overload()
async def roman_converter(ctx, number: int):
result = decimal_to_roman(number)
await ctx.reply(f"Decimal -> Roman: {result}!")
```

```
!roman VI → Roman -> Decimal: 6!
!roman 6 → Decimal -> Roman: VI!
```

**Proposed Solution**
`_commands` currently maps `str and Command`, so the type changes to `Dict[str, Dict[tuple[type, ...], Command]]`. The inner key is a tuple of parameter types derived from what `Command` already computes in its `callback` setter, `tuple(type_hints.get(p.name, str) for p in params)`, with `ctx` already excluded. `register_command` raises `AlreadyRegisteredError` on duplicate names today, so both it and any callers that do a plain `_commands[name]` lookup need to be updated.

A few things worth particular attention during implementation: unannotated parameters default to `str` (matching existing `_convert_type` behaviour), meaning `(ctx, name)` and `(ctx, name: str)` would produce the same key and collide, registration should raise an error in that case. `*args` (VAR_POSITIONAL) doesn't map cleanly to a fixed-length tuple and may need a sentinel value or be excluded from overload dispatch entirely in a first version. Specific types (`int`, `float`, custom resolvers) must be tried before `str` regardless of registration order.

⚠️ There is still lots of unknown to be discussed. Anyone working on this issue should propose a complete solution before implementing it.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.