Habiticalib 0.1.0a1__tar.gz → 0.1.0a3__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.
- {habiticalib-0.1.0a1 → habiticalib-0.1.0a3}/.github/labels.yml +5 -5
- habiticalib-0.1.0a3/.github/release-drafter.yml +94 -0
- {habiticalib-0.1.0a1 → habiticalib-0.1.0a3}/.github/workflows/build.yml +1 -1
- habiticalib-0.1.0a3/PKG-INFO +97 -0
- habiticalib-0.1.0a3/README.md +79 -0
- {habiticalib-0.1.0a1 → habiticalib-0.1.0a3}/pyproject.toml +4 -4
- habiticalib-0.1.0a3/src/habiticalib/__init__.py +71 -0
- {habiticalib-0.1.0a1 → habiticalib-0.1.0a3}/src/habiticalib/const.py +2 -0
- habiticalib-0.1.0a3/src/habiticalib/exceptions.py +50 -0
- {habiticalib-0.1.0a1 → habiticalib-0.1.0a3}/src/habiticalib/helpers.py +28 -5
- {habiticalib-0.1.0a1 → habiticalib-0.1.0a3}/src/habiticalib/lib.py +65 -46
- {habiticalib-0.1.0a1 → habiticalib-0.1.0a3}/src/habiticalib/types.py +89 -67
- habiticalib-0.1.0a3/tests/__snapshots__/test_avatar.ambr +28 -0
- habiticalib-0.1.0a3/tests/__snapshots__/test_user.ambr +4 -0
- habiticalib-0.1.0a3/tests/conftest.py +49 -0
- {habiticalib-0.1.0a1 → habiticalib-0.1.0a3}/tests/fixtures/user.json +10 -5
- habiticalib-0.1.0a3/tests/fixtures/user_styles.json +57 -0
- habiticalib-0.1.0a3/tests/fixtures/user_styles_kickstarter.json +57 -0
- habiticalib-0.1.0a3/tests/fixtures/user_styles_seafoam.json +57 -0
- habiticalib-0.1.0a3/tests/fixtures/user_styles_shinySeed.json +57 -0
- habiticalib-0.1.0a3/tests/fixtures/user_styles_sleeping.json +57 -0
- habiticalib-0.1.0a3/tests/fixtures/user_styles_snowball.json +57 -0
- habiticalib-0.1.0a3/tests/fixtures/user_styles_spookySparkles.json +57 -0
- habiticalib-0.1.0a3/tests/fixtures/user_styles_with_chair.json +57 -0
- habiticalib-0.1.0a3/tests/test_avatar.py +100 -0
- {habiticalib-0.1.0a1 → habiticalib-0.1.0a3}/tests/test_user.py +1 -3
- habiticalib-0.1.0a1/.github/release-drafter.yml +0 -39
- habiticalib-0.1.0a1/PKG-INFO +0 -92
- habiticalib-0.1.0a1/README.md +0 -73
- habiticalib-0.1.0a1/src/habiticalib/__init__.py +0 -12
- habiticalib-0.1.0a1/src/habiticalib/exceptions.py +0 -27
- habiticalib-0.1.0a1/tests/__snapshots__/test_user.ambr +0 -4
- habiticalib-0.1.0a1/tests/conftest.py +0 -27
- {habiticalib-0.1.0a1 → habiticalib-0.1.0a3}/.cruft.json +0 -0
- {habiticalib-0.1.0a1 → habiticalib-0.1.0a3}/.editorconfig +0 -0
- {habiticalib-0.1.0a1 → habiticalib-0.1.0a3}/.github/FUNDING.yml +0 -0
- {habiticalib-0.1.0a1 → habiticalib-0.1.0a3}/.github/dependabot.yml +0 -0
- {habiticalib-0.1.0a1 → habiticalib-0.1.0a3}/.github/workflows/documentation.yml +0 -0
- {habiticalib-0.1.0a1 → habiticalib-0.1.0a3}/.github/workflows/draft.yml +0 -0
- {habiticalib-0.1.0a1 → habiticalib-0.1.0a3}/.github/workflows/labeler.yml +0 -0
- {habiticalib-0.1.0a1 → habiticalib-0.1.0a3}/.gitignore +0 -0
- {habiticalib-0.1.0a1 → habiticalib-0.1.0a3}/.pre-commit-config.yaml +0 -0
- {habiticalib-0.1.0a1 → habiticalib-0.1.0a3}/.vscode/settings.json +0 -0
- {habiticalib-0.1.0a1 → habiticalib-0.1.0a3}/LICENSE +0 -0
- {habiticalib-0.1.0a1 → habiticalib-0.1.0a3}/docs/index.md +0 -0
- {habiticalib-0.1.0a1 → habiticalib-0.1.0a3}/docs/reference/habiticalib.md +0 -0
- {habiticalib-0.1.0a1 → habiticalib-0.1.0a3}/mkdocs.yml +0 -0
- {habiticalib-0.1.0a1 → habiticalib-0.1.0a3}/src/habiticalib/py.typed +0 -0
- {habiticalib-0.1.0a1 → habiticalib-0.1.0a3}/tests/__init__.py +0 -0
- {habiticalib-0.1.0a1 → habiticalib-0.1.0a3}/tests/test_init.py +0 -0
@@ -25,7 +25,7 @@
|
|
25
25
|
- name: duplicate
|
26
26
|
description: This issue or pull request already exists
|
27
27
|
color: cfd3d7
|
28
|
-
- name:
|
28
|
+
- name: feature
|
29
29
|
description: New feature or request
|
30
30
|
color: a2eeef
|
31
31
|
- name: github_actions
|
@@ -49,17 +49,17 @@
|
|
49
49
|
- name: question
|
50
50
|
description: Further information is requested
|
51
51
|
color: d876e3
|
52
|
-
- name:
|
53
|
-
description:
|
52
|
+
- name: code quality
|
53
|
+
description: Code quality improvements
|
54
54
|
color: ef67c4
|
55
|
-
- name:
|
55
|
+
- name: deprecation
|
56
56
|
description: Removals and Deprecations
|
57
57
|
color: 9ae7ea
|
58
58
|
- name: style
|
59
59
|
description: Style
|
60
60
|
color: c120e5
|
61
61
|
- name: testing
|
62
|
-
description:
|
62
|
+
description: Pull request that adds tests
|
63
63
|
color: b1fc6f
|
64
64
|
- name: wontfix
|
65
65
|
description: This will not be worked on
|
@@ -0,0 +1,94 @@
|
|
1
|
+
name-template: '$RESOLVED_VERSION'
|
2
|
+
tag-template: 'v$RESOLVED_VERSION'
|
3
|
+
|
4
|
+
|
5
|
+
categories:
|
6
|
+
- title: '⚠️ Breaking changes'
|
7
|
+
labels:
|
8
|
+
- 'breaking'
|
9
|
+
- title: '🚀 Features'
|
10
|
+
labels:
|
11
|
+
- 'feature'
|
12
|
+
- 'enhancement'
|
13
|
+
- title: '🐛 Bug Fixes'
|
14
|
+
labels:
|
15
|
+
- 'bug'
|
16
|
+
- title: '⏳ Deprecations'
|
17
|
+
labels:
|
18
|
+
- 'deprecation'
|
19
|
+
- title: '📃 Documentation'
|
20
|
+
labels:
|
21
|
+
- 'documentation'
|
22
|
+
- title: '🧩 Dependency Updates'
|
23
|
+
labels:
|
24
|
+
- 'dependencies'
|
25
|
+
- 'github_actions'
|
26
|
+
collapse-after: 5
|
27
|
+
- title: '🧰 Maintenance'
|
28
|
+
labels:
|
29
|
+
- 'perfomance'
|
30
|
+
- 'refactor'
|
31
|
+
- 'ci'
|
32
|
+
- 'build'
|
33
|
+
- title: '🔬 Other updates'
|
34
|
+
labels:
|
35
|
+
- 'style'
|
36
|
+
- 'testing'
|
37
|
+
|
38
|
+
autolabeler:
|
39
|
+
- label: 'feature'
|
40
|
+
title:
|
41
|
+
- '/adds/i'
|
42
|
+
- label: 'bug'
|
43
|
+
title:
|
44
|
+
- '/fix/i'
|
45
|
+
- label: 'code quality'
|
46
|
+
title:
|
47
|
+
- '/Refactor/i'
|
48
|
+
- label: 'testing'
|
49
|
+
title:
|
50
|
+
- '/test:/i'
|
51
|
+
files:
|
52
|
+
- 'test_*'
|
53
|
+
- 'conftest.py'
|
54
|
+
- label: 'documentation'
|
55
|
+
title:
|
56
|
+
- '/docs:/i'
|
57
|
+
files:
|
58
|
+
- '*.md'
|
59
|
+
- 'mkdocs.yml'
|
60
|
+
- label: 'ci'
|
61
|
+
title:
|
62
|
+
- '/ci:/i'
|
63
|
+
files:
|
64
|
+
- '.github/*'
|
65
|
+
- label: 'dependencies'
|
66
|
+
title:
|
67
|
+
- '/bump/i'
|
68
|
+
- label: 'deprecation'
|
69
|
+
title:
|
70
|
+
- '/Deprecate/i'
|
71
|
+
|
72
|
+
change-template: '- $TITLE @$AUTHOR (#$NUMBER)'
|
73
|
+
change-title-escapes: '\<*_&' # You can add # and @ to disable mentions, and add ` to disable code blocks.
|
74
|
+
exclude-contributors:
|
75
|
+
- 'tr4nt0r'
|
76
|
+
|
77
|
+
version-resolver:
|
78
|
+
major:
|
79
|
+
labels:
|
80
|
+
- 'major'
|
81
|
+
minor:
|
82
|
+
labels:
|
83
|
+
- 'minor'
|
84
|
+
patch:
|
85
|
+
labels:
|
86
|
+
- 'patch'
|
87
|
+
default: patch
|
88
|
+
|
89
|
+
template: |
|
90
|
+
## Changes
|
91
|
+
|
92
|
+
$CHANGES
|
93
|
+
|
94
|
+
Special thanks to: $CONTRIBUTORS
|
@@ -0,0 +1,97 @@
|
|
1
|
+
Metadata-Version: 2.3
|
2
|
+
Name: Habiticalib
|
3
|
+
Version: 0.1.0a3
|
4
|
+
Summary: Asynchronous Python client library for the Habitica API
|
5
|
+
Project-URL: Documentation, https://tr4nt0r.github.io/habiticalib/
|
6
|
+
Project-URL: Source, https://github.com/tr4nt0r/habiticalib
|
7
|
+
Author-email: Manfred Dennerlein Rodelo <manfred@dennerlein.name>
|
8
|
+
License: MIT License
|
9
|
+
Classifier: License :: OSI Approved :: MIT License
|
10
|
+
Classifier: Operating System :: OS Independent
|
11
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
12
|
+
Requires-Python: >=3.12
|
13
|
+
Requires-Dist: aiohttp~=3.9
|
14
|
+
Requires-Dist: mashumaro~=3.13
|
15
|
+
Requires-Dist: orjson~=3.10
|
16
|
+
Requires-Dist: pillow~=11.0
|
17
|
+
Description-Content-Type: text/markdown
|
18
|
+
|
19
|
+
# Habiticalib
|
20
|
+
|
21
|
+
<p align="center">
|
22
|
+
<em>Modern asynchronous Python client library for the Habitica API</em>
|
23
|
+
</p>
|
24
|
+
|
25
|
+
[](https://github.com/tr4nt0r/habiticalib/actions)
|
26
|
+
[](https://codecov.io/gh/tr4nt0r/habiticalib)
|
27
|
+
[](https://badge.fury.io/py/habiticalib)
|
28
|
+
|
29
|
+
**Habiticalib** is a Python library for interacting with the [Habitica API](https://habitica.com). It provides an organized, typed interface to work with Habitica’s features, including tasks, user data, and avatars. The goal of this library is to simplify integration with Habitica.
|
30
|
+
|
31
|
+
## Key features
|
32
|
+
|
33
|
+
- **Asynchronous**: The library is fully asynchronous, allowing non-blocking API calls.
|
34
|
+
- **Fully typed with Dataclasses**: The library is fully typed using Python `dataclasses`. It handles serialization with `mashumaro` and `orjson` for efficient conversion between Habitica API JSON data and Python objects.
|
35
|
+
- **Dynamic avatar image generation**: Habiticalib can fetch all necessary assets (like equipped items, pets, and mounts) and combine them into a single avatar image. This image can be saved to disk or returned as a byte buffer for further processing.
|
36
|
+
**Fetch user data**: Retrieve and manage user data such as stats, preferences, and items. User data is structured with dataclasses to make it easy to work with.
|
37
|
+
- **Task management**: Support for creating, updating, and retrieving Habitica tasks (to-dos, dailies, habits, rewards) is provided.
|
38
|
+
- **Task status updates**: The library allows updates for task statuses, habit scoring, and daily completion.
|
39
|
+
- **Tags**: Habiticalib supports the creation, updating and deletion of tags.
|
40
|
+
- **Stat allocation, class cystem and sleep**: The library offers methods for stat point allocation and switching between Habitica classes. It also provides the ability to disable the class system and pausing damage(resting in the inn)
|
41
|
+
|
42
|
+
## Installation
|
43
|
+
|
44
|
+
```bash
|
45
|
+
pip install habiticalib
|
46
|
+
```
|
47
|
+
|
48
|
+
## Getting started
|
49
|
+
Here’s an example to demonstrate basic usage:
|
50
|
+
|
51
|
+
```python
|
52
|
+
import asyncio
|
53
|
+
|
54
|
+
from aiohttp import ClientSession
|
55
|
+
|
56
|
+
from habiticalib import Habitica, TaskType
|
57
|
+
|
58
|
+
|
59
|
+
async def main():
|
60
|
+
async with ClientSession() as session:
|
61
|
+
habitica = Habitica(session)
|
62
|
+
|
63
|
+
# Login to Habitica
|
64
|
+
habitica.login(username="your_username", password="your_password")
|
65
|
+
|
66
|
+
# Fetch user data
|
67
|
+
user_data = await habitica.user()
|
68
|
+
print(f"Your current health: {user_data.stats.hp}")
|
69
|
+
|
70
|
+
# Fetch all tasks (to-dos, dailies, habits, and rewards)
|
71
|
+
tasks = await habitica.get_tasks()
|
72
|
+
print("All tasks:")
|
73
|
+
for task in tasks:
|
74
|
+
print(f"- {task.text} (type: {task.type})")
|
75
|
+
|
76
|
+
# Fetch only to-dos
|
77
|
+
todos = await habitica.get_tasks(task_type=TaskType.TODO)
|
78
|
+
print("\nTo-Do tasks:")
|
79
|
+
for todo in todos:
|
80
|
+
print(f"- {todo.text} (due: {todo.date})")
|
81
|
+
|
82
|
+
# Fetch only dailies
|
83
|
+
dailies = await habitica.tasks(task_type=TaskType.DAILY)
|
84
|
+
print("\nDailies:")
|
85
|
+
for daily in dailies:
|
86
|
+
print(f"- {daily.text}")
|
87
|
+
|
88
|
+
asyncio.run(main())
|
89
|
+
```
|
90
|
+
|
91
|
+
## Documentation
|
92
|
+
|
93
|
+
For full documentation and detailed usage examples, please visit the [Habiticalib documentation](https://tr4nt0r.github.io/habiticalib/).
|
94
|
+
|
95
|
+
## License
|
96
|
+
|
97
|
+
This project is licensed under the terms of the MIT license.
|
@@ -0,0 +1,79 @@
|
|
1
|
+
# Habiticalib
|
2
|
+
|
3
|
+
<p align="center">
|
4
|
+
<em>Modern asynchronous Python client library for the Habitica API</em>
|
5
|
+
</p>
|
6
|
+
|
7
|
+
[](https://github.com/tr4nt0r/habiticalib/actions)
|
8
|
+
[](https://codecov.io/gh/tr4nt0r/habiticalib)
|
9
|
+
[](https://badge.fury.io/py/habiticalib)
|
10
|
+
|
11
|
+
**Habiticalib** is a Python library for interacting with the [Habitica API](https://habitica.com). It provides an organized, typed interface to work with Habitica’s features, including tasks, user data, and avatars. The goal of this library is to simplify integration with Habitica.
|
12
|
+
|
13
|
+
## Key features
|
14
|
+
|
15
|
+
- **Asynchronous**: The library is fully asynchronous, allowing non-blocking API calls.
|
16
|
+
- **Fully typed with Dataclasses**: The library is fully typed using Python `dataclasses`. It handles serialization with `mashumaro` and `orjson` for efficient conversion between Habitica API JSON data and Python objects.
|
17
|
+
- **Dynamic avatar image generation**: Habiticalib can fetch all necessary assets (like equipped items, pets, and mounts) and combine them into a single avatar image. This image can be saved to disk or returned as a byte buffer for further processing.
|
18
|
+
**Fetch user data**: Retrieve and manage user data such as stats, preferences, and items. User data is structured with dataclasses to make it easy to work with.
|
19
|
+
- **Task management**: Support for creating, updating, and retrieving Habitica tasks (to-dos, dailies, habits, rewards) is provided.
|
20
|
+
- **Task status updates**: The library allows updates for task statuses, habit scoring, and daily completion.
|
21
|
+
- **Tags**: Habiticalib supports the creation, updating and deletion of tags.
|
22
|
+
- **Stat allocation, class cystem and sleep**: The library offers methods for stat point allocation and switching between Habitica classes. It also provides the ability to disable the class system and pausing damage(resting in the inn)
|
23
|
+
|
24
|
+
## Installation
|
25
|
+
|
26
|
+
```bash
|
27
|
+
pip install habiticalib
|
28
|
+
```
|
29
|
+
|
30
|
+
## Getting started
|
31
|
+
Here’s an example to demonstrate basic usage:
|
32
|
+
|
33
|
+
```python
|
34
|
+
import asyncio
|
35
|
+
|
36
|
+
from aiohttp import ClientSession
|
37
|
+
|
38
|
+
from habiticalib import Habitica, TaskType
|
39
|
+
|
40
|
+
|
41
|
+
async def main():
|
42
|
+
async with ClientSession() as session:
|
43
|
+
habitica = Habitica(session)
|
44
|
+
|
45
|
+
# Login to Habitica
|
46
|
+
habitica.login(username="your_username", password="your_password")
|
47
|
+
|
48
|
+
# Fetch user data
|
49
|
+
user_data = await habitica.user()
|
50
|
+
print(f"Your current health: {user_data.stats.hp}")
|
51
|
+
|
52
|
+
# Fetch all tasks (to-dos, dailies, habits, and rewards)
|
53
|
+
tasks = await habitica.get_tasks()
|
54
|
+
print("All tasks:")
|
55
|
+
for task in tasks:
|
56
|
+
print(f"- {task.text} (type: {task.type})")
|
57
|
+
|
58
|
+
# Fetch only to-dos
|
59
|
+
todos = await habitica.get_tasks(task_type=TaskType.TODO)
|
60
|
+
print("\nTo-Do tasks:")
|
61
|
+
for todo in todos:
|
62
|
+
print(f"- {todo.text} (due: {todo.date})")
|
63
|
+
|
64
|
+
# Fetch only dailies
|
65
|
+
dailies = await habitica.tasks(task_type=TaskType.DAILY)
|
66
|
+
print("\nDailies:")
|
67
|
+
for daily in dailies:
|
68
|
+
print(f"- {daily.text}")
|
69
|
+
|
70
|
+
asyncio.run(main())
|
71
|
+
```
|
72
|
+
|
73
|
+
## Documentation
|
74
|
+
|
75
|
+
For full documentation and detailed usage examples, please visit the [Habiticalib documentation](https://tr4nt0r.github.io/habiticalib/).
|
76
|
+
|
77
|
+
## License
|
78
|
+
|
79
|
+
This project is licensed under the terms of the MIT license.
|
@@ -25,7 +25,7 @@ max-complexity = 25
|
|
25
25
|
|
26
26
|
[tool.ruff.lint.per-file-ignores]
|
27
27
|
"types.py" = ["N815"]
|
28
|
-
"tests/*" = ["SLF001", "S101"]
|
28
|
+
"tests/*" = ["SLF001", "S101", "ARG001"]
|
29
29
|
|
30
30
|
[tool.pytest.ini_options]
|
31
31
|
testpaths = ["tests"]
|
@@ -61,7 +61,7 @@ allow-direct-references = true
|
|
61
61
|
[tool.hatch.version]
|
62
62
|
source = "regex_commit"
|
63
63
|
commit_extra_args = ["-e"]
|
64
|
-
path = "src/habiticalib/
|
64
|
+
path = "src/habiticalib/const.py"
|
65
65
|
|
66
66
|
[tool.hatch.envs.default]
|
67
67
|
python = "3.12"
|
@@ -69,7 +69,7 @@ dependencies = [
|
|
69
69
|
"aiohttp==3.10.10",
|
70
70
|
"mashumaro==3.13.1",
|
71
71
|
"orjson==3.10.7",
|
72
|
-
"Pillow==
|
72
|
+
"Pillow==11.0.0",
|
73
73
|
"mypy==1.12.0",
|
74
74
|
"ruff==0.7.0",
|
75
75
|
"pytest==8.3.3",
|
@@ -125,7 +125,7 @@ dependencies = [
|
|
125
125
|
"aiohttp~=3.9",
|
126
126
|
"mashumaro~=3.13",
|
127
127
|
"orjson~=3.10",
|
128
|
-
"Pillow~=
|
128
|
+
"Pillow~=11.0"
|
129
129
|
]
|
130
130
|
|
131
131
|
[project.urls]
|
@@ -0,0 +1,71 @@
|
|
1
|
+
"""Modern asynchronous Python client library for the Habitica API."""
|
2
|
+
|
3
|
+
from .const import ASSETS_URL, DEFAULT_URL, __version__
|
4
|
+
from .exceptions import (
|
5
|
+
BadRequestError,
|
6
|
+
HabiticaException,
|
7
|
+
NotAuthorizedError,
|
8
|
+
NotFoundError,
|
9
|
+
TooManyRequestsError,
|
10
|
+
)
|
11
|
+
from .lib import Habitica
|
12
|
+
from .types import (
|
13
|
+
Attributes,
|
14
|
+
Direction,
|
15
|
+
Frequency,
|
16
|
+
HabiticaClass,
|
17
|
+
HabiticaClassSystemResponse,
|
18
|
+
HabiticaErrorResponse,
|
19
|
+
HabiticaLoginResponse,
|
20
|
+
HabiticaResponse,
|
21
|
+
HabiticaScoreResponse,
|
22
|
+
HabiticaStatsResponse,
|
23
|
+
HabiticaTagResponse,
|
24
|
+
HabiticaTagsResponse,
|
25
|
+
HabiticaTaskOrderResponse,
|
26
|
+
HabiticaTaskResponse,
|
27
|
+
HabiticaTasksResponse,
|
28
|
+
HabiticaUserExport,
|
29
|
+
HabiticaUserResponse,
|
30
|
+
Language,
|
31
|
+
Skill,
|
32
|
+
Task,
|
33
|
+
TaskFilter,
|
34
|
+
TaskType,
|
35
|
+
UserStyles,
|
36
|
+
)
|
37
|
+
|
38
|
+
__all__ = [
|
39
|
+
"__version__",
|
40
|
+
"ASSETS_URL",
|
41
|
+
"Attributes",
|
42
|
+
"BadRequestError",
|
43
|
+
"DEFAULT_URL",
|
44
|
+
"Direction",
|
45
|
+
"Frequency",
|
46
|
+
"Habitica",
|
47
|
+
"HabiticaClass",
|
48
|
+
"HabiticaClassSystemResponse",
|
49
|
+
"HabiticaErrorResponse",
|
50
|
+
"HabiticaException",
|
51
|
+
"HabiticaLoginResponse",
|
52
|
+
"HabiticaResponse",
|
53
|
+
"HabiticaScoreResponse",
|
54
|
+
"HabiticaStatsResponse",
|
55
|
+
"HabiticaTagResponse",
|
56
|
+
"HabiticaTagsResponse",
|
57
|
+
"HabiticaTaskOrderResponse",
|
58
|
+
"HabiticaTaskResponse",
|
59
|
+
"HabiticaTasksResponse",
|
60
|
+
"HabiticaUserExport",
|
61
|
+
"HabiticaUserResponse",
|
62
|
+
"Language",
|
63
|
+
"NotAuthorizedError",
|
64
|
+
"NotFoundError",
|
65
|
+
"Skill",
|
66
|
+
"Task",
|
67
|
+
"TaskFilter",
|
68
|
+
"TaskType",
|
69
|
+
"TooManyRequestsError",
|
70
|
+
"UserStyles",
|
71
|
+
]
|
@@ -0,0 +1,50 @@
|
|
1
|
+
"""Exceptions for Habiticalib."""
|
2
|
+
|
3
|
+
from datetime import datetime
|
4
|
+
from typing import Self
|
5
|
+
|
6
|
+
from multidict import CIMultiDictProxy
|
7
|
+
|
8
|
+
from habiticalib.types import HabiticaErrorResponse
|
9
|
+
|
10
|
+
|
11
|
+
class HabiticaException(Exception): # noqa: N818
|
12
|
+
"""Base class for Habitica errors."""
|
13
|
+
|
14
|
+
def __init__(
|
15
|
+
self: Self,
|
16
|
+
error: HabiticaErrorResponse,
|
17
|
+
headers: CIMultiDictProxy,
|
18
|
+
) -> None:
|
19
|
+
"""Initialize the Exception."""
|
20
|
+
self.error = error
|
21
|
+
self.rate_limit: int | None = (
|
22
|
+
int(r) if (r := headers.get("x-ratelimit-limit")) else None
|
23
|
+
)
|
24
|
+
self.rate_limit_remaining: int | None = (
|
25
|
+
int(r) if (r := headers.get("x-ratelimit-remaining")) else None
|
26
|
+
)
|
27
|
+
self.rate_limit_reset: datetime | None = (
|
28
|
+
datetime.strptime(r[:33], "%a %b %d %Y %H:%M:%S %Z%z")
|
29
|
+
if (r := headers.get("x-ratelimit-reset"))
|
30
|
+
else None
|
31
|
+
)
|
32
|
+
self.retry_after: int = round(float(headers.get("retry-after", 0)))
|
33
|
+
|
34
|
+
super().__init__(error.message)
|
35
|
+
|
36
|
+
|
37
|
+
class NotAuthorizedError(HabiticaException):
|
38
|
+
"""NotAuthorized error."""
|
39
|
+
|
40
|
+
|
41
|
+
class NotFoundError(HabiticaException):
|
42
|
+
"""NotFound error."""
|
43
|
+
|
44
|
+
|
45
|
+
class BadRequestError(HabiticaException):
|
46
|
+
"""BadRequest error."""
|
47
|
+
|
48
|
+
|
49
|
+
class TooManyRequestsError(HabiticaException):
|
50
|
+
"""TooManyRequests error."""
|
@@ -1,13 +1,15 @@
|
|
1
1
|
"""Helper functions for Habiticalib."""
|
2
2
|
|
3
|
-
from dataclasses import asdict
|
4
|
-
from
|
3
|
+
from dataclasses import asdict, is_dataclass
|
4
|
+
from datetime import date, datetime
|
5
|
+
from enum import Enum
|
5
6
|
import platform
|
7
|
+
from typing import Any
|
6
8
|
import uuid
|
7
9
|
|
8
10
|
import aiohttp
|
9
11
|
|
10
|
-
from .const import DEVELOPER_ID
|
12
|
+
from .const import DEVELOPER_ID, __version__
|
11
13
|
from .types import HabiticaUserResponse, UserData, UserStyles
|
12
14
|
|
13
15
|
|
@@ -58,7 +60,7 @@ def get_user_agent() -> str:
|
|
58
60
|
os_info = f"{os_name} {os_release} ({os_version}); {arch}"
|
59
61
|
|
60
62
|
return (
|
61
|
-
f"Habiticalib/{
|
63
|
+
f"Habiticalib/{__version__} ({os_info}) "
|
62
64
|
f"aiohttp/{aiohttp.__version__} Python/{platform.python_version()} "
|
63
65
|
" +https://github.com/tr4nt0r/habiticalib)"
|
64
66
|
)
|
@@ -106,10 +108,31 @@ def get_x_client(x_client: str | None = None) -> str:
|
|
106
108
|
|
107
109
|
return x_client
|
108
110
|
|
109
|
-
return f"{DEVELOPER_ID} - Habiticalib/{
|
111
|
+
return f"{DEVELOPER_ID} - Habiticalib/{__version__}"
|
110
112
|
|
111
113
|
|
112
114
|
def extract_user_styles(user_data: HabiticaUserResponse) -> UserStyles:
|
113
115
|
"""Extract user styles from a user data object."""
|
114
116
|
data: UserData = user_data.data
|
115
117
|
return UserStyles.from_dict(asdict(data))
|
118
|
+
|
119
|
+
|
120
|
+
def deserialize_task(value: Any) -> Any: # noqa: PLR0911
|
121
|
+
"""Recursively convert Enums to values, dates to ISO strings, UUIDs to strings."""
|
122
|
+
|
123
|
+
if is_dataclass(value) and not isinstance(value, type):
|
124
|
+
# Convert dataclass to dict and recursively deserialize
|
125
|
+
return deserialize_task(asdict(value))
|
126
|
+
if isinstance(value, Enum):
|
127
|
+
return value.value # Convert Enum to its value
|
128
|
+
if isinstance(value, uuid.UUID):
|
129
|
+
return str(value) # Convert UUID to string
|
130
|
+
if isinstance(value, datetime | date):
|
131
|
+
return value.isoformat() # Convert datetime/date to ISO string
|
132
|
+
if isinstance(value, list):
|
133
|
+
# Recursively apply deserialization to each item in the list
|
134
|
+
return [deserialize_task(item) for item in value]
|
135
|
+
if isinstance(value, dict):
|
136
|
+
# Recursively apply deserialization to each key-value pair in the dictionary
|
137
|
+
return {k: deserialize_task(v) for k, v in value.items()}
|
138
|
+
return value # Return other types unchanged
|