spoolman 0.1.0__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.
- spoolman-0.1.0/LICENSE +21 -0
- spoolman-0.1.0/PKG-INFO +218 -0
- spoolman-0.1.0/README.md +187 -0
- spoolman-0.1.0/pyproject.toml +149 -0
- spoolman-0.1.0/src/spoolman/__init__.py +16 -0
- spoolman-0.1.0/src/spoolman/exceptions.py +17 -0
- spoolman-0.1.0/src/spoolman/models.py +77 -0
- spoolman-0.1.0/src/spoolman/py.typed +0 -0
- spoolman-0.1.0/src/spoolman/spoolman.py +232 -0
spoolman-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 Klaas Schoute
|
|
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 all
|
|
13
|
+
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 THE
|
|
21
|
+
SOFTWARE.
|
spoolman-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: spoolman
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Asynchronous Python client for Spoolman API
|
|
5
|
+
Home-page: https://github.com/klaasnicolaas/python-spoolman
|
|
6
|
+
License: MIT
|
|
7
|
+
Keywords: spoolman,api,async,client
|
|
8
|
+
Author: Klaas Schoute
|
|
9
|
+
Author-email: hello@student-techlife.com
|
|
10
|
+
Maintainer: Klaas Schoute
|
|
11
|
+
Maintainer-email: hello@student-techlife.com
|
|
12
|
+
Requires-Python: >=3.11,<4.0
|
|
13
|
+
Classifier: Framework :: AsyncIO
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
16
|
+
Classifier: Natural Language :: English
|
|
17
|
+
Classifier: Programming Language :: Python :: 3
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
21
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
22
|
+
Requires-Dist: aiohttp (>=3.0.0)
|
|
23
|
+
Requires-Dist: mashumaro (>=3.15,<4.0)
|
|
24
|
+
Requires-Dist: yarl (>=1.6.0)
|
|
25
|
+
Project-URL: Bug Tracker, https://github.com/klaasnicolaas/python-spoolman/issues
|
|
26
|
+
Project-URL: Changelog, https://github.com/klaasnicolaas/python-spoolman/releases
|
|
27
|
+
Project-URL: Documentation, https://github.com/klaasnicolaas/python-spoolman
|
|
28
|
+
Project-URL: Repository, https://github.com/klaasnicolaas/python-spoolman
|
|
29
|
+
Description-Content-Type: text/markdown
|
|
30
|
+
|
|
31
|
+
<!-- Banner -->
|
|
32
|
+

|
|
33
|
+
|
|
34
|
+
<!-- PROJECT SHIELDS -->
|
|
35
|
+
[![GitHub Release][releases-shield]][releases]
|
|
36
|
+
[![Python Versions][python-versions-shield]][pypi]
|
|
37
|
+
![Project Stage][project-stage-shield]
|
|
38
|
+
![Project Maintenance][maintenance-shield]
|
|
39
|
+
[![License][license-shield]](LICENSE)
|
|
40
|
+
|
|
41
|
+
[![GitHub Activity][commits-shield]][commits-url]
|
|
42
|
+
[![PyPi Downloads][downloads-shield]][downloads-url]
|
|
43
|
+
[![GitHub Last Commit][last-commit-shield]][commits-url]
|
|
44
|
+
[![Open in Dev Containers][devcontainer-shield]][devcontainer]
|
|
45
|
+
|
|
46
|
+
[![Build Status][build-shield]][build-url]
|
|
47
|
+
[![Typing Status][typing-shield]][typing-url]
|
|
48
|
+
[![Code Coverage][codecov-shield]][codecov-url]
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
Asynchronous Python client for [Spoolman][spoolman].
|
|
52
|
+
|
|
53
|
+
## About
|
|
54
|
+
|
|
55
|
+
Spoolman is a self-hosted platform for managing 3D printer filament spools. It integrates with popular 3D printing software to track spool weights in real time, providing instant insights into filament usage.
|
|
56
|
+
|
|
57
|
+
## Installation
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
pip install spoolman
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Data
|
|
64
|
+
|
|
65
|
+
- Application info and health
|
|
66
|
+
- Filaments
|
|
67
|
+
- Spools
|
|
68
|
+
- Vendors
|
|
69
|
+
|
|
70
|
+
### Example
|
|
71
|
+
|
|
72
|
+
```python
|
|
73
|
+
import asyncio
|
|
74
|
+
|
|
75
|
+
from spoolman import Spoolman
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
async def main() -> None:
|
|
79
|
+
"""Show example on using this package."""
|
|
80
|
+
async with Spoolman(host="IP_ADDRESS") as client:
|
|
81
|
+
# Get all filaments
|
|
82
|
+
filaments = await client.get_filaments()
|
|
83
|
+
print(filaments)
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
if __name__ == "__main__":
|
|
87
|
+
asyncio.run(main())
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
More examples can be found in the [examples folder](./examples/).
|
|
91
|
+
|
|
92
|
+
## Class Parameters
|
|
93
|
+
|
|
94
|
+
| Parameter | value Type | Description |
|
|
95
|
+
| :-------- | :--------- | :---------------------------------------------------------------- |
|
|
96
|
+
| `host` | `str` | The IP address of your Spoolman instance. |
|
|
97
|
+
| `port` | `int` | The port of your Spoolman instance (optional). Default is `7912`. |
|
|
98
|
+
|
|
99
|
+
## Contributing
|
|
100
|
+
|
|
101
|
+
This is an active open-source project. We are always open to people who want to
|
|
102
|
+
use the code or contribute to it.
|
|
103
|
+
|
|
104
|
+
We've set up a separate document for our
|
|
105
|
+
[contribution guidelines](CONTRIBUTING.md).
|
|
106
|
+
|
|
107
|
+
Thank you for being involved! :heart_eyes:
|
|
108
|
+
|
|
109
|
+
## Setting up development environment
|
|
110
|
+
|
|
111
|
+
The simplest way to begin is by utilizing the [Dev Container][devcontainer]
|
|
112
|
+
feature of Visual Studio Code or by opening a CodeSpace directly on GitHub.
|
|
113
|
+
By clicking the button below you immediately start a Dev Container in Visual Studio Code.
|
|
114
|
+
|
|
115
|
+
[![Open in Dev Containers][devcontainer-shield]][devcontainer]
|
|
116
|
+
|
|
117
|
+
This Python project relies on [Poetry][poetry] as its dependency manager,
|
|
118
|
+
providing comprehensive management and control over project dependencies.
|
|
119
|
+
|
|
120
|
+
You need at least:
|
|
121
|
+
|
|
122
|
+
- Python 3.11+
|
|
123
|
+
- [Poetry][poetry-install]
|
|
124
|
+
|
|
125
|
+
### Installation
|
|
126
|
+
|
|
127
|
+
Install all packages, including all development requirements:
|
|
128
|
+
|
|
129
|
+
```bash
|
|
130
|
+
poetry install
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
_Poetry creates by default an virtual environment where it installs all
|
|
134
|
+
necessary pip packages_.
|
|
135
|
+
|
|
136
|
+
### Pre-commit
|
|
137
|
+
|
|
138
|
+
This repository uses the [pre-commit][pre-commit] framework, all changes
|
|
139
|
+
are linted and tested with each commit. To setup the pre-commit check, run:
|
|
140
|
+
|
|
141
|
+
```bash
|
|
142
|
+
poetry run pre-commit install
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
And to run all checks and tests manually, use the following command:
|
|
146
|
+
|
|
147
|
+
```bash
|
|
148
|
+
poetry run pre-commit run --all-files
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
### Testing
|
|
152
|
+
|
|
153
|
+
It uses [pytest](https://docs.pytest.org/en/stable/) as the test framework. To run the tests:
|
|
154
|
+
|
|
155
|
+
```bash
|
|
156
|
+
poetry run pytest
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
To update the [syrupy](https://github.com/tophat/syrupy) snapshot tests:
|
|
160
|
+
|
|
161
|
+
```bash
|
|
162
|
+
poetry run pytest --snapshot-update
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
## License
|
|
166
|
+
|
|
167
|
+
MIT License
|
|
168
|
+
|
|
169
|
+
Copyright (c) 2024 Klaas Schoute
|
|
170
|
+
|
|
171
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
172
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
173
|
+
in the Software without restriction, including without limitation the rights
|
|
174
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
175
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
176
|
+
furnished to do so, subject to the following conditions:
|
|
177
|
+
|
|
178
|
+
The above copyright notice and this permission notice shall be included in all
|
|
179
|
+
copies or substantial portions of the Software.
|
|
180
|
+
|
|
181
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
182
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
183
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
184
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
185
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
186
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
187
|
+
SOFTWARE.
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
<!-- LINKS FROM PLATFORM -->
|
|
191
|
+
[spoolman]: https://github.com/Donkie/Spoolman
|
|
192
|
+
|
|
193
|
+
<!-- MARKDOWN LINKS & IMAGES -->
|
|
194
|
+
[build-shield]: https://github.com/klaasnicolaas/python-spoolman/actions/workflows/tests.yaml/badge.svg
|
|
195
|
+
[build-url]: https://github.com/klaasnicolaas/python-spoolman/actions/workflows/tests.yaml
|
|
196
|
+
[codecov-shield]: https://codecov.io/gh/klaasnicolaas/python-spoolman/branch/main/graph/badge.svg?token=C92VQ5QJ21
|
|
197
|
+
[codecov-url]: https://codecov.io/gh/klaasnicolaas/python-spoolman
|
|
198
|
+
[commits-shield]: https://img.shields.io/github/commit-activity/y/klaasnicolaas/python-spoolman.svg
|
|
199
|
+
[commits-url]: https://github.com/klaasnicolaas/python-spoolman/commits/main
|
|
200
|
+
[devcontainer-shield]: https://img.shields.io/static/v1?label=Dev%20Containers&message=Open&color=blue&logo=visualstudiocode
|
|
201
|
+
[devcontainer]: https://vscode.dev/redirect?url=vscode://ms-vscode-remote.remote-containers/cloneInVolume?url=https://github.com/klaasnicolaas/python-spoolman
|
|
202
|
+
[downloads-shield]: https://img.shields.io/pypi/dm/spoolman
|
|
203
|
+
[downloads-url]: https://pypistats.org/packages/spoolman
|
|
204
|
+
[last-commit-shield]: https://img.shields.io/github/last-commit/klaasnicolaas/python-spoolman.svg
|
|
205
|
+
[license-shield]: https://img.shields.io/github/license/klaasnicolaas/python-spoolman.svg
|
|
206
|
+
[maintenance-shield]: https://img.shields.io/maintenance/yes/2024.svg
|
|
207
|
+
[project-stage-shield]: https://img.shields.io/badge/project%20stage-experimental-yellow.svg
|
|
208
|
+
[pypi]: https://pypi.org/project/spoolman/
|
|
209
|
+
[python-versions-shield]: https://img.shields.io/pypi/pyversions/spoolman
|
|
210
|
+
[releases-shield]: https://img.shields.io/github/release/klaasnicolaas/python-spoolman.svg
|
|
211
|
+
[releases]: https://github.com/klaasnicolaas/python-spoolman/releases
|
|
212
|
+
[typing-shield]: https://github.com/klaasnicolaas/python-spoolman/actions/workflows/typing.yaml/badge.svg
|
|
213
|
+
[typing-url]: https://github.com/klaasnicolaas/python-spoolman/actions/workflows/typing.yaml
|
|
214
|
+
|
|
215
|
+
[poetry-install]: https://python-poetry.org/docs/#installation
|
|
216
|
+
[poetry]: https://python-poetry.org
|
|
217
|
+
[pre-commit]: https://pre-commit.com
|
|
218
|
+
|
spoolman-0.1.0/README.md
ADDED
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
<!-- Banner -->
|
|
2
|
+

|
|
3
|
+
|
|
4
|
+
<!-- PROJECT SHIELDS -->
|
|
5
|
+
[![GitHub Release][releases-shield]][releases]
|
|
6
|
+
[![Python Versions][python-versions-shield]][pypi]
|
|
7
|
+
![Project Stage][project-stage-shield]
|
|
8
|
+
![Project Maintenance][maintenance-shield]
|
|
9
|
+
[![License][license-shield]](LICENSE)
|
|
10
|
+
|
|
11
|
+
[![GitHub Activity][commits-shield]][commits-url]
|
|
12
|
+
[![PyPi Downloads][downloads-shield]][downloads-url]
|
|
13
|
+
[![GitHub Last Commit][last-commit-shield]][commits-url]
|
|
14
|
+
[![Open in Dev Containers][devcontainer-shield]][devcontainer]
|
|
15
|
+
|
|
16
|
+
[![Build Status][build-shield]][build-url]
|
|
17
|
+
[![Typing Status][typing-shield]][typing-url]
|
|
18
|
+
[![Code Coverage][codecov-shield]][codecov-url]
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
Asynchronous Python client for [Spoolman][spoolman].
|
|
22
|
+
|
|
23
|
+
## About
|
|
24
|
+
|
|
25
|
+
Spoolman is a self-hosted platform for managing 3D printer filament spools. It integrates with popular 3D printing software to track spool weights in real time, providing instant insights into filament usage.
|
|
26
|
+
|
|
27
|
+
## Installation
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
pip install spoolman
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Data
|
|
34
|
+
|
|
35
|
+
- Application info and health
|
|
36
|
+
- Filaments
|
|
37
|
+
- Spools
|
|
38
|
+
- Vendors
|
|
39
|
+
|
|
40
|
+
### Example
|
|
41
|
+
|
|
42
|
+
```python
|
|
43
|
+
import asyncio
|
|
44
|
+
|
|
45
|
+
from spoolman import Spoolman
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
async def main() -> None:
|
|
49
|
+
"""Show example on using this package."""
|
|
50
|
+
async with Spoolman(host="IP_ADDRESS") as client:
|
|
51
|
+
# Get all filaments
|
|
52
|
+
filaments = await client.get_filaments()
|
|
53
|
+
print(filaments)
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
if __name__ == "__main__":
|
|
57
|
+
asyncio.run(main())
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
More examples can be found in the [examples folder](./examples/).
|
|
61
|
+
|
|
62
|
+
## Class Parameters
|
|
63
|
+
|
|
64
|
+
| Parameter | value Type | Description |
|
|
65
|
+
| :-------- | :--------- | :---------------------------------------------------------------- |
|
|
66
|
+
| `host` | `str` | The IP address of your Spoolman instance. |
|
|
67
|
+
| `port` | `int` | The port of your Spoolman instance (optional). Default is `7912`. |
|
|
68
|
+
|
|
69
|
+
## Contributing
|
|
70
|
+
|
|
71
|
+
This is an active open-source project. We are always open to people who want to
|
|
72
|
+
use the code or contribute to it.
|
|
73
|
+
|
|
74
|
+
We've set up a separate document for our
|
|
75
|
+
[contribution guidelines](CONTRIBUTING.md).
|
|
76
|
+
|
|
77
|
+
Thank you for being involved! :heart_eyes:
|
|
78
|
+
|
|
79
|
+
## Setting up development environment
|
|
80
|
+
|
|
81
|
+
The simplest way to begin is by utilizing the [Dev Container][devcontainer]
|
|
82
|
+
feature of Visual Studio Code or by opening a CodeSpace directly on GitHub.
|
|
83
|
+
By clicking the button below you immediately start a Dev Container in Visual Studio Code.
|
|
84
|
+
|
|
85
|
+
[![Open in Dev Containers][devcontainer-shield]][devcontainer]
|
|
86
|
+
|
|
87
|
+
This Python project relies on [Poetry][poetry] as its dependency manager,
|
|
88
|
+
providing comprehensive management and control over project dependencies.
|
|
89
|
+
|
|
90
|
+
You need at least:
|
|
91
|
+
|
|
92
|
+
- Python 3.11+
|
|
93
|
+
- [Poetry][poetry-install]
|
|
94
|
+
|
|
95
|
+
### Installation
|
|
96
|
+
|
|
97
|
+
Install all packages, including all development requirements:
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
poetry install
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
_Poetry creates by default an virtual environment where it installs all
|
|
104
|
+
necessary pip packages_.
|
|
105
|
+
|
|
106
|
+
### Pre-commit
|
|
107
|
+
|
|
108
|
+
This repository uses the [pre-commit][pre-commit] framework, all changes
|
|
109
|
+
are linted and tested with each commit. To setup the pre-commit check, run:
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
poetry run pre-commit install
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
And to run all checks and tests manually, use the following command:
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
poetry run pre-commit run --all-files
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
### Testing
|
|
122
|
+
|
|
123
|
+
It uses [pytest](https://docs.pytest.org/en/stable/) as the test framework. To run the tests:
|
|
124
|
+
|
|
125
|
+
```bash
|
|
126
|
+
poetry run pytest
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
To update the [syrupy](https://github.com/tophat/syrupy) snapshot tests:
|
|
130
|
+
|
|
131
|
+
```bash
|
|
132
|
+
poetry run pytest --snapshot-update
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
## License
|
|
136
|
+
|
|
137
|
+
MIT License
|
|
138
|
+
|
|
139
|
+
Copyright (c) 2024 Klaas Schoute
|
|
140
|
+
|
|
141
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
142
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
143
|
+
in the Software without restriction, including without limitation the rights
|
|
144
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
145
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
146
|
+
furnished to do so, subject to the following conditions:
|
|
147
|
+
|
|
148
|
+
The above copyright notice and this permission notice shall be included in all
|
|
149
|
+
copies or substantial portions of the Software.
|
|
150
|
+
|
|
151
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
152
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
153
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
154
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
155
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
156
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
157
|
+
SOFTWARE.
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
<!-- LINKS FROM PLATFORM -->
|
|
161
|
+
[spoolman]: https://github.com/Donkie/Spoolman
|
|
162
|
+
|
|
163
|
+
<!-- MARKDOWN LINKS & IMAGES -->
|
|
164
|
+
[build-shield]: https://github.com/klaasnicolaas/python-spoolman/actions/workflows/tests.yaml/badge.svg
|
|
165
|
+
[build-url]: https://github.com/klaasnicolaas/python-spoolman/actions/workflows/tests.yaml
|
|
166
|
+
[codecov-shield]: https://codecov.io/gh/klaasnicolaas/python-spoolman/branch/main/graph/badge.svg?token=C92VQ5QJ21
|
|
167
|
+
[codecov-url]: https://codecov.io/gh/klaasnicolaas/python-spoolman
|
|
168
|
+
[commits-shield]: https://img.shields.io/github/commit-activity/y/klaasnicolaas/python-spoolman.svg
|
|
169
|
+
[commits-url]: https://github.com/klaasnicolaas/python-spoolman/commits/main
|
|
170
|
+
[devcontainer-shield]: https://img.shields.io/static/v1?label=Dev%20Containers&message=Open&color=blue&logo=visualstudiocode
|
|
171
|
+
[devcontainer]: https://vscode.dev/redirect?url=vscode://ms-vscode-remote.remote-containers/cloneInVolume?url=https://github.com/klaasnicolaas/python-spoolman
|
|
172
|
+
[downloads-shield]: https://img.shields.io/pypi/dm/spoolman
|
|
173
|
+
[downloads-url]: https://pypistats.org/packages/spoolman
|
|
174
|
+
[last-commit-shield]: https://img.shields.io/github/last-commit/klaasnicolaas/python-spoolman.svg
|
|
175
|
+
[license-shield]: https://img.shields.io/github/license/klaasnicolaas/python-spoolman.svg
|
|
176
|
+
[maintenance-shield]: https://img.shields.io/maintenance/yes/2024.svg
|
|
177
|
+
[project-stage-shield]: https://img.shields.io/badge/project%20stage-experimental-yellow.svg
|
|
178
|
+
[pypi]: https://pypi.org/project/spoolman/
|
|
179
|
+
[python-versions-shield]: https://img.shields.io/pypi/pyversions/spoolman
|
|
180
|
+
[releases-shield]: https://img.shields.io/github/release/klaasnicolaas/python-spoolman.svg
|
|
181
|
+
[releases]: https://github.com/klaasnicolaas/python-spoolman/releases
|
|
182
|
+
[typing-shield]: https://github.com/klaasnicolaas/python-spoolman/actions/workflows/typing.yaml/badge.svg
|
|
183
|
+
[typing-url]: https://github.com/klaasnicolaas/python-spoolman/actions/workflows/typing.yaml
|
|
184
|
+
|
|
185
|
+
[poetry-install]: https://python-poetry.org/docs/#installation
|
|
186
|
+
[poetry]: https://python-poetry.org
|
|
187
|
+
[pre-commit]: https://pre-commit.com
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
[tool.poetry]
|
|
2
|
+
name = "spoolman"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
description = "Asynchronous Python client for Spoolman API"
|
|
5
|
+
authors = ["Klaas Schoute <hello@student-techlife.com>"]
|
|
6
|
+
maintainers = ["Klaas Schoute <hello@student-techlife.com>"]
|
|
7
|
+
license = "MIT"
|
|
8
|
+
readme = "README.md"
|
|
9
|
+
homepage = "https://github.com/klaasnicolaas/python-spoolman"
|
|
10
|
+
repository = "https://github.com/klaasnicolaas/python-spoolman"
|
|
11
|
+
documentation = "https://github.com/klaasnicolaas/python-spoolman"
|
|
12
|
+
keywords = ["spoolman", "api", "async", "client"]
|
|
13
|
+
classifiers = [
|
|
14
|
+
"Framework :: AsyncIO",
|
|
15
|
+
"Intended Audience :: Developers",
|
|
16
|
+
"License :: OSI Approved :: MIT License",
|
|
17
|
+
"Natural Language :: English",
|
|
18
|
+
"Programming Language :: Python :: 3.11",
|
|
19
|
+
"Programming Language :: Python :: 3.12",
|
|
20
|
+
"Programming Language :: Python :: 3.13",
|
|
21
|
+
"Programming Language :: Python :: 3",
|
|
22
|
+
"Topic :: Software Development :: Libraries :: Python Modules",
|
|
23
|
+
]
|
|
24
|
+
packages = [
|
|
25
|
+
{ include = "spoolman", from = "src"},
|
|
26
|
+
]
|
|
27
|
+
|
|
28
|
+
[tool.poetry.dependencies]
|
|
29
|
+
aiohttp = ">=3.0.0"
|
|
30
|
+
python = "^3.11"
|
|
31
|
+
yarl = ">=1.6.0"
|
|
32
|
+
mashumaro = "^3.15"
|
|
33
|
+
|
|
34
|
+
[tool.poetry.urls]
|
|
35
|
+
"Bug Tracker" = "https://github.com/klaasnicolaas/python-spoolman/issues"
|
|
36
|
+
Changelog = "https://github.com/klaasnicolaas/python-spoolman/releases"
|
|
37
|
+
|
|
38
|
+
[tool.poetry.group.dev.dependencies]
|
|
39
|
+
aresponses = "3.0.0"
|
|
40
|
+
codespell = "2.3.0"
|
|
41
|
+
covdefaults = "2.3.0"
|
|
42
|
+
coverage = {version = "7.6.10", extras = ["toml"]}
|
|
43
|
+
mypy = "1.13.0"
|
|
44
|
+
pre-commit = "4.0.1"
|
|
45
|
+
pre-commit-hooks = "5.0.0"
|
|
46
|
+
pylint = "3.3.3"
|
|
47
|
+
pytest = "8.3.4"
|
|
48
|
+
pytest-asyncio = "0.24.0"
|
|
49
|
+
pytest-cov = "6.0.0"
|
|
50
|
+
ruff = "0.8.0"
|
|
51
|
+
syrupy = "4.8.0"
|
|
52
|
+
yamllint = "1.35.1"
|
|
53
|
+
|
|
54
|
+
[tool.coverage.run]
|
|
55
|
+
plugins = ["covdefaults"]
|
|
56
|
+
source = ["spoolman"]
|
|
57
|
+
|
|
58
|
+
[tool.coverage.report]
|
|
59
|
+
fail_under = 90
|
|
60
|
+
show_missing = true
|
|
61
|
+
|
|
62
|
+
[tool.mypy]
|
|
63
|
+
# Specify the target platform details in config, so your developers are
|
|
64
|
+
# free to run mypy on Windows, Linux, or macOS and get consistent
|
|
65
|
+
# results.
|
|
66
|
+
platform = "linux"
|
|
67
|
+
python_version = "3.11"
|
|
68
|
+
|
|
69
|
+
# flake8-mypy expects the two following for sensible formatting
|
|
70
|
+
show_column_numbers = true
|
|
71
|
+
|
|
72
|
+
# show error messages from unrelated files
|
|
73
|
+
follow_imports = "normal"
|
|
74
|
+
|
|
75
|
+
# suppress errors about unsatisfied imports
|
|
76
|
+
ignore_missing_imports = true
|
|
77
|
+
|
|
78
|
+
# be strict
|
|
79
|
+
check_untyped_defs = true
|
|
80
|
+
disallow_any_generics = true
|
|
81
|
+
disallow_incomplete_defs = true
|
|
82
|
+
disallow_subclassing_any = true
|
|
83
|
+
disallow_untyped_calls = true
|
|
84
|
+
disallow_untyped_decorators = true
|
|
85
|
+
disallow_untyped_defs = true
|
|
86
|
+
no_implicit_optional = true
|
|
87
|
+
no_implicit_reexport = true
|
|
88
|
+
strict_optional = true
|
|
89
|
+
warn_incomplete_stub = true
|
|
90
|
+
warn_no_return = true
|
|
91
|
+
warn_redundant_casts = true
|
|
92
|
+
warn_return_any = true
|
|
93
|
+
warn_unused_configs = true
|
|
94
|
+
warn_unused_ignores = true
|
|
95
|
+
|
|
96
|
+
[tool.pylint.MASTER]
|
|
97
|
+
ignore = ["tests"]
|
|
98
|
+
|
|
99
|
+
[tool.pylint.BASIC]
|
|
100
|
+
good-names = ["_", "ex", "fp", "i", "id", "j", "k", "on", "Run", "T"]
|
|
101
|
+
|
|
102
|
+
[tool.pylint."MESSAGES CONTROL"]
|
|
103
|
+
disable= [
|
|
104
|
+
"duplicate-code",
|
|
105
|
+
"format",
|
|
106
|
+
"unsubscriptable-object",
|
|
107
|
+
]
|
|
108
|
+
|
|
109
|
+
[tool.pylint.SIMILARITIES]
|
|
110
|
+
ignore-imports = true
|
|
111
|
+
|
|
112
|
+
[tool.pylint.FORMAT]
|
|
113
|
+
max-line-length = 88
|
|
114
|
+
|
|
115
|
+
[tool.pylint.DESIGN]
|
|
116
|
+
max-attributes = 20
|
|
117
|
+
|
|
118
|
+
[tool.pytest.ini_options]
|
|
119
|
+
addopts = "--cov"
|
|
120
|
+
asyncio_mode = "auto"
|
|
121
|
+
|
|
122
|
+
[tool.ruff]
|
|
123
|
+
lint.select = ["ALL"]
|
|
124
|
+
lint.ignore = [
|
|
125
|
+
"ANN401", # Opinioated warning on disallowing dynamically typed expressions
|
|
126
|
+
"D203", # Conflicts with other rules
|
|
127
|
+
"D213", # Conflicts with other rules
|
|
128
|
+
"D417", # False positives in some occasions
|
|
129
|
+
"PLR2004", # Just annoying, not really useful
|
|
130
|
+
"SLOT000", # Has a bug with enums: https://github.com/astral-sh/ruff/issues/5748
|
|
131
|
+
|
|
132
|
+
# Conflicts with the Ruff formatter
|
|
133
|
+
"COM812",
|
|
134
|
+
"ISC001",
|
|
135
|
+
]
|
|
136
|
+
|
|
137
|
+
[tool.ruff.lint.flake8-pytest-style]
|
|
138
|
+
mark-parentheses = false
|
|
139
|
+
fixture-parentheses = false
|
|
140
|
+
|
|
141
|
+
[tool.ruff.lint.isort]
|
|
142
|
+
known-first-party = ["spoolman"]
|
|
143
|
+
|
|
144
|
+
[tool.ruff.lint.mccabe]
|
|
145
|
+
max-complexity = 25
|
|
146
|
+
|
|
147
|
+
[build-system]
|
|
148
|
+
build-backend = "poetry.core.masonry.api"
|
|
149
|
+
requires = ["poetry-core>=1.0.0"]
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"""Asynchronous Python client for Spoolman."""
|
|
2
|
+
|
|
3
|
+
from .exceptions import SpoolmanConnectionError, SpoolmanError, SpoolmanResponseError
|
|
4
|
+
from .models import Filament, Info, Spool, Vendor
|
|
5
|
+
from .spoolman import Spoolman
|
|
6
|
+
|
|
7
|
+
__all__ = [
|
|
8
|
+
"Filament",
|
|
9
|
+
"Info",
|
|
10
|
+
"Spool",
|
|
11
|
+
"Spoolman",
|
|
12
|
+
"SpoolmanConnectionError",
|
|
13
|
+
"SpoolmanError",
|
|
14
|
+
"SpoolmanResponseError",
|
|
15
|
+
"Vendor",
|
|
16
|
+
]
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"""Asynchronous Python client for Spoolman."""
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class SpoolmanError(Exception):
|
|
5
|
+
"""Base class for Spoolman exceptions."""
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class SpoolmanConnectionError(SpoolmanError):
|
|
9
|
+
"""Error raised when connection to the API fails."""
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class SpoolmanResponseError(SpoolmanError):
|
|
13
|
+
"""Error raised when the API returns a error."""
|
|
14
|
+
|
|
15
|
+
def __init__(self, data: dict[str, str], code: int) -> None:
|
|
16
|
+
"""Initialize the exception."""
|
|
17
|
+
super().__init__(f'{data["message"]} (code: {code})')
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
"""Asynchronous Python client for Spoolman."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from dataclasses import dataclass, field
|
|
6
|
+
from datetime import datetime # noqa: TC003
|
|
7
|
+
|
|
8
|
+
from mashumaro import DataClassDictMixin, field_options
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@dataclass
|
|
12
|
+
class Info(DataClassDictMixin):
|
|
13
|
+
"""Data class for the 'info' endpoint."""
|
|
14
|
+
|
|
15
|
+
version: str
|
|
16
|
+
debug_mode: bool
|
|
17
|
+
automatic_backups: bool
|
|
18
|
+
db_type: str
|
|
19
|
+
git_commit: str
|
|
20
|
+
build_date: datetime
|
|
21
|
+
data_dir: str
|
|
22
|
+
logs_dir: str
|
|
23
|
+
backups_dir: str
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
@dataclass
|
|
27
|
+
class Filament(DataClassDictMixin):
|
|
28
|
+
"""Data class for filament data."""
|
|
29
|
+
|
|
30
|
+
id: int
|
|
31
|
+
name: str
|
|
32
|
+
color: str = field(metadata=field_options(alias="color_hex"))
|
|
33
|
+
vendor: Vendor
|
|
34
|
+
external_id: str
|
|
35
|
+
registered: datetime
|
|
36
|
+
|
|
37
|
+
material: str
|
|
38
|
+
density: float
|
|
39
|
+
diameter: float
|
|
40
|
+
weight: float
|
|
41
|
+
spool_weight: float
|
|
42
|
+
extruder_temp: int = field(metadata=field_options(alias="settings_extruder_temp"))
|
|
43
|
+
bed_temp: int = field(metadata=field_options(alias="settings_bed_temp"))
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
@dataclass
|
|
47
|
+
class Spool(DataClassDictMixin):
|
|
48
|
+
"""Data class for spool data."""
|
|
49
|
+
|
|
50
|
+
id: int
|
|
51
|
+
filament: Filament
|
|
52
|
+
|
|
53
|
+
initial_weight: float
|
|
54
|
+
spool_weight: float
|
|
55
|
+
used_weight: float
|
|
56
|
+
used_length: float
|
|
57
|
+
remaining_weight: float
|
|
58
|
+
remaining_length: float
|
|
59
|
+
|
|
60
|
+
archived: bool
|
|
61
|
+
registered: datetime
|
|
62
|
+
first_used: datetime | None = field(
|
|
63
|
+
default=None, metadata=field_options(alias="first_used")
|
|
64
|
+
)
|
|
65
|
+
last_used: datetime | None = field(
|
|
66
|
+
default=None, metadata=field_options(alias="last_used")
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
@dataclass
|
|
71
|
+
class Vendor(DataClassDictMixin):
|
|
72
|
+
"""Data class for vendor data."""
|
|
73
|
+
|
|
74
|
+
id: int
|
|
75
|
+
name: str
|
|
76
|
+
external_id: str
|
|
77
|
+
registered: datetime
|
|
File without changes
|
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
"""Asynchronous Python client for Spoolman."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import asyncio
|
|
6
|
+
import socket
|
|
7
|
+
from dataclasses import dataclass
|
|
8
|
+
from importlib import metadata
|
|
9
|
+
from typing import Any, Self, cast
|
|
10
|
+
|
|
11
|
+
from aiohttp import ClientError, ClientSession
|
|
12
|
+
from aiohttp.hdrs import METH_GET
|
|
13
|
+
from yarl import URL
|
|
14
|
+
|
|
15
|
+
from .exceptions import SpoolmanConnectionError, SpoolmanError, SpoolmanResponseError
|
|
16
|
+
from .models import Filament, Info, Spool, Vendor
|
|
17
|
+
|
|
18
|
+
VERSION = metadata.version(__package__)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
@dataclass
|
|
22
|
+
class Spoolman:
|
|
23
|
+
"""Main class for handling connections with the Spoolman API."""
|
|
24
|
+
|
|
25
|
+
host: str
|
|
26
|
+
port: int = 7912
|
|
27
|
+
|
|
28
|
+
request_timeout: float = 10.0
|
|
29
|
+
session: ClientSession | None = None
|
|
30
|
+
|
|
31
|
+
_close_session: bool = False
|
|
32
|
+
|
|
33
|
+
async def _request(
|
|
34
|
+
self,
|
|
35
|
+
uri: str,
|
|
36
|
+
*,
|
|
37
|
+
method: str = METH_GET,
|
|
38
|
+
params: dict[str, Any] | None = None,
|
|
39
|
+
) -> Any:
|
|
40
|
+
"""Handle a request to the Spoolman API.
|
|
41
|
+
|
|
42
|
+
Args:
|
|
43
|
+
----
|
|
44
|
+
uri: Request URI, without '/api/', for example, 'status'.
|
|
45
|
+
method: HTTP method to use.
|
|
46
|
+
params: Extra options to improve or limit the response.
|
|
47
|
+
|
|
48
|
+
Returns:
|
|
49
|
+
-------
|
|
50
|
+
A Python dictionary (JSON decoded) with the response from
|
|
51
|
+
the Spoolman API.
|
|
52
|
+
|
|
53
|
+
Raises:
|
|
54
|
+
------
|
|
55
|
+
SpoolmanConnectionError: If the connection to the API fails.
|
|
56
|
+
SpoolmanError: If the API returns an error.
|
|
57
|
+
SpoolmanResponseError: If the API returns a error.
|
|
58
|
+
|
|
59
|
+
"""
|
|
60
|
+
url = URL.build(
|
|
61
|
+
scheme="http",
|
|
62
|
+
host=self.host,
|
|
63
|
+
port=int(self.port),
|
|
64
|
+
path="/api/v1/",
|
|
65
|
+
).join(URL(uri))
|
|
66
|
+
|
|
67
|
+
headers = {
|
|
68
|
+
"User-Agent": f"PythonSpoolman/{VERSION}",
|
|
69
|
+
"Accept": "application/json",
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
if self.session is None:
|
|
73
|
+
self.session = ClientSession()
|
|
74
|
+
self._close_session = True
|
|
75
|
+
|
|
76
|
+
try:
|
|
77
|
+
async with asyncio.timeout(self.request_timeout):
|
|
78
|
+
response = await self.session.request(
|
|
79
|
+
method,
|
|
80
|
+
url,
|
|
81
|
+
params=params,
|
|
82
|
+
headers=headers,
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
if response.status == 404:
|
|
86
|
+
response_data = await response.json()
|
|
87
|
+
raise SpoolmanResponseError(response_data, response.status)
|
|
88
|
+
|
|
89
|
+
response.raise_for_status()
|
|
90
|
+
|
|
91
|
+
except TimeoutError as exception:
|
|
92
|
+
msg = "Timeout occurred while connecting to the Spoolman API."
|
|
93
|
+
raise SpoolmanConnectionError(msg) from exception
|
|
94
|
+
except (ClientError, socket.gaierror) as exception:
|
|
95
|
+
msg = "Error occurred while connecting to the Spoolman API."
|
|
96
|
+
raise SpoolmanConnectionError(msg) from exception
|
|
97
|
+
|
|
98
|
+
content_type = response.headers.get("content-type", "")
|
|
99
|
+
if "application/json" not in content_type:
|
|
100
|
+
text = await response.text()
|
|
101
|
+
msg = "Unexpected response from the Spoolman API."
|
|
102
|
+
raise SpoolmanError(
|
|
103
|
+
msg,
|
|
104
|
+
{"Content-Type": content_type, "Response": text},
|
|
105
|
+
)
|
|
106
|
+
|
|
107
|
+
return cast(dict[str, Any], await response.json())
|
|
108
|
+
|
|
109
|
+
async def info(self) -> Info:
|
|
110
|
+
"""Get information about the Spoolman API.
|
|
111
|
+
|
|
112
|
+
Returns
|
|
113
|
+
-------
|
|
114
|
+
A dictionary with information about the Spoolman API.
|
|
115
|
+
|
|
116
|
+
"""
|
|
117
|
+
response = await self._request("info")
|
|
118
|
+
return Info.from_dict(response)
|
|
119
|
+
|
|
120
|
+
async def health(self) -> bool:
|
|
121
|
+
"""Check the health of the Spoolman API.
|
|
122
|
+
|
|
123
|
+
Returns
|
|
124
|
+
-------
|
|
125
|
+
True if the API is healthy, False otherwise.
|
|
126
|
+
|
|
127
|
+
"""
|
|
128
|
+
response: dict[str, str] = await self._request("health")
|
|
129
|
+
return response["status"] == "healthy"
|
|
130
|
+
|
|
131
|
+
async def get_filaments(self) -> list[Filament]:
|
|
132
|
+
"""Get a list of all available filaments.
|
|
133
|
+
|
|
134
|
+
Returns
|
|
135
|
+
-------
|
|
136
|
+
A list with filament data.
|
|
137
|
+
|
|
138
|
+
"""
|
|
139
|
+
response = await self._request("filament")
|
|
140
|
+
return [Filament.from_dict(item) for item in response]
|
|
141
|
+
|
|
142
|
+
async def get_filament(self, filament_id: int) -> Filament:
|
|
143
|
+
"""Get a specific filament by ID.
|
|
144
|
+
|
|
145
|
+
Args:
|
|
146
|
+
----
|
|
147
|
+
filament_id: The ID of the filament to retrieve.
|
|
148
|
+
|
|
149
|
+
Returns:
|
|
150
|
+
-------
|
|
151
|
+
A dictionary with the filament data.
|
|
152
|
+
|
|
153
|
+
"""
|
|
154
|
+
response = await self._request(f"filament/{filament_id}")
|
|
155
|
+
return Filament.from_dict(response)
|
|
156
|
+
|
|
157
|
+
async def get_spools(self) -> list[Spool]:
|
|
158
|
+
"""Get a list of all available spools.
|
|
159
|
+
|
|
160
|
+
Returns
|
|
161
|
+
-------
|
|
162
|
+
A list with spool data.
|
|
163
|
+
|
|
164
|
+
"""
|
|
165
|
+
response = await self._request("spool")
|
|
166
|
+
return [Spool.from_dict(item) for item in response]
|
|
167
|
+
|
|
168
|
+
async def get_spool(self, spool_id: int) -> Spool:
|
|
169
|
+
"""Get a specific spool by ID.
|
|
170
|
+
|
|
171
|
+
Args:
|
|
172
|
+
----
|
|
173
|
+
spool_id: The ID of the spool to retrieve.
|
|
174
|
+
|
|
175
|
+
Returns:
|
|
176
|
+
-------
|
|
177
|
+
A dictionary with the spool data.
|
|
178
|
+
|
|
179
|
+
"""
|
|
180
|
+
response = await self._request(f"spool/{spool_id}")
|
|
181
|
+
return Spool.from_dict(response)
|
|
182
|
+
|
|
183
|
+
async def get_vendors(self) -> list[Vendor]:
|
|
184
|
+
"""Get a list of all available vendors.
|
|
185
|
+
|
|
186
|
+
Returns
|
|
187
|
+
-------
|
|
188
|
+
A list with vendor data.
|
|
189
|
+
|
|
190
|
+
"""
|
|
191
|
+
response = await self._request("vendor")
|
|
192
|
+
return [Vendor.from_dict(item) for item in response]
|
|
193
|
+
|
|
194
|
+
async def get_vendor(self, vendor_id: int) -> Vendor:
|
|
195
|
+
"""Get a specific vendor by ID.
|
|
196
|
+
|
|
197
|
+
Args:
|
|
198
|
+
----
|
|
199
|
+
vendor_id: The ID of the vendor to retrieve.
|
|
200
|
+
|
|
201
|
+
Returns:
|
|
202
|
+
-------
|
|
203
|
+
A dictionary with the vendor data.
|
|
204
|
+
|
|
205
|
+
"""
|
|
206
|
+
response = await self._request(f"vendor/{vendor_id}")
|
|
207
|
+
return Vendor.from_dict(response)
|
|
208
|
+
|
|
209
|
+
async def close(self) -> None:
|
|
210
|
+
"""Close open client session."""
|
|
211
|
+
if self.session and self._close_session:
|
|
212
|
+
await self.session.close()
|
|
213
|
+
|
|
214
|
+
async def __aenter__(self) -> Self:
|
|
215
|
+
"""Async enter.
|
|
216
|
+
|
|
217
|
+
Returns
|
|
218
|
+
-------
|
|
219
|
+
The Spoolman object.
|
|
220
|
+
|
|
221
|
+
"""
|
|
222
|
+
return self
|
|
223
|
+
|
|
224
|
+
async def __aexit__(self, *_exc_info: object) -> None:
|
|
225
|
+
"""Async exit.
|
|
226
|
+
|
|
227
|
+
Args:
|
|
228
|
+
----
|
|
229
|
+
_exc_info: Exec type.
|
|
230
|
+
|
|
231
|
+
"""
|
|
232
|
+
await self.close()
|