Habiticalib 0.1.0a2__py3-none-any.whl → 0.2.0__py3-none-any.whl

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/__init__.py CHANGED
@@ -6,18 +6,26 @@ from .exceptions import (
6
6
  HabiticaException,
7
7
  NotAuthorizedError,
8
8
  NotFoundError,
9
+ TooManyRequestsError,
9
10
  )
11
+ from .helpers import deserialize_task
10
12
  from .lib import Habitica
11
13
  from .types import (
12
14
  Attributes,
13
- Class,
15
+ ChangeClassData,
16
+ ContentData,
14
17
  Direction,
15
18
  Frequency,
19
+ HabiticaClass,
16
20
  HabiticaClassSystemResponse,
21
+ HabiticaContentResponse,
17
22
  HabiticaErrorResponse,
23
+ HabiticaGroupMembersResponse,
18
24
  HabiticaLoginResponse,
25
+ HabiticaQuestResponse,
19
26
  HabiticaResponse,
20
27
  HabiticaScoreResponse,
28
+ HabiticaSleepResponse,
21
29
  HabiticaStatsResponse,
22
30
  HabiticaTagResponse,
23
31
  HabiticaTagsResponse,
@@ -27,10 +35,18 @@ from .types import (
27
35
  HabiticaUserExport,
28
36
  HabiticaUserResponse,
29
37
  Language,
38
+ LoginData,
39
+ QuestData,
40
+ ScoreData,
30
41
  Skill,
42
+ StatsUser,
43
+ TagsUser,
31
44
  Task,
45
+ TaskData,
32
46
  TaskFilter,
47
+ TaskPriority,
33
48
  TaskType,
49
+ UserData,
34
50
  UserStyles,
35
51
  )
36
52
 
@@ -39,17 +55,24 @@ __all__ = [
39
55
  "ASSETS_URL",
40
56
  "Attributes",
41
57
  "BadRequestError",
42
- "Class",
58
+ "ChangeClassData",
59
+ "ContentData",
43
60
  "DEFAULT_URL",
61
+ "deserialize_task",
44
62
  "Direction",
45
63
  "Frequency",
46
64
  "Habitica",
65
+ "HabiticaClass",
47
66
  "HabiticaClassSystemResponse",
67
+ "HabiticaContentResponse",
48
68
  "HabiticaErrorResponse",
49
69
  "HabiticaException",
70
+ "HabiticaGroupMembersResponse",
50
71
  "HabiticaLoginResponse",
72
+ "HabiticaQuestResponse",
51
73
  "HabiticaResponse",
52
74
  "HabiticaScoreResponse",
75
+ "HabiticaSleepResponse",
53
76
  "HabiticaStatsResponse",
54
77
  "HabiticaTagResponse",
55
78
  "HabiticaTagsResponse",
@@ -59,11 +82,20 @@ __all__ = [
59
82
  "HabiticaUserExport",
60
83
  "HabiticaUserResponse",
61
84
  "Language",
85
+ "LoginData",
62
86
  "NotAuthorizedError",
63
87
  "NotFoundError",
88
+ "QuestData",
89
+ "ScoreData",
64
90
  "Skill",
91
+ "StatsUser",
92
+ "TagsUser",
65
93
  "Task",
94
+ "TaskData",
66
95
  "TaskFilter",
96
+ "TaskPriority",
67
97
  "TaskType",
98
+ "TooManyRequestsError",
99
+ "UserData",
68
100
  "UserStyles",
69
101
  ]
habiticalib/const.py CHANGED
@@ -1,6 +1,6 @@
1
1
  """Constants for Habiticalib."""
2
2
 
3
- __version__ = "0.1.0a2"
3
+ __version__ = "0.2.0"
4
4
 
5
5
  DEFAULT_URL = "https://habitica.com/"
6
6
  ASSETS_URL = "https://habitica-assets.s3.amazonaws.com/mobileApp/images/"
@@ -14,3 +14,5 @@ BACKER_ONLY_GEAR = {
14
14
  "shield_special_ks2019": "BackerOnly-Equip-MythicGryphonShield.gif",
15
15
  "weapon_special_ks2019": "BackerOnly-Equip-MythicGryphonGlaive.gif",
16
16
  }
17
+
18
+ PAGE_LIMIT = 60
habiticalib/exceptions.py CHANGED
@@ -1,5 +1,6 @@
1
1
  """Exceptions for Habiticalib."""
2
2
 
3
+ from datetime import datetime
3
4
  from typing import Self
4
5
 
5
6
  from multidict import CIMultiDictProxy
@@ -17,10 +18,18 @@ class HabiticaException(Exception): # noqa: N818
17
18
  ) -> None:
18
19
  """Initialize the Exception."""
19
20
  self.error = error
20
- self.rate_limit = headers.get("x-ratelimit-limit")
21
- self.rate_limit_remaining = headers.get("x-ratelimit-remaining")
22
- self.rate_limit_reset = headers.get("x-ratelimit-reset")
23
- self.retry_after = headers.get("retry-after")
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)))
24
33
 
25
34
  super().__init__(error.message)
26
35
 
habiticalib/helpers.py CHANGED
@@ -1,7 +1,10 @@
1
1
  """Helper functions for Habiticalib."""
2
2
 
3
- from dataclasses import asdict
3
+ from dataclasses import asdict, is_dataclass
4
+ from datetime import date, datetime
5
+ from enum import Enum
4
6
  import platform
7
+ from typing import Any
5
8
  import uuid
6
9
 
7
10
  import aiohttp
@@ -112,3 +115,24 @@ def extract_user_styles(user_data: HabiticaUserResponse) -> UserStyles:
112
115
  """Extract user styles from a user data object."""
113
116
  data: UserData = user_data.data
114
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