matrix-python 1.4.8a0__py3-none-any.whl → 1.4.9a0__py3-none-any.whl

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.
matrix/_version.py CHANGED
@@ -18,7 +18,7 @@ version_tuple: tuple[int | str, ...]
18
18
  commit_id: str | None
19
19
  __commit_id__: str | None
20
20
 
21
- __version__ = version = '1.4.8a0'
22
- __version_tuple__ = version_tuple = (1, 4, 8, 'a0')
21
+ __version__ = version = '1.4.9a0'
22
+ __version_tuple__ = version_tuple = (1, 4, 9, 'a0')
23
23
 
24
24
  __commit_id__ = commit_id = None
matrix/extension.py CHANGED
@@ -1,21 +1,31 @@
1
1
  import inspect
2
2
  import logging
3
- from typing import Callable, Optional
3
+ from typing import Callable
4
4
 
5
5
  from matrix.protocols import BotLike
6
6
  from matrix.registry import Registry
7
+ from matrix.config import Config
7
8
  from matrix.room import Room
8
9
 
9
10
  logger = logging.getLogger(__name__)
10
11
 
11
12
 
12
13
  class Extension(Registry):
13
- def __init__(self, name: str, prefix: Optional[str] = None) -> None:
14
+ def __init__(self, name: str, prefix: str | None = None) -> None:
14
15
  super().__init__(name, prefix=prefix)
15
16
 
16
- self.bot: Optional[BotLike] = None
17
- self._on_load: Optional[Callable] = None
18
- self._on_unload: Optional[Callable] = None
17
+ self._bot: BotLike | None = None
18
+ self._on_load: Callable | None = None
19
+ self._on_unload: Callable | None = None
20
+
21
+ @property
22
+ def bot(self) -> BotLike:
23
+ assert self._bot, "Extension is not loaded"
24
+ return self._bot
25
+
26
+ @property
27
+ def config(self) -> Config:
28
+ return self.bot.config
19
29
 
20
30
  def get_room(self, room_id: str) -> Room | None:
21
31
  """Retrieve a `Room` instance by its Matrix room ID.
@@ -31,12 +41,10 @@ class Extension(Registry):
31
41
  print(room.name)
32
42
  ```
33
43
  """
34
- if self.bot is None:
35
- raise RuntimeError("Extension is not loaded")
36
44
  return self.bot.get_room(room_id)
37
45
 
38
46
  def load(self, bot: BotLike) -> None:
39
- self.bot = bot
47
+ self._bot = bot
40
48
 
41
49
  if self._on_load:
42
50
  self._on_load()
@@ -59,7 +67,7 @@ class Extension(Registry):
59
67
  return func
60
68
 
61
69
  def unload(self) -> None:
62
- self.bot = None
70
+ self._bot = None
63
71
 
64
72
  if self._on_unload:
65
73
  self._on_unload()
matrix/protocols.py CHANGED
@@ -1,9 +1,13 @@
1
1
  from typing import Protocol
2
2
 
3
+ from matrix.config import Config
3
4
  from matrix.room import Room
4
5
 
5
6
 
6
7
  class BotLike(Protocol):
7
8
  prefix: str | None
8
9
 
10
+ @property
11
+ def config(self) -> Config: ...
12
+
9
13
  def get_room(self, room_id: str) -> Room | None: ...
matrix/registry.py CHANGED
@@ -2,7 +2,20 @@ import inspect
2
2
  import logging
3
3
 
4
4
  from collections import defaultdict
5
- from typing import Any, Callable, Coroutine, Optional, Type, Union, Dict, List
5
+ from typing import (
6
+ TypeVar,
7
+ Any,
8
+ Callable,
9
+ Coroutine,
10
+ Literal,
11
+ Optional,
12
+ Type,
13
+ Union,
14
+ Dict,
15
+ List,
16
+ cast,
17
+ overload,
18
+ )
6
19
 
7
20
  from nio import (
8
21
  Event,
@@ -25,6 +38,8 @@ GroupCallable = Callable[[Callable[..., Coroutine[Any, Any, Any]]], Group]
25
38
  ErrorCallback = Callable[[Exception], Coroutine]
26
39
  CommandErrorCallback = Callable[[Context, Exception], Coroutine[Any, Any, Any]]
27
40
 
41
+ F = TypeVar("F", ErrorCallback, CommandErrorCallback)
42
+
28
43
 
29
44
  class Registry:
30
45
  """
@@ -355,43 +370,91 @@ class Registry:
355
370
 
356
371
  return wrapper
357
372
 
373
+ @overload
358
374
  def error(
359
- self, exception: Optional[type[Exception]] = None
360
- ) -> Callable[[ErrorCallback], ErrorCallback]:
375
+ self,
376
+ exception: Optional[type[Exception]] = None,
377
+ *,
378
+ context: Literal[True],
379
+ ) -> Callable[[CommandErrorCallback], CommandErrorCallback]: ...
380
+
381
+ @overload
382
+ def error(
383
+ self,
384
+ exception: Optional[type[Exception]] = None,
385
+ *,
386
+ context: Literal[False] = ...,
387
+ ) -> Callable[[ErrorCallback], ErrorCallback]: ...
388
+
389
+ def error(
390
+ self,
391
+ exception: Optional[type[Exception]] = None,
392
+ *,
393
+ context: bool = False,
394
+ ) -> Union[
395
+ Callable[[ErrorCallback], ErrorCallback],
396
+ Callable[[CommandErrorCallback], CommandErrorCallback],
397
+ ]:
361
398
  """Decorator to register an error handler.
362
399
 
363
400
  If an exception type is provided, the handler is only invoked for
364
401
  that specific exception. If omitted, the handler acts as a generic
365
402
  fallback for any unhandled error.
366
403
 
404
+ Set ``context=True`` to receive the command context alongside the error,
405
+ useful for command-specific errors where you want to reply to the user.
406
+
367
407
  ## Example
368
408
 
369
409
  ```python
370
410
  @bot.error(ValueError)
371
411
  async def on_value_error(error):
372
- await room.send(f"Bad value: {error}")
412
+ pass
373
413
 
374
414
  @bot.error()
375
415
  async def on_any_error(error):
376
- await room.send(f"Something went wrong: {error}")
416
+ pass
417
+
418
+ @bot.error(CommandNotFoundError, context=True)
419
+ async def on_command_not_found(ctx, error):
420
+ await ctx.reply("Command not found!")
377
421
  ```
378
422
  """
379
423
 
380
- if not exception:
381
- exception = Exception
382
-
383
- def wrapper(func: ErrorCallback) -> ErrorCallback:
424
+ def wrapper(
425
+ func: F,
426
+ ) -> F:
384
427
  if not inspect.iscoroutinefunction(func):
385
428
  raise TypeError("Error handlers must be coroutines")
386
429
 
387
- self._error_handlers[exception] = func
430
+ if context:
431
+ self._register_command_error(
432
+ cast(CommandErrorCallback, func), exception
433
+ )
434
+ else:
435
+ self._register_error(cast(ErrorCallback, func), exception)
388
436
 
389
437
  logger.debug(
390
438
  "registered error handler '%s' on %s",
391
439
  func.__name__,
392
440
  type(self).__name__,
393
441
  )
394
-
395
442
  return func
396
443
 
397
444
  return wrapper
445
+
446
+ def _register_error(
447
+ self, func: ErrorCallback, exception: Optional[type[Exception]] = None
448
+ ) -> None:
449
+ if not exception:
450
+ exception = Exception
451
+ self._error_handlers[exception] = func
452
+
453
+ def _register_command_error(
454
+ self,
455
+ func: CommandErrorCallback,
456
+ exception: Optional[type[Exception]] = None,
457
+ ) -> None:
458
+ if not exception:
459
+ exception = Exception
460
+ self._command_error_handlers[exception] = func
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: matrix-python
3
- Version: 1.4.8a0
3
+ Version: 1.4.9a0
4
4
  Summary: An easy-to-use Matrix bot framework designed for quick development and minimal setup
5
5
  Author: Simon Roy, Chris Dedman Rollet
6
6
  Maintainer-email: Code Society Lab <admin@codesociety.xyz>
@@ -1,5 +1,5 @@
1
1
  matrix/__init__.py,sha256=g8yEFjELnnwlvOKns-Ug6LgOezkjAFZ-Opt7esbBHKg,728
2
- matrix/_version.py,sha256=Sp0Aavn8Gz-jkQehzIA2xsa-Il-CUVey1i9m5oSJ344,528
2
+ matrix/_version.py,sha256=IJ3HlP4Svp0RN0mpe6HhSO9QSg0hWZBUdUwTFQyE4bY,528
3
3
  matrix/bot.py,sha256=tbcn1Ra025I9plM-gf0NpzPKSTBlYe0_L8_RLO8w9GM,11984
4
4
  matrix/checks.py,sha256=F_7432_OcFO-im4fRAj62MUsyv1mXywT4OsGC_7xbBQ,486
5
5
  matrix/command.py,sha256=GrP3WsT07sKehGX7PHfnT7gRX22d99877VPd0X2ViEw,10514
@@ -7,19 +7,19 @@ matrix/config.py,sha256=JW_BBs-msIhtv1AGebZumLsx4td-Gp-NZaNYPJxRsEo,3680
7
7
  matrix/content.py,sha256=z5_E2rTvHsODE52OiDkhDHNQAryx5NLhyHjBb65Xe-U,3853
8
8
  matrix/context.py,sha256=-CbxY-LtK9-jgHERhvJH73B3SpO-Uk5ty0j1TMKfzuI,4032
9
9
  matrix/errors.py,sha256=HKGb5NUeFuZvieXgpLlVSmUxK4jpA0ODuiPQqQlbQTE,1676
10
- matrix/extension.py,sha256=RbCx58CdRXF8kGUgS-ec1aZdd-K5hQedhCCQ0-YR4Vg,2272
10
+ matrix/extension.py,sha256=5f6pW_6D8wwN5qKhnQRkCWWDkkQw9t47j5XRNZNsyGQ,2399
11
11
  matrix/group.py,sha256=TRIX7PE3lcB2ZWu3xY2W2OAmE_a8-i2zHNBYnX5uj28,3691
12
12
  matrix/message.py,sha256=w6pu86goylxdrX5fgXPUMB_tW0bOFIk6tKy6qkXTjl4,5136
13
- matrix/protocols.py,sha256=nFb4tLanwtrKWoIhZ96xMwXPjD3RF5ITca_yXtakXC4,166
13
+ matrix/protocols.py,sha256=pIkHL4yuenvxh-gFhRPudCHJcfMBRxq2lUL5S5sPxpM,250
14
14
  matrix/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
15
- matrix/registry.py,sha256=PgdmbBADS-yqdFdj9x3QSsVfefx8Li848CU_UBbqCLQ,12646
15
+ matrix/registry.py,sha256=OiEWaO66k4QOnOPCaXL5Ys-_TnVioI4q5ulyRP_fGS4,14202
16
16
  matrix/room.py,sha256=PBuMWQo8mKy2d2XIeMbBlVBTnnqZjOPPGpKLp4K1AVM,14038
17
17
  matrix/scheduler.py,sha256=EXsL9i8IDXhcpdW8lti0BR5XcIgkmud4iwOPaqcE9Gw,1727
18
18
  matrix/types.py,sha256=UFjC7p8RAf7piEPvp2X3NuWdqBwkM9Yc3He7KWb9icc,384
19
19
  matrix/help/__init__.py,sha256=1u7V7T_-VgYDeQCTXsc4y8Fo-8gJhOqYJq2U3cUjMWg,168
20
20
  matrix/help/help_command.py,sha256=xCLmKklw74LEMjbUfgQR9eaPMFvi3sPtDw2n2pnAnVQ,12800
21
21
  matrix/help/pagination.py,sha256=sJk0wC46sFHf7xl7WsGRAUc4FC7b9hPqmwQDmvcjwgM,2717
22
- matrix_python-1.4.8a0.dist-info/METADATA,sha256=Cw_QAKOVIvymFvEELdhYf72O0UkQOSk21KMpc01KAOY,5421
23
- matrix_python-1.4.8a0.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
24
- matrix_python-1.4.8a0.dist-info/top_level.txt,sha256=BvHVM9c7-5SLzg-1OCRpHKgqAubWhRN1e38e6coHs-g,7
25
- matrix_python-1.4.8a0.dist-info/RECORD,,
22
+ matrix_python-1.4.9a0.dist-info/METADATA,sha256=brnqebUw6xsHqIDXvyCZuyMVWzgGKy70BSjFoM2NNm8,5421
23
+ matrix_python-1.4.9a0.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
24
+ matrix_python-1.4.9a0.dist-info/top_level.txt,sha256=BvHVM9c7-5SLzg-1OCRpHKgqAubWhRN1e38e6coHs-g,7
25
+ matrix_python-1.4.9a0.dist-info/RECORD,,