matrix-python 1.4.6a0__tar.gz → 1.4.8a0__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.
Files changed (65) hide show
  1. matrix_python-1.4.8a0/LICENSE +21 -0
  2. matrix_python-1.4.8a0/PKG-INFO +128 -0
  3. {matrix_python-1.4.6a0 → matrix_python-1.4.8a0}/README.md +2 -1
  4. {matrix_python-1.4.6a0 → matrix_python-1.4.8a0}/matrix/_version.py +3 -3
  5. {matrix_python-1.4.6a0 → matrix_python-1.4.8a0}/matrix/bot.py +11 -11
  6. matrix_python-1.4.8a0/matrix/py.typed +0 -0
  7. {matrix_python-1.4.6a0 → matrix_python-1.4.8a0}/matrix/registry.py +5 -5
  8. matrix_python-1.4.8a0/matrix_python.egg-info/PKG-INFO +128 -0
  9. {matrix_python-1.4.6a0 → matrix_python-1.4.8a0}/matrix_python.egg-info/SOURCES.txt +1 -0
  10. {matrix_python-1.4.6a0 → matrix_python-1.4.8a0}/pyproject.toml +3 -0
  11. {matrix_python-1.4.6a0 → matrix_python-1.4.8a0}/tests/test_bot.py +19 -25
  12. {matrix_python-1.4.6a0 → matrix_python-1.4.8a0}/tests/test_registry.py +0 -10
  13. matrix_python-1.4.6a0/LICENSE +0 -674
  14. matrix_python-1.4.6a0/PKG-INFO +0 -781
  15. matrix_python-1.4.6a0/matrix_python.egg-info/PKG-INFO +0 -781
  16. {matrix_python-1.4.6a0 → matrix_python-1.4.8a0}/.github/dependabot.yml +0 -0
  17. {matrix_python-1.4.6a0 → matrix_python-1.4.8a0}/.github/workflows/CODEOWNERS +0 -0
  18. {matrix_python-1.4.6a0 → matrix_python-1.4.8a0}/.github/workflows/codeql.yml +0 -0
  19. {matrix_python-1.4.6a0 → matrix_python-1.4.8a0}/.github/workflows/publish.yml +0 -0
  20. {matrix_python-1.4.6a0 → matrix_python-1.4.8a0}/.github/workflows/scorecard.yml +0 -0
  21. {matrix_python-1.4.6a0 → matrix_python-1.4.8a0}/.github/workflows/tests.yml +0 -0
  22. {matrix_python-1.4.6a0 → matrix_python-1.4.8a0}/.gitignore +0 -0
  23. {matrix_python-1.4.6a0 → matrix_python-1.4.8a0}/CODE_OF_CONDUCT.md +0 -0
  24. {matrix_python-1.4.6a0 → matrix_python-1.4.8a0}/CONTRIBUTING.md +0 -0
  25. {matrix_python-1.4.6a0 → matrix_python-1.4.8a0}/examples/README.md +0 -0
  26. {matrix_python-1.4.6a0 → matrix_python-1.4.8a0}/examples/checks.py +0 -0
  27. {matrix_python-1.4.6a0 → matrix_python-1.4.8a0}/examples/config.yaml +0 -0
  28. {matrix_python-1.4.6a0 → matrix_python-1.4.8a0}/examples/cooldown.py +0 -0
  29. {matrix_python-1.4.6a0 → matrix_python-1.4.8a0}/examples/error_handling.py +0 -0
  30. {matrix_python-1.4.6a0 → matrix_python-1.4.8a0}/examples/extension.py +0 -0
  31. {matrix_python-1.4.6a0 → matrix_python-1.4.8a0}/examples/ping.py +0 -0
  32. {matrix_python-1.4.6a0 → matrix_python-1.4.8a0}/examples/reaction.py +0 -0
  33. {matrix_python-1.4.6a0 → matrix_python-1.4.8a0}/examples/scheduler.py +0 -0
  34. {matrix_python-1.4.6a0 → matrix_python-1.4.8a0}/matrix/__init__.py +0 -0
  35. {matrix_python-1.4.6a0 → matrix_python-1.4.8a0}/matrix/checks.py +0 -0
  36. {matrix_python-1.4.6a0 → matrix_python-1.4.8a0}/matrix/command.py +0 -0
  37. {matrix_python-1.4.6a0 → matrix_python-1.4.8a0}/matrix/config.py +0 -0
  38. {matrix_python-1.4.6a0 → matrix_python-1.4.8a0}/matrix/content.py +0 -0
  39. {matrix_python-1.4.6a0 → matrix_python-1.4.8a0}/matrix/context.py +0 -0
  40. {matrix_python-1.4.6a0 → matrix_python-1.4.8a0}/matrix/errors.py +0 -0
  41. {matrix_python-1.4.6a0 → matrix_python-1.4.8a0}/matrix/extension.py +0 -0
  42. {matrix_python-1.4.6a0 → matrix_python-1.4.8a0}/matrix/group.py +0 -0
  43. {matrix_python-1.4.6a0 → matrix_python-1.4.8a0}/matrix/help/__init__.py +0 -0
  44. {matrix_python-1.4.6a0 → matrix_python-1.4.8a0}/matrix/help/help_command.py +0 -0
  45. {matrix_python-1.4.6a0 → matrix_python-1.4.8a0}/matrix/help/pagination.py +0 -0
  46. {matrix_python-1.4.6a0 → matrix_python-1.4.8a0}/matrix/message.py +0 -0
  47. {matrix_python-1.4.6a0 → matrix_python-1.4.8a0}/matrix/protocols.py +0 -0
  48. {matrix_python-1.4.6a0 → matrix_python-1.4.8a0}/matrix/room.py +0 -0
  49. {matrix_python-1.4.6a0 → matrix_python-1.4.8a0}/matrix/scheduler.py +0 -0
  50. {matrix_python-1.4.6a0 → matrix_python-1.4.8a0}/matrix/types.py +0 -0
  51. {matrix_python-1.4.6a0 → matrix_python-1.4.8a0}/matrix_python.egg-info/dependency_links.txt +0 -0
  52. {matrix_python-1.4.6a0 → matrix_python-1.4.8a0}/matrix_python.egg-info/requires.txt +0 -0
  53. {matrix_python-1.4.6a0 → matrix_python-1.4.8a0}/matrix_python.egg-info/top_level.txt +0 -0
  54. {matrix_python-1.4.6a0 → matrix_python-1.4.8a0}/mypy.ini +0 -0
  55. {matrix_python-1.4.6a0 → matrix_python-1.4.8a0}/setup.cfg +0 -0
  56. {matrix_python-1.4.6a0 → matrix_python-1.4.8a0}/tests/help/test_default_help_command.py +0 -0
  57. {matrix_python-1.4.6a0 → matrix_python-1.4.8a0}/tests/help/test_help_command.py +0 -0
  58. {matrix_python-1.4.6a0 → matrix_python-1.4.8a0}/tests/help/test_pagination.py +0 -0
  59. {matrix_python-1.4.6a0 → matrix_python-1.4.8a0}/tests/test_command.py +0 -0
  60. {matrix_python-1.4.6a0 → matrix_python-1.4.8a0}/tests/test_config.py +0 -0
  61. {matrix_python-1.4.6a0 → matrix_python-1.4.8a0}/tests/test_context.py +0 -0
  62. {matrix_python-1.4.6a0 → matrix_python-1.4.8a0}/tests/test_extension.py +0 -0
  63. {matrix_python-1.4.6a0 → matrix_python-1.4.8a0}/tests/test_group.py +0 -0
  64. {matrix_python-1.4.6a0 → matrix_python-1.4.8a0}/tests/test_message.py +0 -0
  65. {matrix_python-1.4.6a0 → matrix_python-1.4.8a0}/tests/test_room.py +0 -0
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2021 Sebastián Ramírez
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
@@ -0,0 +1,128 @@
1
+ Metadata-Version: 2.4
2
+ Name: matrix-python
3
+ Version: 1.4.8a0
4
+ Summary: An easy-to-use Matrix bot framework designed for quick development and minimal setup
5
+ Author: Simon Roy, Chris Dedman Rollet
6
+ Maintainer-email: Code Society Lab <admin@codesociety.xyz>
7
+ License: The MIT License (MIT)
8
+
9
+ Copyright (c) 2021 Sebastián Ramírez
10
+
11
+ Permission is hereby granted, free of charge, to any person obtaining a copy
12
+ of this software and associated documentation files (the "Software"), to deal
13
+ in the Software without restriction, including without limitation the rights
14
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15
+ copies of the Software, and to permit persons to whom the Software is
16
+ furnished to do so, subject to the following conditions:
17
+
18
+ The above copyright notice and this permission notice shall be included in
19
+ all copies or substantial portions of the Software.
20
+
21
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
27
+ THE SOFTWARE.
28
+ Project-URL: Homepage, https://codesociety.xyz
29
+ Project-URL: Source, https://github.com/Code-Society-Lab/matrixpy
30
+ Project-URL: Issues, https://github.com/Code-Society-Lab/matrixpy/issues
31
+ Requires-Python: >=3.10
32
+ Description-Content-Type: text/markdown
33
+ Requires-Dist: matrix-nio==0.25.2
34
+ Requires-Dist: logger
35
+ Requires-Dist: PyYAML==6.0.3
36
+ Requires-Dist: markdown==3.10.2
37
+ Requires-Dist: APScheduler==3.11.2
38
+ Requires-Dist: envyaml==1.10.211231
39
+ Provides-Extra: dev
40
+ Requires-Dist: pytest==9.0.3; extra == "dev"
41
+ Requires-Dist: pytest-asyncio==1.3.0; extra == "dev"
42
+ Requires-Dist: black==26.3.1; extra == "dev"
43
+ Requires-Dist: mypy==1.20.0; extra == "dev"
44
+ Requires-Dist: types-PyYAML==6.0.12.20260408; extra == "dev"
45
+ Requires-Dist: types-Markdown==3.10.2.20260408; extra == "dev"
46
+
47
+ <div align="center">
48
+ <em>A simple, developer-friendly library to create powerful <a href="https://matrix.org">Matrix</a> bots.</em>
49
+ </div>
50
+
51
+ <img alt="image" src="https://github.com/user-attachments/assets/d9140a9e-27fa-44e4-a5ca-87ee7bbf868f" />
52
+
53
+ <hr />
54
+
55
+ [![Static Badge](https://img.shields.io/badge/%F0%9F%93%9A-Documentation-%235c5c5c)](https://github.com/Code-Society-Lab/matrixpy/wiki)
56
+ [![Join Discord](https://discordapp.com/api/guilds/823178343943897088/widget.png?style=shield)](https://discord.gg/code-society-823178343943897088)
57
+ [![Join Matrix](https://img.shields.io/matrix/codesociety%3Amatrix.org?logo=matrix&label=%20&labelColor=%23202020&color=%23202020)](https://matrix.to/#/%23codesociety:matrix.org )
58
+ [![Tests](https://github.com/Code-Society-Lab/matrixpy/actions/workflows/tests.yml/badge.svg)](https://github.com/Code-Society-Lab/matrixpy/actions/workflows/tests.yml)
59
+ [![CodeQL Advanced](https://github.com/Code-Society-Lab/matrixpy/actions/workflows/codeql.yml/badge.svg)](https://github.com/Code-Society-Lab/matrixpy/actions/workflows/codeql.yml)
60
+ [![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/Code-Society-Lab/matrixpy/badge)](https://securityscorecards.dev/viewer/?uri=github.com/Code-Society-Lab/matrixpy)
61
+
62
+ Matrix.py is a lightweight and intuitive Python library to build bots on
63
+ the [Matrix protocol](https://matrix.org). It provides a clean,
64
+ decorator-based API similar to popular event-driven frameworks, allowing
65
+ developers to focus on behavior rather than boilerplate.
66
+
67
+ #### Key Features
68
+
69
+ - Minimal setup, easy to extend
70
+ - Event-driven API using async/await
71
+ - Clean command registration
72
+ - Automatic event handler registration
73
+ - Built on [matrix-nio](https://github.com/matrix-nio/matrix-nio)
74
+
75
+ # Quickstart
76
+
77
+ **Requirements**
78
+
79
+ - Python 3.10+
80
+
81
+ ```
82
+ pip install matrix-python
83
+ ```
84
+
85
+ If you plan on contributing to matrix.py, we recommend to install the development libraries:
86
+
87
+ ```
88
+ pip install -e .[dev]
89
+ ```
90
+
91
+ *Note*: It is recommended to use
92
+ a [virtual environment](https://packaging.python.org/en/latest/guides/installing-using-pip-and-virtual-environments/)
93
+ when installing python packages.
94
+
95
+ ```python
96
+ from matrix import Bot, Context
97
+
98
+ bot = Bot()
99
+
100
+
101
+ @bot.command("ping")
102
+ async def ping(ctx: Context):
103
+ await ctx.reply("Pong!")
104
+
105
+
106
+ bot.start(config="config.yml")
107
+ ```
108
+
109
+ [Documentation](https://github.com/Code-Society-Lab/matrixpy/wiki) - [Examples](https://github.com/Code-Society-Lab/matrixpy/tree/main/examples)
110
+
111
+ # Contributing
112
+
113
+ We welcome everyone to contribute!
114
+
115
+ Whether it's fixing bugs, suggesting features, or improving the docs - every bit helps.
116
+
117
+ - Submit an issue
118
+ - Open a pull request
119
+ - Or just hop into our [Matrix](https://matrix.to/#/%23codesociety:matrix.org)
120
+ or [Discord](https://discord.gg/code-society-823178343943897088) server and say hi!
121
+
122
+ If you intend to contribute, please read the [CONTRIBUTING.md](./CONTRIBUTING.md) first. Additionally, **every
123
+ contributor** is expected to follow the [code of conduct](./CODE_OF_CONDUCT.md).
124
+
125
+ # License
126
+
127
+ This project is licensed under the terms
128
+ of [MIT license](https://github.com/Code-Society-Lab/matrixpy/blob/main/LICENSE).
@@ -78,4 +78,5 @@ contributor** is expected to follow the [code of conduct](./CODE_OF_CONDUCT.md).
78
78
 
79
79
  # License
80
80
 
81
- matrix.py is released under [GPL-3.0](https://opensource.org/license/gpl-3-0)
81
+ This project is licensed under the terms
82
+ of [MIT license](https://github.com/Code-Society-Lab/matrixpy/blob/main/LICENSE).
@@ -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.6a0'
22
- __version_tuple__ = version_tuple = (1, 4, 6, 'a0')
21
+ __version__ = version = '1.4.8a0'
22
+ __version_tuple__ = version_tuple = (1, 4, 8, 'a0')
23
23
 
24
- __commit_id__ = commit_id = 'g9d2b531d5'
24
+ __commit_id__ = commit_id = 'g16bd59854'
@@ -184,10 +184,6 @@ class Bot(Registry):
184
184
  await handler(error)
185
185
  return
186
186
 
187
- if self._fallback_error_handler:
188
- await self._fallback_error_handler(error)
189
- return
190
-
191
187
  await self._dispatch("on_error", error)
192
188
 
193
189
  async def on_command(self, _ctx: Context) -> None:
@@ -326,15 +322,19 @@ class Bot(Registry):
326
322
 
327
323
  async def _process_commands(self, room: Room, event: Event) -> None:
328
324
  """Parse and execute commands"""
329
- ctx = await self._build_context(room, event)
325
+ try:
326
+ ctx = await self._build_context(room, event)
330
327
 
331
- if ctx.command:
332
- for check in self._checks:
333
- if not await check(ctx):
334
- raise CheckError(ctx.command, check)
328
+ if ctx.command:
329
+ for check in self._checks:
330
+ if not await check(ctx):
331
+ raise CheckError(ctx.command, check)
335
332
 
336
- await self._on_command(ctx)
337
- await ctx.command(ctx)
333
+ await self._on_command(ctx)
334
+ await ctx.command(ctx)
335
+ except Exception as error:
336
+ ctx = Context(bot=self, room=room, event=event)
337
+ await self._on_command_error(ctx, error)
338
338
 
339
339
  async def _build_context(self, matrix_room: Room, event: Event) -> Context:
340
340
  room = self.get_room(matrix_room.room_id)
File without changes
@@ -65,7 +65,6 @@ class Registry:
65
65
 
66
66
  self._event_handlers: Dict[Type[Event], List[Callback]] = defaultdict(list)
67
67
  self._hook_handlers: Dict[str, List[Callback]] = defaultdict(list)
68
- self._fallback_error_handler: Optional[ErrorCallback] = None
69
68
  self._error_handlers: Dict[type[Exception], ErrorCallback] = {}
70
69
  self._command_error_handlers: Dict[type[Exception], CommandErrorCallback] = {}
71
70
 
@@ -378,14 +377,15 @@ class Registry:
378
377
  ```
379
378
  """
380
379
 
380
+ if not exception:
381
+ exception = Exception
382
+
381
383
  def wrapper(func: ErrorCallback) -> ErrorCallback:
382
384
  if not inspect.iscoroutinefunction(func):
383
385
  raise TypeError("Error handlers must be coroutines")
384
386
 
385
- if exception:
386
- self._error_handlers[exception] = func
387
- else:
388
- self._fallback_error_handler = func
387
+ self._error_handlers[exception] = func
388
+
389
389
  logger.debug(
390
390
  "registered error handler '%s' on %s",
391
391
  func.__name__,
@@ -0,0 +1,128 @@
1
+ Metadata-Version: 2.4
2
+ Name: matrix-python
3
+ Version: 1.4.8a0
4
+ Summary: An easy-to-use Matrix bot framework designed for quick development and minimal setup
5
+ Author: Simon Roy, Chris Dedman Rollet
6
+ Maintainer-email: Code Society Lab <admin@codesociety.xyz>
7
+ License: The MIT License (MIT)
8
+
9
+ Copyright (c) 2021 Sebastián Ramírez
10
+
11
+ Permission is hereby granted, free of charge, to any person obtaining a copy
12
+ of this software and associated documentation files (the "Software"), to deal
13
+ in the Software without restriction, including without limitation the rights
14
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15
+ copies of the Software, and to permit persons to whom the Software is
16
+ furnished to do so, subject to the following conditions:
17
+
18
+ The above copyright notice and this permission notice shall be included in
19
+ all copies or substantial portions of the Software.
20
+
21
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
27
+ THE SOFTWARE.
28
+ Project-URL: Homepage, https://codesociety.xyz
29
+ Project-URL: Source, https://github.com/Code-Society-Lab/matrixpy
30
+ Project-URL: Issues, https://github.com/Code-Society-Lab/matrixpy/issues
31
+ Requires-Python: >=3.10
32
+ Description-Content-Type: text/markdown
33
+ Requires-Dist: matrix-nio==0.25.2
34
+ Requires-Dist: logger
35
+ Requires-Dist: PyYAML==6.0.3
36
+ Requires-Dist: markdown==3.10.2
37
+ Requires-Dist: APScheduler==3.11.2
38
+ Requires-Dist: envyaml==1.10.211231
39
+ Provides-Extra: dev
40
+ Requires-Dist: pytest==9.0.3; extra == "dev"
41
+ Requires-Dist: pytest-asyncio==1.3.0; extra == "dev"
42
+ Requires-Dist: black==26.3.1; extra == "dev"
43
+ Requires-Dist: mypy==1.20.0; extra == "dev"
44
+ Requires-Dist: types-PyYAML==6.0.12.20260408; extra == "dev"
45
+ Requires-Dist: types-Markdown==3.10.2.20260408; extra == "dev"
46
+
47
+ <div align="center">
48
+ <em>A simple, developer-friendly library to create powerful <a href="https://matrix.org">Matrix</a> bots.</em>
49
+ </div>
50
+
51
+ <img alt="image" src="https://github.com/user-attachments/assets/d9140a9e-27fa-44e4-a5ca-87ee7bbf868f" />
52
+
53
+ <hr />
54
+
55
+ [![Static Badge](https://img.shields.io/badge/%F0%9F%93%9A-Documentation-%235c5c5c)](https://github.com/Code-Society-Lab/matrixpy/wiki)
56
+ [![Join Discord](https://discordapp.com/api/guilds/823178343943897088/widget.png?style=shield)](https://discord.gg/code-society-823178343943897088)
57
+ [![Join Matrix](https://img.shields.io/matrix/codesociety%3Amatrix.org?logo=matrix&label=%20&labelColor=%23202020&color=%23202020)](https://matrix.to/#/%23codesociety:matrix.org )
58
+ [![Tests](https://github.com/Code-Society-Lab/matrixpy/actions/workflows/tests.yml/badge.svg)](https://github.com/Code-Society-Lab/matrixpy/actions/workflows/tests.yml)
59
+ [![CodeQL Advanced](https://github.com/Code-Society-Lab/matrixpy/actions/workflows/codeql.yml/badge.svg)](https://github.com/Code-Society-Lab/matrixpy/actions/workflows/codeql.yml)
60
+ [![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/Code-Society-Lab/matrixpy/badge)](https://securityscorecards.dev/viewer/?uri=github.com/Code-Society-Lab/matrixpy)
61
+
62
+ Matrix.py is a lightweight and intuitive Python library to build bots on
63
+ the [Matrix protocol](https://matrix.org). It provides a clean,
64
+ decorator-based API similar to popular event-driven frameworks, allowing
65
+ developers to focus on behavior rather than boilerplate.
66
+
67
+ #### Key Features
68
+
69
+ - Minimal setup, easy to extend
70
+ - Event-driven API using async/await
71
+ - Clean command registration
72
+ - Automatic event handler registration
73
+ - Built on [matrix-nio](https://github.com/matrix-nio/matrix-nio)
74
+
75
+ # Quickstart
76
+
77
+ **Requirements**
78
+
79
+ - Python 3.10+
80
+
81
+ ```
82
+ pip install matrix-python
83
+ ```
84
+
85
+ If you plan on contributing to matrix.py, we recommend to install the development libraries:
86
+
87
+ ```
88
+ pip install -e .[dev]
89
+ ```
90
+
91
+ *Note*: It is recommended to use
92
+ a [virtual environment](https://packaging.python.org/en/latest/guides/installing-using-pip-and-virtual-environments/)
93
+ when installing python packages.
94
+
95
+ ```python
96
+ from matrix import Bot, Context
97
+
98
+ bot = Bot()
99
+
100
+
101
+ @bot.command("ping")
102
+ async def ping(ctx: Context):
103
+ await ctx.reply("Pong!")
104
+
105
+
106
+ bot.start(config="config.yml")
107
+ ```
108
+
109
+ [Documentation](https://github.com/Code-Society-Lab/matrixpy/wiki) - [Examples](https://github.com/Code-Society-Lab/matrixpy/tree/main/examples)
110
+
111
+ # Contributing
112
+
113
+ We welcome everyone to contribute!
114
+
115
+ Whether it's fixing bugs, suggesting features, or improving the docs - every bit helps.
116
+
117
+ - Submit an issue
118
+ - Open a pull request
119
+ - Or just hop into our [Matrix](https://matrix.to/#/%23codesociety:matrix.org)
120
+ or [Discord](https://discord.gg/code-society-823178343943897088) server and say hi!
121
+
122
+ If you intend to contribute, please read the [CONTRIBUTING.md](./CONTRIBUTING.md) first. Additionally, **every
123
+ contributor** is expected to follow the [code of conduct](./CODE_OF_CONDUCT.md).
124
+
125
+ # License
126
+
127
+ This project is licensed under the terms
128
+ of [MIT license](https://github.com/Code-Society-Lab/matrixpy/blob/main/LICENSE).
@@ -33,6 +33,7 @@ matrix/extension.py
33
33
  matrix/group.py
34
34
  matrix/message.py
35
35
  matrix/protocols.py
36
+ matrix/py.typed
36
37
  matrix/registry.py
37
38
  matrix/room.py
38
39
  matrix/scheduler.py
@@ -44,6 +44,9 @@ dev = [
44
44
  packages = ["matrix"]
45
45
  license-files = []
46
46
 
47
+ [tool.setuptools.package-data]
48
+ matrix = ["py.typed"]
49
+
47
50
  [tool.setuptools_scm]
48
51
  write_to = "matrix/_version.py"
49
52
 
@@ -3,9 +3,7 @@ import pytest
3
3
  from unittest.mock import AsyncMock, MagicMock, patch
4
4
  from nio import MatrixRoom, RoomMessageText
5
5
 
6
- from matrix.bot import Bot
7
- from matrix.config import Config
8
- from matrix.extension import Extension
6
+ from matrix.bot import Bot, Config, Extension, Room
9
7
  from matrix.errors import (
10
8
  CheckError,
11
9
  CommandNotFoundError,
@@ -118,7 +116,8 @@ async def test_dispatch_calls_all_handlers(bot):
118
116
  "type": "m.room.message",
119
117
  }
120
118
  )
121
- room = MatrixRoom("!roomid:matrix.org", "room_alias")
119
+ matrix_room = MatrixRoom("!roomid:matrix.org", "room_alias")
120
+ room = Room(matrix_room, bot.client)
122
121
 
123
122
  await bot._dispatch_matrix_event(room, event)
124
123
  assert "h1" in called
@@ -206,9 +205,7 @@ async def test_on_error_calls_fallback_handler(bot):
206
205
  nonlocal called
207
206
  called = True
208
207
 
209
- await bot._fallback_error_handler(Exception("test error"))
210
- await bot.on_error(Exception("test error"))
211
-
208
+ await bot._on_error(Exception("test error"))
212
209
  assert called, "Fallback error handler was not called"
213
210
 
214
211
 
@@ -245,7 +242,9 @@ async def test_process_commands_executes_command(bot, event):
245
242
 
246
243
 
247
244
  @pytest.mark.asyncio
248
- async def test_command_not_found_raises(bot):
245
+ async def test_command_not_found_calls_command_error_handler(bot):
246
+ bot._on_command_error = AsyncMock()
247
+
249
248
  event = RoomMessageText.from_dict(
250
249
  {
251
250
  "content": {"body": "!nonexistent", "msgtype": "m.text"},
@@ -258,17 +257,14 @@ async def test_command_not_found_raises(bot):
258
257
 
259
258
  room = MatrixRoom("!roomid", "alias")
260
259
 
261
- with patch("matrix.context.Context", autospec=True) as MockContext:
262
- mock_ctx = MagicMock()
263
- mock_ctx.body = "!nonexistent"
264
- MockContext.return_value = mock_ctx
260
+ await bot._process_commands(room, event)
265
261
 
266
- with pytest.raises(CommandNotFoundError):
267
- await bot._process_commands(room, event)
262
+ bot._on_command_error.assert_awaited_once()
263
+ assert isinstance(bot._on_command_error.call_args[0][1], CommandNotFoundError)
268
264
 
269
265
 
270
266
  @pytest.mark.asyncio
271
- async def test_bot_does_not_execute_when_global_check_fails(bot, event):
267
+ async def test_bot_does_not_execute_command_when_global_check_fails(bot):
272
268
  called = False
273
269
 
274
270
  @bot.command()
@@ -280,6 +276,8 @@ async def test_bot_does_not_execute_when_global_check_fails(bot, event):
280
276
  async def global_check(ctx):
281
277
  return False
282
278
 
279
+ bot._on_command_error = AsyncMock()
280
+
283
281
  event = RoomMessageText.from_dict(
284
282
  {
285
283
  "content": {"body": "!greet", "msgtype": "m.text"},
@@ -290,18 +288,14 @@ async def test_bot_does_not_execute_when_global_check_fails(bot, event):
290
288
  }
291
289
  )
292
290
 
293
- room = MatrixRoom("!roomid", "alias")
291
+ matrix_room = MatrixRoom("!roomid", "alias")
292
+ room = Room(matrix_room, bot.client)
294
293
 
295
- with patch("matrix.context.Context", autospec=True) as MockContext:
296
- mock_ctx = MagicMock()
297
- mock_ctx.body = "!greet"
298
- mock_ctx.command = bot.commands["greet"]
299
- MockContext.return_value = mock_ctx
300
-
301
- with pytest.raises(CheckError):
302
- await bot._process_commands(room, event)
294
+ await bot._process_commands(room, event)
303
295
 
304
- assert not called, "Expected command handler not to be called"
296
+ assert not called
297
+ bot._on_command_error.assert_awaited_once()
298
+ assert isinstance(bot._on_command_error.call_args[0][1], CheckError)
305
299
 
306
300
 
307
301
  @pytest.mark.asyncio
@@ -297,16 +297,6 @@ def test_register_error_handler_with_exception_type__expect_handler_in_dict(
297
297
  assert registry._error_handlers[ValueError] is on_value_error
298
298
 
299
299
 
300
- def test_register_generic_error_handler__expect_fallback_error_handler_set(
301
- registry: Registry,
302
- ):
303
- @registry.error()
304
- async def on_any_error(error):
305
- pass
306
-
307
- assert registry._fallback_error_handler is on_any_error
308
-
309
-
310
300
  def test_register_error_handler_with_non_coroutine__expect_type_error(
311
301
  registry: Registry,
312
302
  ):