Habiticalib 0.2.0a2__tar.gz → 0.3.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. {habiticalib-0.2.0a2 → habiticalib-0.3.1}/.github/release-drafter.yml +6 -1
  2. {habiticalib-0.2.0a2 → habiticalib-0.3.1}/.github/workflows/build.yml +3 -0
  3. {habiticalib-0.2.0a2 → habiticalib-0.3.1}/PKG-INFO +2 -1
  4. {habiticalib-0.2.0a2 → habiticalib-0.3.1}/pyproject.toml +13 -12
  5. {habiticalib-0.2.0a2 → habiticalib-0.3.1}/src/habiticalib/__init__.py +28 -2
  6. {habiticalib-0.2.0a2 → habiticalib-0.3.1}/src/habiticalib/const.py +1 -1
  7. {habiticalib-0.2.0a2 → habiticalib-0.3.1}/src/habiticalib/lib.py +77 -12
  8. {habiticalib-0.2.0a2 → habiticalib-0.3.1}/src/habiticalib/types.py +16 -1
  9. {habiticalib-0.2.0a2 → habiticalib-0.3.1}/.cruft.json +0 -0
  10. {habiticalib-0.2.0a2 → habiticalib-0.3.1}/.editorconfig +0 -0
  11. {habiticalib-0.2.0a2 → habiticalib-0.3.1}/.github/FUNDING.yml +0 -0
  12. {habiticalib-0.2.0a2 → habiticalib-0.3.1}/.github/dependabot.yml +0 -0
  13. {habiticalib-0.2.0a2 → habiticalib-0.3.1}/.github/labels.yml +0 -0
  14. {habiticalib-0.2.0a2 → habiticalib-0.3.1}/.github/workflows/documentation.yml +0 -0
  15. {habiticalib-0.2.0a2 → habiticalib-0.3.1}/.github/workflows/draft.yml +0 -0
  16. {habiticalib-0.2.0a2 → habiticalib-0.3.1}/.github/workflows/labeler.yml +0 -0
  17. {habiticalib-0.2.0a2 → habiticalib-0.3.1}/.gitignore +0 -0
  18. {habiticalib-0.2.0a2 → habiticalib-0.3.1}/.pre-commit-config.yaml +0 -0
  19. {habiticalib-0.2.0a2 → habiticalib-0.3.1}/.vscode/settings.json +0 -0
  20. {habiticalib-0.2.0a2 → habiticalib-0.3.1}/LICENSE +0 -0
  21. {habiticalib-0.2.0a2 → habiticalib-0.3.1}/README.md +0 -0
  22. {habiticalib-0.2.0a2 → habiticalib-0.3.1}/docs/index.md +0 -0
  23. {habiticalib-0.2.0a2 → habiticalib-0.3.1}/docs/reference/habiticalib.md +0 -0
  24. {habiticalib-0.2.0a2 → habiticalib-0.3.1}/mkdocs.yml +0 -0
  25. {habiticalib-0.2.0a2 → habiticalib-0.3.1}/src/habiticalib/exceptions.py +0 -0
  26. {habiticalib-0.2.0a2 → habiticalib-0.3.1}/src/habiticalib/helpers.py +0 -0
  27. {habiticalib-0.2.0a2 → habiticalib-0.3.1}/src/habiticalib/py.typed +0 -0
  28. {habiticalib-0.2.0a2 → habiticalib-0.3.1}/tests/__init__.py +0 -0
  29. {habiticalib-0.2.0a2 → habiticalib-0.3.1}/tests/__snapshots__/test_avatar.ambr +0 -0
  30. {habiticalib-0.2.0a2 → habiticalib-0.3.1}/tests/__snapshots__/test_lib.ambr +0 -0
  31. {habiticalib-0.2.0a2 → habiticalib-0.3.1}/tests/conftest.py +0 -0
  32. {habiticalib-0.2.0a2 → habiticalib-0.3.1}/tests/fixtures/login.json +0 -0
  33. {habiticalib-0.2.0a2 → habiticalib-0.3.1}/tests/fixtures/user.json +0 -0
  34. {habiticalib-0.2.0a2 → habiticalib-0.3.1}/tests/fixtures/user_styles.json +0 -0
  35. {habiticalib-0.2.0a2 → habiticalib-0.3.1}/tests/fixtures/user_styles_kickstarter.json +0 -0
  36. {habiticalib-0.2.0a2 → habiticalib-0.3.1}/tests/fixtures/user_styles_seafoam.json +0 -0
  37. {habiticalib-0.2.0a2 → habiticalib-0.3.1}/tests/fixtures/user_styles_shinySeed.json +0 -0
  38. {habiticalib-0.2.0a2 → habiticalib-0.3.1}/tests/fixtures/user_styles_sleeping.json +0 -0
  39. {habiticalib-0.2.0a2 → habiticalib-0.3.1}/tests/fixtures/user_styles_snowball.json +0 -0
  40. {habiticalib-0.2.0a2 → habiticalib-0.3.1}/tests/fixtures/user_styles_spookySparkles.json +0 -0
  41. {habiticalib-0.2.0a2 → habiticalib-0.3.1}/tests/fixtures/user_styles_with_chair.json +0 -0
  42. {habiticalib-0.2.0a2 → habiticalib-0.3.1}/tests/test_avatar.py +0 -0
  43. {habiticalib-0.2.0a2 → habiticalib-0.3.1}/tests/test_init.py +0 -0
  44. {habiticalib-0.2.0a2 → habiticalib-0.3.1}/tests/test_lib.py +0 -0
@@ -1,4 +1,4 @@
1
- name-template: '$RESOLVED_VERSION'
1
+ name-template: 'v$RESOLVED_VERSION'
2
2
  tag-template: 'v$RESOLVED_VERSION'
3
3
 
4
4
 
@@ -39,6 +39,7 @@ autolabeler:
39
39
  - label: 'feature'
40
40
  title:
41
41
  - '/adds/i'
42
+ - '/add method/i'
42
43
  - label: 'bug'
43
44
  title:
44
45
  - '/fix/i'
@@ -48,6 +49,7 @@ autolabeler:
48
49
  - label: 'testing'
49
50
  title:
50
51
  - '/test:/i'
52
+ - '/add test/i'
51
53
  files:
52
54
  - 'test_*'
53
55
  - 'conftest.py'
@@ -78,12 +80,15 @@ version-resolver:
78
80
  major:
79
81
  labels:
80
82
  - 'major'
83
+ - 'breaking'
81
84
  minor:
82
85
  labels:
83
86
  - 'minor'
87
+ - 'feature'
84
88
  patch:
85
89
  labels:
86
90
  - 'patch'
91
+ - 'bug'
87
92
  default: patch
88
93
 
89
94
  template: |
@@ -82,5 +82,8 @@ jobs:
82
82
  with:
83
83
  draft: true
84
84
  body: ${{ github.event.head_commit.message }}
85
+ allowUpdates: true
86
+ omitBodyDuringUpdate: true
87
+ updateOnlyUnreleased: true
85
88
  artifacts: dist/*.whl,dist/*.tar.gz
86
89
  token: ${{ secrets.GITHUB_TOKEN }}
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: Habiticalib
3
- Version: 0.2.0a2
3
+ Version: 0.3.1
4
4
  Summary: Asynchronous Python client library for the Habitica API
5
5
  Project-URL: Documentation, https://tr4nt0r.github.io/habiticalib/
6
6
  Project-URL: Source, https://github.com/tr4nt0r/habiticalib
@@ -11,6 +11,7 @@ Classifier: Operating System :: OS Independent
11
11
  Classifier: Programming Language :: Python :: 3 :: Only
12
12
  Requires-Python: >=3.12
13
13
  Requires-Dist: aiohttp~=3.9
14
+ Requires-Dist: habitipy~=0.3.3
14
15
  Requires-Dist: mashumaro~=3.13
15
16
  Requires-Dist: orjson~=3.10
16
17
  Requires-Dist: pillow~=11.0
@@ -24,7 +24,7 @@ indent-style = "space"
24
24
  max-complexity = 25
25
25
 
26
26
  [tool.ruff.lint.per-file-ignores]
27
- "types.py" = ["N815"]
27
+ "types.py" = ["N815", "TCH003"]
28
28
  "tests/*" = ["SLF001", "S101", "ARG001"]
29
29
 
30
30
  [tool.pytest.ini_options]
@@ -66,20 +66,20 @@ path = "src/habiticalib/const.py"
66
66
  [tool.hatch.envs.default]
67
67
  python = "3.12"
68
68
  dependencies = [
69
- "aiohttp==3.10.10",
70
- "mashumaro==3.13.1",
71
- "orjson==3.10.7",
69
+ "aiohttp==3.11.7",
70
+ "mashumaro==3.15",
71
+ "orjson==3.10.12",
72
72
  "Pillow==11.0.0",
73
- "mypy==1.12.0",
74
- "ruff==0.7.0",
73
+ "mypy==1.13.0",
74
+ "ruff==0.8.0",
75
75
  "pytest==8.3.3",
76
- "pytest-cov==5.0.0",
77
- "mkdocs-material==9.5.41",
78
- "mkdocstrings[python]==0.26.2",
76
+ "pytest-cov==6.0.0",
77
+ "mkdocs-material==9.5.45",
78
+ "mkdocstrings[python]==0.27.0",
79
79
  "pytest-asyncio==0.24.0",
80
- "aioresponses==0.7.6",
80
+ "aioresponses==0.7.7",
81
81
  "pre-commit==4.0.1",
82
- "syrupy==4.7.2"
82
+ "syrupy==4.8.0"
83
83
  ]
84
84
  installer = "uv"
85
85
 
@@ -125,7 +125,8 @@ dependencies = [
125
125
  "aiohttp~=3.9",
126
126
  "mashumaro~=3.13",
127
127
  "orjson~=3.10",
128
- "Pillow~=11.0"
128
+ "Pillow~=11.0",
129
+ "habitipy~=0.3.3"
129
130
  ]
130
131
 
131
132
  [project.urls]
@@ -8,9 +8,12 @@ from .exceptions import (
8
8
  NotFoundError,
9
9
  TooManyRequestsError,
10
10
  )
11
+ from .helpers import deserialize_task
11
12
  from .lib import Habitica
12
13
  from .types import (
13
14
  Attributes,
15
+ ChangeClassData,
16
+ ContentData,
14
17
  Direction,
15
18
  Frequency,
16
19
  HabiticaClass,
@@ -29,22 +32,33 @@ from .types import (
29
32
  HabiticaTaskOrderResponse,
30
33
  HabiticaTaskResponse,
31
34
  HabiticaTasksResponse,
35
+ HabiticaUserAnonymizedrResponse,
32
36
  HabiticaUserExport,
33
37
  HabiticaUserResponse,
34
38
  Language,
39
+ LoginData,
40
+ QuestData,
41
+ ScoreData,
35
42
  Skill,
43
+ StatsUser,
44
+ TagsUser,
36
45
  Task,
46
+ TaskData,
37
47
  TaskFilter,
48
+ TaskPriority,
38
49
  TaskType,
50
+ UserAnonymizedData,
51
+ UserData,
39
52
  UserStyles,
40
53
  )
41
54
 
42
55
  __all__ = [
43
- "__version__",
44
56
  "ASSETS_URL",
57
+ "DEFAULT_URL",
45
58
  "Attributes",
46
59
  "BadRequestError",
47
- "DEFAULT_URL",
60
+ "ChangeClassData",
61
+ "ContentData",
48
62
  "Direction",
49
63
  "Frequency",
50
64
  "Habitica",
@@ -65,15 +79,27 @@ __all__ = [
65
79
  "HabiticaTaskOrderResponse",
66
80
  "HabiticaTaskResponse",
67
81
  "HabiticaTasksResponse",
82
+ "HabiticaUserAnonymizedrResponse",
68
83
  "HabiticaUserExport",
69
84
  "HabiticaUserResponse",
70
85
  "Language",
86
+ "LoginData",
71
87
  "NotAuthorizedError",
72
88
  "NotFoundError",
89
+ "QuestData",
90
+ "ScoreData",
73
91
  "Skill",
92
+ "StatsUser",
93
+ "TagsUser",
74
94
  "Task",
95
+ "TaskData",
75
96
  "TaskFilter",
97
+ "TaskPriority",
76
98
  "TaskType",
77
99
  "TooManyRequestsError",
100
+ "UserAnonymizedData",
101
+ "UserData",
78
102
  "UserStyles",
103
+ "__version__",
104
+ "deserialize_task",
79
105
  ]
@@ -1,6 +1,6 @@
1
1
  """Constants for Habiticalib."""
2
2
 
3
- __version__ = "0.2.0a2"
3
+ __version__ = "0.3.1"
4
4
 
5
5
  DEFAULT_URL = "https://habitica.com/"
6
6
  ASSETS_URL = "https://habitica-assets.s3.amazonaws.com/mobileApp/images/"
@@ -6,9 +6,10 @@ import asyncio
6
6
  from http import HTTPStatus
7
7
  from io import BytesIO
8
8
  import logging
9
- from typing import IO, TYPE_CHECKING, Self
9
+ from typing import IO, TYPE_CHECKING, Any, Self
10
10
 
11
11
  from aiohttp import ClientError, ClientResponseError, ClientSession
12
+ from habitipy.aio import HabitipyAsync # type: ignore[import-untyped]
12
13
  from PIL import Image
13
14
  from yarl import URL
14
15
 
@@ -45,6 +46,7 @@ from .types import (
45
46
  HabiticaTaskOrderResponse,
46
47
  HabiticaTaskResponse,
47
48
  HabiticaTasksResponse,
49
+ HabiticaUserAnonymizedrResponse,
48
50
  HabiticaUserExport,
49
51
  HabiticaUserResponse,
50
52
  Language,
@@ -206,10 +208,7 @@ class Habitica:
206
208
  return response
207
209
 
208
210
  async def get_user(
209
- self,
210
- user_fields: str | list[str] | None = None,
211
- *,
212
- anonymized: bool = False,
211
+ self, user_fields: str | list[str] | None = None
213
212
  ) -> HabiticaUserResponse:
214
213
  """Get the authenticated user's profile.
215
214
 
@@ -219,11 +218,6 @@ class Habitica:
219
218
  A string or a list of fields to include in the response.
220
219
  If provided as a list, the fields will be joined with commas.
221
220
  If None, the full user profile document is returned. Default is None.
222
- anonymized : bool
223
- When True, returns the user's data without: Authentication information,
224
- New Messages/Invitations/Inbox, Profile, Purchased information,
225
- Contributor information, Special items, Webhooks, Notifications.
226
- (default is False)
227
221
 
228
222
  Returns
229
223
  -------
@@ -253,13 +247,54 @@ class Habitica:
253
247
 
254
248
  if user_fields:
255
249
  params = {"userFields": join_fields(user_fields)}
256
- if anonymized:
257
- url = url / "anonymized"
258
250
 
259
251
  return HabiticaUserResponse.from_json(
260
252
  await self._request("get", url=url, params=params),
261
253
  )
262
254
 
255
+ async def get_user_anonymized(
256
+ self,
257
+ ) -> HabiticaUserAnonymizedrResponse:
258
+ """Get the authenticated user's anonymized profile.
259
+
260
+ This method retrieves the user's profile data while excluding sensitive
261
+ and personally identifiable information such as authentication details,
262
+ profile data, purchased items, contributor information, special items,
263
+ webhooks, and notifications.
264
+
265
+ Returns
266
+ -------
267
+ HabiticaUserAnonymized
268
+ A response object containing the anonymized user profile data.
269
+
270
+
271
+ Raises
272
+ ------
273
+ NotAuthorizedError
274
+ If the API request is unauthorized (HTTP 401).
275
+ aiohttp.ClientResponseError
276
+ For other HTTP-related errors raised by aiohttp, such as HTTP 400 or 500.
277
+ aiohttp.ClientConnectionError
278
+ If the connection to the API fails.
279
+ aiohttp.ClientError
280
+ For any other exceptions raised by aiohttp during the request.
281
+ TimeoutError
282
+ If the connection times out.
283
+
284
+ Examples
285
+ --------
286
+ >>> response = await habitica.get_user_anonymized()
287
+ >>> response.data.user # Access the anonymized user data
288
+ >>> response.data.tasks # Access the user's anonymized tasks
289
+ """
290
+ url = self.url / "api/v3/user"
291
+
292
+ url = url / "anonymized"
293
+
294
+ return HabiticaUserAnonymizedrResponse.from_json(
295
+ await self._request("get", url=url),
296
+ )
297
+
263
298
  async def get_tasks(
264
299
  self,
265
300
  task_type: TaskFilter | None = None,
@@ -1998,3 +2033,33 @@ class Habitica:
1998
2033
  image.save(fp, fmt)
1999
2034
 
2000
2035
  return user_styles
2036
+
2037
+ async def habitipy(self) -> HabitipyAsync:
2038
+ """Create a Habitipy instance."""
2039
+
2040
+ _session = self._session
2041
+ _headers = self._headers
2042
+ loop = asyncio.get_running_loop()
2043
+
2044
+ class HAHabitipyAsync(HabitipyAsync):
2045
+ """Closure API class to hold session."""
2046
+
2047
+ def __call__(self, **kwargs) -> Any:
2048
+ """Pass session to habitipy."""
2049
+ return super().__call__(_session, **kwargs)
2050
+
2051
+ def _make_headers(self) -> dict[str, str]:
2052
+ """Inject headers."""
2053
+ headers = super()._make_headers()
2054
+ headers.update(_headers)
2055
+ return headers
2056
+
2057
+ return await loop.run_in_executor(
2058
+ None,
2059
+ HAHabitipyAsync,
2060
+ {
2061
+ "url": str(self.url),
2062
+ "login": self._headers.get("X-API-USER"),
2063
+ "password": self._headers.get("X-API-KEY"),
2064
+ }, # type: ignore[var-annotated]
2065
+ )
@@ -8,7 +8,7 @@ import datetime as dt
8
8
  from datetime import UTC, datetime
9
9
  from enum import Enum, StrEnum
10
10
  from typing import Any, NotRequired, TypedDict
11
- from uuid import UUID # noqa: TCH003
11
+ from uuid import UUID
12
12
 
13
13
  from mashumaro import field_options
14
14
  from mashumaro.mixins.orjson import DataClassORJSONMixin
@@ -1041,6 +1041,21 @@ class HabiticaUserExport(UserData, DataClassORJSONMixin):
1041
1041
  tasks: TasksUserExport = field(default_factory=TasksUserExport)
1042
1042
 
1043
1043
 
1044
+ @dataclass
1045
+ class UserAnonymizedData:
1046
+ """Anonymized user data."""
1047
+
1048
+ user: UserData = field(default_factory=UserData)
1049
+ tasks: list[TaskData] = field(default_factory=list)
1050
+
1051
+
1052
+ @dataclass(kw_only=True)
1053
+ class HabiticaUserAnonymizedrResponse(DataClassORJSONMixin):
1054
+ """Representation of a anonymized user data export."""
1055
+
1056
+ data: UserAnonymizedData
1057
+
1058
+
1044
1059
  @dataclass(kw_only=True)
1045
1060
  class HabiticaStatsResponse(HabiticaResponse):
1046
1061
  """Representation of a response containing stats data."""
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes