Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
0d92719
Version Bump
Aug 21, 2015
92d6620
Add promotion parsers
Aug 21, 2015
7f627b2
Add promotion object to product.
Aug 21, 2015
8b589ac
Update readme with elementtree information
freak3dot Aug 21, 2015
72f6aa8
Formatting updates for code in readme
freak3dot Aug 21, 2015
c26454c
Merge branch 'master' of github.com:smartfile/sharpy into add-promotions
Aug 21, 2015
02b7295
Add readme for testing
freak3dot Aug 21, 2015
ded5aed
Needs line break for code to show
freak3dot Aug 21, 2015
acfc60c
Add code formatting to install line.
freak3dot Aug 21, 2015
6c05b9a
Merge branch 'master' of github.com:smartfile/sharpy into add-promotions
Aug 21, 2015
7ffa8a2
Update readme with cheddargetter unittest setup.
freak3dot Aug 24, 2015
018c6da
CheddarGetter setup will probably happen before config.
freak3dot Aug 24, 2015
35fa3cc
Update readme.rst
freak3dot Aug 24, 2015
6926b4f
Update readme.rst
freak3dot Aug 24, 2015
4d0fd82
Try to be more clean on plans.
freak3dot Aug 24, 2015
fbed197
Update readme.rst
freak3dot Aug 24, 2015
ed573e1
Update readme.rst
freak3dot Aug 24, 2015
f8f0500
Remove the debug code.
Aug 24, 2015
12d08b3
Don't request response twice. Verify response is return before trying…
Aug 24, 2015
daad8f1
Merge branch 'master' of github.com:smartfile/sharpy into add-promotions
Aug 24, 2015
6072a77
Add unit test for new methods. Skipping failing tests due to issues o…
Aug 24, 2015
3a25cdf
Update readme.rst
freak3dot Aug 27, 2015
cb4ffb8
Merge branch 'master' of github.com:smartfile/sharpy into add-promotions
Aug 27, 2015
1824bcf
parse_promotions is not needed because it is not used.
Aug 27, 2015
8408830
The convention used in the other classes is to include a __repr__. In…
Aug 27, 2015
721cd38
Also consider clearing customers a failure if success is not in the r…
Aug 27, 2015
6e22417
Remove skipped decorator from tests.
Aug 27, 2015
77af8cc
Add unittests for __repr__ and __unicode__ on the Promotion object. R…
Aug 27, 2015
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 14 additions & 1 deletion README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ Getting Started
To get started with Sharpy, simply install it like you would any other python
package

.. code::

pip install sharpy

Optionally, you can also install `lxml <http://codespeak.net/lxml/>`_ on your
Expand All @@ -50,8 +52,19 @@ Code
You can checkout and download Sharpy's latest code at `Github
<https://github.com/saaspire/sharpy>`_.

Installing elementtree for Development and Unit Testing
=======================================================
When trying to install elementtree, pip may report that there is no such package. If this happens to you, you can work around by downloading and installing it manually.

.. code::

wget http://effbot.org/media/downloads/elementtree-1.2.6-20050316.zip
unzip elementtree-1.2.6-20050316.zip
cd elementtree-1.2.6-20050316/
pip install .

TODOs
=====

* Flesh out the documentation to cover the full API.
* Add support for the various filtering options in the `get_customers` call.
* Add support for the various filtering options in the `get_customers` call.
2 changes: 1 addition & 1 deletion sharpy/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
VERSION = (0, 8)
VERSION = (0, 9)
67 changes: 66 additions & 1 deletion sharpy/parsers.py
Original file line number Diff line number Diff line change
Expand Up @@ -328,4 +328,69 @@ def parse_subscription_item(self, item_element):
item['modified_datetime'] = self.parse_datetime(item_element.findtext('modifiedDatetime'))

return item



class PromotionsParser(CheddarOutputParser):
'''
A utility class for parsing cheddar's xml output for promotions.
'''
def parse_xml(self, xml_str):
promotions = []
promotions_xml = XML(xml_str)
for promotion_xml in promotions_xml:
promotion = self.parse_promotion(promotion_xml)
promotions.append(promotion)

return promotions

def parse_promotion(self, promotion_element):
promotion = {}
promotion['id'] = promotion_element.attrib['id']
promotion['name'] = promotion_element.findtext('name')
promotion['description'] = promotion_element.findtext('description')
promotion['created_datetime'] = self.parse_datetime(promotion_element.findtext('createdDatetime'))

promotion['incentives'] = self.parse_incentives(promotion_element.find('incentives'))
promotion['coupons'] = self.parse_coupons(promotion_element.find('coupons'))

return promotion

def parse_incentives(self, incentives_element):
incentives = []

if incentives_element is not None:
for incentive_element in incentives_element:
incentives.append(self.parse_incentive(incentive_element))

return incentives

def parse_incentive(self, incentive_element):
incentive = {}

incentive['id'] = incentive_element.attrib['id']
incentive['type'] = incentive_element.findtext('type')
incentive['percentage'] = incentive_element.findtext('percentage')
incentive['months'] = incentive_element.findtext('months')
incentive['created_datetime'] = self.parse_datetime(incentive_element.findtext('createdDatetime'))

return incentive

def parse_coupons(self, coupons_element):
coupons = []

if coupons_element is not None:
for coupon_element in coupons_element:
coupons.append(self.parse_coupon(coupon_element))

return coupons

def parse_coupon(self, coupon_element):
coupon = {}

coupon['id'] = coupon_element.attrib['id']
coupon['code'] = coupon_element.attrib['code']
coupon['max_redemptions'] = coupon_element.findtext('maxRedemptions')
coupon['expiration_datetime'] = self.parse_datetime(coupon_element.findtext('expirationDatetime'))
coupon['created_datetime'] = self.parse_datetime(coupon_element.findtext('createdDatetime'))

return coupon
87 changes: 76 additions & 11 deletions sharpy/product.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

from sharpy.client import Client
from sharpy.exceptions import NotFound
from sharpy.parsers import PlansParser, CustomersParser
from sharpy.parsers import PlansParser, CustomersParser, PromotionsParser

class CheddarProduct(object):

Expand Down Expand Up @@ -263,8 +263,42 @@ def delete_all_customers(self):
path='customers/delete-all/confirm/%d' % int(time()),
method='POST'
)



def get_all_promotions(self):
'''
Returns all promotions.
https://cheddargetter.com/developers#promotions
'''
promotions = []

try:
response = self.client.make_request(path='promotions/get')
except NotFound:
response = None

if response:
promotions_parser = PromotionsParser()
promotions_data = promotions_parser.parse_xml(response.content)
promotions = [Promotion(**promotion_data) for promotion_data in promotions_data]

return promotions

def get_promotion(self, code):
'''
Get the promotion with the specified coupon code.
https://cheddargetter.com/developers#single-promotion
'''

response = self.client.make_request(
path='promotions/get',
params={'code': code},
)
promotion_parser = PromotionsParser()
promotion_data = promotion_parser.parse_xml(response.content)

return Promotion(**promotion_data[0])


class PricingPlan(object):

def __init__(self, name, code, id, description, is_active, is_free,
Expand Down Expand Up @@ -576,12 +610,12 @@ def __init__(self, id, gateway_token, cc_first_name, cc_last_name,

super(Subscription, self).__init__()

def load_data(self, id, gateway_token, cc_first_name, cc_last_name, \
cc_company, cc_country, cc_address, cc_city, cc_state, \
cc_zip, cc_type, cc_last_four, cc_expiration_date, customer,\
cc_email=None, canceled_datetime=None ,created_datetime=None, \
plans=None, invoices=None, items=None, gateway_account=None, \
cancel_reason=None, cancel_type=None, redirect_url=None):
def load_data(self, id, gateway_token, cc_first_name, cc_last_name,
cc_company, cc_country, cc_address, cc_city, cc_state,
cc_zip, cc_type, cc_last_four, cc_expiration_date, customer,
cc_email=None, canceled_datetime=None ,created_datetime=None,
plans=None, invoices=None, items=None, gateway_account=None,
cancel_reason=None, cancel_type=None, redirect_url=None):

self.id = id
self.gateway_token = gateway_token
Expand Down Expand Up @@ -764,5 +798,36 @@ def set(self, quantity):
)

return self.subscription.customer.load_data_from_xml(response.content)




class Promotion(object):
def __init__(self, id=None, code=None, name=None, description=None,
created_datetime=None, incentives=None, coupons=None):

self.load_data(code=code, id=id, name=name, description=description,
created_datetime=created_datetime,
incentives=incentives, coupons=coupons)

super(Promotion, self).__init__()

def __repr__(self):
return u'Promotion: %s (%s)' % (self.name, self.code,)

def __unicode__(self):
return u'{0} ({1})'.format(self.name, self.code)

def load_data(self, id=None, code=None, name=None, description=None,
created_datetime=None, incentives=None, coupons=None):

self.code = code
self.id = id
self.name = name
self.description = description
self.created = created_datetime

self.incentives = incentives
self.coupons = coupons

# Bring coupon code up to parent promotion
if self.code is None and self.coupons and len(self.coupons) > 0:
self.code = self.coupons[0].get('code')
10 changes: 6 additions & 4 deletions tests/client_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,8 +93,9 @@ def test_make_request_access_denied(self):
client = self.get_client(username=bad_username)
client.make_request(path)

@raises(BadRequest)
@raises(NotFound)
def test_make_request_bad_request(self):
""" Attempt to grab the plans without adding /get to the url. """
path = 'plans'
client = self.get_client()
client.make_request(path)
Expand All @@ -104,7 +105,7 @@ def test_make_request_not_found(self):
path = 'things-which-dont-exist'
client = self.get_client()
client.make_request(path)

@clear_users
def test_post_request(self):
path = 'customers/new'
Expand All @@ -118,7 +119,6 @@ def test_post_request(self):
client = self.get_client()
client.make_request(path, data=data)


def generate_error_response(self, auxcode=None, path=None, params=None, **overrides):
'''
Creates a request to cheddar which should return an error
Expand Down Expand Up @@ -244,7 +244,9 @@ def test_format_datetime_with_now(self):

@clear_users
def test_chedder_update_customer_error(self):
# Overriding the zipcode so a customer actually gets created
"""
Test overriding the zipcode so a customer actually gets updated.
"""
overrides = {
'subscription[ccZip]': 12345
}
Expand Down
Loading