pysportbot 0.0.13__tar.gz → 0.0.15__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 (23) hide show
  1. {pysportbot-0.0.13 → pysportbot-0.0.15}/PKG-INFO +2 -2
  2. {pysportbot-0.0.13 → pysportbot-0.0.15}/pyproject.toml +10 -10
  3. {pysportbot-0.0.13 → pysportbot-0.0.15}/pysportbot/activities.py +32 -8
  4. {pysportbot-0.0.13 → pysportbot-0.0.15}/LICENSE +0 -0
  5. {pysportbot-0.0.13 → pysportbot-0.0.15}/README.md +0 -0
  6. {pysportbot-0.0.13 → pysportbot-0.0.15}/pysportbot/__init__.py +0 -0
  7. {pysportbot-0.0.13 → pysportbot-0.0.15}/pysportbot/authenticator.py +0 -0
  8. {pysportbot-0.0.13 → pysportbot-0.0.15}/pysportbot/bookings.py +0 -0
  9. {pysportbot-0.0.13 → pysportbot-0.0.15}/pysportbot/centres.py +0 -0
  10. {pysportbot-0.0.13 → pysportbot-0.0.15}/pysportbot/endpoints.py +0 -0
  11. {pysportbot-0.0.13 → pysportbot-0.0.15}/pysportbot/service/__init__.py +0 -0
  12. {pysportbot-0.0.13 → pysportbot-0.0.15}/pysportbot/service/__main__.py +0 -0
  13. {pysportbot-0.0.13 → pysportbot-0.0.15}/pysportbot/service/booking.py +0 -0
  14. {pysportbot-0.0.13 → pysportbot-0.0.15}/pysportbot/service/config_loader.py +0 -0
  15. {pysportbot-0.0.13 → pysportbot-0.0.15}/pysportbot/service/config_validator.py +0 -0
  16. {pysportbot-0.0.13 → pysportbot-0.0.15}/pysportbot/service/scheduling.py +0 -0
  17. {pysportbot-0.0.13 → pysportbot-0.0.15}/pysportbot/service/service.py +0 -0
  18. {pysportbot-0.0.13 → pysportbot-0.0.15}/pysportbot/service/threading.py +0 -0
  19. {pysportbot-0.0.13 → pysportbot-0.0.15}/pysportbot/session.py +0 -0
  20. {pysportbot-0.0.13 → pysportbot-0.0.15}/pysportbot/utils/__init__.py +0 -0
  21. {pysportbot-0.0.13 → pysportbot-0.0.15}/pysportbot/utils/errors.py +0 -0
  22. {pysportbot-0.0.13 → pysportbot-0.0.15}/pysportbot/utils/logger.py +0 -0
  23. {pysportbot-0.0.13 → pysportbot-0.0.15}/pysportbot/utils/time.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: pysportbot
3
- Version: 0.0.13
3
+ Version: 0.0.15
4
4
  Summary: A python-based bot for automatic resasports slot booking
5
5
  Author: Joshua Falco Beirer
6
6
  Author-email: jbeirer@cern.ch
@@ -12,7 +12,7 @@ Classifier: Programming Language :: Python :: 3.12
12
12
  Classifier: Programming Language :: Python :: 3.13
13
13
  Requires-Dist: beautifulsoup4 (>=4.13.3,<5.0.0)
14
14
  Requires-Dist: pandas (>=2.2.3,<3.0.0)
15
- Requires-Dist: pytz (>=2025.1,<2026.0)
15
+ Requires-Dist: pytz (>=2025.2,<2026.0)
16
16
  Requires-Dist: requests (>=2.32.3,<3.0.0)
17
17
  Description-Content-Type: text/markdown
18
18
 
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "pysportbot"
3
- version = "v0.0.13"
3
+ version = "v0.0.15"
4
4
  description = "A python-based bot for automatic resasports slot booking"
5
5
  authors = [
6
6
  { name = "Joshua Falco Beirer", email = "jbeirer@cern.ch" }
@@ -18,26 +18,26 @@ python = ">=3.10,<3.14"
18
18
  requests = "^2.32.3"
19
19
  beautifulsoup4 = "^4.13.3"
20
20
  pandas = "^2.2.3"
21
- pytz = "^2025.1"
21
+ pytz = "^2025.2"
22
22
 
23
23
  [tool.poetry.group.dev.dependencies]
24
- pytest = "^8.3.4"
24
+ pytest = "^8.3.5"
25
25
  pytest-cov = "^6.0.0"
26
26
  deptry = "^0.23.0"
27
27
  mypy = "^1.15.0"
28
- pre-commit = "^4.1.0"
29
- tox = "^4.24.1"
28
+ pre-commit = "^4.2.0"
29
+ tox = "^4.24.2"
30
30
  ipykernel = "^6.29.5"
31
- types-pytz = "^2025.1.0.20250204"
32
- types-requests = "^2.32.0.20241016"
31
+ types-pytz = "^2025.1.0.20250318"
32
+ types-requests = "^2.32.0.20250306"
33
33
 
34
34
  [tool.poetry.group.docs.dependencies]
35
35
  mkdocs = "^1.6.1"
36
- mkdocs-material = "^9.6.3"
37
- mkdocstrings = {extras = ["python"], version = "^0.28.0"}
36
+ mkdocs-material = "^9.6.9"
37
+ mkdocstrings = {extras = ["python"], version = "^0.29.0"}
38
38
 
39
39
  [build-system]
40
- requires = ["poetry-core>=2.0.1"]
40
+ requires = ["poetry-core>=2.1.1"]
41
41
  build-backend = "poetry.core.masonry.api"
42
42
 
43
43
  [tool.black]
@@ -32,13 +32,27 @@ class Activities:
32
32
  """
33
33
  logger.info("Fetching activities...")
34
34
  response = self.session.post(Endpoints.ACTIVITIES, headers=self.headers)
35
+
35
36
  if response.status_code != 200:
36
37
  error_msg = ErrorMessages.failed_fetch("activities")
37
38
  logger.error(error_msg)
38
39
  raise RuntimeError(error_msg)
40
+
41
+ try:
42
+ activities = response.json().get("activities", {})
43
+ except json.JSONDecodeError as err:
44
+ error_msg = "Invalid JSON response while fetching activities."
45
+ logger.error(error_msg)
46
+ raise RuntimeError(error_msg) from err
47
+
48
+ if not activities:
49
+ logger.warning("No activities found in the response.")
50
+
51
+ df_activities = pd.DataFrame.from_dict(activities, orient="index")
52
+ df_activities.index = df_activities.index.astype(int) # Ensure index is integer for consistency
53
+
39
54
  logger.info("Activities fetched successfully.")
40
- activities = json.loads(response.content.decode("utf-8"))["activities"]
41
- return pd.DataFrame.from_dict(activities, orient="index")
55
+ return df_activities
42
56
 
43
57
  def daily_slots(self, df_activities: DataFrame, activity_name: str, day: str) -> DataFrame:
44
58
  """
@@ -67,9 +81,10 @@ class Activities:
67
81
  logger.error(error_msg)
68
82
  raise ValueError(error_msg)
69
83
 
70
- # Extract activity ID
71
- activity_id = str(activity_match.id_activity.iloc[0])
72
- id_category_activity = df_activities.loc[activity_id].activityCategoryId
84
+ # Extract activity ID and category ID
85
+ # Ensures activity_id is an integer
86
+ activity_id = activity_match.index[0]
87
+ id_category_activity = activity_match.at[activity_id, "activityCategoryId"]
73
88
 
74
89
  # Get Unix timestamp bounds for the day
75
90
  unix_day_bounds = get_unix_day_bounds(day)
@@ -81,12 +96,19 @@ class Activities:
81
96
  "end": unix_day_bounds[1],
82
97
  }
83
98
  response = self.session.get(Endpoints.SLOTS, headers=self.headers, params=params)
99
+
84
100
  if response.status_code != 200:
85
101
  error_msg = ErrorMessages.failed_fetch("slots")
86
102
  logger.error(error_msg)
87
103
  raise RuntimeError(error_msg)
88
104
 
89
- slots = json.loads(response.content.decode("utf-8"))
105
+ try:
106
+ slots = response.json()
107
+ except json.JSONDecodeError as err:
108
+ error_msg = "Invalid JSON response while fetching slots."
109
+ logger.error(error_msg)
110
+ raise RuntimeError(error_msg) from err
111
+
90
112
  if not slots:
91
113
  warning_msg = ErrorMessages.no_slots(activity_name, day)
92
114
  logger.warning(warning_msg)
@@ -110,10 +132,12 @@ class Activities:
110
132
  "trainer",
111
133
  ]
112
134
  df_slots = pd.DataFrame(slots)
113
- df_slots = df_slots[df_slots.columns.intersection(columns)] # Ensure no KeyError
135
+
136
+ # Ensure only desired columns are selected without KeyError
137
+ df_slots = df_slots.loc[:, df_slots.columns.intersection(columns)]
114
138
 
115
139
  # Only select rows of the specified activity
116
- df_slots = df_slots[df_slots.id_activity == activity_id]
140
+ df_slots = df_slots[df_slots["id_activity"] == activity_id]
117
141
  if df_slots.empty:
118
142
  warning_msg = ErrorMessages.no_matching_slots(activity_name, day)
119
143
  logger.warning(warning_msg)
File without changes
File without changes