amazon-orders 3.2.1__tar.gz → 3.2.2__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.
- {amazon_orders-3.2.1 → amazon_orders-3.2.2}/CHANGELOG.md +11 -1
- {amazon_orders-3.2.1/amazon_orders.egg-info → amazon_orders-3.2.2}/PKG-INFO +2 -2
- {amazon_orders-3.2.1 → amazon_orders-3.2.2/amazon_orders.egg-info}/PKG-INFO +2 -2
- {amazon_orders-3.2.1 → amazon_orders-3.2.2}/amazonorders/__init__.py +1 -1
- {amazon_orders-3.2.1 → amazon_orders-3.2.2}/amazonorders/orders.py +6 -0
- {amazon_orders-3.2.1 → amazon_orders-3.2.2}/amazonorders/selectors.py +1 -0
- {amazon_orders-3.2.1 → amazon_orders-3.2.2}/amazonorders/transactions.py +8 -14
- {amazon_orders-3.2.1 → amazon_orders-3.2.2}/tests/test_cli.py +2 -2
- {amazon_orders-3.2.1 → amazon_orders-3.2.2}/tests/test_orders.py +24 -0
- {amazon_orders-3.2.1 → amazon_orders-3.2.2}/tests/test_transactions.py +5 -5
- {amazon_orders-3.2.1 → amazon_orders-3.2.2}/LICENSE +0 -0
- {amazon_orders-3.2.1 → amazon_orders-3.2.2}/MANIFEST.in +0 -0
- {amazon_orders-3.2.1 → amazon_orders-3.2.2}/README.md +0 -0
- {amazon_orders-3.2.1 → amazon_orders-3.2.2}/amazon_orders.egg-info/SOURCES.txt +0 -0
- {amazon_orders-3.2.1 → amazon_orders-3.2.2}/amazon_orders.egg-info/dependency_links.txt +0 -0
- {amazon_orders-3.2.1 → amazon_orders-3.2.2}/amazon_orders.egg-info/entry_points.txt +0 -0
- {amazon_orders-3.2.1 → amazon_orders-3.2.2}/amazon_orders.egg-info/requires.txt +0 -0
- {amazon_orders-3.2.1 → amazon_orders-3.2.2}/amazon_orders.egg-info/top_level.txt +0 -0
- {amazon_orders-3.2.1 → amazon_orders-3.2.2}/amazonorders/banner.txt +0 -0
- {amazon_orders-3.2.1 → amazon_orders-3.2.2}/amazonorders/cli.py +0 -0
- {amazon_orders-3.2.1 → amazon_orders-3.2.2}/amazonorders/conf.py +0 -0
- {amazon_orders-3.2.1 → amazon_orders-3.2.2}/amazonorders/constants.py +0 -0
- {amazon_orders-3.2.1 → amazon_orders-3.2.2}/amazonorders/entity/__init__.py +0 -0
- {amazon_orders-3.2.1 → amazon_orders-3.2.2}/amazonorders/entity/item.py +0 -0
- {amazon_orders-3.2.1 → amazon_orders-3.2.2}/amazonorders/entity/order.py +0 -0
- {amazon_orders-3.2.1 → amazon_orders-3.2.2}/amazonorders/entity/parsable.py +0 -0
- {amazon_orders-3.2.1 → amazon_orders-3.2.2}/amazonorders/entity/recipient.py +0 -0
- {amazon_orders-3.2.1 → amazon_orders-3.2.2}/amazonorders/entity/seller.py +0 -0
- {amazon_orders-3.2.1 → amazon_orders-3.2.2}/amazonorders/entity/shipment.py +0 -0
- {amazon_orders-3.2.1 → amazon_orders-3.2.2}/amazonorders/entity/transaction.py +0 -0
- {amazon_orders-3.2.1 → amazon_orders-3.2.2}/amazonorders/exception.py +0 -0
- {amazon_orders-3.2.1 → amazon_orders-3.2.2}/amazonorders/forms.py +0 -0
- {amazon_orders-3.2.1 → amazon_orders-3.2.2}/amazonorders/session.py +0 -0
- {amazon_orders-3.2.1 → amazon_orders-3.2.2}/amazonorders/util.py +0 -0
- {amazon_orders-3.2.1 → amazon_orders-3.2.2}/pyproject.toml +0 -0
- {amazon_orders-3.2.1 → amazon_orders-3.2.2}/setup.cfg +0 -0
- {amazon_orders-3.2.1 → amazon_orders-3.2.2}/tests/test_conf.py +0 -0
- {amazon_orders-3.2.1 → amazon_orders-3.2.2}/tests/test_session.py +0 -0
- {amazon_orders-3.2.1 → amazon_orders-3.2.2}/tests/test_util.py +0 -0
- {amazon_orders-3.2.1 → amazon_orders-3.2.2}/tests/testcase.py +0 -0
|
@@ -4,7 +4,17 @@ All notable changes to this project will be documented in this file.
|
|
|
4
4
|
|
|
5
5
|
This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
6
6
|
|
|
7
|
-
## [Unreleased](https://github.com/alexdlaird/amazon-orders/compare/3.2.
|
|
7
|
+
## [Unreleased](https://github.com/alexdlaird/amazon-orders/compare/3.2.2...HEAD)
|
|
8
|
+
|
|
9
|
+
## [3.2.2](https://github.com/alexdlaird/amazon-orders/compare/3.2.1...3.2.2) - 2025-01-28
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
|
|
13
|
+
- Stability improvements.
|
|
14
|
+
|
|
15
|
+
### Fixed
|
|
16
|
+
|
|
17
|
+
- Broken parsing of Amazon Fresh orders, these are now skipped.
|
|
8
18
|
|
|
9
19
|
## [3.2.1](https://github.com/alexdlaird/amazon-orders/compare/3.2.0...3.2.1) - 2024-11-08
|
|
10
20
|
|
|
@@ -73,6 +73,12 @@ class AmazonOrders:
|
|
|
73
73
|
response_parsed = self.amazon_session.last_response_parsed
|
|
74
74
|
|
|
75
75
|
for order_tag in util.select(response_parsed, self.config.selectors.ORDER_HISTORY_ENTITY_SELECTOR):
|
|
76
|
+
# If we find a brand logo (for instance, Amazon Fresh), we don't know how to parse this. If we know how
|
|
77
|
+
# to do this in the future, we can implement it, but right now we have no reliable way, so skipping
|
|
78
|
+
# these orders.
|
|
79
|
+
if util.select(order_tag, self.config.selectors.ORDER_HISTORY_BRAND_SELECTOR):
|
|
80
|
+
continue
|
|
81
|
+
|
|
76
82
|
order: Order = self.config.order_cls(order_tag, self.config)
|
|
77
83
|
|
|
78
84
|
if full_details:
|
|
@@ -55,6 +55,7 @@ class Selectors:
|
|
|
55
55
|
SHIPMENT_ENTITY_SELECTOR = ["[data-component='orderCard'] [data-component='shipments'] .a-box",
|
|
56
56
|
"div.shipment",
|
|
57
57
|
"div.delivery-box"]
|
|
58
|
+
ORDER_HISTORY_BRAND_SELECTOR = ".brand-info-box .brand-logo img"
|
|
58
59
|
|
|
59
60
|
#####################################
|
|
60
61
|
# CSS selectors for Item fields
|
|
@@ -17,19 +17,15 @@ from amazonorders.session import AmazonSession
|
|
|
17
17
|
logger = logging.getLogger(__name__)
|
|
18
18
|
|
|
19
19
|
|
|
20
|
-
def
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
def _parse_transaction_form_tag(
|
|
25
|
-
form_tag: Tag, config: AmazonOrdersConfig
|
|
26
|
-
) -> Tuple[List[Transaction], Optional[str], Optional[Dict[str, str]]]:
|
|
20
|
+
def _parse_transaction_form_tag(form_tag: Tag,
|
|
21
|
+
config: AmazonOrdersConfig) \
|
|
22
|
+
-> Tuple[List[Transaction], Optional[str], Optional[Dict[str, str]]]:
|
|
27
23
|
transactions = []
|
|
28
24
|
date_container_tags = util.select(form_tag, config.selectors.TRANSACTION_DATE_CONTAINERS_SELECTOR)
|
|
29
25
|
for date_container_tag in date_container_tags:
|
|
30
26
|
date_tag = util.select_one(date_container_tag, config.selectors.FIELD_TRANSACTION_COMPLETED_DATE_SELECTOR)
|
|
31
27
|
if not date_tag:
|
|
32
|
-
logger.warning("Could not find date tag in
|
|
28
|
+
logger.warning("Could not find date tag in Transaction form.")
|
|
33
29
|
continue
|
|
34
30
|
|
|
35
31
|
date_str = date_tag.text
|
|
@@ -38,9 +34,7 @@ def _parse_transaction_form_tag(
|
|
|
38
34
|
transactions_container_tag = date_container_tag.find_next_sibling(
|
|
39
35
|
config.selectors.TRANSACTIONS_CONTAINER_SELECTOR)
|
|
40
36
|
if not isinstance(transactions_container_tag, Tag):
|
|
41
|
-
logger.warning(
|
|
42
|
-
"Could not find transactions container tag in transaction form."
|
|
43
|
-
)
|
|
37
|
+
logger.warning("Could not find transactions container tag in Transaction form.")
|
|
44
38
|
continue
|
|
45
39
|
|
|
46
40
|
transaction_tags = util.select(transactions_container_tag, config.selectors.TRANSACTIONS_SELECTOR)
|
|
@@ -52,7 +46,7 @@ def _parse_transaction_form_tag(
|
|
|
52
46
|
form_ie_input = util.select_one(form_tag, config.selectors.TRANSACTIONS_NEXT_PAGE_INPUT_IE_SELECTOR)
|
|
53
47
|
next_page_input = util.select_one(form_tag, config.selectors.TRANSACTIONS_NEXT_PAGE_INPUT_SELECTOR)
|
|
54
48
|
if not next_page_input or not form_state_input or not form_ie_input:
|
|
55
|
-
return
|
|
49
|
+
return transactions, None, None
|
|
56
50
|
|
|
57
51
|
next_page_post_url = str(form_tag["action"])
|
|
58
52
|
next_page_post_data = {
|
|
@@ -61,7 +55,7 @@ def _parse_transaction_form_tag(
|
|
|
61
55
|
str(next_page_input["name"]): "",
|
|
62
56
|
}
|
|
63
57
|
|
|
64
|
-
return
|
|
58
|
+
return transactions, next_page_post_url, next_page_post_data
|
|
65
59
|
|
|
66
60
|
|
|
67
61
|
class AmazonTransactions:
|
|
@@ -100,7 +94,7 @@ class AmazonTransactions:
|
|
|
100
94
|
if not self.amazon_session.is_authenticated:
|
|
101
95
|
raise AmazonOrdersError("Call AmazonSession.login() to authenticate first.")
|
|
102
96
|
|
|
103
|
-
min_date =
|
|
97
|
+
min_date = datetime.date.today() - datetime.timedelta(days=days)
|
|
104
98
|
|
|
105
99
|
self.amazon_session.get(self.config.constants.TRANSACTION_HISTORY_LANDING_URL)
|
|
106
100
|
if not self.amazon_session.last_response_parsed:
|
|
@@ -86,10 +86,10 @@ class TestCli(UnitTestCase):
|
|
|
86
86
|
self.assertIn("Order #112-2961628-4757846", response.output)
|
|
87
87
|
|
|
88
88
|
@responses.activate
|
|
89
|
-
@patch("amazonorders.transactions.
|
|
89
|
+
@patch("amazonorders.transactions.datetime", wraps=datetime)
|
|
90
90
|
def test_transactions_command(self, mock_get_today: Mock):
|
|
91
91
|
# GIVEN
|
|
92
|
-
mock_get_today.return_value = datetime.date(2024, 10, 11)
|
|
92
|
+
mock_get_today.date.today.return_value = datetime.date(2024, 10, 11)
|
|
93
93
|
days = 1
|
|
94
94
|
self.given_login_responses_success()
|
|
95
95
|
with open(os.path.join(self.RESOURCES_DIR, "get-transactions.html"), "r", encoding="utf-8") as f:
|
|
@@ -103,6 +103,30 @@ class TestOrders(UnitTestCase):
|
|
|
103
103
|
self.assertEqual(1, resp2.call_count)
|
|
104
104
|
self.assertEqual(1, resp3.call_count)
|
|
105
105
|
|
|
106
|
+
@responses.activate
|
|
107
|
+
def test_get_order_history_skip_fresh(self):
|
|
108
|
+
# GIVEN
|
|
109
|
+
self.amazon_session.is_authenticated = True
|
|
110
|
+
year = 2024
|
|
111
|
+
start_index = 0
|
|
112
|
+
resp1 = self.given_order_history_landing_exists()
|
|
113
|
+
with open(os.path.join(self.RESOURCES_DIR, "order-history-fresh.html"), "r",
|
|
114
|
+
encoding="utf-8") as f:
|
|
115
|
+
resp2 = responses.add(
|
|
116
|
+
responses.GET,
|
|
117
|
+
self.test_config.constants.ORDER_HISTORY_URL,
|
|
118
|
+
body=f.read(),
|
|
119
|
+
status=200,
|
|
120
|
+
)
|
|
121
|
+
|
|
122
|
+
# WHEN
|
|
123
|
+
orders = self.amazon_orders.get_order_history(year=year, start_index=start_index)
|
|
124
|
+
|
|
125
|
+
# THEN
|
|
126
|
+
self.assertEqual(9, len(orders))
|
|
127
|
+
self.assertEqual(1, resp1.call_count)
|
|
128
|
+
self.assertEqual(1, resp2.call_count)
|
|
129
|
+
|
|
106
130
|
@responses.activate
|
|
107
131
|
def test_get_order_history_full_details(self):
|
|
108
132
|
# GIVEN
|
|
@@ -31,16 +31,16 @@ class TestOrders(UnitTestCase):
|
|
|
31
31
|
self.amazon_transactions = AmazonTransactions(self.amazon_session)
|
|
32
32
|
|
|
33
33
|
@responses.activate
|
|
34
|
-
@patch("amazonorders.transactions.
|
|
34
|
+
@patch("amazonorders.transactions.datetime", wraps=datetime)
|
|
35
35
|
def test_transactions_command(self, mock_get_today: Mock):
|
|
36
36
|
# GIVEN
|
|
37
|
-
mock_get_today.return_value = datetime.date(2024, 10, 11)
|
|
37
|
+
mock_get_today.date.today.return_value = datetime.date(2024, 10, 11)
|
|
38
38
|
days = 1
|
|
39
39
|
self.amazon_session.is_authenticated = True
|
|
40
40
|
with open(
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
41
|
+
os.path.join(self.RESOURCES_DIR, "get-transactions.html"),
|
|
42
|
+
"r",
|
|
43
|
+
encoding="utf-8",
|
|
44
44
|
) as f:
|
|
45
45
|
responses.add(
|
|
46
46
|
responses.GET,
|
|
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
|
|
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
|