-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #10 from MattTimms/dev
release: v1.3.0
- Loading branch information
Showing
18 changed files
with
120 additions
and
147 deletions.
There are no files selected for viewing
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,4 @@ | ||
.idea | ||
.github/actions-runner | ||
shopping-list.json | ||
shopping-list.bkup.json | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,6 @@ | ||
# 🍎 coles_vs_woolies 🍏 | ||
|
||
![Python](https://img.shields.io/badge/python-3.9%20%7C%203.10%20%7C%203.11-blue) | ||
![Python](https://img.shields.io/badge/python-3.10%20%7C%203.11-blue) | ||
[![pass](https://github.com/MattTimms/coles_vs_woolies/actions/workflows/test.yml/badge.svg)](https://github.com/MattTimms/coles_vs_woolies/actions/workflows/test.yml) | ||
[![working just fine for me](https://github.com/MattTimms/coles_vs_woolies/actions/workflows/run.yml/badge.svg)](https://github.com/MattTimms/coles_vs_woolies/actions/workflows/run.yml) | ||
|
||
|
@@ -54,32 +54,25 @@ pip install -r requirements.txt | |
|
||
```shell | ||
$ python coles_vs_woolies --help | ||
# usage: coles_vs_woolies [-h] {display,send} ... | ||
# usage: coles_vs_woolies [-h] [-o OUT_DIR] [-d] file_path | ||
# | ||
# Compare prices between Aussie grocers | ||
# | ||
# positional arguments: | ||
# {display,send} | ||
# display Display product price comparisons | ||
# send Email product price comparisons | ||
# file_path File path to a JSON config shopping list; see `shopping-list.example.json` | ||
# | ||
# options: | ||
# -h, --help show this help message and exit | ||
# | ||
# example: | ||
# python coles_vs_woolies display | ||
# "Cadbury Dairy Milk Chocolate Block 180g" | ||
# "Connoisseur Ice Cream Vanilla Caramel Brownie 1L" | ||
# | ||
# python coles_vs_woolies send | ||
# "Cadbury Dairy Milk Chocolate Block 180g" | ||
# "Connoisseur Ice Cream Vanilla Caramel Brownie 4 Pack" | ||
# --to_addrs <[email protected]> <[email protected]> | ||
# -h, --help show this help message and exit | ||
# -o OUT_DIR, --out_dir OUT_DIR | ||
# Directory for saving copy of the email HTML template. | ||
# -d, --dry_run Disable email delivery | ||
``` | ||
|
||
```shell | ||
cp .env.example .env | ||
# populate .env to simplify calls | ||
cp shopping-list.example.json shopping-list.json | ||
# populate the shopping list with your email & desired items | ||
``` | ||
|
||
## Install w/ GitHub Actions | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,93 +1,41 @@ | ||
import argparse | ||
import json | ||
import os | ||
import textwrap | ||
from argparse import ArgumentParser | ||
from typing import List | ||
|
||
from pydantic import BaseModel | ||
from pydantic import BaseModel, Extra | ||
|
||
from coles_vs_woolies.main import display, send | ||
from coles_vs_woolies.main import send | ||
|
||
|
||
def cli(): | ||
example_usage = '''example: | ||
python coles_vs_woolies display | ||
"Cadbury Dairy Milk Chocolate Block 180g" | ||
"Connoisseur Ice Cream Vanilla Caramel Brownie 4 Pack" | ||
python coles_vs_woolies send | ||
"Cadbury Dairy Milk Chocolate Block 180g" | ||
"Connoisseur Ice Cream Vanilla Caramel Brownie 4 Pack" | ||
--to_addrs <[email protected]> <[email protected]> | ||
''' | ||
class ShoppingList(BaseModel, extra=Extra.allow): | ||
""" Model for the `shopping-list` json config file. """ | ||
to_addrs: list[str] | ||
products: list[str] | ||
|
||
|
||
def cli(): | ||
parser = ArgumentParser( | ||
prog='coles_vs_woolies', | ||
description='Compare prices between Aussie grocers', | ||
formatter_class=argparse.RawDescriptionHelpFormatter, | ||
epilog=textwrap.dedent(example_usage) | ||
) | ||
|
||
subparsers = parser.add_subparsers(dest='action') | ||
|
||
help_product = 'List of descriptive product search terms. Brand, package weight or size should be included. ' \ | ||
'Can be file path. E.g. "Cadbury Dairy Milk Chocolate Block 180g"' \ | ||
'"Connoisseur Ice Cream Vanilla Caramel Brownie 4 Pack"' | ||
|
||
# Display parser | ||
display_parser = subparsers.add_parser('display', help='Display product price comparisons') | ||
display_parser.add_argument('products', nargs='+', help=help_product) | ||
|
||
# Send parser | ||
send_parser = subparsers.add_parser('send', help='Email product price comparisons') | ||
send_parser.add_argument('products', nargs='+', help=help_product) | ||
send_parser.add_argument('-t', '--to_addrs', nargs='+', help="Recipients' email address.", required=False) | ||
send_parser.add_argument('-o', '--out_dir', type=str, help='Directory for saving copy of the email HTML template.', | ||
required=False) | ||
send_parser.add_argument('-d', '--dry_run', action='store_true', help='Disable email delivery', | ||
default=False, required=False) | ||
parser.add_argument('file_path', type=str, | ||
help='File path to a JSON config shopping list; see `shopping-list.example.json`') | ||
parser.add_argument('-o', '--out_dir', type=str, required=False, | ||
help='Directory for saving copy of the email HTML template.') | ||
parser.add_argument('-d', '--dry_run', action='store_true', default=False, required=False, | ||
help='Disable email delivery') | ||
|
||
# Parse inputs | ||
kwargs = vars(parser.parse_args()) | ||
action = kwargs.pop('action') | ||
|
||
_product_inputs = kwargs.pop('products') | ||
if os.path.isfile(fp := _product_inputs[0]) and fp.endswith('.json'): | ||
with open(fp, 'r') as f: | ||
jobs = [_JsonInput.parse_obj(x) for x in json.load(f)] | ||
_ = kwargs.pop('to_addrs', None) | ||
for job in jobs: | ||
_run(action, job.products, to_addrs=job.to_addrs, **kwargs) | ||
else: | ||
if action == 'send' and kwargs.get('to_addrs', None) is None: | ||
parser.error('the following arguments are required: -t/--to_addrs') | ||
products = _parse_product_inputs(_product_inputs) | ||
_run(action, products, **kwargs) | ||
|
||
|
||
class _JsonInput(BaseModel): | ||
to_addrs: List[str] | ||
products: List[str] | ||
|
||
|
||
def _run(action: str, products: List[str], **kwargs): | ||
if action == 'send': | ||
send(products=products, **kwargs) | ||
else: | ||
display(products=products) | ||
|
||
|
||
def _parse_product_inputs(args: List[str]) -> List[str]: | ||
""" Return product list from input list of products/file-paths """ | ||
products = [] | ||
for input_ in args: | ||
if os.path.isfile(input_): | ||
with open(input_, 'r') as f: | ||
products.extend(f.read().splitlines()) | ||
else: | ||
products.append(input_) | ||
return sorted(list(set(products))) | ||
with open(kwargs.pop('file_path'), 'r') as fp: | ||
shopping_lists: list[ShoppingList] = [ShoppingList.parse_obj(list_) for list_ in json.load(fp)] | ||
|
||
# Run for each shopping list | ||
for shopping_list in shopping_lists: | ||
send(products=shopping_list.products, | ||
to_addrs=shopping_list.to_addrs, | ||
**kwargs) | ||
|
||
|
||
if __name__ == '__main__': | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.