MouseTools 4.3.0__tar.gz → 4.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 (30) hide show
  1. {mousetools-4.3.0 → mousetools-4.3.1}/PKG-INFO +1 -1
  2. {mousetools-4.3.0 → mousetools-4.3.1}/mousetools/api/menu.py +19 -13
  3. {mousetools-4.3.0 → mousetools-4.3.1}/mousetools/auth.py +5 -0
  4. {mousetools-4.3.0 → mousetools-4.3.1}/mousetools/channels/__init__.py +31 -19
  5. {mousetools-4.3.0 → mousetools-4.3.1}/mousetools/channels/facilities/__init__.py +1 -9
  6. {mousetools-4.3.0 → mousetools-4.3.1}/mousetools/channels/facilitystatus/__init__.py +3 -1
  7. {mousetools-4.3.0 → mousetools-4.3.1}/mousetools/decorators.py +2 -0
  8. {mousetools-4.3.0 → mousetools-4.3.1}/mousetools/mixins/couchbase.py +4 -1
  9. {mousetools-4.3.0 → mousetools-4.3.1}/mousetools/mixins/disney.py +1 -1
  10. {mousetools-4.3.0 → mousetools-4.3.1}/mousetools.egg-info/PKG-INFO +1 -1
  11. {mousetools-4.3.0 → mousetools-4.3.1}/pyproject.toml +1 -1
  12. {mousetools-4.3.0 → mousetools-4.3.1}/LICENSE +0 -0
  13. {mousetools-4.3.0 → mousetools-4.3.1}/README.md +0 -0
  14. {mousetools-4.3.0 → mousetools-4.3.1}/mousetools/__init__.py +0 -0
  15. {mousetools-4.3.0 → mousetools-4.3.1}/mousetools/api/__init__.py +0 -0
  16. {mousetools-4.3.0 → mousetools-4.3.1}/mousetools/api/search.py +0 -0
  17. {mousetools-4.3.0 → mousetools-4.3.1}/mousetools/channels/calendar/__init__.py +0 -0
  18. {mousetools-4.3.0 → mousetools-4.3.1}/mousetools/channels/characters/__init__.py +0 -0
  19. {mousetools-4.3.0 → mousetools-4.3.1}/mousetools/channels/enums.py +0 -0
  20. {mousetools-4.3.0 → mousetools-4.3.1}/mousetools/channels/facilities/enums.py +0 -0
  21. {mousetools-4.3.0 → mousetools-4.3.1}/mousetools/channels/forecastedwaittimes/__init__.py +0 -0
  22. {mousetools-4.3.0 → mousetools-4.3.1}/mousetools/enums.py +0 -0
  23. {mousetools-4.3.0 → mousetools-4.3.1}/mousetools/mixins/__init__.py +0 -0
  24. {mousetools-4.3.0 → mousetools-4.3.1}/mousetools/resources/environments.bin +0 -0
  25. {mousetools-4.3.0 → mousetools-4.3.1}/mousetools.egg-info/SOURCES.txt +0 -0
  26. {mousetools-4.3.0 → mousetools-4.3.1}/mousetools.egg-info/dependency_links.txt +0 -0
  27. {mousetools-4.3.0 → mousetools-4.3.1}/mousetools.egg-info/requires.txt +0 -0
  28. {mousetools-4.3.0 → mousetools-4.3.1}/mousetools.egg-info/top_level.txt +0 -0
  29. {mousetools-4.3.0 → mousetools-4.3.1}/setup.cfg +0 -0
  30. {mousetools-4.3.0 → mousetools-4.3.1}/tests/test_mixins.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mousetools
3
- Version: 4.3.0
3
+ Version: 4.3.1
4
4
  Summary: An unofficial Python wrapper for Disney's API
5
5
  Author: Scott Caratozzolo
6
6
  License-Expression: MIT
@@ -1,3 +1,4 @@
1
+ import logging
1
2
  import typing
2
3
  from datetime import datetime, timedelta
3
4
  from zoneinfo import ZoneInfo
@@ -8,7 +9,7 @@ from mousetools.auth import auth_obj
8
9
  from mousetools.decorators import disney_property, json_property
9
10
  from mousetools.mixins.disney import DisneyAPIMixin
10
11
 
11
- # menus -> menu -> menugroups -> menuitems
12
+ logger = logging.getLogger(__name__)
12
13
 
13
14
 
14
15
  class MenuItem:
@@ -351,7 +352,17 @@ class Menus(DisneyAPIMixin):
351
352
 
352
353
  def refresh(self) -> None:
353
354
  """Pulls initial data if none exists or if it is older than the refresh interval"""
354
- if self._disney_data is None or datetime.now(tz=self._tz) - self.last_refresh > self._refresh_interval:
355
+ no_data_check = self._disney_data is None
356
+ time_since_pull = datetime.now(tz=self._tz) - self._disney_data_pull_time
357
+ old_data_check = time_since_pull > self._refresh_interval
358
+ logger.debug(
359
+ "No data check: %s, Time since last update: %s, Old data check: %s",
360
+ no_data_check,
361
+ time_since_pull,
362
+ old_data_check,
363
+ )
364
+ if no_data_check or old_data_check:
365
+ logger.info("Refreshing menu data %s", self.entity_id)
355
366
  self._disney_data = self.get_disney_data(self._menu_service_url)
356
367
  self._disney_data_pull_time = datetime.now(tz=self._tz)
357
368
 
@@ -396,19 +407,14 @@ class Menus(DisneyAPIMixin):
396
407
  """
397
408
  return self._disney_data["ancestorLocationLandArea"]
398
409
 
399
- @property
400
- def last_refresh(self) -> datetime:
410
+ @disney_property()
411
+ def last_refresh(self) -> typing.Optional[datetime]:
401
412
  """
402
413
  The last time the menus were refreshed.
403
414
 
404
415
  Returns:
405
- (datetime): The last time the menus were refreshed.
416
+ (typing.Optional[datetime]): The last time the menus were refreshed.
406
417
  """
407
- if self._disney_data is None:
408
- self._disney_data = self.get_disney_data(self.entity_id)
409
- try:
410
- refresh_time = isoparse(self._disney_data["lastRefresh"])
411
- refresh_time = refresh_time.replace(tzinfo=self._tz)
412
- return refresh_time
413
- except (KeyError, TypeError, ValueError):
414
- return self._disney_data_pull_time
418
+ refresh_time = isoparse(self._disney_data["lastRefresh"])
419
+ refresh_time = refresh_time.replace(tzinfo=self._tz)
420
+ return refresh_time
@@ -1,5 +1,6 @@
1
1
  import base64
2
2
  import json
3
+ import logging
3
4
  import typing
4
5
  from datetime import datetime, timedelta
5
6
  from importlib.resources import as_file, files
@@ -7,6 +8,8 @@ from importlib.resources import as_file, files
7
8
  import httpx
8
9
  from Crypto.Cipher import AES
9
10
 
11
+ logger = logging.getLogger(__name__)
12
+
10
13
 
11
14
  class Authentication:
12
15
  def __init__(self):
@@ -38,6 +41,7 @@ class Authentication:
38
41
  "client_id": self._environments["authzClientId"],
39
42
  }
40
43
 
44
+ logger.debug("Sending request for authentication token")
41
45
  response = httpx.post(
42
46
  f"{self._environments['authzServiceUrl']}/token",
43
47
  headers=headers,
@@ -57,6 +61,7 @@ class Authentication:
57
61
  """
58
62
 
59
63
  if self.time_of_expire is None or (datetime.now() > self.time_of_expire):
64
+ logger.info("Requesting new authentication token")
60
65
  access_token, expires_in = self.authenticate()
61
66
  self.time_of_expire = datetime.now() + timedelta(seconds=(expires_in - 10))
62
67
  self.access_token = access_token
@@ -6,6 +6,7 @@ from enum import Enum
6
6
  from dateutil.parser import isoparse
7
7
 
8
8
  from mousetools.channels.enums import DestinationTimezones, DLRCouchbaseChannels, WDWCouchbaseChannels
9
+ from mousetools.decorators import disney_property
9
10
  from mousetools.enums import DestinationShort, EntityType
10
11
  from mousetools.mixins.couchbase import CouchbaseMixin
11
12
 
@@ -26,7 +27,7 @@ class CouchbaseChildChannel(CouchbaseMixin):
26
27
  if self._destination_short == DestinationShort.WALT_DISNEY_WORLD
27
28
  else DestinationTimezones.DISNEYLAND_RESORT
28
29
  )
29
- self._refresh_interval: timedelta = timedelta(minutes=30)
30
+ self._refresh_interval: timedelta = timedelta(hours=12)
30
31
  self._cb_data: typing.Optional[dict] = None
31
32
  self._cb_data_pull_time: datetime = datetime.now(tz=self._tz.value)
32
33
  if not lazy_load:
@@ -34,28 +35,29 @@ class CouchbaseChildChannel(CouchbaseMixin):
34
35
 
35
36
  def refresh(self) -> None:
36
37
  """Pulls initial data if none exists or if it is older than the refresh interval"""
37
- if self._cb_data is None or datetime.now(tz=self._tz.value) - self.last_update > self._refresh_interval:
38
+
39
+ no_data_check = self._cb_data is None
40
+ time_since_pull = datetime.now(tz=self._tz.value) - self._cb_data_pull_time
41
+ old_data_check = time_since_pull > self._refresh_interval
42
+ logger.debug(
43
+ "No data check: %s, Time since pull: %s, Old data check: %s", no_data_check, time_since_pull, old_data_check
44
+ )
45
+ if no_data_check or old_data_check:
46
+ logger.info("Refreshing %s", self.channel_id)
38
47
  self._cb_data = self.get_channel_data(self.channel_id)
39
48
  self._cb_data_pull_time = datetime.now(tz=self._tz.value)
40
49
 
41
- @property
42
- def last_update(self) -> datetime:
50
+ @disney_property()
51
+ def last_update(self) -> typing.Optional[datetime]:
43
52
  """
44
- The last time the data was updated.
53
+ The last time disney updated the data.
45
54
 
46
55
  Returns:
47
- (datetime): The last time the entity's data was updated, or None if no such data exists.
56
+ (typing.Optional[datetime]): The last time the entity's data was updated, or None if no such data exists.
48
57
  """
49
- if self._cb_data is None:
50
- self._cb_data = self.get_channel_data(self.channel_id)
51
-
52
- try:
53
- dt = isoparse(self._cb_data["lastUpdate"])
54
- dt = dt.replace(tzinfo=self._tz.value)
55
- return dt
56
- except (KeyError, TypeError, ValueError):
57
- logger.debug("No last updated found for %s", self.channel_id)
58
- return self._cb_data_pull_time
58
+ dt = isoparse(self._cb_data["lastUpdate"])
59
+ dt = dt.replace(tzinfo=self._tz.value)
60
+ return dt
59
61
 
60
62
 
61
63
  class CouchbaseChannel(CouchbaseMixin):
@@ -78,16 +80,26 @@ class CouchbaseChannel(CouchbaseMixin):
78
80
 
79
81
  self._cb_data = None
80
82
  self._refresh_interval = timedelta(minutes=10)
81
- self.last_update = datetime.now(tz=self._tz.value)
83
+ self._cb_data_pull_time = datetime.now(tz=self._tz.value)
82
84
 
83
85
  if not lazy_load:
84
86
  self.refresh()
85
87
 
86
88
  def refresh(self) -> None:
87
89
  """Pulls initial data if none exists or if it is older than the refresh interval"""
88
- if self._cb_data is None or datetime.now(tz=self._tz.value) - self.last_update > self._refresh_interval:
90
+ no_data_check = self._cb_data is None
91
+ time_since_pull = datetime.now(tz=self._tz.value) - self._cb_data_pull_time
92
+ old_data_check = time_since_pull > self._refresh_interval
93
+ logger.debug(
94
+ "No data check: %s, Time since last update: %s, Old data check: %s",
95
+ no_data_check,
96
+ time_since_pull,
97
+ old_data_check,
98
+ )
99
+ if no_data_check or old_data_check:
100
+ logger.info("Refreshing %s", self.channel_id)
89
101
  self._cb_data = self.get_channel_changes(self.channel_id)
90
- self.last_update = datetime.now(tz=self._tz.value)
102
+ self._cb_data_pull_time = datetime.now(tz=self._tz.value)
91
103
 
92
104
  def get_children_channel_ids(self) -> list[str]:
93
105
  """Returns a list of child channel ids for the channel."""
@@ -49,18 +49,10 @@ class FacilityChildChannel(CouchbaseChildChannel):
49
49
  """
50
50
  super().__init__(channel_id, lazy_load=lazy_load)
51
51
 
52
- self._refresh_interval: timedelta = timedelta(
53
- hours=12
54
- ) # properties are rarely updated, no need to spam the API
52
+ self._refresh_interval = timedelta(weeks=1) # properties are rarely updated
55
53
 
56
54
  self._today_calendar: typing.Optional[CalendarChildChannel] = None
57
55
 
58
- def refresh(self) -> None:
59
- """Pulls initial data if none exists or if it is older than the refresh interval"""
60
- if self._cb_data is None or datetime.now(tz=self._tz.value) - self.last_update > self._refresh_interval:
61
- self._cb_data = self.get_channel_data(self.channel_id)
62
- self._cb_data_pull_time = datetime.now(tz=self._tz.value)
63
-
64
56
  def pull_today_calendar(self) -> None:
65
57
  """Pulls today's calendar.
66
58
 
@@ -1,6 +1,6 @@
1
1
  import logging
2
2
  import typing
3
- from datetime import datetime
3
+ from datetime import datetime, timedelta
4
4
 
5
5
  from dateutil.parser import isoparse
6
6
 
@@ -21,6 +21,8 @@ class FacilityStatusChildChannel(CouchbaseChildChannel):
21
21
  """
22
22
  super().__init__(channel_id, lazy_load=lazy_load)
23
23
 
24
+ self._refresh_interval: timedelta = timedelta(minutes=10)
25
+
24
26
  def get_status(self) -> typing.Optional[str]:
25
27
  """Get the operating status of the facility
26
28
 
@@ -18,6 +18,7 @@ def disney_property(
18
18
  try:
19
19
  return func(self)
20
20
  except (KeyError, TypeError, ValueError):
21
+ logger.debug("No data found for disney property %s, returning default value", func.__name__)
21
22
  return default_value
22
23
 
23
24
  wrapper.__annotations__ = func.__annotations__
@@ -34,6 +35,7 @@ def json_property(func: Callable) -> property:
34
35
  try:
35
36
  return func(self)
36
37
  except (KeyError, TypeError, ValueError):
38
+ logger.debug("No data found for json property %s", func.__name__)
37
39
  return None
38
40
 
39
41
  return wrapper
@@ -35,8 +35,9 @@ class CouchbaseMixin:
35
35
  "json": True,
36
36
  }
37
37
 
38
+ logger.info("Sending request for channel data: %s", channel_name)
38
39
  response = httpx.post(self._couchbase_url + "/_bulk_get", json=payload, headers=self._headers)
39
- logger.debug("Response status: %s", response.status_code)
40
+ logger.debug("Response status for %s: %s", channel_name, response.status_code)
40
41
  data = None
41
42
  try:
42
43
  response.raise_for_status()
@@ -71,7 +72,9 @@ class CouchbaseMixin:
71
72
  if since:
72
73
  payload["since"] = since
73
74
 
75
+ logger.info("Sending request for channel changes: %s", channel_name)
74
76
  response = httpx.post(self._couchbase_url + "/_changes", json=payload, headers=self._headers)
77
+ logger.debug("Response status for %s: %s", channel_name, response.status_code)
75
78
  data = response.raise_for_status().json()
76
79
  except httpx.HTTPError as err:
77
80
  logger.error("Request failed: %s", err)
@@ -31,7 +31,7 @@ class DisneyAPIMixin:
31
31
  response.raise_for_status()
32
32
  data = response.json()
33
33
  except (httpx.HTTPError, json.decoder.JSONDecodeError) as err:
34
- logger.warning("Request failed. Error: %s", err)
34
+ logger.error("Request failed. Error: %s", err)
35
35
  return None
36
36
 
37
37
  return data
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mousetools
3
- Version: 4.3.0
3
+ Version: 4.3.1
4
4
  Summary: An unofficial Python wrapper for Disney's API
5
5
  Author: Scott Caratozzolo
6
6
  License-Expression: MIT
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "mousetools"
3
- version = "4.3.0"
3
+ version = "4.3.1"
4
4
  authors = [{name = "Scott Caratozzolo"}]
5
5
  description = "An unofficial Python wrapper for Disney's API"
6
6
  readme = "README.md"
File without changes
File without changes
File without changes