petsafe-api 3.0.1__tar.gz → 3.0.4__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: petsafe-api
3
- Version: 3.0.1
3
+ Version: 3.0.4
4
4
  Summary: Provides ability to connect and control a PetSafe Smart Feed, Scoopfree, and Smart Door devices using the PetSafe API.
5
5
  Home-page: https://github.com/ThomasHFWright/petsafe-api
6
6
  Author: Jordan Stremming & Dominick Meglio & Thomas Wright
@@ -0,0 +1,46 @@
1
+ import sys
2
+ import argparse
3
+ import asyncio
4
+
5
+ from petsafe import PetSafeClient
6
+
7
+ # create parser for arguments
8
+ parser = argparse.ArgumentParser(
9
+ usage="python -m petsafe email [-t email_code]"
10
+ )
11
+ parser.add_argument("email", help="account email address")
12
+
13
+ # if no arguments specified, show help
14
+ if len(sys.argv) < 2:
15
+ parser.print_help()
16
+ sys.exit(1)
17
+
18
+ # parse for arguments
19
+ args = parser.parse_args()
20
+
21
+ async def main() -> None:
22
+ client = PetSafeClient(email=args.email)
23
+ await client.request_code()
24
+ print("Code requested, please check your email.")
25
+ print("")
26
+
27
+ try:
28
+ code = input("Enter email code: ")
29
+ except EOFError:
30
+ print("\nNo code entered (EOF). Exiting.")
31
+ return
32
+
33
+ await client.request_tokens_from_code(code)
34
+
35
+ print("")
36
+ print("IdToken:")
37
+ print(client.id_token)
38
+ print("")
39
+ print("AccessToken:")
40
+ print(client.access_token)
41
+ print("")
42
+ print("RefreshToken:")
43
+ print(client.refresh_token)
44
+
45
+
46
+ asyncio.run(main())
@@ -83,10 +83,13 @@ class DeviceSmartFeed:
83
83
 
84
84
  """
85
85
  messages = await self.get_messages_since()
86
- for message in messages:
87
- if message["message_type"] == "FEED_DONE":
88
- return message
89
- return None
86
+ feed_done = [
87
+ message for message in messages
88
+ if message.get("message_type") == "FEED_DONE"
89
+ and isinstance(message.get("payload"), dict)
90
+ and isinstance(message["payload"].get("time"), int)
91
+ ]
92
+ return max(feed_done, key=lambda message: message["payload"]["time"], default=None)
90
93
 
91
94
  async def feed(
92
95
  self, amount: int = 1, slow_feed: bool = None, update_data: bool = True
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: petsafe-api
3
- Version: 3.0.1
3
+ Version: 3.0.4
4
4
  Summary: Provides ability to connect and control a PetSafe Smart Feed, Scoopfree, and Smart Door devices using the PetSafe API.
5
5
  Home-page: https://github.com/ThomasHFWright/petsafe-api
6
6
  Author: Jordan Stremming & Dominick Meglio & Thomas Wright
@@ -13,4 +13,5 @@ petsafe_api.egg-info/SOURCES.txt
13
13
  petsafe_api.egg-info/dependency_links.txt
14
14
  petsafe_api.egg-info/requires.txt
15
15
  petsafe_api.egg-info/top_level.txt
16
- tests/test_smartdoor_modes.py
16
+ tests/test_smartdoor_modes.py
17
+ tests/test_smartfeed_last_feeding.py
@@ -5,7 +5,7 @@ with open("README.md", "r") as fh:
5
5
 
6
6
  setuptools.setup(
7
7
  name="petsafe-api",
8
- version="3.0.1",
8
+ version="3.0.4",
9
9
  author="Jordan Stremming & Dominick Meglio & Thomas Wright",
10
10
  license="MIT",
11
11
  author_email="thomas.h.f.wright@gmail.com",
@@ -0,0 +1,34 @@
1
+ """Regression check for unordered SmartFeed messages."""
2
+
3
+ import asyncio
4
+ from itertools import permutations
5
+ from unittest.mock import AsyncMock
6
+
7
+ from petsafe.devices import DeviceSmartFeed
8
+
9
+
10
+ def test_last_feeding_uses_latest_valid_timestamp():
11
+ async def check():
12
+ feeder = DeviceSmartFeed(None, {})
13
+ oldest = {"message_type": "FEED_DONE", "payload": {"time": 100, "amount": 1}}
14
+ middle = {"message_type": "FEED_DONE", "payload": {"time": 200, "amount": 2}}
15
+ newest = {"message_type": "FEED_DONE", "payload": {"time": 300, "amount": 3}}
16
+ invalid = [
17
+ {},
18
+ {"message_type": "FEED_START", "payload": {"time": 400}},
19
+ {"message_type": "FEED_DONE"},
20
+ {"message_type": "FEED_DONE", "payload": None},
21
+ {"message_type": "FEED_DONE", "payload": []},
22
+ {"message_type": "FEED_DONE", "payload": {}},
23
+ {"message_type": "FEED_DONE", "payload": {"time": "400"}},
24
+ ]
25
+ for order in permutations((oldest, middle, newest)):
26
+ messages = invalid + list(order)
27
+ feeder.get_messages_since = AsyncMock(return_value=messages)
28
+ assert await feeder.get_last_feeding() is newest
29
+ assert messages == invalid + list(order)
30
+ for messages, expected in (([], None), (invalid, None), ([oldest], oldest)):
31
+ feeder.get_messages_since = AsyncMock(return_value=messages)
32
+ assert await feeder.get_last_feeding() is expected
33
+
34
+ asyncio.run(check())
@@ -1,36 +0,0 @@
1
- import sys
2
- import argparse
3
-
4
- from petsafe import PetSafeClient
5
-
6
- # create parser for arguments
7
- parser = argparse.ArgumentParser(
8
- usage="python -m petsafe email [-t email_code]"
9
- )
10
- parser.add_argument("email", help="account email address")
11
-
12
- # if no arguments specified, show help
13
- if len(sys.argv) < 2:
14
- parser.print_help()
15
- sys.exit(1)
16
-
17
- # parse for arguments
18
- args = parser.parse_args()
19
-
20
- client = PetSafeClient(email=args.email)
21
- client.request_code()
22
- print("Code requested, please check your email.")
23
- print("")
24
-
25
- code = input("Enter email code: ")
26
- client.request_tokens_from_code(code)
27
-
28
- print("")
29
- print("IdToken:")
30
- print(client.id_token)
31
- print("")
32
- print("AccessToken:")
33
- print(client.access_token)
34
- print("")
35
- print("RefreshToken:")
36
- print(client.refresh_token)
File without changes
File without changes
File without changes
File without changes