dbus-fast 2.39.5__tar.gz → 2.45.2__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.
Potentially problematic release.
This version of dbus-fast might be problematic. Click here for more details.
- {dbus_fast-2.39.5 → dbus_fast-2.45.2}/PKG-INFO +8 -7
- {dbus_fast-2.39.5 → dbus_fast-2.45.2}/README.md +3 -3
- {dbus_fast-2.39.5 → dbus_fast-2.45.2}/build_ext.py +1 -1
- {dbus_fast-2.39.5 → dbus_fast-2.45.2}/pyproject.toml +11 -11
- {dbus_fast-2.39.5 → dbus_fast-2.45.2}/setup.py +3 -3
- {dbus_fast-2.39.5 → dbus_fast-2.45.2}/src/dbus_fast/__version__.py +1 -1
- {dbus_fast-2.39.5 → dbus_fast-2.45.2}/src/dbus_fast/_private/marshaller.pxd +2 -2
- {dbus_fast-2.39.5 → dbus_fast-2.45.2}/src/dbus_fast/_private/marshaller.py +2 -1
- {dbus_fast-2.39.5 → dbus_fast-2.45.2}/src/dbus_fast/_private/unmarshaller.pxd +4 -1
- {dbus_fast-2.39.5 → dbus_fast-2.45.2}/src/dbus_fast/_private/unmarshaller.py +36 -24
- {dbus_fast-2.39.5 → dbus_fast-2.45.2}/src/dbus_fast/_private/util.py +2 -1
- {dbus_fast-2.39.5 → dbus_fast-2.45.2}/src/dbus_fast/aio/message_bus.py +2 -1
- {dbus_fast-2.39.5 → dbus_fast-2.45.2}/src/dbus_fast/aio/message_reader.py +1 -1
- {dbus_fast-2.39.5 → dbus_fast-2.45.2}/src/dbus_fast/auth.py +2 -3
- {dbus_fast-2.39.5 → dbus_fast-2.45.2}/src/dbus_fast/constants.py +3 -9
- {dbus_fast-2.39.5 → dbus_fast-2.45.2}/src/dbus_fast/errors.py +1 -4
- {dbus_fast-2.39.5 → dbus_fast-2.45.2}/src/dbus_fast/glib/message_bus.py +8 -10
- {dbus_fast-2.39.5 → dbus_fast-2.45.2}/src/dbus_fast/glib/proxy_object.py +1 -2
- {dbus_fast-2.39.5 → dbus_fast-2.45.2}/src/dbus_fast/introspection.py +19 -20
- {dbus_fast-2.39.5 → dbus_fast-2.45.2}/src/dbus_fast/message.pxd +1 -1
- {dbus_fast-2.39.5 → dbus_fast-2.45.2}/src/dbus_fast/message.py +19 -19
- {dbus_fast-2.39.5 → dbus_fast-2.45.2}/src/dbus_fast/message_bus.py +2 -1
- {dbus_fast-2.39.5 → dbus_fast-2.45.2}/src/dbus_fast/proxy_object.py +1 -2
- {dbus_fast-2.39.5 → dbus_fast-2.45.2}/src/dbus_fast/service.pxd +1 -1
- {dbus_fast-2.39.5 → dbus_fast-2.45.2}/src/dbus_fast/service.py +10 -6
- {dbus_fast-2.39.5 → dbus_fast-2.45.2}/src/dbus_fast/signature.pxd +2 -0
- {dbus_fast-2.39.5 → dbus_fast-2.45.2}/src/dbus_fast/signature.py +33 -11
- {dbus_fast-2.39.5 → dbus_fast-2.45.2}/LICENSE +0 -0
- {dbus_fast-2.39.5 → dbus_fast-2.45.2}/src/dbus_fast/__init__.py +0 -0
- {dbus_fast-2.39.5 → dbus_fast-2.45.2}/src/dbus_fast/_private/__init__.py +0 -0
- {dbus_fast-2.39.5 → dbus_fast-2.45.2}/src/dbus_fast/_private/_cython_compat.py +0 -0
- {dbus_fast-2.39.5 → dbus_fast-2.45.2}/src/dbus_fast/_private/address.pxd +0 -0
- {dbus_fast-2.39.5 → dbus_fast-2.45.2}/src/dbus_fast/_private/address.py +0 -0
- {dbus_fast-2.39.5 → dbus_fast-2.45.2}/src/dbus_fast/_private/constants.py +0 -0
- {dbus_fast-2.39.5 → dbus_fast-2.45.2}/src/dbus_fast/aio/__init__.py +0 -0
- {dbus_fast-2.39.5 → dbus_fast-2.45.2}/src/dbus_fast/aio/message_reader.pxd +0 -0
- {dbus_fast-2.39.5 → dbus_fast-2.45.2}/src/dbus_fast/aio/proxy_object.py +0 -0
- {dbus_fast-2.39.5 → dbus_fast-2.45.2}/src/dbus_fast/glib/__init__.py +0 -0
- {dbus_fast-2.39.5 → dbus_fast-2.45.2}/src/dbus_fast/message_bus.pxd +0 -0
- {dbus_fast-2.39.5 → dbus_fast-2.45.2}/src/dbus_fast/py.typed +0 -0
- {dbus_fast-2.39.5 → dbus_fast-2.45.2}/src/dbus_fast/send_reply.py +0 -0
- {dbus_fast-2.39.5 → dbus_fast-2.45.2}/src/dbus_fast/unpack.pxd +0 -0
- {dbus_fast-2.39.5 → dbus_fast-2.45.2}/src/dbus_fast/unpack.py +0 -0
- {dbus_fast-2.39.5 → dbus_fast-2.45.2}/src/dbus_fast/validators.py +0 -0
|
@@ -1,22 +1,23 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: dbus-fast
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.45.2
|
|
4
4
|
Summary: A faster version of dbus-next
|
|
5
5
|
License: MIT
|
|
6
|
+
License-File: LICENSE
|
|
6
7
|
Author: Bluetooth Devices Authors
|
|
7
8
|
Author-email: bluetooth@koston.org
|
|
8
|
-
Requires-Python: >=3.
|
|
9
|
+
Requires-Python: >=3.10
|
|
9
10
|
Classifier: Development Status :: 5 - Production/Stable
|
|
10
11
|
Classifier: Intended Audience :: Developers
|
|
11
12
|
Classifier: License :: OSI Approved :: MIT License
|
|
12
13
|
Classifier: Natural Language :: English
|
|
13
14
|
Classifier: Operating System :: OS Independent
|
|
14
15
|
Classifier: Programming Language :: Python :: 3
|
|
15
|
-
Classifier: Programming Language :: Python :: 3.9
|
|
16
16
|
Classifier: Programming Language :: Python :: 3.10
|
|
17
17
|
Classifier: Programming Language :: Python :: 3.11
|
|
18
18
|
Classifier: Programming Language :: Python :: 3.12
|
|
19
19
|
Classifier: Programming Language :: Python :: 3.13
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
20
21
|
Classifier: Topic :: Software Development :: Libraries
|
|
21
22
|
Project-URL: Bug Tracker, https://github.com/bluetooth-devices/dbus-fast/issues
|
|
22
23
|
Project-URL: Changelog, https://github.com/bluetooth-devices/dbus-fast/blob/main/CHANGELOG.md
|
|
@@ -141,7 +142,7 @@ asyncio.run(main())
|
|
|
141
142
|
|
|
142
143
|
To define a service on the bus, use the `ServiceInterface` class and decorate class methods to specify DBus methods, properties, and signals with their type signatures.
|
|
143
144
|
|
|
144
|
-
For more information, see the [overview for the high-level service](https://
|
|
145
|
+
For more information, see the [overview for the high-level service](https://dbus-fast.readthedocs.io/en/latest/high-level-service/index.html).
|
|
145
146
|
|
|
146
147
|
```python
|
|
147
148
|
from dbus_fast.service import ServiceInterface, method, dbus_property, signal, Variant
|
|
@@ -194,7 +195,7 @@ asyncio.run(main())
|
|
|
194
195
|
|
|
195
196
|
The low-level interface works with DBus messages directly.
|
|
196
197
|
|
|
197
|
-
For more information, see the [overview for the low-level interface](https://
|
|
198
|
+
For more information, see the [overview for the low-level interface](https://dbus-fast.readthedocs.io/en/latest/low-level-interface/index.html).
|
|
198
199
|
|
|
199
200
|
```python
|
|
200
201
|
from dbus_fast.message import Message, MessageType
|
|
@@ -222,7 +223,7 @@ async def main():
|
|
|
222
223
|
asyncio.run(main())
|
|
223
224
|
```
|
|
224
225
|
|
|
225
|
-
## Projects that use
|
|
226
|
+
## Projects that use dbus-fast
|
|
226
227
|
|
|
227
228
|
- [Bluetooth Adapters](https://github.com/bluetooth-devices/bluetooth-adapters)
|
|
228
229
|
|
|
@@ -115,7 +115,7 @@ asyncio.run(main())
|
|
|
115
115
|
|
|
116
116
|
To define a service on the bus, use the `ServiceInterface` class and decorate class methods to specify DBus methods, properties, and signals with their type signatures.
|
|
117
117
|
|
|
118
|
-
For more information, see the [overview for the high-level service](https://
|
|
118
|
+
For more information, see the [overview for the high-level service](https://dbus-fast.readthedocs.io/en/latest/high-level-service/index.html).
|
|
119
119
|
|
|
120
120
|
```python
|
|
121
121
|
from dbus_fast.service import ServiceInterface, method, dbus_property, signal, Variant
|
|
@@ -168,7 +168,7 @@ asyncio.run(main())
|
|
|
168
168
|
|
|
169
169
|
The low-level interface works with DBus messages directly.
|
|
170
170
|
|
|
171
|
-
For more information, see the [overview for the low-level interface](https://
|
|
171
|
+
For more information, see the [overview for the low-level interface](https://dbus-fast.readthedocs.io/en/latest/low-level-interface/index.html).
|
|
172
172
|
|
|
173
173
|
```python
|
|
174
174
|
from dbus_fast.message import Message, MessageType
|
|
@@ -196,7 +196,7 @@ async def main():
|
|
|
196
196
|
asyncio.run(main())
|
|
197
197
|
```
|
|
198
198
|
|
|
199
|
-
## Projects that use
|
|
199
|
+
## Projects that use dbus-fast
|
|
200
200
|
|
|
201
201
|
- [Bluetooth Adapters](https://github.com/bluetooth-devices/bluetooth-adapters)
|
|
202
202
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[tool.poetry]
|
|
2
2
|
name = "dbus-fast"
|
|
3
|
-
version = "2.
|
|
3
|
+
version = "2.45.2"
|
|
4
4
|
description = "A faster version of dbus-next"
|
|
5
5
|
authors = ["Bluetooth Devices Authors <bluetooth@koston.org>"]
|
|
6
6
|
license = "MIT"
|
|
@@ -13,11 +13,11 @@ classifiers = [
|
|
|
13
13
|
"Natural Language :: English",
|
|
14
14
|
"Operating System :: OS Independent",
|
|
15
15
|
"Topic :: Software Development :: Libraries",
|
|
16
|
-
"Programming Language :: Python :: 3.9",
|
|
17
16
|
"Programming Language :: Python :: 3.10",
|
|
18
17
|
"Programming Language :: Python :: 3.11",
|
|
19
18
|
"Programming Language :: Python :: 3.12",
|
|
20
19
|
"Programming Language :: Python :: 3.13",
|
|
20
|
+
"Programming Language :: Python :: 3.14",
|
|
21
21
|
]
|
|
22
22
|
packages = [
|
|
23
23
|
{ include = "dbus_fast", from = "src" },
|
|
@@ -34,7 +34,7 @@ script = "build_ext.py"
|
|
|
34
34
|
"Changelog" = "https://github.com/bluetooth-devices/dbus-fast/blob/main/CHANGELOG.md"
|
|
35
35
|
|
|
36
36
|
[tool.poetry.dependencies]
|
|
37
|
-
python = "
|
|
37
|
+
python = ">=3.10"
|
|
38
38
|
|
|
39
39
|
# duplicated in docs/requirements.txt for readthedocs compatibility
|
|
40
40
|
[tool.poetry.group.docs.dependencies]
|
|
@@ -46,14 +46,14 @@ sphinxcontrib-fulltoc = "^1.2.0"
|
|
|
46
46
|
|
|
47
47
|
[tool.poetry.group.dev.dependencies]
|
|
48
48
|
pytest = ">=7,<9"
|
|
49
|
-
pytest-cov = ">=3,<
|
|
50
|
-
pytest-asyncio = ">=0.19,<
|
|
49
|
+
pytest-cov = ">=3,<8"
|
|
50
|
+
pytest-asyncio = ">=0.19,<1.3"
|
|
51
51
|
pycairo = "^1.21.0"
|
|
52
|
-
PyGObject = "
|
|
53
|
-
Cython = ">=3,<3.
|
|
54
|
-
setuptools = ">=65.4.1,<
|
|
52
|
+
PyGObject = {version = ">=3.50,<3.51", python = "<4"}
|
|
53
|
+
Cython = ">=3,<3.3.0"
|
|
54
|
+
setuptools = ">=65.4.1,<81.0.0"
|
|
55
55
|
pytest-timeout = "^2.1.0"
|
|
56
|
-
pytest-codspeed = "
|
|
56
|
+
pytest-codspeed = ">=3.1.1,<5.0.0"
|
|
57
57
|
covdefaults = "^2.3.0"
|
|
58
58
|
|
|
59
59
|
[tool.semantic_release]
|
|
@@ -104,11 +104,11 @@ module = "docs.*"
|
|
|
104
104
|
ignore_errors = true
|
|
105
105
|
|
|
106
106
|
[build-system]
|
|
107
|
-
requires = ['setuptools>=65.4.1', 'wheel', 'Cython>=3,<3.
|
|
107
|
+
requires = ['setuptools>=65.4.1', 'wheel', 'Cython>=3,<3.3.0', "poetry-core>=1.0.0"]
|
|
108
108
|
build-backend = "poetry.core.masonry.api"
|
|
109
109
|
|
|
110
110
|
[tool.ruff]
|
|
111
|
-
target-version = "
|
|
111
|
+
target-version = "py310"
|
|
112
112
|
line-length = 88
|
|
113
113
|
|
|
114
114
|
[tool.ruff.lint]
|
|
@@ -12,9 +12,9 @@ package_data = \
|
|
|
12
12
|
|
|
13
13
|
setup_kwargs = {
|
|
14
14
|
'name': 'dbus-fast',
|
|
15
|
-
'version': '2.
|
|
15
|
+
'version': '2.45.2',
|
|
16
16
|
'description': 'A faster version of dbus-next',
|
|
17
|
-
'long_description': '# dbus-fast\n\n<p align="center">\n <a href="https://github.com/bluetooth-devices/dbus-fast/actions?query=workflow%3ACI">\n <img src="https://img.shields.io/github/workflow/status/bluetooth-devices/dbus-fast/CI/main?label=CI&logo=github&style=flat-square" alt="CI Status" >\n </a>\n <a href="https://dbus-fast.readthedocs.io">\n <img src="https://img.shields.io/readthedocs/dbus-fast.svg?logo=read-the-docs&logoColor=fff&style=flat-square" alt="Documentation Status">\n </a>\n <a href="https://codecov.io/gh/bluetooth-devices/dbus-fast">\n <img src="https://img.shields.io/codecov/c/github/bluetooth-devices/dbus-fast.svg?logo=codecov&logoColor=fff&style=flat-square" alt="Test coverage percentage">\n </a>\n</p>\n<p align="center">\n <a href="https://python-poetry.org/">\n <img src="https://img.shields.io/badge/packaging-poetry-299bd7?style=flat-square&logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAASCAYAAABrXO8xAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAJJSURBVHgBfZLPa1NBEMe/s7tNXoxW1KJQKaUHkXhQvHgW6UHQQ09CBS/6V3hKc/AP8CqCrUcpmop3Cx48eDB4yEECjVQrlZb80CRN8t6OM/teagVxYZi38+Yz853dJbzoMV3MM8cJUcLMSUKIE8AzQ2PieZzFxEJOHMOgMQQ+dUgSAckNXhapU/NMhDSWLs1B24A8sO1xrN4NECkcAC9ASkiIJc6k5TRiUDPhnyMMdhKc+Zx19l6SgyeW76BEONY9exVQMzKExGKwwPsCzza7KGSSWRWEQhyEaDXp6ZHEr416ygbiKYOd7TEWvvcQIeusHYMJGhTwF9y7sGnSwaWyFAiyoxzqW0PM/RjghPxF2pWReAowTEXnDh0xgcLs8l2YQmOrj3N7ByiqEoH0cARs4u78WgAVkoEDIDoOi3AkcLOHU60RIg5wC4ZuTC7FaHKQm8Hq1fQuSOBvX/sodmNJSB5geaF5CPIkUeecdMxieoRO5jz9bheL6/tXjrwCyX/UYBUcjCaWHljx1xiX6z9xEjkYAzbGVnB8pvLmyXm9ep+W8CmsSHQQY77Zx1zboxAV0w7ybMhQmfqdmmw3nEp1I0Z+FGO6M8LZdoyZnuzzBdjISicKRnpxzI9fPb+0oYXsNdyi+d3h9bm9MWYHFtPeIZfLwzmFDKy1ai3p+PDls1Llz4yyFpferxjnyjJDSEy9CaCx5m2cJPerq6Xm34eTrZt3PqxYO1XOwDYZrFlH1fWnpU38Y9HRze3lj0vOujZcXKuuXm3jP+s3KbZVra7y2EAAAAAASUVORK5CYII=" alt="Poetry">\n </a>\n <a href="https://github.com/astral-sh/ruff">\n <img src="https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json" alt="Ruff">\n </a>\n <a href="https://github.com/pre-commit/pre-commit">\n <img src="https://img.shields.io/badge/pre--commit-enabled-brightgreen?logo=pre-commit&logoColor=white&style=flat-square" alt="pre-commit">\n </a>\n <a href="https://codspeed.io/Bluetooth-Devices/dbus-fast"><img src="https://img.shields.io/endpoint?url=https://codspeed.io/badge.json" alt="CodSpeed Badge"/></a>\n</p>\n<p align="center">\n <a href="https://pypi.org/project/dbus-fast/">\n <img src="https://img.shields.io/pypi/v/dbus-fast.svg?logo=python&logoColor=fff&style=flat-square" alt="PyPI Version">\n </a>\n <img src="https://img.shields.io/pypi/pyversions/dbus-fast.svg?style=flat-square&logo=python&logoColor=fff" alt="Supported Python versions">\n <img src="https://img.shields.io/pypi/l/dbus-fast.svg?style=flat-square" alt="License">\n</p>\n\nA faster version of dbus-next originally from the [great DBus next library](https://github.com/altdesktop/python-dbus-next) ❤️\n\n## Installation\n\nInstall this via pip (or your favourite package manager):\n\n`pip install dbus-fast`\n\n[Documentation](https://dbus-fast.readthedocs.io/en/latest/)\n\ndbus-fast is a Python library for DBus that aims to be a performant fully featured high level library primarily geared towards integration of applications into Linux desktop and mobile environments.\n\nDesktop application developers can use this library for integrating their applications into desktop environments by implementing common DBus standard interfaces or creating custom plugin interfaces.\n\nDesktop users can use this library to create their own scripts and utilities to interact with those interfaces for customization of their desktop environment.\n\ndbus-fast plans to improve over other DBus libraries for Python in the following ways:\n\n- Zero dependencies and pure Python 3\n- An optional cython extension is available to speed up (un)marshalling\n- Focus on performance\n- Support for multiple IO backends including asyncio and the GLib main loop.\n- Nonblocking IO suitable for GUI development.\n- Target the latest language features of Python for beautiful services and clients.\n- Complete implementation of the DBus type system without ever guessing types.\n- Integration tests for all features of the library.\n- Completely documented public API.\n\n## Installing\n\nThis library is available on PyPi as [dbus-fast](https://pypi.org/project/dbus-fast/).\n\n```\npip3 install dbus-fast\n```\n\n## The Client Interface\n\nTo use a service on the bus, the library constructs a proxy object you can use to call methods, get and set properties, and listen to signals.\n\nFor more information, see the [overview for the high-level client](https://dbus-fast.readthedocs.io/en/latest/high-level-client/index.html).\n\nThis example connects to a media player and controls it with the [MPRIS](https://specifications.freedesktop.org/mpris-spec/latest/) DBus interface.\n\n```python\nfrom dbus_fast.aio import MessageBus\n\nimport asyncio\n\n\nasync def main():\n bus = await MessageBus().connect()\n # the introspection xml would normally be included in your project, but\n # this is convenient for development\n introspection = await bus.introspect(\'org.mpris.MediaPlayer2.vlc\', \'/org/mpris/MediaPlayer2\')\n\n obj = bus.get_proxy_object(\'org.mpris.MediaPlayer2.vlc\', \'/org/mpris/MediaPlayer2\', introspection)\n player = obj.get_interface(\'org.mpris.MediaPlayer2.Player\')\n properties = obj.get_interface(\'org.freedesktop.DBus.Properties\')\n\n # call methods on the interface (this causes the media player to play)\n await player.call_play()\n\n volume = await player.get_volume()\n print(f\'current volume: {volume}, setting to 0.5\')\n\n await player.set_volume(0.5)\n\n # listen to signals\n def on_properties_changed(interface_name, changed_properties, invalidated_properties):\n for changed, variant in changed_properties.items():\n print(f\'property changed: {changed} - {variant.value}\')\n\n properties.on_properties_changed(on_properties_changed)\n\n await asyncio.Event().wait()\n\nasyncio.run(main())\n```\n\n## The Service Interface\n\nTo define a service on the bus, use the `ServiceInterface` class and decorate class methods to specify DBus methods, properties, and signals with their type signatures.\n\nFor more information, see the [overview for the high-level service](https://
|
|
17
|
+
'long_description': '# dbus-fast\n\n<p align="center">\n <a href="https://github.com/bluetooth-devices/dbus-fast/actions?query=workflow%3ACI">\n <img src="https://img.shields.io/github/workflow/status/bluetooth-devices/dbus-fast/CI/main?label=CI&logo=github&style=flat-square" alt="CI Status" >\n </a>\n <a href="https://dbus-fast.readthedocs.io">\n <img src="https://img.shields.io/readthedocs/dbus-fast.svg?logo=read-the-docs&logoColor=fff&style=flat-square" alt="Documentation Status">\n </a>\n <a href="https://codecov.io/gh/bluetooth-devices/dbus-fast">\n <img src="https://img.shields.io/codecov/c/github/bluetooth-devices/dbus-fast.svg?logo=codecov&logoColor=fff&style=flat-square" alt="Test coverage percentage">\n </a>\n</p>\n<p align="center">\n <a href="https://python-poetry.org/">\n <img src="https://img.shields.io/badge/packaging-poetry-299bd7?style=flat-square&logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAASCAYAAABrXO8xAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAJJSURBVHgBfZLPa1NBEMe/s7tNXoxW1KJQKaUHkXhQvHgW6UHQQ09CBS/6V3hKc/AP8CqCrUcpmop3Cx48eDB4yEECjVQrlZb80CRN8t6OM/teagVxYZi38+Yz853dJbzoMV3MM8cJUcLMSUKIE8AzQ2PieZzFxEJOHMOgMQQ+dUgSAckNXhapU/NMhDSWLs1B24A8sO1xrN4NECkcAC9ASkiIJc6k5TRiUDPhnyMMdhKc+Zx19l6SgyeW76BEONY9exVQMzKExGKwwPsCzza7KGSSWRWEQhyEaDXp6ZHEr416ygbiKYOd7TEWvvcQIeusHYMJGhTwF9y7sGnSwaWyFAiyoxzqW0PM/RjghPxF2pWReAowTEXnDh0xgcLs8l2YQmOrj3N7ByiqEoH0cARs4u78WgAVkoEDIDoOi3AkcLOHU60RIg5wC4ZuTC7FaHKQm8Hq1fQuSOBvX/sodmNJSB5geaF5CPIkUeecdMxieoRO5jz9bheL6/tXjrwCyX/UYBUcjCaWHljx1xiX6z9xEjkYAzbGVnB8pvLmyXm9ep+W8CmsSHQQY77Zx1zboxAV0w7ybMhQmfqdmmw3nEp1I0Z+FGO6M8LZdoyZnuzzBdjISicKRnpxzI9fPb+0oYXsNdyi+d3h9bm9MWYHFtPeIZfLwzmFDKy1ai3p+PDls1Llz4yyFpferxjnyjJDSEy9CaCx5m2cJPerq6Xm34eTrZt3PqxYO1XOwDYZrFlH1fWnpU38Y9HRze3lj0vOujZcXKuuXm3jP+s3KbZVra7y2EAAAAAASUVORK5CYII=" alt="Poetry">\n </a>\n <a href="https://github.com/astral-sh/ruff">\n <img src="https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json" alt="Ruff">\n </a>\n <a href="https://github.com/pre-commit/pre-commit">\n <img src="https://img.shields.io/badge/pre--commit-enabled-brightgreen?logo=pre-commit&logoColor=white&style=flat-square" alt="pre-commit">\n </a>\n <a href="https://codspeed.io/Bluetooth-Devices/dbus-fast"><img src="https://img.shields.io/endpoint?url=https://codspeed.io/badge.json" alt="CodSpeed Badge"/></a>\n</p>\n<p align="center">\n <a href="https://pypi.org/project/dbus-fast/">\n <img src="https://img.shields.io/pypi/v/dbus-fast.svg?logo=python&logoColor=fff&style=flat-square" alt="PyPI Version">\n </a>\n <img src="https://img.shields.io/pypi/pyversions/dbus-fast.svg?style=flat-square&logo=python&logoColor=fff" alt="Supported Python versions">\n <img src="https://img.shields.io/pypi/l/dbus-fast.svg?style=flat-square" alt="License">\n</p>\n\nA faster version of dbus-next originally from the [great DBus next library](https://github.com/altdesktop/python-dbus-next) ❤️\n\n## Installation\n\nInstall this via pip (or your favourite package manager):\n\n`pip install dbus-fast`\n\n[Documentation](https://dbus-fast.readthedocs.io/en/latest/)\n\ndbus-fast is a Python library for DBus that aims to be a performant fully featured high level library primarily geared towards integration of applications into Linux desktop and mobile environments.\n\nDesktop application developers can use this library for integrating their applications into desktop environments by implementing common DBus standard interfaces or creating custom plugin interfaces.\n\nDesktop users can use this library to create their own scripts and utilities to interact with those interfaces for customization of their desktop environment.\n\ndbus-fast plans to improve over other DBus libraries for Python in the following ways:\n\n- Zero dependencies and pure Python 3\n- An optional cython extension is available to speed up (un)marshalling\n- Focus on performance\n- Support for multiple IO backends including asyncio and the GLib main loop.\n- Nonblocking IO suitable for GUI development.\n- Target the latest language features of Python for beautiful services and clients.\n- Complete implementation of the DBus type system without ever guessing types.\n- Integration tests for all features of the library.\n- Completely documented public API.\n\n## Installing\n\nThis library is available on PyPi as [dbus-fast](https://pypi.org/project/dbus-fast/).\n\n```\npip3 install dbus-fast\n```\n\n## The Client Interface\n\nTo use a service on the bus, the library constructs a proxy object you can use to call methods, get and set properties, and listen to signals.\n\nFor more information, see the [overview for the high-level client](https://dbus-fast.readthedocs.io/en/latest/high-level-client/index.html).\n\nThis example connects to a media player and controls it with the [MPRIS](https://specifications.freedesktop.org/mpris-spec/latest/) DBus interface.\n\n```python\nfrom dbus_fast.aio import MessageBus\n\nimport asyncio\n\n\nasync def main():\n bus = await MessageBus().connect()\n # the introspection xml would normally be included in your project, but\n # this is convenient for development\n introspection = await bus.introspect(\'org.mpris.MediaPlayer2.vlc\', \'/org/mpris/MediaPlayer2\')\n\n obj = bus.get_proxy_object(\'org.mpris.MediaPlayer2.vlc\', \'/org/mpris/MediaPlayer2\', introspection)\n player = obj.get_interface(\'org.mpris.MediaPlayer2.Player\')\n properties = obj.get_interface(\'org.freedesktop.DBus.Properties\')\n\n # call methods on the interface (this causes the media player to play)\n await player.call_play()\n\n volume = await player.get_volume()\n print(f\'current volume: {volume}, setting to 0.5\')\n\n await player.set_volume(0.5)\n\n # listen to signals\n def on_properties_changed(interface_name, changed_properties, invalidated_properties):\n for changed, variant in changed_properties.items():\n print(f\'property changed: {changed} - {variant.value}\')\n\n properties.on_properties_changed(on_properties_changed)\n\n await asyncio.Event().wait()\n\nasyncio.run(main())\n```\n\n## The Service Interface\n\nTo define a service on the bus, use the `ServiceInterface` class and decorate class methods to specify DBus methods, properties, and signals with their type signatures.\n\nFor more information, see the [overview for the high-level service](https://dbus-fast.readthedocs.io/en/latest/high-level-service/index.html).\n\n```python\nfrom dbus_fast.service import ServiceInterface, method, dbus_property, signal, Variant\nfrom dbus_fast.aio MessageBus\n\nimport asyncio\n\nclass ExampleInterface(ServiceInterface):\n def __init__(self, name):\n super().__init__(name)\n self._string_prop = \'kevin\'\n\n @method()\n def Echo(self, what: \'s\') -> \'s\':\n return what\n\n @method()\n def GetVariantDict() -> \'a{sv}\':\n return {\n \'foo\': Variant(\'s\', \'bar\'),\n \'bat\': Variant(\'x\', -55),\n \'a_list\': Variant(\'as\', [\'hello\', \'world\'])\n }\n\n @dbus_property()\n def string_prop(self) -> \'s\':\n return self._string_prop\n\n @string_prop.setter\n def string_prop_setter(self, val: \'s\'):\n self._string_prop = val\n\n @signal()\n def signal_simple(self) -> \'s\':\n return \'hello\'\n\nasync def main():\n bus = await MessageBus().connect()\n interface = ExampleInterface(\'test.interface\')\n bus.export(\'/test/path\', interface)\n # now that we are ready to handle requests, we can request name from D-Bus\n await bus.request_name(\'test.name\')\n # wait indefinitely\n await asyncio.Event().wait()\n\nasyncio.run(main())\n```\n\n## The Low-Level Interface\n\nThe low-level interface works with DBus messages directly.\n\nFor more information, see the [overview for the low-level interface](https://dbus-fast.readthedocs.io/en/latest/low-level-interface/index.html).\n\n```python\nfrom dbus_fast.message import Message, MessageType\nfrom dbus_fast.aio import MessageBus\n\nimport asyncio\nimport json\n\n\nasync def main():\n bus = await MessageBus().connect()\n\n reply = await bus.call(\n Message(destination=\'org.freedesktop.DBus\',\n path=\'/org/freedesktop/DBus\',\n interface=\'org.freedesktop.DBus\',\n member=\'ListNames\'))\n\n if reply.message_type == MessageType.ERROR:\n raise Exception(reply.body[0])\n\n print(json.dumps(reply.body[0], indent=2))\n\n\nasyncio.run(main())\n```\n\n## Projects that use dbus-fast\n\n- [Bluetooth Adapters](https://github.com/bluetooth-devices/bluetooth-adapters)\n\n## Contributing\n\nContributions are welcome. Development happens on [Github](https://github.com/Bluetooth-Devices/dbus-fast).\n\nBefore you commit, run `pre-commit run --all-files` to run the linter, code formatter, and the test suite.\n\n## Copyright\n\nYou can use this code under an MIT license (see LICENSE).\n\n- © 2019, Tony Crisci\n- © 2022, Bluetooth Devices authors\n\n## Contributors ✨\n\nThanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)):\n\n<!-- prettier-ignore-start -->\n<!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->\n<!-- markdownlint-disable -->\n<!-- markdownlint-enable -->\n<!-- ALL-CONTRIBUTORS-LIST:END -->\n<!-- prettier-ignore-end -->\n\nThis project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome!\n\n## Credits\n\nThis package was created with\n[Cookiecutter](https://github.com/audreyr/cookiecutter) and the\n[browniebroke/cookiecutter-pypackage](https://github.com/browniebroke/cookiecutter-pypackage)\nproject template.\n',
|
|
18
18
|
'author': 'Bluetooth Devices Authors',
|
|
19
19
|
'author_email': 'bluetooth@koston.org',
|
|
20
20
|
'maintainer': 'None',
|
|
@@ -23,7 +23,7 @@ setup_kwargs = {
|
|
|
23
23
|
'package_dir': package_dir,
|
|
24
24
|
'packages': packages,
|
|
25
25
|
'package_data': package_data,
|
|
26
|
-
'python_requires': '>=3.
|
|
26
|
+
'python_requires': '>=3.10',
|
|
27
27
|
}
|
|
28
28
|
from build_ext import *
|
|
29
29
|
build(setup_kwargs)
|
|
@@ -3,7 +3,7 @@ __description__ = (
|
|
|
3
3
|
"A performant zero-dependency DBus library for Python with asyncio support"
|
|
4
4
|
)
|
|
5
5
|
__url__ = "https://github.com/bluetooth-devices/dbus-fast"
|
|
6
|
-
__version__ = "2.
|
|
6
|
+
__version__ = "2.45.2"
|
|
7
7
|
__author__ = "Bluetooth Devices authors, Tony Crisci"
|
|
8
8
|
__author_email__ = "bluetooth@koston.org"
|
|
9
9
|
__license__ = "MIT"
|
|
@@ -28,12 +28,12 @@ cdef class Marshaller:
|
|
|
28
28
|
)
|
|
29
29
|
cdef unsigned int _align(self, unsigned int n)
|
|
30
30
|
|
|
31
|
-
cpdef write_boolean(self,
|
|
31
|
+
cpdef write_boolean(self, bint boolean, SignatureType type_)
|
|
32
32
|
|
|
33
33
|
@cython.locals(
|
|
34
34
|
written=cython.uint,
|
|
35
35
|
)
|
|
36
|
-
cdef unsigned int _write_boolean(self,
|
|
36
|
+
cdef unsigned int _write_boolean(self, bint boolean)
|
|
37
37
|
|
|
38
38
|
cpdef write_string(self, object value, SignatureType type_)
|
|
39
39
|
|
|
@@ -109,6 +109,9 @@ cdef unsigned int TOKEN_LEFT_PAREN_AS_INT
|
|
|
109
109
|
cdef object MARSHALL_STREAM_END_ERROR
|
|
110
110
|
cdef object DEFAULT_BUFFER_SIZE
|
|
111
111
|
|
|
112
|
+
cdef Variant VARIANT_BOOL_TRUE
|
|
113
|
+
cdef Variant VARIANT_BOOL_FALSE
|
|
114
|
+
|
|
112
115
|
cdef list _EMPTY_HEADERS
|
|
113
116
|
|
|
114
117
|
cdef cython.uint EAGAIN
|
|
@@ -178,7 +181,7 @@ cdef class Unmarshaller:
|
|
|
178
181
|
|
|
179
182
|
cpdef read_boolean(self, SignatureType type_)
|
|
180
183
|
|
|
181
|
-
cdef _read_boolean(self)
|
|
184
|
+
cdef bint _read_boolean(self)
|
|
182
185
|
|
|
183
186
|
cpdef read_uint32_unpack(self, SignatureType type_)
|
|
184
187
|
|
|
@@ -5,9 +5,9 @@ import errno
|
|
|
5
5
|
import io
|
|
6
6
|
import socket
|
|
7
7
|
import sys
|
|
8
|
-
from collections.abc import Iterable
|
|
8
|
+
from collections.abc import Callable, Iterable
|
|
9
9
|
from struct import Struct
|
|
10
|
-
from typing import TYPE_CHECKING, Any
|
|
10
|
+
from typing import TYPE_CHECKING, Any
|
|
11
11
|
|
|
12
12
|
from ..constants import MESSAGE_FLAG_MAP, MESSAGE_TYPE_MAP, MessageFlag
|
|
13
13
|
from ..errors import InvalidMessageError
|
|
@@ -19,7 +19,7 @@ MESSAGE_FLAG_INTENUM = MessageFlag
|
|
|
19
19
|
|
|
20
20
|
MAX_UNIX_FDS = 16
|
|
21
21
|
MAX_UNIX_FDS_SIZE = array.array("i").itemsize
|
|
22
|
-
UNIX_FDS_CMSG_LENGTH = socket.CMSG_LEN(MAX_UNIX_FDS_SIZE)
|
|
22
|
+
UNIX_FDS_CMSG_LENGTH = socket.CMSG_LEN(MAX_UNIX_FDS_SIZE * MAX_UNIX_FDS)
|
|
23
23
|
|
|
24
24
|
UNPACK_SYMBOL = {LITTLE_ENDIAN: "<", BIG_ENDIAN: ">"}
|
|
25
25
|
|
|
@@ -120,6 +120,10 @@ TOKEN_LEFT_CURLY_AS_INT = ord("{")
|
|
|
120
120
|
TOKEN_LEFT_PAREN_AS_INT = ord("(")
|
|
121
121
|
|
|
122
122
|
|
|
123
|
+
VARIANT_BOOL_TRUE = Variant._factory(SIGNATURE_TREE_B, True)
|
|
124
|
+
VARIANT_BOOL_FALSE = Variant._factory(SIGNATURE_TREE_B, False)
|
|
125
|
+
|
|
126
|
+
|
|
123
127
|
ARRAY = array.array
|
|
124
128
|
SOL_SOCKET = socket.SOL_SOCKET
|
|
125
129
|
SCM_RIGHTS = socket.SCM_RIGHTS
|
|
@@ -539,14 +543,17 @@ class Unmarshaller:
|
|
|
539
543
|
if token_as_int == TOKEN_S_AS_INT:
|
|
540
544
|
return Variant._factory(SIGNATURE_TREE_S, self._read_string_unpack())
|
|
541
545
|
if token_as_int == TOKEN_B_AS_INT:
|
|
542
|
-
return
|
|
546
|
+
return VARIANT_BOOL_TRUE if self._read_boolean() else VARIANT_BOOL_FALSE
|
|
543
547
|
if token_as_int == TOKEN_O_AS_INT:
|
|
544
548
|
return Variant._factory(SIGNATURE_TREE_O, self._read_string_unpack())
|
|
545
549
|
if token_as_int == TOKEN_U_AS_INT:
|
|
546
550
|
return Variant._factory(SIGNATURE_TREE_U, self._read_uint32_unpack())
|
|
547
551
|
if token_as_int == TOKEN_Y_AS_INT:
|
|
552
|
+
if cython.compiled:
|
|
553
|
+
if self._buf_len < self._pos:
|
|
554
|
+
raise IndexError("Not enough data to read byte")
|
|
548
555
|
self._pos += 1
|
|
549
|
-
return Variant._factory(SIGNATURE_TREE_Y, self.
|
|
556
|
+
return Variant._factory(SIGNATURE_TREE_Y, self._buf_ustr[self._pos - 1])
|
|
550
557
|
elif token_as_int == TOKEN_A_AS_INT:
|
|
551
558
|
if signature == "ay":
|
|
552
559
|
return Variant._factory(
|
|
@@ -600,39 +607,41 @@ class Unmarshaller:
|
|
|
600
607
|
)
|
|
601
608
|
else:
|
|
602
609
|
array_length = self._uint32_unpack(self._buf, self._pos - UINT32_SIZE)[0]
|
|
603
|
-
child_type
|
|
610
|
+
child_type = type_._child_0
|
|
604
611
|
token_as_int = child_type.token_as_int
|
|
605
612
|
|
|
606
|
-
if
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
+
if token_as_int in {
|
|
614
|
+
TOKEN_X_AS_INT,
|
|
615
|
+
TOKEN_T_AS_INT,
|
|
616
|
+
TOKEN_D_AS_INT,
|
|
617
|
+
TOKEN_LEFT_CURLY_AS_INT,
|
|
618
|
+
TOKEN_LEFT_PAREN_AS_INT,
|
|
619
|
+
}:
|
|
613
620
|
# the first alignment is not included in the array size
|
|
614
621
|
self._pos += -self._pos & 7 # align 8
|
|
615
622
|
|
|
616
623
|
if token_as_int == TOKEN_Y_AS_INT:
|
|
617
624
|
self._pos += array_length
|
|
618
|
-
|
|
625
|
+
if cython.compiled:
|
|
626
|
+
if self._buf_len < self._pos:
|
|
627
|
+
raise IndexError("Not enough data to read byte")
|
|
628
|
+
return self._buf_ustr[self._pos - array_length : self._pos]
|
|
619
629
|
|
|
620
630
|
if token_as_int == TOKEN_LEFT_CURLY_AS_INT:
|
|
621
631
|
result_dict: dict[Any, Any] = {}
|
|
622
632
|
key: str | int
|
|
623
633
|
beginning_pos = self._pos
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
child_1 = children[1]
|
|
634
|
+
child_0 = child_type._child_0
|
|
635
|
+
child_1 = child_type._child_1
|
|
627
636
|
child_0_token_as_int = child_0.token_as_int
|
|
628
637
|
child_1_token_as_int = child_1.token_as_int
|
|
629
638
|
# Strings with variant values are the most common case
|
|
630
639
|
# so we optimize for that by inlining the string reading
|
|
631
640
|
# and the variant reading here
|
|
632
641
|
if (
|
|
633
|
-
child_0_token_as_int
|
|
634
|
-
|
|
635
|
-
)
|
|
642
|
+
child_0_token_as_int in {TOKEN_O_AS_INT, TOKEN_S_AS_INT}
|
|
643
|
+
and child_1_token_as_int == TOKEN_V_AS_INT
|
|
644
|
+
):
|
|
636
645
|
while self._pos - beginning_pos < array_length:
|
|
637
646
|
self._pos += -self._pos & 7 # align 8
|
|
638
647
|
key = self._read_string_unpack()
|
|
@@ -646,9 +655,9 @@ class Unmarshaller:
|
|
|
646
655
|
key = self._read_uint16_unpack()
|
|
647
656
|
result_dict[key] = self._read_variant()
|
|
648
657
|
elif (
|
|
649
|
-
child_0_token_as_int
|
|
650
|
-
|
|
651
|
-
)
|
|
658
|
+
child_0_token_as_int in {TOKEN_O_AS_INT, TOKEN_S_AS_INT}
|
|
659
|
+
and child_1_token_as_int == TOKEN_A_AS_INT
|
|
660
|
+
):
|
|
652
661
|
while self._pos - beginning_pos < array_length:
|
|
653
662
|
self._pos += -self._pos & 7 # align 8
|
|
654
663
|
key = self._read_string_unpack()
|
|
@@ -693,6 +702,9 @@ class Unmarshaller:
|
|
|
693
702
|
# first we read the signature
|
|
694
703
|
signature_len = self._buf_ustr[self._pos] # byte
|
|
695
704
|
o = self._pos + 1
|
|
705
|
+
if cython.compiled:
|
|
706
|
+
if self._buf_len < o + signature_len:
|
|
707
|
+
raise IndexError("Not enough data to read signature")
|
|
696
708
|
self._pos += signature_len + 2 # one for the byte, one for the '\0'
|
|
697
709
|
if field_0 == HEADER_UNIX_FDS_IDX: # defined by self._unix_fds
|
|
698
710
|
continue
|
|
@@ -705,7 +717,7 @@ class Unmarshaller:
|
|
|
705
717
|
elif token_as_int == TOKEN_G_AS_INT:
|
|
706
718
|
headers[field_0] = self._read_signature()
|
|
707
719
|
else:
|
|
708
|
-
token = self.
|
|
720
|
+
token = self._buf_ustr[o : o + signature_len].decode()
|
|
709
721
|
# There shouldn't be any other types in the header
|
|
710
722
|
# but just in case, we'll read it using the slow path
|
|
711
723
|
headers[field_0] = self._readers[token](
|
|
@@ -6,9 +6,10 @@ import contextlib
|
|
|
6
6
|
import logging
|
|
7
7
|
import socket
|
|
8
8
|
from collections import deque
|
|
9
|
+
from collections.abc import Callable
|
|
9
10
|
from copy import copy
|
|
10
11
|
from functools import partial
|
|
11
|
-
from typing import Any
|
|
12
|
+
from typing import Any
|
|
12
13
|
|
|
13
14
|
from .. import introspection as intr
|
|
14
15
|
from ..auth import Authenticator, AuthExternal
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import enum
|
|
2
2
|
import os
|
|
3
|
-
from typing import Optional
|
|
4
3
|
|
|
5
4
|
from .errors import AuthError
|
|
6
5
|
|
|
@@ -65,10 +64,10 @@ class AuthExternal(Authenticator):
|
|
|
65
64
|
:sealso: https://dbus.freedesktop.org/doc/dbus-specification.html#auth-protocol
|
|
66
65
|
"""
|
|
67
66
|
|
|
68
|
-
def __init__(self, uid:
|
|
67
|
+
def __init__(self, uid: int | None = None) -> None:
|
|
69
68
|
self.negotiate_unix_fd: bool = False
|
|
70
69
|
self.negotiating_fds: bool = False
|
|
71
|
-
self.uid:
|
|
70
|
+
self.uid: int | None = uid
|
|
72
71
|
|
|
73
72
|
def _authentication_start(self, negotiate_unix_fd: bool = False) -> str:
|
|
74
73
|
self.negotiate_unix_fd = negotiate_unix_fd
|
|
@@ -108,15 +108,9 @@ class ErrorType(str, Enum):
|
|
|
108
108
|
:seealso: http://man7.org/linux/man-pages/man3/sd-bus-errors.3.html
|
|
109
109
|
"""
|
|
110
110
|
|
|
111
|
-
SERVICE_ERROR =
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
INTERNAL_ERROR = (
|
|
115
|
-
"com.dubstepdish.dbus.next.InternalError"
|
|
116
|
-
) #: A custom error to indicate something went wrong with the library.
|
|
117
|
-
CLIENT_ERROR = (
|
|
118
|
-
"com.dubstepdish.dbus.next.ClientError"
|
|
119
|
-
) #: A custom error to indicate something went wrong with the client.
|
|
111
|
+
SERVICE_ERROR = "com.dubstepdish.dbus.next.ServiceError" #: A custom error to indicate an exported service threw an exception.
|
|
112
|
+
INTERNAL_ERROR = "com.dubstepdish.dbus.next.InternalError" #: A custom error to indicate something went wrong with the library.
|
|
113
|
+
CLIENT_ERROR = "com.dubstepdish.dbus.next.ClientError" #: A custom error to indicate something went wrong with the client.
|
|
120
114
|
|
|
121
115
|
FAILED = "org.freedesktop.DBus.Error.Failed"
|
|
122
116
|
NO_MEMORY = "org.freedesktop.DBus.Error.NoMemory"
|
|
@@ -1,6 +1,3 @@
|
|
|
1
|
-
from typing import Optional, Union
|
|
2
|
-
|
|
3
|
-
|
|
4
1
|
class SignatureBodyMismatchError(ValueError):
|
|
5
2
|
pass
|
|
6
3
|
|
|
@@ -60,7 +57,7 @@ from .validators import assert_interface_name_valid # noqa: E402
|
|
|
60
57
|
|
|
61
58
|
class DBusError(Exception):
|
|
62
59
|
def __init__(
|
|
63
|
-
self, type_:
|
|
60
|
+
self, type_: ErrorType | str, text: str, reply: Message | None = None
|
|
64
61
|
) -> None:
|
|
65
62
|
super().__init__(text)
|
|
66
63
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import io
|
|
2
2
|
import logging
|
|
3
3
|
import traceback
|
|
4
|
-
from
|
|
4
|
+
from collections.abc import Callable
|
|
5
5
|
|
|
6
6
|
from .. import introspection as intr
|
|
7
7
|
from .._private.unmarshaller import Unmarshaller
|
|
@@ -161,9 +161,9 @@ class MessageBus(BaseMessageBus):
|
|
|
161
161
|
|
|
162
162
|
def __init__(
|
|
163
163
|
self,
|
|
164
|
-
bus_address:
|
|
164
|
+
bus_address: str | None = None,
|
|
165
165
|
bus_type: BusType = BusType.SESSION,
|
|
166
|
-
auth:
|
|
166
|
+
auth: Authenticator | None = None,
|
|
167
167
|
):
|
|
168
168
|
if _import_error:
|
|
169
169
|
raise _import_error
|
|
@@ -188,9 +188,8 @@ class MessageBus(BaseMessageBus):
|
|
|
188
188
|
|
|
189
189
|
def connect(
|
|
190
190
|
self,
|
|
191
|
-
connect_notify:
|
|
192
|
-
|
|
193
|
-
] = None,
|
|
191
|
+
connect_notify: None
|
|
192
|
+
| (Callable[["MessageBus", Exception | None], None]) = None,
|
|
194
193
|
):
|
|
195
194
|
"""Connect this message bus to the DBus daemon.
|
|
196
195
|
|
|
@@ -277,9 +276,8 @@ class MessageBus(BaseMessageBus):
|
|
|
277
276
|
def call(
|
|
278
277
|
self,
|
|
279
278
|
msg: Message,
|
|
280
|
-
reply_notify:
|
|
281
|
-
|
|
282
|
-
] = None,
|
|
279
|
+
reply_notify: None
|
|
280
|
+
| (Callable[[Message | None, Exception | None], None]) = None,
|
|
283
281
|
):
|
|
284
282
|
"""Send a method call and asynchronously wait for a reply from the DBus
|
|
285
283
|
daemon.
|
|
@@ -293,7 +291,7 @@ class MessageBus(BaseMessageBus):
|
|
|
293
291
|
BaseMessageBus._check_callback_type(reply_notify)
|
|
294
292
|
self._call(msg, reply_notify)
|
|
295
293
|
|
|
296
|
-
def call_sync(self, msg: Message) ->
|
|
294
|
+
def call_sync(self, msg: Message) -> Message | None:
|
|
297
295
|
"""Send a method call and synchronously wait for a reply from the DBus
|
|
298
296
|
daemon.
|
|
299
297
|
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import xml.etree.ElementTree as ET
|
|
2
|
-
from typing import Union
|
|
3
2
|
|
|
4
3
|
from .. import introspection as intr
|
|
5
4
|
from ..constants import ErrorType
|
|
@@ -307,7 +306,7 @@ class ProxyObject(BaseProxyObject):
|
|
|
307
306
|
self,
|
|
308
307
|
bus_name: str,
|
|
309
308
|
path: str,
|
|
310
|
-
introspection:
|
|
309
|
+
introspection: intr.Node | str | ET.Element,
|
|
311
310
|
bus: BaseMessageBus,
|
|
312
311
|
):
|
|
313
312
|
super().__init__(bus_name, path, introspection, bus, ProxyInterface)
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import xml.etree.ElementTree as ET
|
|
2
|
-
from typing import Optional, Union
|
|
3
2
|
|
|
4
3
|
from .constants import ArgDirection, PropertyAccess
|
|
5
4
|
from .errors import InvalidIntrospectionError
|
|
@@ -50,10 +49,10 @@ class Arg:
|
|
|
50
49
|
|
|
51
50
|
def __init__(
|
|
52
51
|
self,
|
|
53
|
-
signature:
|
|
54
|
-
direction:
|
|
55
|
-
name:
|
|
56
|
-
annotations:
|
|
52
|
+
signature: SignatureType | str,
|
|
53
|
+
direction: ArgDirection | None = None,
|
|
54
|
+
name: str | None = None,
|
|
55
|
+
annotations: dict[str, str] | None = None,
|
|
57
56
|
):
|
|
58
57
|
type_ = None
|
|
59
58
|
if type(signature) is SignatureType:
|
|
@@ -132,9 +131,9 @@ class Signal:
|
|
|
132
131
|
|
|
133
132
|
def __init__(
|
|
134
133
|
self,
|
|
135
|
-
name:
|
|
136
|
-
args:
|
|
137
|
-
annotations:
|
|
134
|
+
name: str,
|
|
135
|
+
args: list[Arg] | None = None,
|
|
136
|
+
annotations: dict[str, str] | None = None,
|
|
138
137
|
):
|
|
139
138
|
if name is not None:
|
|
140
139
|
assert_member_name_valid(name)
|
|
@@ -210,7 +209,7 @@ class Method:
|
|
|
210
209
|
name: str,
|
|
211
210
|
in_args: list[Arg] = [],
|
|
212
211
|
out_args: list[Arg] = [],
|
|
213
|
-
annotations:
|
|
212
|
+
annotations: dict[str, str] | None = None,
|
|
214
213
|
):
|
|
215
214
|
assert_member_name_valid(name)
|
|
216
215
|
|
|
@@ -295,7 +294,7 @@ class Property:
|
|
|
295
294
|
name: str,
|
|
296
295
|
signature: str,
|
|
297
296
|
access: PropertyAccess = PropertyAccess.READWRITE,
|
|
298
|
-
annotations:
|
|
297
|
+
annotations: dict[str, str] | None = None,
|
|
299
298
|
validate: bool = True,
|
|
300
299
|
):
|
|
301
300
|
if validate:
|
|
@@ -373,10 +372,10 @@ class Interface:
|
|
|
373
372
|
def __init__(
|
|
374
373
|
self,
|
|
375
374
|
name: str,
|
|
376
|
-
methods:
|
|
377
|
-
signals:
|
|
378
|
-
properties:
|
|
379
|
-
annotations:
|
|
375
|
+
methods: list[Method] | None = None,
|
|
376
|
+
signals: list[Signal] | None = None,
|
|
377
|
+
properties: list[Property] | None = None,
|
|
378
|
+
annotations: dict[str, str] | None = None,
|
|
380
379
|
):
|
|
381
380
|
assert_interface_name_valid(name)
|
|
382
381
|
|
|
@@ -467,15 +466,15 @@ class Node:
|
|
|
467
466
|
|
|
468
467
|
def __init__(
|
|
469
468
|
self,
|
|
470
|
-
name:
|
|
471
|
-
interfaces:
|
|
469
|
+
name: str | None = None,
|
|
470
|
+
interfaces: list[Interface] | None = None,
|
|
472
471
|
is_root: bool = True,
|
|
473
472
|
):
|
|
474
473
|
if not is_root and not name:
|
|
475
474
|
raise InvalidIntrospectionError('child nodes must have a "name" attribute')
|
|
476
475
|
|
|
477
476
|
self.interfaces = interfaces if interfaces is not None else []
|
|
478
|
-
self.nodes = []
|
|
477
|
+
self.nodes: list[Node] = []
|
|
479
478
|
self.name = name
|
|
480
479
|
self.is_root = is_root
|
|
481
480
|
|
|
@@ -564,8 +563,8 @@ class Node:
|
|
|
564
563
|
elem.text = i + " "
|
|
565
564
|
if not elem.tail or not elem.tail.strip():
|
|
566
565
|
elem.tail = i
|
|
567
|
-
for
|
|
568
|
-
indent(
|
|
566
|
+
for elem_ in elem:
|
|
567
|
+
indent(elem_, level + 1)
|
|
569
568
|
if not elem.tail or not elem.tail.strip():
|
|
570
569
|
elem.tail = i
|
|
571
570
|
elif level and (not elem.tail or not elem.tail.strip()):
|
|
@@ -576,7 +575,7 @@ class Node:
|
|
|
576
575
|
return header + ET.tostring(xml, encoding="unicode").rstrip()
|
|
577
576
|
|
|
578
577
|
@staticmethod
|
|
579
|
-
def default(name:
|
|
578
|
+
def default(name: str | None = None) -> "Node":
|
|
580
579
|
"""Create a :class:`Node` with the default interfaces supported by this library.
|
|
581
580
|
|
|
582
581
|
The default interfaces include:
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
from typing import Any
|
|
1
|
+
from typing import Any
|
|
2
2
|
|
|
3
3
|
from ._private.constants import LITTLE_ENDIAN, PROTOCOL_VERSION, HeaderField
|
|
4
4
|
from ._private.marshaller import Marshaller
|
|
@@ -112,19 +112,19 @@ class Message:
|
|
|
112
112
|
|
|
113
113
|
def __init__(
|
|
114
114
|
self,
|
|
115
|
-
destination:
|
|
116
|
-
path:
|
|
117
|
-
interface:
|
|
118
|
-
member:
|
|
115
|
+
destination: str | None = None,
|
|
116
|
+
path: str | None = None,
|
|
117
|
+
interface: str | None = None,
|
|
118
|
+
member: str | None = None,
|
|
119
119
|
message_type: MessageType = MESSAGE_TYPE_METHOD_CALL,
|
|
120
|
-
flags:
|
|
121
|
-
error_name:
|
|
122
|
-
reply_serial:
|
|
123
|
-
sender:
|
|
120
|
+
flags: MessageFlag | int = MESSAGE_FLAG_NONE,
|
|
121
|
+
error_name: str | ErrorType | None = None,
|
|
122
|
+
reply_serial: int | None = None,
|
|
123
|
+
sender: str | None = None,
|
|
124
124
|
unix_fds: list[int] = [],
|
|
125
|
-
signature:
|
|
125
|
+
signature: SignatureTree | str | None = None,
|
|
126
126
|
body: list[Any] = [],
|
|
127
|
-
serial:
|
|
127
|
+
serial: int | None = None,
|
|
128
128
|
validate: bool = True,
|
|
129
129
|
) -> None:
|
|
130
130
|
self._fast_init(
|
|
@@ -148,13 +148,13 @@ class Message:
|
|
|
148
148
|
|
|
149
149
|
def _fast_init(
|
|
150
150
|
self,
|
|
151
|
-
destination:
|
|
152
|
-
path:
|
|
153
|
-
interface:
|
|
154
|
-
member:
|
|
151
|
+
destination: _str | None,
|
|
152
|
+
path: _str | None,
|
|
153
|
+
interface: _str | None,
|
|
154
|
+
member: _str | None,
|
|
155
155
|
message_type: _MessageType,
|
|
156
156
|
flags: _MessageFlag,
|
|
157
|
-
error_name:
|
|
157
|
+
error_name: _str | None,
|
|
158
158
|
reply_serial: _int,
|
|
159
159
|
sender: _str,
|
|
160
160
|
unix_fds: _list[int],
|
|
@@ -216,7 +216,7 @@ class Message:
|
|
|
216
216
|
|
|
217
217
|
@staticmethod
|
|
218
218
|
def new_error(
|
|
219
|
-
msg: "Message", error_name:
|
|
219
|
+
msg: "Message", error_name: str | ErrorType, error_text: str
|
|
220
220
|
) -> "Message":
|
|
221
221
|
"""A convenience constructor to create an error message in reply to the given message.
|
|
222
222
|
|
|
@@ -280,8 +280,8 @@ class Message:
|
|
|
280
280
|
interface: str,
|
|
281
281
|
member: str,
|
|
282
282
|
signature: str = "",
|
|
283
|
-
body:
|
|
284
|
-
unix_fds:
|
|
283
|
+
body: list[Any] | None = None,
|
|
284
|
+
unix_fds: list[int] | None = None,
|
|
285
285
|
) -> "Message":
|
|
286
286
|
"""A convenience constructor to create a new signal message.
|
|
287
287
|
|
|
@@ -5,8 +5,9 @@ import logging
|
|
|
5
5
|
import socket
|
|
6
6
|
import traceback
|
|
7
7
|
import xml.etree.ElementTree as ET
|
|
8
|
+
from collections.abc import Callable
|
|
8
9
|
from functools import partial
|
|
9
|
-
from typing import TYPE_CHECKING, Any
|
|
10
|
+
from typing import TYPE_CHECKING, Any
|
|
10
11
|
|
|
11
12
|
from . import introspection as intr
|
|
12
13
|
from ._private.address import get_bus_address, parse_address
|
|
@@ -5,10 +5,9 @@ import inspect
|
|
|
5
5
|
import logging
|
|
6
6
|
import re
|
|
7
7
|
import xml.etree.ElementTree as ET
|
|
8
|
-
from collections.abc import Coroutine
|
|
8
|
+
from collections.abc import Callable, Coroutine
|
|
9
9
|
from dataclasses import dataclass
|
|
10
10
|
from functools import lru_cache
|
|
11
|
-
from typing import Callable
|
|
12
11
|
|
|
13
12
|
from . import introspection as intr
|
|
14
13
|
from . import message_bus
|
|
@@ -33,7 +33,7 @@ cdef class ServiceInterface:
|
|
|
33
33
|
cdef list __signals
|
|
34
34
|
cdef set __buses
|
|
35
35
|
cdef dict __handlers
|
|
36
|
-
cdef dict
|
|
36
|
+
cdef dict __handlers_by_name_signature
|
|
37
37
|
|
|
38
38
|
@cython.locals(handlers=dict,in_signature=str,method=_Method)
|
|
39
39
|
@staticmethod
|
|
@@ -3,8 +3,9 @@ from __future__ import annotations
|
|
|
3
3
|
import asyncio
|
|
4
4
|
import copy
|
|
5
5
|
import inspect
|
|
6
|
+
from collections.abc import Callable
|
|
6
7
|
from functools import wraps
|
|
7
|
-
from typing import TYPE_CHECKING, Any,
|
|
8
|
+
from typing import TYPE_CHECKING, Any, Protocol
|
|
8
9
|
|
|
9
10
|
from . import introspection as intr
|
|
10
11
|
from ._private.util import (
|
|
@@ -33,8 +34,7 @@ HandlerType = Callable[[Message, SendReply], None]
|
|
|
33
34
|
|
|
34
35
|
|
|
35
36
|
class _MethodCallbackProtocol(Protocol):
|
|
36
|
-
def __call__(self, interface: ServiceInterface, *args: Any) -> Any:
|
|
37
|
-
...
|
|
37
|
+
def __call__(self, interface: ServiceInterface, *args: Any) -> Any: ...
|
|
38
38
|
|
|
39
39
|
|
|
40
40
|
class _Method:
|
|
@@ -381,7 +381,7 @@ class ServiceInterface:
|
|
|
381
381
|
self.__handlers_by_name_signature: dict[
|
|
382
382
|
BaseMessageBus, dict[str, tuple[_Method, HandlerType]]
|
|
383
383
|
] = {}
|
|
384
|
-
for
|
|
384
|
+
for _, member in inspect.getmembers(type(self)):
|
|
385
385
|
member_dict = getattr(member, "__dict__", {})
|
|
386
386
|
if type(member) is _Property:
|
|
387
387
|
# XXX The getter and the setter may show up as different
|
|
@@ -516,6 +516,10 @@ class ServiceInterface:
|
|
|
516
516
|
bus: BaseMessageBus,
|
|
517
517
|
maker: Callable[[ServiceInterface, _Method], HandlerType],
|
|
518
518
|
) -> None:
|
|
519
|
+
if bus in interface.__buses:
|
|
520
|
+
raise ValueError(
|
|
521
|
+
"Same interface instance cannot be added to the same bus twice"
|
|
522
|
+
)
|
|
519
523
|
interface.__buses.add(bus)
|
|
520
524
|
interface.__handlers[bus] = {
|
|
521
525
|
method: maker(interface, method) for method in interface.__methods
|
|
@@ -668,8 +672,8 @@ class ServiceInterface:
|
|
|
668
672
|
else:
|
|
669
673
|
try:
|
|
670
674
|
result[prop.name] = Variant(prop.signature, value)
|
|
671
|
-
except SignatureBodyMismatchError as
|
|
672
|
-
result_error =
|
|
675
|
+
except SignatureBodyMismatchError as exc:
|
|
676
|
+
result_error = exc
|
|
673
677
|
del result[prop.name]
|
|
674
678
|
|
|
675
679
|
if any(v is None for v in result.values()):
|
|
@@ -1,11 +1,12 @@
|
|
|
1
|
+
from collections.abc import Callable
|
|
1
2
|
from functools import lru_cache
|
|
2
|
-
from typing import Any
|
|
3
|
+
from typing import Any
|
|
3
4
|
|
|
4
5
|
from .errors import InvalidSignatureError, SignatureBodyMismatchError
|
|
5
6
|
from .validators import is_object_path_valid
|
|
6
7
|
|
|
7
8
|
|
|
8
|
-
class SignatureType:
|
|
9
|
+
class SignatureType: # noqa: PLW1641
|
|
9
10
|
"""A class that represents a single complete type within a signature.
|
|
10
11
|
|
|
11
12
|
This class is not meant to be constructed directly. Use the :class:`SignatureTree`
|
|
@@ -21,14 +22,23 @@ class SignatureType:
|
|
|
21
22
|
"""
|
|
22
23
|
|
|
23
24
|
_tokens = "ybnqiuxtdsogavh({"
|
|
24
|
-
__slots__ = (
|
|
25
|
+
__slots__ = (
|
|
26
|
+
"_child_0",
|
|
27
|
+
"_child_1",
|
|
28
|
+
"_signature",
|
|
29
|
+
"children",
|
|
30
|
+
"token",
|
|
31
|
+
"token_as_int",
|
|
32
|
+
)
|
|
25
33
|
|
|
26
34
|
def __init__(self, token: str) -> None:
|
|
27
35
|
"""Init a new SignatureType."""
|
|
28
36
|
self.token: str = token
|
|
29
37
|
self.token_as_int = ord(token)
|
|
30
38
|
self.children: list[SignatureType] = []
|
|
31
|
-
self.
|
|
39
|
+
self._child_0: SignatureType | None = None
|
|
40
|
+
self._child_1: SignatureType | None = None
|
|
41
|
+
self._signature: str | None = None
|
|
32
42
|
|
|
33
43
|
def __eq__(self, other: object) -> bool:
|
|
34
44
|
"""Compare this type to another type or signature string."""
|
|
@@ -60,6 +70,18 @@ class SignatureType:
|
|
|
60
70
|
self._signature = self._collapse()
|
|
61
71
|
return self._signature
|
|
62
72
|
|
|
73
|
+
def _add_child(self, child: "SignatureType") -> None:
|
|
74
|
+
"""Add a child type to this type.
|
|
75
|
+
|
|
76
|
+
:param child: The child type to add.
|
|
77
|
+
:type child: :class:`SignatureType`
|
|
78
|
+
"""
|
|
79
|
+
if self._child_0 is None:
|
|
80
|
+
self._child_0 = child
|
|
81
|
+
elif self._child_1 is None:
|
|
82
|
+
self._child_1 = child
|
|
83
|
+
self.children.append(child)
|
|
84
|
+
|
|
63
85
|
@staticmethod
|
|
64
86
|
def _parse_next(signature: str) -> tuple["SignatureType", str]:
|
|
65
87
|
if not signature:
|
|
@@ -76,7 +98,7 @@ class SignatureType:
|
|
|
76
98
|
(child, signature) = SignatureType._parse_next(signature[1:])
|
|
77
99
|
if not child:
|
|
78
100
|
raise InvalidSignatureError("missing type for array")
|
|
79
|
-
self.
|
|
101
|
+
self._add_child(child)
|
|
80
102
|
return (self, signature)
|
|
81
103
|
if token == "(":
|
|
82
104
|
self = SignatureType("(")
|
|
@@ -85,7 +107,7 @@ class SignatureType:
|
|
|
85
107
|
(child, signature) = SignatureType._parse_next(signature)
|
|
86
108
|
if not signature:
|
|
87
109
|
raise InvalidSignatureError('missing closing ")" for struct')
|
|
88
|
-
self.
|
|
110
|
+
self._add_child(child)
|
|
89
111
|
if signature[0] == ")":
|
|
90
112
|
return (self, signature[1:])
|
|
91
113
|
elif token == "{":
|
|
@@ -94,13 +116,13 @@ class SignatureType:
|
|
|
94
116
|
(key_child, signature) = SignatureType._parse_next(signature)
|
|
95
117
|
if not key_child or len(key_child.children):
|
|
96
118
|
raise InvalidSignatureError("expected a simple type for dict entry key")
|
|
97
|
-
self.
|
|
119
|
+
self._add_child(key_child)
|
|
98
120
|
(value_child, signature) = SignatureType._parse_next(signature)
|
|
99
121
|
if not value_child:
|
|
100
122
|
raise InvalidSignatureError("expected a value for dict entry")
|
|
101
123
|
if not signature or signature[0] != "}":
|
|
102
124
|
raise InvalidSignatureError('missing closing "}" for dict entry')
|
|
103
|
-
self.
|
|
125
|
+
self._add_child(value_child)
|
|
104
126
|
return (self, signature[1:])
|
|
105
127
|
|
|
106
128
|
# basic type
|
|
@@ -316,7 +338,7 @@ class SignatureType:
|
|
|
316
338
|
}
|
|
317
339
|
|
|
318
340
|
|
|
319
|
-
class SignatureTree:
|
|
341
|
+
class SignatureTree: # noqa: PLW1641
|
|
320
342
|
"""A class that represents a signature as a tree structure for conveniently
|
|
321
343
|
working with DBus signatures.
|
|
322
344
|
|
|
@@ -381,7 +403,7 @@ class SignatureTree:
|
|
|
381
403
|
return True
|
|
382
404
|
|
|
383
405
|
|
|
384
|
-
class Variant:
|
|
406
|
+
class Variant: # noqa: PLW1641
|
|
385
407
|
"""A class to represent a DBus variant (type "v").
|
|
386
408
|
|
|
387
409
|
This class is used in message bodies to represent variants. The user can
|
|
@@ -403,7 +425,7 @@ class Variant:
|
|
|
403
425
|
|
|
404
426
|
def __init__(
|
|
405
427
|
self,
|
|
406
|
-
signature:
|
|
428
|
+
signature: str | SignatureTree | SignatureType,
|
|
407
429
|
value: Any,
|
|
408
430
|
verify: bool = True,
|
|
409
431
|
) -> None:
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|