From e0a8928a1e06ff9c763896e4fcc311acb646e68e Mon Sep 17 00:00:00 2001 From: Jarvis Johnson Date: Thu, 14 Jun 2018 08:35:02 -0700 Subject: [PATCH 1/3] replace rogue tab with space in order.py to prevent TabError on import --- pizzapi/order.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pizzapi/order.py b/pizzapi/order.py index 324186c..8f05476 100755 --- a/pizzapi/order.py +++ b/pizzapi/order.py @@ -127,4 +127,4 @@ def pay_with(self, card=False): } ] - return response + return response From f28b08d806153d04a0d54a2b611ec2efe2464df3 Mon Sep 17 00:00:00 2001 From: Jarvis Johnson Date: Tue, 19 Jun 2018 09:04:16 -0700 Subject: [PATCH 2/3] jarvis refactor --- README.rst | 36 +++++++++++------- docs/conf.py | 14 +++---- pizzapi/customer.py | 13 ------- pizzapi/store.py | 25 ------------- {pizzapi => pizzapy}/__init__.py | 4 +- {pizzapi => pizzapy}/address.py | 3 ++ {pizzapi => pizzapy}/coupon.py | 0 pizzapy/customer.py | 20 ++++++++++ {pizzapi => pizzapy}/menu.py | 8 ++-- {pizzapi => pizzapy}/order.py | 16 ++++++-- {pizzapi => pizzapy}/payment.py | 7 +++- pizzapy/store.py | 63 ++++++++++++++++++++++++++++++++ {pizzapi => pizzapy}/track.py | 0 {pizzapi => pizzapy}/urls.py | 2 +- {pizzapi => pizzapy}/utils.py | 0 setup.py | 6 +-- tests/test_address.py | 8 ++-- tests/test_menu.py | 6 +-- 18 files changed, 150 insertions(+), 81 deletions(-) delete mode 100755 pizzapi/customer.py delete mode 100755 pizzapi/store.py rename {pizzapi => pizzapy}/__init__.py (76%) rename {pizzapi => pizzapy}/address.py (95%) rename {pizzapi => pizzapy}/coupon.py (100%) create mode 100755 pizzapy/customer.py rename {pizzapi => pizzapy}/menu.py (96%) rename {pizzapi => pizzapy}/order.py (91%) rename {pizzapi => pizzapy}/payment.py (87%) create mode 100755 pizzapy/store.py rename {pizzapi => pizzapy}/track.py (100%) rename {pizzapi => pizzapy}/urls.py (98%) rename {pizzapi => pizzapy}/utils.py (100%) diff --git a/README.rst b/README.rst index e310973..cc643a2 100644 --- a/README.rst +++ b/README.rst @@ -1,6 +1,23 @@ -pizzapi +pizzapy ======= +Disclaimer +----------- +This is my fork of https://github.com/gamagori/pizzapi +It's heavily modified and not well documented, but i'm going to get to that. the below example should work though. + +sorry! was kind of in a rush this morning. + +Setup +----- + +1. install python3 +2. download this repository +3. install the requirements of the repository `pip install -r requirements.txt` +4. start a python3 interpreter inside of the folder called pizzapy +5. have fun + + Description ----------- @@ -16,14 +33,12 @@ First construct a ``Customer`` object and set the customer's address: .. code-block:: python customer = Customer('Barack', 'Obama', 'barack@whitehouse.gov', '2024561111', '700 Pennsylvania Avenue NW, Washington, DC, 20408') - address = Address('700 Pennsylvania Avenue NW', 'Washington', 'DC', '20408') - # or Address(*customer.address.split(',')) if you're lazy Then, find a store that will deliver to the address. .. code-block:: python - store = address.closest_store() + my_local_dominos = StoreLocator.find_closest_store_to_customer(customer) In order to add items to your order, you'll need the items' product codes. To find the codes, get the menu from the store, then search for items you want to add. @@ -53,7 +68,7 @@ After you've found your items' product codes, you can create an ``Order`` object .. code-block:: python - order = Order(store, customer, address) + order = Order.begin_customer_order(customer, my_local_dominos) order.add_item('P12IPAZA') # add a 12-inch pan pizza order.add_item('MARINARA') # with an extra marinara cup order.add_item('20BCOKE') # and a 20oz bottle of coke @@ -64,20 +79,15 @@ You can remove items as well! order.remove_item('20BCOKE') -Wrap your credit card information in a ``PaymentObject``: +Wrap your credit card information in a ``CreditCard``: .. code-block:: python - card = PaymentObject('4100123422343234', '0115', '777', '90210') + card = CreditCard('4100123422343234', '0115', '777', '90210') And that's it! Now you can place your order. .. code-block:: python order.place(card) - -Or if you're just testing and don't want to actually order something, use ``.pay_with``. - -.. code-block:: python - - order.pay_with(card) + my_local_dominos.place_order(order, card) diff --git a/docs/conf.py b/docs/conf.py index d68d9e1..656a699 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # -# pizzapi documentation build configuration file, created by +# pizzapy documentation build configuration file, created by # sphinx-quickstart on Sun Feb 4 22:05:18 2018. # # This file is execfile()d with the current directory set to its @@ -47,7 +47,7 @@ master_doc = 'index' # General information about the project. -project = u'pizzapi' +project = u'pizzapy' copyright = u'2018, Arie van Luttikhuizen, Grant Gordon' author = u'Arie van Luttikhuizen, Grant Gordon' @@ -113,7 +113,7 @@ # -- Options for HTMLHelp output ------------------------------------------ # Output file base name for HTML help builder. -htmlhelp_basename = 'pizzapidoc' +htmlhelp_basename = 'pizzapydoc' # -- Options for LaTeX output --------------------------------------------- @@ -140,7 +140,7 @@ # (source start file, target name, title, # author, documentclass [howto, manual, or own class]). latex_documents = [ - (master_doc, 'pizzapi.tex', u'pizzapi Documentation', + (master_doc, 'pizzapy.tex', u'pizzapy Documentation', u'Arie van Luttikhuizen, Grant Gordon', 'manual'), ] @@ -150,7 +150,7 @@ # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). man_pages = [ - (master_doc, 'pizzapi', u'pizzapi Documentation', + (master_doc, 'pizzapy', u'pizzapy Documentation', [author], 1) ] @@ -161,8 +161,8 @@ # (source start file, target name, title, author, # dir menu entry, description, category) texinfo_documents = [ - (master_doc, 'pizzapi', u'pizzapi Documentation', - author, 'pizzapi', 'One line description of project.', + (master_doc, 'pizzapy', u'pizzapy Documentation', + author, 'pizzapy', 'One line description of project.', 'Miscellaneous'), ] diff --git a/pizzapi/customer.py b/pizzapi/customer.py deleted file mode 100755 index 6081364..0000000 --- a/pizzapi/customer.py +++ /dev/null @@ -1,13 +0,0 @@ -class Customer(object): - """The Customer orders a pizza. - - You need a Customer to create an Order. The proprietors of the API - use this information, presumably for nefarious Pizza Purposes. - """ - - def __init__(self, fname='', lname='', email='', phone='', address=None): - self.first_name = fname.strip() - self.last_name = lname.strip() - self.email = email.strip() - self.phone = str(phone).strip() - self.address = address diff --git a/pizzapi/store.py b/pizzapi/store.py deleted file mode 100755 index fb26901..0000000 --- a/pizzapi/store.py +++ /dev/null @@ -1,25 +0,0 @@ -from .menu import Menu -from .urls import Urls, COUNTRY_USA -from .utils import request_json - - -class Store(object): - """The interface to the Store API - - You can use this to find store information about stores near an - address, or to find the closest store to an address. - """ - def __init__(self, data={}, country=COUNTRY_USA): - self.id = str(data.get('StoreID', -1)) - self.country = country - self.urls = Urls(country) - self.data = data - - def get_details(self): - details = request_json(self.urls.info_url(), store_id=self.id) - return details - - def get_menu(self, lang='en'): - response = request_json(self.urls.menu_url(), store_id=self.id, lang=lang) - menu = Menu(response, self.country) - return menu diff --git a/pizzapi/__init__.py b/pizzapy/__init__.py similarity index 76% rename from pizzapi/__init__.py rename to pizzapy/__init__.py index 09069e8..5b8d93c 100755 --- a/pizzapi/__init__.py +++ b/pizzapy/__init__.py @@ -3,7 +3,7 @@ from .customer import Customer from .menu import Menu from .order import Order -from .payment import PaymentObject -from .store import Store +from .payment import CreditCard +from .store import Store, StoreLocator from .track import track_by_order, track_by_phone from .utils import request_json, request_xml diff --git a/pizzapi/address.py b/pizzapy/address.py similarity index 95% rename from pizzapi/address.py rename to pizzapy/address.py index 6785cec..102ea9d 100755 --- a/pizzapi/address.py +++ b/pizzapy/address.py @@ -26,6 +26,9 @@ def __init__(self, street, city, region='', zip='', country=COUNTRY_USA, *args): self.urls = Urls(country) self.country = country + def __repr__(self): + return ", ".join([self.street, self.city, self.region, self.zip]) + @property def data(self): return {'Street': self.street, 'City': self.city, diff --git a/pizzapi/coupon.py b/pizzapy/coupon.py similarity index 100% rename from pizzapi/coupon.py rename to pizzapy/coupon.py diff --git a/pizzapy/customer.py b/pizzapy/customer.py new file mode 100755 index 0000000..ee3c30e --- /dev/null +++ b/pizzapy/customer.py @@ -0,0 +1,20 @@ +from .address import Address + +class Customer: + """The Customer who orders a pizza.""" + + def __init__(self, fname='', lname='', email='', phone='', address=None): + self.first_name = fname.strip() + self.last_name = lname.strip() + self.email = email.strip() + self.phone = str(phone).strip() + self.address = Address(*address.split(',')) + + def __repr__(self): + return "Name: {} {}\nEmail: {}\nPhone: {}\nAddress: {}".format( + self.first_name, + self.last_name, + self.email, + self.phone, + self.address, + ) diff --git a/pizzapi/menu.py b/pizzapy/menu.py similarity index 96% rename from pizzapi/menu.py rename to pizzapy/menu.py index 8ba08ae..9a6fc41 100755 --- a/pizzapi/menu.py +++ b/pizzapy/menu.py @@ -105,7 +105,7 @@ def search(self, **conditions): if all(y in v.get(x, '') for x, y in conditions.items()): print(v['Code'], end=' ') print(v['Name'], end=' ') - print('$' + v['Price'], end=' ') - print(v['SizeCode'], end=' ') - print(v['ProductCode'], end=' ') - print(v['Toppings']) + print('$' + v['Price']) + #print(v['SizeCode'], end=' ') + #print(v['ProductCode'], end=' ') + #print(v['Toppings']) diff --git a/pizzapi/order.py b/pizzapy/order.py similarity index 91% rename from pizzapi/order.py rename to pizzapy/order.py index 8f05476..73d4422 100755 --- a/pizzapi/order.py +++ b/pizzapy/order.py @@ -12,11 +12,11 @@ class Order(object): up all the logic for actually placing the order, after we've determined what we want from the Menu. """ - def __init__(self, store, customer, address, country=COUNTRY_USA): + def __init__(self, store, customer, country=COUNTRY_USA): self.store = store self.menu = Menu.from_store(store_id=store.id, country=country) self.customer = customer - self.address = address + self.address = customer.address self.urls = Urls(country) self.data = { 'Address': {'Street': self.address.street, @@ -35,6 +35,16 @@ def __init__(self, store, customer, address, country=COUNTRY_USA): 'PriceOrderTime': '', 'AmountsBreakdown': {} } + @staticmethod + def begin_customer_order(customer, store, country=COUNTRY_USA): + return Order(store, customer, country=country) + + def __repr__(self): + return "An order for {} with {} items in it\n".format( + self.customer.first_name, + len(self.data['Products']) if self.data['Products'] else 'no', + ) + # TODO: Implement item options # TODO: Add exception handling for KeyErrors def add_item(self, code, qty=1, options=[]): @@ -65,8 +75,6 @@ def _send(self, url, merge): FirstName=self.customer.first_name, LastName=self.customer.last_name, Phone=self.customer.phone, - #Address=self.address.street - ) for key in ('Products', 'StoreID', 'Address'): diff --git a/pizzapi/payment.py b/pizzapy/payment.py similarity index 87% rename from pizzapi/payment.py rename to pizzapy/payment.py index 826cf32..a3f2d92 100755 --- a/pizzapi/payment.py +++ b/pizzapy/payment.py @@ -1,8 +1,8 @@ import re -class PaymentObject(object): - """A PaymentObject represents a credit card. +class CreditCard(object): + """A CreditCard represents a credit card. There's some sweet logic in here to make sure that the type of card you passed is valid. @@ -15,6 +15,9 @@ def __init__(self, number='', expiration='', cvv='', zip=''): self.cvv = str(cvv).strip() self.zip = str(zip).strip() + def __repr__(self): + return "Credit Card with last four #{}".format(self.number[-4:]) + def validate(self): is_valid = self.number and self.card_type and self.expiration is_valid &= re.match(r'^[0-9]{3,4}$', self.cvv) diff --git a/pizzapy/store.py b/pizzapy/store.py new file mode 100755 index 0000000..f7a4cfe --- /dev/null +++ b/pizzapy/store.py @@ -0,0 +1,63 @@ +from .menu import Menu +from .urls import Urls, COUNTRY_USA +from .utils import request_json + + + +class Store(object): + """The interface to the Store API + + You can use this to find store information about stores near an + address, or to find the closest store to an address. + """ + def __init__(self, data={}, country=COUNTRY_USA): + self.id = str(data.get('StoreID', -1)) + self.country = country + self.urls = Urls(country) + self.data = data + + def __repr__(self): + return "Store #{}\nAddress: {}\n\nOpen Now: {}".format( + self.id, + self.data['AddressDescription'], + 'Yes' if self.data.get('IsOpen', False) else 'No', + ) + + def get_details(self): + details = request_json(self.urls.info_url(), store_id=self.id) + return details + + def place_order(self, order, card): + print('Order placed for {}'.format(order.customer.first_name)) + return order.place(card=card) + + def get_menu(self, lang='en'): + response = request_json(self.urls.menu_url(), store_id=self.id, lang=lang) + menu = Menu(response, self.country) + return menu + + +class StoreLocator(object): + @classmethod + def __repr__(self): + return 'I locate stores and nothing else' + + @staticmethod + def nearby_stores(address, service='Delivery'): + """Query the API to find nearby stores. + + nearby_stores will filter the information we receive from the API + to exclude stores that are not currently online (!['IsOnlineNow']), + and stores that are not currently in service (!['ServiceIsOpen']). + """ + data = request_json(address.urls.find_url(), line1=address.line1, line2=address.line2, type=service) + return [Store(x, address.country) for x in data['Stores'] + if x['IsOnlineNow'] and x['ServiceIsOpen'][service]] + + @staticmethod + def find_closest_store_to_customer(customer, service='Delivery'): + stores = StoreLocator.nearby_stores(customer.address, service=service) + if not stores: + raise Exception('No local stores are currently open') + return stores[0] + diff --git a/pizzapi/track.py b/pizzapy/track.py similarity index 100% rename from pizzapi/track.py rename to pizzapy/track.py diff --git a/pizzapi/urls.py b/pizzapy/urls.py similarity index 98% rename from pizzapi/urls.py rename to pizzapy/urls.py index 4e869b4..4358f8d 100755 --- a/pizzapi/urls.py +++ b/pizzapy/urls.py @@ -7,7 +7,7 @@ class Urls(object): This initializes some dicts that contain country-unique information on how to interact with the API, and some getter methods for getting to that information. These are handy to pass as a first argument to - pizzapi.utils.request_[xml|json]. + pizzapy.utils.request_[xml|json]. """ def __init__(self, country=COUNTRY_USA): diff --git a/pizzapi/utils.py b/pizzapy/utils.py similarity index 100% rename from pizzapi/utils.py rename to pizzapy/utils.py diff --git a/setup.py b/setup.py index 1e8ba85..4fd6fc7 100644 --- a/setup.py +++ b/setup.py @@ -62,7 +62,7 @@ def run(self): # Where the magic happens: setup( - name='pizzapi', + name='pizzapy', # Versions should comply with PEP440. For a discussion on single-sourcing # the version across setup.py and the project code, see @@ -73,7 +73,7 @@ def run(self): long_description=long_description, # The project's main homepage. - url='https://github.com/aluttik/pizzapi', + url='https://github.com/aluttik/pizzapy', # Author details author='aluttik', @@ -121,7 +121,7 @@ def run(self): # pip to create the appropriate form of executable for the target platform. # entry_points={ # 'console_scripts': [ - # 'pizzapi=pizzapi:main' + # 'pizzapy=pizzapy:main' # ], # }, diff --git a/tests/test_address.py b/tests/test_address.py index 5b44690..659f4b0 100644 --- a/tests/test_address.py +++ b/tests/test_address.py @@ -5,8 +5,8 @@ from mock import patch from pytest import mark -from pizzapi.address import Address -from pizzapi.urls import Urls, COUNTRY_USA +from pizzapy.address import Address +from pizzapy.urls import Urls, COUNTRY_USA fixture_path = os.path.join('tests', 'fixtures', 'stores.json') @@ -55,7 +55,7 @@ def test_address_init(street, city, region, zip): @address_params -@patch('pizzapi.address.request_json', side_effect=mocked_request_json) +@patch('pizzapy.address.request_json', side_effect=mocked_request_json) def test_address_closest_store(mocked, street, city, region, zip): address = Address(street, city, region, zip) assert_that(address, has_properties( @@ -99,7 +99,7 @@ def test_address_closest_store(mocked, street, city, region, zip): @address_params -@patch('pizzapi.address.request_json', side_effect=mocked_request_json) +@patch('pizzapy.address.request_json', side_effect=mocked_request_json) def test_address_nearby_stores(mocked, street, city, region, zip): address = Address(street, city, region, zip) assert_that(address, has_properties( diff --git a/tests/test_menu.py b/tests/test_menu.py index bf62609..4236cf5 100644 --- a/tests/test_menu.py +++ b/tests/test_menu.py @@ -5,8 +5,8 @@ from mock import patch from pytest import mark -from pizzapi.menu import Menu -from pizzapi.urls import Urls, COUNTRY_USA +from pizzapy.menu import Menu +from pizzapy.urls import Urls, COUNTRY_USA fixture_path = os.path.join('tests', 'fixtures', 'menu.json') @@ -22,6 +22,6 @@ def mocked_request_json(url, **kwargs): return menu_fixture -@patch('pizzapi.address.request_json', side_effect=mocked_request_json) +@patch('pizzapy.address.request_json', side_effect=mocked_request_json) def test_menu_from_store(store_id): pass From 816f9cd777289633f8653b825e16fc9876def7a9 Mon Sep 17 00:00:00 2001 From: Russell Ratcliffe Date: Wed, 18 Jul 2018 20:07:10 -0500 Subject: [PATCH 3/3] Fixing incorrect code in readme "store" does not exist. Changed it to use the Store object that the user created earlier. --- README.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.rst b/README.rst index cc643a2..8a96e41 100644 --- a/README.rst +++ b/README.rst @@ -46,7 +46,7 @@ You can do this by asking your ``Store`` object for its ``Menu``. .. code-block:: python - menu = store.get_menu() + menu = my_local_dominos.get_menu() Then search ``menu`` with ``menu.search``. For example, running this command: