Skip to content

Commit

Permalink
Added IODefault for I/O operations, which can be extended to use so…
Browse files Browse the repository at this point in the history
…mething other than `print()` and `input()`. `Orders.print_output` variable, `cli.py` now handles output.
  • Loading branch information
alexdlaird committed Jan 18, 2024
1 parent 94cc734 commit e7fbac1
Show file tree
Hide file tree
Showing 7 changed files with 70 additions and 33 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@ All notable changes to this project will be documented in this file.
This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased](https://github.com/alexdlaird/amazon-orders-python/compare/1.0.1...HEAD)
### Added
- `IODefault` for I/O operations, which can be extended to use something other than `print()` and `input()`.

### Removed
`Orders.print_output` variable, `cli.py` now handles output.

## [1.0.1](https://github.com/alexdlaird/pyngrok/compare/1.0.0...1.0.1) - 2024-01-17
### Added
Expand Down
39 changes: 27 additions & 12 deletions amazonorders/cli.py
Original file line number Diff line number Diff line change
@@ -1,22 +1,33 @@
import datetime
import logging
import os
from typing import Any

import click
from click.core import Context

from amazonorders.exception import AmazonOrdersError
from amazonorders.orders import AmazonOrders
from amazonorders.session import AmazonSession
from amazonorders.session import AmazonSession, IODefault

__author__ = "Alex Laird"
__copyright__ = "Copyright 2024, Alex Laird"
__version__ = "1.0.1"
__version__ = "1.0.2"

logger = logging.getLogger("amazonorders")


class IOClick(IODefault):
"""
"""

def echo(self, msg):
click.echo(msg)

def prompt(self, msg):
return click.prompt(msg)


@click.group()
@click.option('--username', help="An Amazon username.")
@click.option('--password', help="An Amazon password.")
Expand Down Expand Up @@ -51,7 +62,8 @@ def amazon_orders_cli(ctx,

amazon_session = AmazonSession(username,
password,
debug=kwargs["debug"])
debug=kwargs["debug"],
io=IOClick())

if amazon_session.auth_cookies_stored():
if username or password:
Expand Down Expand Up @@ -83,12 +95,14 @@ def history(ctx: Context,
amazon_session.login()

amazon_orders = AmazonOrders(amazon_session,
debug=amazon_session.debug,
print_output=True)
debug=amazon_session.debug)

amazon_orders.get_order_history(year=kwargs["year"],
start_index=kwargs["start_index"],
full_details=kwargs["full_details"])
orders = amazon_orders.get_order_history(year=kwargs["year"],
start_index=kwargs["start_index"],
full_details=kwargs["full_details"])

for o in orders:
click.echo(o)
except AmazonOrdersError as e:
logger.debug("An error occurred.", exc_info=True)
ctx.fail(str(e))
Expand All @@ -108,10 +122,11 @@ def order(ctx: Context,
amazon_session.login()

amazon_orders = AmazonOrders(amazon_session,
debug=amazon_session.debug,
print_output=True)
debug=amazon_session.debug)

o = amazon_orders.get_order(order_id)

amazon_orders.get_order(order_id)
click.echo(o)
except AmazonOrdersError as e:
logger.debug("An error occurred.", exc_info=True)
ctx.fail(str(e))
Expand Down
14 changes: 2 additions & 12 deletions amazonorders/orders.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

__author__ = "Alex Laird"
__copyright__ = "Copyright 2024, Alex Laird"
__version__ = "1.0.0"
__version__ = "1.0.2"

logger = logging.getLogger(__name__)

Expand All @@ -20,17 +20,14 @@ class AmazonOrders:

def __init__(self,
amazon_session: AmazonSession,
debug: bool = False,
print_output: bool = False) -> None:
debug: bool = False) -> None:
#:
self.amazon_session: AmazonSession = amazon_session

#: Set logger ``DEBUG`` and send output to ``stderr``.
self.debug: bool = debug
if self.debug:
logger.setLevel(logging.DEBUG)
#: In addition to return Order objects, print them to stdout.
self.print_output: bool = print_output

def get_order_history(self,
year: int = datetime.date.today().year,
Expand Down Expand Up @@ -76,10 +73,6 @@ def get_order_history(self,
else:
logger.debug("start_index is given, not paging")

if self.print_output:
for order in orders:
print("{}\n".format(order))

return orders

def get_order(self,
Expand All @@ -97,7 +90,4 @@ def get_order(self,
order_details_tag = self.amazon_session.last_response_parsed.find("div", id="orderDetails")
order = Order(order_details_tag, full_details=True)

if self.print_output:
print(order)

return order
37 changes: 31 additions & 6 deletions amazonorders/session.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

__author__ = "Alex Laird"
__copyright__ = "Copyright 2024, Alex Laird"
__version__ = "1.0.1"
__version__ = "1.0.2"

logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -50,6 +50,28 @@
DEFAULT_COOKIE_JAR_PATH = os.path.join(os.path.expanduser("~"), ".config", "amazon-orders", "cookies.json")


class IODefault:
"""
"""

def echo(self, msg):
"""
:param msg:
:return:
"""
print(msg)

def prompt(self, msg):
"""
:param msg:
:return:
"""
return input(msg)


class AmazonSession:
"""
Expand All @@ -60,7 +82,8 @@ def __init__(self,
password: str,
debug: bool = False,
max_auth_attempts: int = 10,
cookie_jar_path: str = None) -> None:
cookie_jar_path: str = None,
io: IODefault = IODefault()) -> None:
if not cookie_jar_path:
cookie_jar_path = DEFAULT_COOKIE_JAR_PATH

Expand All @@ -77,6 +100,8 @@ def __init__(self,
self.max_auth_attempts: int = max_auth_attempts
#: The path to persist session cookies, defaults to ``conf.DEFAULT_COOKIE_JAR_PATH``.
self.cookie_jar_path: str = cookie_jar_path
#:
self.io = io

#:
self.session: Session = Session()
Expand Down Expand Up @@ -240,10 +265,10 @@ def _mfa_device_select(self) -> None:
contexts = form.find_all("input", {"name": "otpDeviceContext"})
i = 1
for field in contexts:
print("{}: {}".format(i, field.attrs["value"].strip()))
self.io.echo("{}: {}".format(i, field.attrs["value"].strip()))
i += 1
otp_device = int(
input("Where would you like your one-time passcode sent? "))
self.io.prompt("Where would you like your one-time passcode sent? "))

form = self.last_response_parsed.find("form",
id=MFA_DEVICE_SELECT_FORM_ID)
Expand All @@ -260,7 +285,7 @@ def _mfa_device_select(self) -> None:
self._handle_errors()

def _mfa_submit(self) -> None:
otp = input("Enter the one-time passcode sent to your device: ")
otp = self.io.prompt("Enter the one-time passcode sent to your device: ")

form = self.last_response_parsed.find("form", id=MFA_FORM_ID)
data = self._build_from_form(form,
Expand Down Expand Up @@ -364,7 +389,7 @@ def _handle_errors(self,
if critical:
raise AmazonOrdersAuthError(error_msg)
else:
print(error_msg)
self.io.echo(error_msg)

def _solve_captcha(self,
url: str) -> str:
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

__author__ = "Alex Laird"
__copyright__ = "Copyright 2024, Alex Laird"
__version__ = "1.0.1"
__version__ = "1.0.2"

with open("README.md", "r") as f:
long_description = f.read()
Expand Down
4 changes: 3 additions & 1 deletion tests/test_integration.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,14 @@

__author__ = "Alex Laird"
__copyright__ = "Copyright 2024, Alex Laird"
__version__ = "1.0.1"
__version__ = "1.0.2"


@unittest.skipIf(os.environ.get("INTEGRATION_TESTS", "False") != "True",
"Skipping, INTEGRATION_TESTS=True was not set in the environment")
class TestIntegration(TestCase):
amazon_session = None

@classmethod
def setUpClass(cls):
cls.credentials_found = os.environ.get("AMAZON_USERNAME") and os.environ.get("AMAZON_PASSWORD")
Expand Down
2 changes: 1 addition & 1 deletion tests/unittestcase.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
import unittest

import responses
from amazonorders import session

from amazonorders import session
from amazonorders.session import BASE_URL
from tests.testcase import TestCase

Expand Down

0 comments on commit e7fbac1

Please # to comment.