Coverage for amazonorders/orders.py: 98.04%
51 statements
« prev ^ index » next coverage.py v7.4.0, created at 2024-01-25 22:50 +0000
« prev ^ index » next coverage.py v7.4.0, created at 2024-01-25 22:50 +0000
1import datetime
2import logging
3from typing import List, Optional
5from amazonorders.conf import DEFAULT_OUTPUT_DIR
6from amazonorders.entity.order import Order
7from amazonorders.exception import AmazonOrdersError
8from amazonorders.session import BASE_URL, AmazonSession
10__author__ = "Alex Laird"
11__copyright__ = "Copyright 2024, Alex Laird"
12__version__ = "1.0.6"
14logger = logging.getLogger(__name__)
16ORDER_HISTORY_CARD_SELECTOR = "div[class*='order-card']:has(script)"
17ORDER_DETAILS_DIV_SELECTOR = "div[id='orderDetails']"
18NEXT_PAGE_LINK_SELECTOR = "ul[class*='a-pagination'] li[class*='a-last'] a"
21class AmazonOrders:
22 """
23 Using an authenticated :class:`~amazonorders.session.AmazonSession`, can be used to query Amazon
24 for Order details and history.
25 """
27 def __init__(self,
28 amazon_session: AmazonSession,
29 debug: bool = False,
30 output_dir: str = None) -> None:
31 if not output_dir:
32 output_dir = DEFAULT_OUTPUT_DIR
34 #: The AmazonSession to use for requests.
35 self.amazon_session: AmazonSession = amazon_session
37 #: Set logger ``DEBUG`` and send output to ``stderr``.
38 self.debug: bool = debug
39 if self.debug:
40 logger.setLevel(logging.DEBUG)
41 #: The directory where any output files will be produced, defaults to ``conf.DEFAULT_OUTPUT_DIR``.
42 self.output_dir = output_dir
44 def get_order_history(self,
45 year: int = datetime.date.today().year,
46 start_index: Optional[int] = None,
47 full_details: bool = False) -> List[Order]:
48 """
49 Get the Amazon order history for the given year.
51 :param year: The year for which to get history.
52 :param start_index: The index to start at within the history.
53 :param full_details: Will execute an additional request per Order in the retrieved history to fully populate it.
54 :return: A list of the requested Orders.
55 """
56 if not self.amazon_session.is_authenticated:
57 raise AmazonOrdersError("Call AmazonSession.login() to authenticate first.")
59 orders = []
60 next_page = "{}/your-orders/orders?timeFilter=year-{}{}".format(BASE_URL,
61 year,
62 "&startIndex={}".format(
63 start_index) if start_index else "")
64 while next_page:
65 self.amazon_session.get(next_page)
66 response_parsed = self.amazon_session.last_response_parsed
68 for order_tag in response_parsed.select(ORDER_HISTORY_CARD_SELECTOR):
69 order = Order(order_tag)
71 if full_details:
72 self.amazon_session.get(order.order_details_link)
73 order_details_tag = self.amazon_session.last_response_parsed.select_one(ORDER_DETAILS_DIV_SELECTOR)
74 order = Order(order_details_tag, full_details=True, clone=order)
76 orders.append(order)
78 next_page = None
79 if start_index is None:
80 next_page_tag = response_parsed.select_one(NEXT_PAGE_LINK_SELECTOR)
81 if next_page_tag:
82 next_page = "{}{}".format(BASE_URL, next_page_tag["href"])
83 else:
84 logger.debug("No next page")
85 else:
86 logger.debug("start_index is given, not paging")
88 return orders
90 def get_order(self,
91 order_id: str) -> Order:
92 """
93 Get the Amazon order represented by the ID.
95 :param order_id: The Amazon Order ID to lookup.
96 :return: The requested Order.
97 """
98 if not self.amazon_session.is_authenticated:
99 raise AmazonOrdersError("Call AmazonSession.login() to authenticate first.")
101 self.amazon_session.get("{}/gp/your-account/order-details?orderID={}".format(BASE_URL, order_id))
103 order_details_tag = self.amazon_session.last_response_parsed.select_one(ORDER_DETAILS_DIV_SELECTOR)
104 order = Order(order_details_tag, full_details=True)
106 return order