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.
- {mousetools-4.3.0 → mousetools-4.3.1}/PKG-INFO +1 -1
- {mousetools-4.3.0 → mousetools-4.3.1}/mousetools/api/menu.py +19 -13
- {mousetools-4.3.0 → mousetools-4.3.1}/mousetools/auth.py +5 -0
- {mousetools-4.3.0 → mousetools-4.3.1}/mousetools/channels/__init__.py +31 -19
- {mousetools-4.3.0 → mousetools-4.3.1}/mousetools/channels/facilities/__init__.py +1 -9
- {mousetools-4.3.0 → mousetools-4.3.1}/mousetools/channels/facilitystatus/__init__.py +3 -1
- {mousetools-4.3.0 → mousetools-4.3.1}/mousetools/decorators.py +2 -0
- {mousetools-4.3.0 → mousetools-4.3.1}/mousetools/mixins/couchbase.py +4 -1
- {mousetools-4.3.0 → mousetools-4.3.1}/mousetools/mixins/disney.py +1 -1
- {mousetools-4.3.0 → mousetools-4.3.1}/mousetools.egg-info/PKG-INFO +1 -1
- {mousetools-4.3.0 → mousetools-4.3.1}/pyproject.toml +1 -1
- {mousetools-4.3.0 → mousetools-4.3.1}/LICENSE +0 -0
- {mousetools-4.3.0 → mousetools-4.3.1}/README.md +0 -0
- {mousetools-4.3.0 → mousetools-4.3.1}/mousetools/__init__.py +0 -0
- {mousetools-4.3.0 → mousetools-4.3.1}/mousetools/api/__init__.py +0 -0
- {mousetools-4.3.0 → mousetools-4.3.1}/mousetools/api/search.py +0 -0
- {mousetools-4.3.0 → mousetools-4.3.1}/mousetools/channels/calendar/__init__.py +0 -0
- {mousetools-4.3.0 → mousetools-4.3.1}/mousetools/channels/characters/__init__.py +0 -0
- {mousetools-4.3.0 → mousetools-4.3.1}/mousetools/channels/enums.py +0 -0
- {mousetools-4.3.0 → mousetools-4.3.1}/mousetools/channels/facilities/enums.py +0 -0
- {mousetools-4.3.0 → mousetools-4.3.1}/mousetools/channels/forecastedwaittimes/__init__.py +0 -0
- {mousetools-4.3.0 → mousetools-4.3.1}/mousetools/enums.py +0 -0
- {mousetools-4.3.0 → mousetools-4.3.1}/mousetools/mixins/__init__.py +0 -0
- {mousetools-4.3.0 → mousetools-4.3.1}/mousetools/resources/environments.bin +0 -0
- {mousetools-4.3.0 → mousetools-4.3.1}/mousetools.egg-info/SOURCES.txt +0 -0
- {mousetools-4.3.0 → mousetools-4.3.1}/mousetools.egg-info/dependency_links.txt +0 -0
- {mousetools-4.3.0 → mousetools-4.3.1}/mousetools.egg-info/requires.txt +0 -0
- {mousetools-4.3.0 → mousetools-4.3.1}/mousetools.egg-info/top_level.txt +0 -0
- {mousetools-4.3.0 → mousetools-4.3.1}/setup.cfg +0 -0
- {mousetools-4.3.0 → mousetools-4.3.1}/tests/test_mixins.py +0 -0
|
@@ -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
|
-
|
|
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
|
-
|
|
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
|
-
@
|
|
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
|
-
|
|
408
|
-
|
|
409
|
-
|
|
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(
|
|
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
|
-
|
|
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
|
-
@
|
|
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
|
|
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
|
-
|
|
50
|
-
|
|
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.
|
|
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
|
-
|
|
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.
|
|
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
|
|
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.
|
|
34
|
+
logger.error("Request failed. Error: %s", err)
|
|
35
35
|
return None
|
|
36
36
|
|
|
37
37
|
return data
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|