pynintendoparental 1.1.3__py3-none-any.whl → 2.0.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.
@@ -6,14 +6,20 @@ import asyncio
6
6
  from datetime import datetime, timedelta, time
7
7
  from typing import Callable
8
8
 
9
+ from pynintendoauth.exceptions import HttpException
10
+
9
11
  from .api import Api
10
12
  from .const import _LOGGER, DAYS_OF_WEEK
11
- from .exceptions import BedtimeOutOfRangeError, DailyPlaytimeOutOfRangeError, HttpException
13
+ from .exceptions import (
14
+ BedtimeOutOfRangeError,
15
+ DailyPlaytimeOutOfRangeError,
16
+ )
12
17
  from .enum import AlarmSettingState, DeviceTimerMode, RestrictionMode
13
18
  from .player import Player
14
19
  from .utils import is_awaitable
15
20
  from .application import Application
16
21
 
22
+
17
23
  class Device:
18
24
  """A device"""
19
25
 
@@ -52,10 +58,7 @@ class Device:
52
58
  @property
53
59
  def model(self) -> str:
54
60
  """Return the model."""
55
- model_map = {
56
- "P00": "Switch",
57
- "P01": "Switch 2"
58
- }
61
+ model_map = {"P00": "Switch", "P01": "Switch 2"}
59
62
  return model_map.get(self.generation, "Unknown")
60
63
 
61
64
  @property
@@ -68,10 +71,10 @@ class Device:
68
71
  _LOGGER.debug(">> Device.update()")
69
72
  now = datetime.now()
70
73
  await asyncio.gather(
71
- self._get_daily_summaries(now),
72
- self._get_parental_control_setting(now),
73
- self.get_monthly_summary(),
74
- self._get_extras()
74
+ self._get_daily_summaries(now),
75
+ self._get_parental_control_setting(now),
76
+ self.get_monthly_summary(),
77
+ self._get_extras(),
75
78
  )
76
79
  if not self.players:
77
80
  self.players = Player.from_device_daily_summary(self.daily_summaries)
@@ -114,9 +117,7 @@ class Device:
114
117
  """Updates the pin for the device."""
115
118
  _LOGGER.debug(">> Device.set_new_pin(pin=REDACTED)")
116
119
  await self._send_api_update(
117
- self._api.async_update_unlock_code,
118
- new_code=pin,
119
- device_id=self.device_id
120
+ self._api.async_update_unlock_code, new_code=pin, device_id=self.device_id
120
121
  )
121
122
 
122
123
  async def add_extra_time(self, minutes: int):
@@ -129,25 +130,30 @@ class Device:
129
130
  async def set_restriction_mode(self, mode: RestrictionMode):
130
131
  """Updates the restriction mode of the device."""
131
132
  _LOGGER.debug(">> Device.set_restriction_mode(mode=%s)", mode)
132
- self.parental_control_settings["playTimerRegulations"]["restrictionMode"] = str(mode)
133
+ self.parental_control_settings["playTimerRegulations"]["restrictionMode"] = str(
134
+ mode
135
+ )
133
136
  response = await self._api.async_update_play_timer(
134
137
  settings={
135
138
  "deviceId": self.device_id,
136
- "playTimerRegulations": self.parental_control_settings["playTimerRegulations"]
139
+ "playTimerRegulations": self.parental_control_settings[
140
+ "playTimerRegulations"
141
+ ],
137
142
  }
138
143
  )
139
144
  now = datetime.now()
140
- self._parse_parental_control_setting(response["json"], now) # Don't need to recalculate times
145
+ self._parse_parental_control_setting(
146
+ response["json"], now
147
+ ) # Don't need to recalculate times
141
148
  await self._execute_callbacks()
142
149
 
143
150
  async def set_bedtime_alarm(self, value: time):
144
151
  """Update the bedtime alarm for the device."""
145
- _LOGGER.debug(">> Device.set_bedtime_alarm(value=%s)",
146
- value)
152
+ _LOGGER.debug(">> Device.set_bedtime_alarm(value=%s)", value)
147
153
  if not (
148
- (16 <= value.hour <= 22) or
149
- (value.hour == 23 and value.minute == 0) or
150
- (value.hour == 0 and value.minute == 0)
154
+ (16 <= value.hour <= 22)
155
+ or (value.hour == 23 and value.minute == 0)
156
+ or (value.hour == 0 and value.minute == 0)
151
157
  ):
152
158
  raise BedtimeOutOfRangeError(value=value)
153
159
  now = datetime.now()
@@ -157,24 +163,25 @@ class Device:
157
163
  if bedtime["enabled"]:
158
164
  bedtime = {
159
165
  **bedtime,
160
- "endingTime": {
161
- "hour": value.hour,
162
- "minute": value.minute
163
- }
166
+ "endingTime": {"hour": value.hour, "minute": value.minute},
164
167
  }
165
168
  if self.timer_mode == DeviceTimerMode.DAILY:
166
- self.parental_control_settings["playTimerRegulations"]["dailyRegulations"]["bedtime"] = bedtime
169
+ self.parental_control_settings["playTimerRegulations"]["dailyRegulations"][
170
+ "bedtime"
171
+ ] = bedtime
167
172
  else:
168
- self.parental_control_settings["playTimerRegulations"]["eachDayOfTheWeekRegulations"][
169
- DAYS_OF_WEEK[now.weekday()]
170
- ]["bedtime"] = bedtime
173
+ self.parental_control_settings["playTimerRegulations"][
174
+ "eachDayOfTheWeekRegulations"
175
+ ][DAYS_OF_WEEK[now.weekday()]]["bedtime"] = bedtime
171
176
  await self._send_api_update(
172
177
  self._api.async_update_play_timer,
173
178
  settings={
174
179
  "deviceId": self.device_id,
175
- "playTimerRegulations": self.parental_control_settings["playTimerRegulations"]
180
+ "playTimerRegulations": self.parental_control_settings[
181
+ "playTimerRegulations"
182
+ ],
176
183
  },
177
- now=now
184
+ now=now,
178
185
  )
179
186
 
180
187
  async def set_timer_mode(self, mode: DeviceTimerMode):
@@ -186,14 +193,15 @@ class Device:
186
193
  self._api.async_update_play_timer,
187
194
  settings={
188
195
  "deviceId": self.device_id,
189
- "playTimerRegulations": self.parental_control_settings["playTimerRegulations"]
190
- }
196
+ "playTimerRegulations": self.parental_control_settings[
197
+ "playTimerRegulations"
198
+ ],
199
+ },
191
200
  )
192
201
 
193
202
  async def update_max_daily_playtime(self, minutes: int | float = 0):
194
203
  """Updates the maximum daily playtime of a device."""
195
- _LOGGER.debug(">> Device.update_max_daily_playtime(minutes=%s)",
196
- minutes)
204
+ _LOGGER.debug(">> Device.update_max_daily_playtime(minutes=%s)", minutes)
197
205
  if isinstance(minutes, float):
198
206
  minutes = int(minutes)
199
207
  if minutes > 360 or minutes < -1:
@@ -207,39 +215,63 @@ class Device:
207
215
  _LOGGER.debug(
208
216
  "Setting timeToPlayInOneDay.limitTime for device %s to value %s",
209
217
  self.device_id,
210
- minutes)
211
- self.parental_control_settings["playTimerRegulations"]["dailyRegulations"]["timeToPlayInOneDay"]["enabled"] = ttpiod
212
- if "limitTime" in self.parental_control_settings["playTimerRegulations"]["dailyRegulations"]["timeToPlayInOneDay"] and minutes is None:
213
- self.parental_control_settings["playTimerRegulations"]["dailyRegulations"]["timeToPlayInOneDay"].pop("limitTime")
218
+ minutes,
219
+ )
220
+ self.parental_control_settings["playTimerRegulations"]["dailyRegulations"][
221
+ "timeToPlayInOneDay"
222
+ ]["enabled"] = ttpiod
223
+ if (
224
+ "limitTime"
225
+ in self.parental_control_settings["playTimerRegulations"][
226
+ "dailyRegulations"
227
+ ]["timeToPlayInOneDay"]
228
+ and minutes is None
229
+ ):
230
+ self.parental_control_settings["playTimerRegulations"][
231
+ "dailyRegulations"
232
+ ]["timeToPlayInOneDay"].pop("limitTime")
214
233
  else:
215
- self.parental_control_settings["playTimerRegulations"]["dailyRegulations"]["timeToPlayInOneDay"]["limitTime"] = minutes
234
+ self.parental_control_settings["playTimerRegulations"][
235
+ "dailyRegulations"
236
+ ]["timeToPlayInOneDay"]["limitTime"] = minutes
216
237
  else:
217
238
  _LOGGER.debug(
218
239
  "Setting timeToPlayInOneDay.limitTime for device %s to value %s",
219
240
  self.device_id,
220
- minutes
241
+ minutes,
221
242
  )
222
- day_of_week_regs = self.parental_control_settings["playTimerRegulations"]["eachDayOfTheWeekRegulations"]
243
+ day_of_week_regs = self.parental_control_settings["playTimerRegulations"][
244
+ "eachDayOfTheWeekRegulations"
245
+ ]
223
246
  current_day = DAYS_OF_WEEK[now.weekday()]
224
247
  day_of_week_regs[current_day]["timeToPlayInOneDay"]["enabled"] = ttpiod
225
- if "limitTime" in day_of_week_regs[current_day]["timeToPlayInOneDay"] and minutes is None:
248
+ if (
249
+ "limitTime" in day_of_week_regs[current_day]["timeToPlayInOneDay"]
250
+ and minutes is None
251
+ ):
226
252
  day_of_week_regs[current_day]["timeToPlayInOneDay"].pop("limitTime")
227
253
  else:
228
- day_of_week_regs[current_day]["timeToPlayInOneDay"]["limitTime"] = minutes
254
+ day_of_week_regs[current_day]["timeToPlayInOneDay"]["limitTime"] = (
255
+ minutes
256
+ )
229
257
 
230
258
  await self._send_api_update(
231
259
  self._api.async_update_play_timer,
232
260
  settings={
233
261
  "deviceId": self.device_id,
234
- "playTimerRegulations": self.parental_control_settings["playTimerRegulations"]
262
+ "playTimerRegulations": self.parental_control_settings[
263
+ "playTimerRegulations"
264
+ ],
235
265
  },
236
- now=now
266
+ now=now,
237
267
  )
238
268
 
239
269
  def _update_applications(self):
240
270
  """Updates applications from daily summary."""
241
271
  _LOGGER.debug(">> Device._update_applications()")
242
- parsed_apps = Application.from_whitelist(self.parental_control_settings.get("whitelistedApplications", []))
272
+ parsed_apps = Application.from_whitelist(
273
+ self.parental_control_settings.get("whitelistedApplications", [])
274
+ )
243
275
  for app in parsed_apps:
244
276
  try:
245
277
  self.get_application(app.application_id).update(app)
@@ -250,9 +282,13 @@ class Device:
250
282
  def _get_today_regulation(self, now: datetime) -> dict:
251
283
  """Returns the regulation settings for the current day."""
252
284
  if self.timer_mode == DeviceTimerMode.EACH_DAY_OF_THE_WEEK:
253
- day_of_week_regs = self.parental_control_settings["playTimerRegulations"].get("eachDayOfTheWeekRegulations", {})
285
+ day_of_week_regs = self.parental_control_settings[
286
+ "playTimerRegulations"
287
+ ].get("eachDayOfTheWeekRegulations", {})
254
288
  return day_of_week_regs.get(DAYS_OF_WEEK[now.weekday()], {})
255
- return self.parental_control_settings.get("playTimerRegulations", {}).get("dailyRegulations", {})
289
+ return self.parental_control_settings.get("playTimerRegulations", {}).get(
290
+ "dailyRegulations", {}
291
+ )
256
292
 
257
293
  def _parse_parental_control_setting(self, pcs: dict, now: datetime):
258
294
  """Parse a parental control setting request response."""
@@ -260,13 +296,23 @@ class Device:
260
296
  self.parental_control_settings = pcs["parentalControlSetting"]
261
297
 
262
298
  # Clean up bedtimeStartingTime if it's empty
263
- if "bedtimeStartingTime" in self.parental_control_settings["playTimerRegulations"]:
264
- if self.parental_control_settings["playTimerRegulations"].get("bedtimeStartingTime", {}).get("hour", 0) == 0:
265
- self.parental_control_settings["playTimerRegulations"].pop("bedtimeStartingTime")
299
+ if (
300
+ "bedtimeStartingTime"
301
+ in self.parental_control_settings["playTimerRegulations"]
302
+ ):
303
+ if (
304
+ self.parental_control_settings["playTimerRegulations"]
305
+ .get("bedtimeStartingTime", {})
306
+ .get("hour", 0)
307
+ == 0
308
+ ):
309
+ self.parental_control_settings["playTimerRegulations"].pop(
310
+ "bedtimeStartingTime"
311
+ )
266
312
 
267
- self.forced_termination_mode = (
268
- self.parental_control_settings["playTimerRegulations"]["restrictionMode"] == str(RestrictionMode.FORCED_TERMINATION)
269
- )
313
+ self.forced_termination_mode = self.parental_control_settings[
314
+ "playTimerRegulations"
315
+ ]["restrictionMode"] == str(RestrictionMode.FORCED_TERMINATION)
270
316
 
271
317
  # Update limit and bedtime from regulations
272
318
  self.timer_mode = DeviceTimerMode(
@@ -280,7 +326,7 @@ class Device:
280
326
  if bedtime_setting.get("enabled"):
281
327
  self.bedtime_alarm = time(
282
328
  hour=bedtime_setting["endingTime"]["hour"],
283
- minute=bedtime_setting["endingTime"]["minute"]
329
+ minute=bedtime_setting["endingTime"]["minute"],
284
330
  )
285
331
  else:
286
332
  self.bedtime_alarm = time(hour=0, minute=0)
@@ -303,8 +349,10 @@ class Device:
303
349
  self.today_playing_time = self.daily_summaries[0].get("playingTime") or 0
304
350
  self.today_disabled_time = self.daily_summaries[0].get("disabledTime") or 0
305
351
  self.today_exceeded_time = self.daily_summaries[0].get("exceededTime") or 0
306
- _LOGGER.debug("Cached playing, disabled and exceeded time for today for device %s",
307
- self.device_id)
352
+ _LOGGER.debug(
353
+ "Cached playing, disabled and exceeded time for today for device %s",
354
+ self.device_id,
355
+ )
308
356
  self._calculate_today_remaining_time(now)
309
357
 
310
358
  month_playing_time: int = 0
@@ -319,56 +367,79 @@ class Device:
319
367
  for app in parsed_apps:
320
368
  try:
321
369
  int_app = self.get_application(app.application_id)
322
- _LOGGER.debug("Updating cached app state %s for device %s",
323
- int_app.application_id,
324
- self.device_id)
370
+ _LOGGER.debug(
371
+ "Updating cached app state %s for device %s",
372
+ int_app.application_id,
373
+ self.device_id,
374
+ )
325
375
  int_app.update(app)
326
376
  except ValueError:
327
- _LOGGER.debug("Creating new cached application entry %s for device %s",
328
- app.application_id,
329
- self.device_id)
377
+ _LOGGER.debug(
378
+ "Creating new cached application entry %s for device %s",
379
+ app.application_id,
380
+ self.device_id,
381
+ )
330
382
  self.applications.append(app)
331
383
 
332
384
  # update application playtime
333
385
  try:
334
386
  for player in self.get_date_summary()[0].get("devicePlayers", []):
335
387
  for app in player.get("playedApps", []):
336
- self.get_application(app["applicationId"]).update_today_time_played(app)
388
+ self.get_application(app["applicationId"]).update_today_time_played(
389
+ app
390
+ )
337
391
  self.application_update_failed = False
338
392
  except ValueError as err:
339
- _LOGGER.debug("Unable to retrieve applications for device %s: %s", self.name, err)
393
+ _LOGGER.debug(
394
+ "Unable to retrieve applications for device %s: %s", self.name, err
395
+ )
340
396
  self.application_update_failed = True
341
397
 
342
398
  def _calculate_today_remaining_time(self, now: datetime):
343
399
  """Calculates the remaining playing time for today."""
344
- self.stats_update_failed = True # Assume failure until success
400
+ self.stats_update_failed = True # Assume failure until success
345
401
  try:
346
- minutes_in_day = 1440 # 24 * 60
402
+ minutes_in_day = 1440 # 24 * 60
347
403
  current_minutes_past_midnight = now.hour * 60 + now.minute
348
404
 
349
405
  if self.limit_time in (-1, None):
350
406
  # No play limit, so remaining time is until end of day.
351
- time_remaining_by_play_limit = minutes_in_day - current_minutes_past_midnight
407
+ time_remaining_by_play_limit = (
408
+ minutes_in_day - current_minutes_past_midnight
409
+ )
352
410
  else:
353
411
  time_remaining_by_play_limit = self.limit_time - self.today_playing_time
354
412
 
355
413
  # 2. Calculate remaining time until bedtime
356
- if self.bedtime_alarm and self.bedtime_alarm != time(hour=0, minute=0) and self.alarms_enabled:
414
+ if (
415
+ self.bedtime_alarm
416
+ and self.bedtime_alarm != time(hour=0, minute=0)
417
+ and self.alarms_enabled
418
+ ):
357
419
  bedtime_dt = datetime.combine(now.date(), self.bedtime_alarm)
358
- if bedtime_dt > now: # Bedtime is in the future today
420
+ if bedtime_dt > now: # Bedtime is in the future today
359
421
  time_remaining_by_bedtime = (bedtime_dt - now).total_seconds() / 60
360
- else: # Bedtime has passed
422
+ else: # Bedtime has passed
361
423
  time_remaining_by_bedtime = 0.0
362
424
  else:
363
- time_remaining_by_bedtime = minutes_in_day - current_minutes_past_midnight
425
+ time_remaining_by_bedtime = (
426
+ minutes_in_day - current_minutes_past_midnight
427
+ )
364
428
 
365
429
  # Effective remaining time is the minimum of the two constraints
366
- effective_remaining_time = min(time_remaining_by_play_limit, time_remaining_by_bedtime)
430
+ effective_remaining_time = min(
431
+ time_remaining_by_play_limit, time_remaining_by_bedtime
432
+ )
367
433
  self.today_time_remaining = int(max(0.0, effective_remaining_time))
368
- _LOGGER.debug("Calculated today's remaining time: %s minutes", self.today_time_remaining)
434
+ _LOGGER.debug(
435
+ "Calculated today's remaining time: %s minutes",
436
+ self.today_time_remaining,
437
+ )
369
438
  self.stats_update_failed = False
370
439
  except (ValueError, TypeError, AttributeError) as err:
371
- _LOGGER.warning("Unable to calculate remaining time for device %s: %s", self.name, err)
440
+ _LOGGER.warning(
441
+ "Unable to calculate remaining time for device %s: %s", self.name, err
442
+ )
372
443
 
373
444
  async def _get_parental_control_setting(self, now: datetime):
374
445
  """Retreives parental control settings from the API."""
@@ -383,7 +454,7 @@ class Device:
383
454
  """Retrieve daily summaries."""
384
455
  _LOGGER.debug(">> Device._get_daily_summaries()")
385
456
  response = await self._api.async_get_device_daily_summaries(
386
- device_id = self.device_id
457
+ device_id=self.device_id
387
458
  )
388
459
  self.daily_summaries = response["json"]["dailySummaries"]
389
460
  _LOGGER.debug("New daily summary %s", self.daily_summaries)
@@ -395,14 +466,16 @@ class Device:
395
466
  if self.alarms_enabled is not None:
396
467
  # first refresh can come from self.extra without http request
397
468
  response = await self._api.async_get_account_device(
398
- device_id = self.device_id
469
+ device_id=self.device_id
399
470
  )
400
471
  self.extra = response["json"]["ownedDevice"]["device"]
401
472
  status = self.extra["alarmSetting"]["visibility"]
402
473
  self.alarms_enabled = status == str(AlarmSettingState.VISIBLE)
403
- _LOGGER.debug("Cached alarms enabled to state %s for device %s",
404
- self.alarms_enabled,
405
- self.device_id)
474
+ _LOGGER.debug(
475
+ "Cached alarms enabled to state %s for device %s",
476
+ self.alarms_enabled,
477
+ self.device_id,
478
+ )
406
479
 
407
480
  async def get_monthly_summary(self, search_date: datetime = None) -> dict | None:
408
481
  """Gets the monthly summary."""
@@ -420,56 +493,71 @@ class Device:
420
493
  available_summaries = response["json"]["available"]
421
494
  _LOGGER.debug("Available monthly summaries: %s", available_summaries)
422
495
  if not available_summaries:
423
- _LOGGER.debug("No monthly summaries available for device %s", self.device_id)
496
+ _LOGGER.debug(
497
+ "No monthly summaries available for device %s", self.device_id
498
+ )
424
499
  return None
425
500
  # Use the most recent available summary
426
501
  available_summary = available_summaries[0]
427
- search_date = datetime.strptime(f"{available_summary['year']}-{available_summary['month']}-01", "%Y-%m-%d")
428
- _LOGGER.debug("Using search date %s for monthly summary request", search_date)
502
+ search_date = datetime.strptime(
503
+ f"{available_summary['year']}-{available_summary['month']}-01",
504
+ "%Y-%m-%d",
505
+ )
506
+ _LOGGER.debug(
507
+ "Using search date %s for monthly summary request", search_date
508
+ )
429
509
  latest = True
430
510
 
431
511
  try:
432
512
  response = await self._api.async_get_device_monthly_summary(
433
- device_id=self.device_id,
434
- year=search_date.year,
435
- month=search_date.month
513
+ device_id=self.device_id, year=search_date.year, month=search_date.month
436
514
  )
437
515
  except HttpException as exc:
438
- _LOGGER.warning("HTTP Exception raised while getting monthly summary for device %s: %s",
439
- self.device_id,
440
- exc)
516
+ _LOGGER.warning(
517
+ "HTTP Exception raised while getting monthly summary for device %s: %s",
518
+ self.device_id,
519
+ exc,
520
+ )
441
521
  return None
442
522
  else:
443
- _LOGGER.debug("Monthly summary query complete for device %s: %s",
444
- self.device_id,
445
- response["json"]["summary"])
523
+ _LOGGER.debug(
524
+ "Monthly summary query complete for device %s: %s",
525
+ self.device_id,
526
+ response["json"]["summary"],
527
+ )
446
528
  if latest:
447
529
  self.last_month_summary = summary = response["json"]["summary"]
448
530
  return summary
449
531
  return response["json"]["summary"]
450
532
 
451
-
452
533
  def get_date_summary(self, input_date: datetime = datetime.now()) -> dict:
453
534
  """Returns usage for a given date."""
454
535
  if not self.daily_summaries:
455
536
  raise ValueError("No daily summaries available to search.")
456
537
  summary = [
457
- x for x in self.daily_summaries
458
- if x["date"] == input_date.strftime('%Y-%m-%d')
538
+ x
539
+ for x in self.daily_summaries
540
+ if x["date"] == input_date.strftime("%Y-%m-%d")
459
541
  ]
460
542
  if len(summary) == 0:
461
543
  input_date -= timedelta(days=1)
462
544
  summary = [
463
- x for x in self.daily_summaries
464
- if x["date"] == input_date.strftime('%Y-%m-%d')
465
- ]
545
+ x
546
+ for x in self.daily_summaries
547
+ if x["date"] == input_date.strftime("%Y-%m-%d")
548
+ ]
466
549
  if len(summary) == 0:
467
- raise ValueError(f"A summary for the given date {input_date} does not exist")
550
+ raise ValueError(
551
+ f"A summary for the given date {input_date} does not exist"
552
+ )
468
553
  return summary
469
554
 
470
555
  def get_application(self, application_id: str) -> Application:
471
556
  """Returns a single application."""
472
- app = next((app for app in self.applications if app.application_id == application_id), None)
557
+ app = next(
558
+ (app for app in self.applications if app.application_id == application_id),
559
+ None,
560
+ )
473
561
  if app:
474
562
  return app
475
563
  raise ValueError(f"Application with id {application_id} not found.")
@@ -482,7 +570,7 @@ class Device:
482
570
  raise ValueError(f"Player with id {player_id} not found.")
483
571
 
484
572
  @classmethod
485
- async def from_devices_response(cls, raw: dict, api) -> list['Device']:
573
+ async def from_devices_response(cls, raw: dict, api) -> list["Device"]:
486
574
  """Parses a device request response body."""
487
575
  _LOGGER.debug("Parsing device list response")
488
576
  if "ownedDevices" not in raw.keys():
@@ -500,7 +588,7 @@ class Device:
500
588
  return devices
501
589
 
502
590
  @classmethod
503
- def from_device_response(cls, raw: dict, api) -> 'Device':
591
+ def from_device_response(cls, raw: dict, api) -> "Device":
504
592
  """Parses a single device request response body."""
505
593
  _LOGGER.debug("Parsing device response")
506
594
  if "deviceId" not in raw.keys():
@@ -2,8 +2,10 @@
2
2
 
3
3
  from enum import Enum, StrEnum
4
4
 
5
+
5
6
  class AlarmSettingState(Enum):
6
7
  """Alarm setting states."""
8
+
7
9
  SUCCESS = 0
8
10
  TO_VISIBLE = 1
9
11
  TO_INVISIBLE = 2
@@ -13,16 +15,20 @@ class AlarmSettingState(Enum):
13
15
  def __str__(self) -> str:
14
16
  return self.name
15
17
 
18
+
16
19
  class RestrictionMode(Enum):
17
20
  """Restriction modes."""
21
+
18
22
  FORCED_TERMINATION = 0
19
23
  ALARM = 1
20
24
 
21
25
  def __str__(self) -> str:
22
26
  return self.name
23
27
 
28
+
24
29
  class DeviceTimerMode(StrEnum):
25
30
  """Device timer modes."""
31
+
26
32
  DAILY = "DAILY"
27
33
  EACH_DAY_OF_THE_WEEK = "EACH_DAY_OF_THE_WEEK"
28
34
 
@@ -8,31 +8,13 @@ class RangeErrorKeys(StrEnum):
8
8
  DAILY_PLAYTIME = "daily_playtime_out_of_range"
9
9
  BEDTIME = "bedtime_alarm_out_of_range"
10
10
 
11
- class HttpException(Exception):
12
- """A HTTP error occured"""
13
- def __init__(self, status_code: int, message: str, error_code: str | None = None) -> None:
14
- """Initialize the exception."""
15
- super().__init__(message)
16
- self.status_code = status_code
17
- self.message = message
18
- self.error_code = error_code
19
-
20
- def __str__(self) -> str:
21
- if self.error_code:
22
- return f"HTTP {self.status_code}: {self.message} ({self.error_code})"
23
- return f"HTTP {self.status_code}: {self.message}"
24
-
25
- class InvalidSessionTokenException(HttpException):
26
- """Provided session token was invalid (invalid_grant)."""
27
-
28
- class InvalidOAuthConfigurationException(HttpException):
29
- """The OAuth scopes are invalid."""
30
-
31
11
  class NoDevicesFoundException(Exception):
32
12
  """No devices were found for the account."""
33
13
 
14
+
34
15
  class InputValidationError(Exception):
35
16
  """Input Validation Failed."""
17
+
36
18
  value: object
37
19
  error_key: str
38
20
 
@@ -40,11 +22,13 @@ class InputValidationError(Exception):
40
22
  super().__init__(f"{self.__doc__} Received value: {value}")
41
23
  self.value = value
42
24
 
25
+
43
26
  class BedtimeOutOfRangeError(InputValidationError):
44
27
  """Bedtime is outside of the allowed range."""
45
28
 
46
29
  error_key = RangeErrorKeys.BEDTIME
47
30
 
31
+
48
32
  class DailyPlaytimeOutOfRangeError(InputValidationError):
49
33
  """Daily playtime is outside of the allowed range."""
50
34
 
@@ -2,8 +2,10 @@
2
2
 
3
3
  from .const import _LOGGER
4
4
 
5
+
5
6
  class Player:
6
7
  """Defines a single player on a Nintendo device."""
8
+
7
9
  def __init__(self):
8
10
  """Init a player."""
9
11
  self.player_image: str = None
@@ -25,7 +27,7 @@ class Player:
25
27
  break
26
28
 
27
29
  @classmethod
28
- def from_device_daily_summary(cls, raw: list[dict]) -> list['Player']:
30
+ def from_device_daily_summary(cls, raw: list[dict]) -> list["Player"]:
29
31
  """Converts a daily summary response into a list of players."""
30
32
  players = []
31
33
  _LOGGER.debug("Building players from device daily summary.")
@@ -2,6 +2,7 @@
2
2
 
3
3
  import inspect
4
4
 
5
+
5
6
  def is_awaitable(func):
6
7
  """Check if a function is awaitable or not."""
7
8
  return inspect.iscoroutinefunction(func) or inspect.isasyncgenfunction(func)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pynintendoparental
3
- Version: 1.1.3
3
+ Version: 2.0.0
4
4
  Summary: A Python module to interact with Nintendo Parental Controls
5
5
  Home-page: http://github.com/pantherale0/pynintendoparental
6
6
  Author: pantherale0
@@ -11,6 +11,7 @@ Classifier: Operating System :: OS Independent
11
11
  Requires-Python: >=3.8, <4
12
12
  Description-Content-Type: text/markdown
13
13
  License-File: LICENSE
14
+ Requires-Dist: pynintendoauth~=1.0.0
14
15
  Provides-Extra: dev
15
16
  Requires-Dist: bandit<1.9,>=1.7; extra == "dev"
16
17
  Requires-Dist: black<26,>=23; extra == "dev"
@@ -29,6 +30,7 @@ Dynamic: home-page
29
30
  Dynamic: license
30
31
  Dynamic: license-file
31
32
  Dynamic: provides-extra
33
+ Dynamic: requires-dist
32
34
  Dynamic: requires-python
33
35
  Dynamic: summary
34
36