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.
- matrix_python-1.4.8a0/LICENSE +21 -0
- matrix_python-1.4.8a0/PKG-INFO +128 -0
- {matrix_python-1.4.6a0 → matrix_python-1.4.8a0}/README.md +2 -1
- {matrix_python-1.4.6a0 → matrix_python-1.4.8a0}/matrix/_version.py +3 -3
- {matrix_python-1.4.6a0 → matrix_python-1.4.8a0}/matrix/bot.py +11 -11
- matrix_python-1.4.8a0/matrix/py.typed +0 -0
- {matrix_python-1.4.6a0 → matrix_python-1.4.8a0}/matrix/registry.py +5 -5
- matrix_python-1.4.8a0/matrix_python.egg-info/PKG-INFO +128 -0
- {matrix_python-1.4.6a0 → matrix_python-1.4.8a0}/matrix_python.egg-info/SOURCES.txt +1 -0
- {matrix_python-1.4.6a0 → matrix_python-1.4.8a0}/pyproject.toml +3 -0
- {matrix_python-1.4.6a0 → matrix_python-1.4.8a0}/tests/test_bot.py +19 -25
- {matrix_python-1.4.6a0 → matrix_python-1.4.8a0}/tests/test_registry.py +0 -10
- matrix_python-1.4.6a0/LICENSE +0 -674
- matrix_python-1.4.6a0/PKG-INFO +0 -781
- matrix_python-1.4.6a0/matrix_python.egg-info/PKG-INFO +0 -781
- {matrix_python-1.4.6a0 → matrix_python-1.4.8a0}/.github/dependabot.yml +0 -0
- {matrix_python-1.4.6a0 → matrix_python-1.4.8a0}/.github/workflows/CODEOWNERS +0 -0
- {matrix_python-1.4.6a0 → matrix_python-1.4.8a0}/.github/workflows/codeql.yml +0 -0
- {matrix_python-1.4.6a0 → matrix_python-1.4.8a0}/.github/workflows/publish.yml +0 -0
- {matrix_python-1.4.6a0 → matrix_python-1.4.8a0}/.github/workflows/scorecard.yml +0 -0
- {matrix_python-1.4.6a0 → matrix_python-1.4.8a0}/.github/workflows/tests.yml +0 -0
- {matrix_python-1.4.6a0 → matrix_python-1.4.8a0}/.gitignore +0 -0
- {matrix_python-1.4.6a0 → matrix_python-1.4.8a0}/CODE_OF_CONDUCT.md +0 -0
- {matrix_python-1.4.6a0 → matrix_python-1.4.8a0}/CONTRIBUTING.md +0 -0
- {matrix_python-1.4.6a0 → matrix_python-1.4.8a0}/examples/README.md +0 -0
- {matrix_python-1.4.6a0 → matrix_python-1.4.8a0}/examples/checks.py +0 -0
- {matrix_python-1.4.6a0 → matrix_python-1.4.8a0}/examples/config.yaml +0 -0
- {matrix_python-1.4.6a0 → matrix_python-1.4.8a0}/examples/cooldown.py +0 -0
- {matrix_python-1.4.6a0 → matrix_python-1.4.8a0}/examples/error_handling.py +0 -0
- {matrix_python-1.4.6a0 → matrix_python-1.4.8a0}/examples/extension.py +0 -0
- {matrix_python-1.4.6a0 → matrix_python-1.4.8a0}/examples/ping.py +0 -0
- {matrix_python-1.4.6a0 → matrix_python-1.4.8a0}/examples/reaction.py +0 -0
- {matrix_python-1.4.6a0 → matrix_python-1.4.8a0}/examples/scheduler.py +0 -0
- {matrix_python-1.4.6a0 → matrix_python-1.4.8a0}/matrix/__init__.py +0 -0
- {matrix_python-1.4.6a0 → matrix_python-1.4.8a0}/matrix/checks.py +0 -0
- {matrix_python-1.4.6a0 → matrix_python-1.4.8a0}/matrix/command.py +0 -0
- {matrix_python-1.4.6a0 → matrix_python-1.4.8a0}/matrix/config.py +0 -0
- {matrix_python-1.4.6a0 → matrix_python-1.4.8a0}/matrix/content.py +0 -0
- {matrix_python-1.4.6a0 → matrix_python-1.4.8a0}/matrix/context.py +0 -0
- {matrix_python-1.4.6a0 → matrix_python-1.4.8a0}/matrix/errors.py +0 -0
- {matrix_python-1.4.6a0 → matrix_python-1.4.8a0}/matrix/extension.py +0 -0
- {matrix_python-1.4.6a0 → matrix_python-1.4.8a0}/matrix/group.py +0 -0
- {matrix_python-1.4.6a0 → matrix_python-1.4.8a0}/matrix/help/__init__.py +0 -0
- {matrix_python-1.4.6a0 → matrix_python-1.4.8a0}/matrix/help/help_command.py +0 -0
- {matrix_python-1.4.6a0 → matrix_python-1.4.8a0}/matrix/help/pagination.py +0 -0
- {matrix_python-1.4.6a0 → matrix_python-1.4.8a0}/matrix/message.py +0 -0
- {matrix_python-1.4.6a0 → matrix_python-1.4.8a0}/matrix/protocols.py +0 -0
- {matrix_python-1.4.6a0 → matrix_python-1.4.8a0}/matrix/room.py +0 -0
- {matrix_python-1.4.6a0 → matrix_python-1.4.8a0}/matrix/scheduler.py +0 -0
- {matrix_python-1.4.6a0 → matrix_python-1.4.8a0}/matrix/types.py +0 -0
- {matrix_python-1.4.6a0 → matrix_python-1.4.8a0}/matrix_python.egg-info/dependency_links.txt +0 -0
- {matrix_python-1.4.6a0 → matrix_python-1.4.8a0}/matrix_python.egg-info/requires.txt +0 -0
- {matrix_python-1.4.6a0 → matrix_python-1.4.8a0}/matrix_python.egg-info/top_level.txt +0 -0
- {matrix_python-1.4.6a0 → matrix_python-1.4.8a0}/mypy.ini +0 -0
- {matrix_python-1.4.6a0 → matrix_python-1.4.8a0}/setup.cfg +0 -0
- {matrix_python-1.4.6a0 → matrix_python-1.4.8a0}/tests/help/test_default_help_command.py +0 -0
- {matrix_python-1.4.6a0 → matrix_python-1.4.8a0}/tests/help/test_help_command.py +0 -0
- {matrix_python-1.4.6a0 → matrix_python-1.4.8a0}/tests/help/test_pagination.py +0 -0
- {matrix_python-1.4.6a0 → matrix_python-1.4.8a0}/tests/test_command.py +0 -0
- {matrix_python-1.4.6a0 → matrix_python-1.4.8a0}/tests/test_config.py +0 -0
- {matrix_python-1.4.6a0 → matrix_python-1.4.8a0}/tests/test_context.py +0 -0
- {matrix_python-1.4.6a0 → matrix_python-1.4.8a0}/tests/test_extension.py +0 -0
- {matrix_python-1.4.6a0 → matrix_python-1.4.8a0}/tests/test_group.py +0 -0
- {matrix_python-1.4.6a0 → matrix_python-1.4.8a0}/tests/test_message.py +0 -0
- {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
|
+
[](https://github.com/Code-Society-Lab/matrixpy/wiki)
|
|
56
|
+
[](https://discord.gg/code-society-823178343943897088)
|
|
57
|
+
[](https://matrix.to/#/%23codesociety:matrix.org )
|
|
58
|
+
[](https://github.com/Code-Society-Lab/matrixpy/actions/workflows/tests.yml)
|
|
59
|
+
[](https://github.com/Code-Society-Lab/matrixpy/actions/workflows/codeql.yml)
|
|
60
|
+
[](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
|
-
|
|
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.
|
|
22
|
-
__version_tuple__ = version_tuple = (1, 4,
|
|
21
|
+
__version__ = version = '1.4.8a0'
|
|
22
|
+
__version_tuple__ = version_tuple = (1, 4, 8, 'a0')
|
|
23
23
|
|
|
24
|
-
__commit_id__ = commit_id = '
|
|
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
|
-
|
|
325
|
+
try:
|
|
326
|
+
ctx = await self._build_context(room, event)
|
|
330
327
|
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
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
|
-
|
|
337
|
-
|
|
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
|
-
|
|
386
|
-
|
|
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
|
+
[](https://github.com/Code-Society-Lab/matrixpy/wiki)
|
|
56
|
+
[](https://discord.gg/code-society-823178343943897088)
|
|
57
|
+
[](https://matrix.to/#/%23codesociety:matrix.org )
|
|
58
|
+
[](https://github.com/Code-Society-Lab/matrixpy/actions/workflows/tests.yml)
|
|
59
|
+
[](https://github.com/Code-Society-Lab/matrixpy/actions/workflows/codeql.yml)
|
|
60
|
+
[](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).
|
|
@@ -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
|
-
|
|
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.
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
267
|
-
|
|
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
|
|
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
|
-
|
|
291
|
+
matrix_room = MatrixRoom("!roomid", "alias")
|
|
292
|
+
room = Room(matrix_room, bot.client)
|
|
294
293
|
|
|
295
|
-
|
|
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
|
|
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
|
):
|