Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
65 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
696f8ac
Merge pull request #1 from smartfile/add-promotions
freak3dot Aug 27, 2015
038ea9a
I hate to be that guy but OCD. PEP8 fixes.
Aug 27, 2015
a803247
Tried to add a return and failed due to the PEP8 on the unused respon…
Aug 27, 2015
b18e794
Add docstrings to the tests. Also add a sleep for a test that fails s…
Aug 27, 2015
e527613
Merge pull request #2 from smartfile/pep8
freak3dot Aug 27, 2015
043620f
Add coupon_code to customer create and update methods. With Testing.
Aug 28, 2015
2c14b93
Merge pull request #3 from smartfile/coupon-create
freak3dot Aug 28, 2015
186f6d6
added plans to Promotion and PromotionParser. See #3141
galitskyd Mar 15, 2016
359c0e8
remove ipdb trace. See #0000
galitskyd Mar 15, 2016
b742d61
got tests to run on sharpy. Added new test to parse promotions. See #…
galitskyd Mar 17, 2016
d6f0718
Merge pull request #4 from smartfile/3141-properly-working-coupons
Mar 31, 2016
5a6e57b
Updated version number.
Ryanb58 Apr 7, 2016
3b818bb
updated version for release.
Ryanb58 Apr 7, 2016
cf21319
Clean credit card info from data that is logged in debug mode
Jun 14, 2016
3a5d7c0
Merge pull request #5 from smartfile/dont-log-cc-num
galitskyd Jun 14, 2016
00ca5ae
Bump version
Jun 14, 2016
357d8ed
update version number
galitskyd Jun 18, 2016
5fa3a6d
Merge pull request #6 from smartfile/fix-keyerror
galitskyd Jun 18, 2016
c66e390
added more under try/except. On exception make credit card None.
galitskyd Jun 19, 2016
05224f8
updated version number
galitskyd Jun 19, 2016
4fd8093
Merge pull request #7 from smartfile/fix-keyerror
galitskyd Jun 19, 2016
8154d0e
Check that cc info is in the request before removing it
Jun 20, 2016
fd10ef4
Update version number
hylyh Jun 20, 2016
b7ded77
Merge pull request #8 from smartfile/fix-keyerror
galitskyd Jun 20, 2016
1017d60
convert to python3
May 31, 2018
14ab2f4
Some minor changes to get sharpy working with cheddar using python3
tahirijaz24 Jun 6, 2018
e5571cd
added the elementtree-1.2.7 archive url to dev-requirements.txt
tahirijaz24 Jun 6, 2018
1762b40
trying citeelementtree instead of elementtree, think they changed the…
tahirijaz24 Jun 11, 2018
df98c29
code to get a paginated json get_customers response from cheddat
tahirijaz24 Jul 12, 2018
5e16ca1
using product_code instead of product_id
tahirijaz24 Jul 13, 2018
56b02e0
fixed typo
tahirijaz24 Jul 23, 2018
f151505
Fix tests
cabarnes Jan 2, 2020
98aa82b
Add Travis CI testing
cabarnes Jan 2, 2020
3b27e56
Send all variables to the job
cabarnes Jan 2, 2020
b1dee2e
Only test in python 3.6
cabarnes Jan 2, 2020
1067df9
Fix encoding of credentials
cabarnes Jan 2, 2020
214dadb
Remove built objects
cabarnes Jan 2, 2020
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
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,6 @@
.coverage
cover
tests/config.ini
.noseids
.noseids
.idea/
venv/
13 changes: 13 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
language: python
python:
- "3.6"
env:
global:
- secure: "qSOQ4EoedKr6NoIuFVmMqhsTxO6zngchbm2uo3Z0vNcAGYVUxKSPDuI/1vjVZZQyP//AyE3Bk2sfiUQUm05ZixqkBocX4CjwESWF/2aEKu1MNXkSpB5Ypn8W3w4cNuy8taT/Wws2XSc7C7Oc/XuLtwZVxQisPh01hwevF496xP2InPhO2ziLqUj4TkAx2pjHSjWXfj68pyTyflkwhRReqQsqPKMFaESKdngYk06cnOdBElk4YvNLJZnAbPXxhEAmz8sY3AC67MEFALmthnm2WfLmVSVQ8kp1yA0Pedlt1xvGh+YO4jkZTw5QrM4dhbA+DTdRt67U3PVDEUg3W+MrBb91PeubveJ3TXY6UXtbc2KXAh48yfc+veB4r0anlmVv19VDWDGqUJFzmtJRrbX9UhvKNh62P5JPDQqlATnEd08BZrtMBxn3gc5HLw097qvDo4DmvyP2cX2rbrk29lTJeUshol+TYnV/hYmJ0Bao8685I48rAW/ZRvZBw76549/f9e58kzY0dEcrDLQ0qHmOOJumPYSBp5wZ6nDfikGOie8z88mxxu7Blz7a09ZmH/f2uCMoAr+4vUU5HrLPaGJexGn718ZxvVLuY/qhDilIDtL+l/qXMXA2cCChKOjmWi8PrN9bNkt/QLEQj3Ke0vMyjeX6eLjhIAfiqzKBTSM/UGw="
- secure: "A0SM/sb8fBHQBag07DxICRzgvmyogFF9xwtXwS63CSzekLhe9sqZF4KShCDhCOk8rbwtSOBJ96z4Hl2Bq/y8DBVwaMV0x9lX5eDi1wWEDBTHqV5Dtw6Y2S0hCfEKYdiIy2Byt3qXRZ9+bumi3llb4z7A4Jg1Kb2+MzqhY7qjFsc8ZZu33eqnQMnCQ2zmRy332xaiV77/jjMn/buMTZEE9hwXCvRT3mtYYak7OR7jTxMbQKOLG+TlOsGO9+uuY2xigBatY1sLSq5tQwrw6dgZS7D8QYQ4rKdaG4DjoE0UcoWsLw5IGMhxFuEnIbnjvLyej2eZnwZtlGnN5wyHbOj2/Cc/tkV46toFGyqeEvmEZEecKx1muamOdK4ZLEBr+5qZVD71d+j4H1q/5bvZsJ+gLSoOxVnha/B1vW4JkVZP1BDygd1ml/DF8XjdmLwYV6nT7ArjWpPFKPIejZil9AlY88J0xo3DSpw5C4AYBJLKDnI+ui0LGkrCt4rEUKojd2OGd9inTso3dTuRBQuEyr+wiCSsbOiROimM3kANoiSUg+dw9urwPyb9wKkqQ0UhNWSLGdxPZLvTWTajwv8HMM63MK/xTsqr9KejRXA1ibaic3Es/bFD1LZmzPkFLOweLtaqYr5c/ye5wDin22GkTW4jojA85ELfi8RR8fle2LAOsCQ="
- secure: "ha/L3Wwd3eLW/r75au906RUwrR9KZn6OuHy/w4xTKmHirk5oTyHo+XbsthSHs2Xis0RfcZ+Zb862L75psS6C/PdZ0Xb8tg9LbcBausVRMdzvykgsH2DOavvTJs778OOsHU1uF0geOKNo4FJv5onFjMtQ8UZW05kP1LQAu/6BdKEo+CfBfKr5uIRfDaTY+NqRhrIZsGbX/1rD1T5jqOZxXO3tj/NxIBrqTDz/4He7mGQbDR1pwrWrTTdPkPV2xLGfTiTbBbigRi675MimtCz8eBERkLjgb3BRpsjcAtNYPrZySIzsaHeSxeNFBDfoBmJ3ufeBQLx0umSKU++O7JRB1j0lhHczj/YokjHSz5KxnYZc/MXWghjA8g+cIeg9xa//ev+vuqzhH+8hiaqn6bq55ht9ZMPbDUPqQrSZldaVs4Bb1926d7QbhH8RxcfD/sb69Febl0BBpYpS+RqM6tGHw42fL3sinzdkFESgNv8/PjWWwFdIMBGYaXnXM7TyhnnQZaPRFkPf3eqapIg8Q84C3zI9lSWFq5q3oVlQ4fiyMwFeLzrelpb94ArOU95EkEGvcDz06vvjgdmhvP0eitF5aNoy2vJuarDnxRWdoafLL1ilU2PrXdov55Y1vL+7MwmE8JbnnsSh/LwPKOiG2oiEQiDPcJMp6NgXwhDguR9UFAA="
install:
- pip install -r dev-requirements.txt
script:
- cd tests
- nosetests --tc=cheddar.username:$USERNAME --tc=cheddar.password:$PASSWORD --tc=cheddar.product_code:$PRODUCT --tc=cheddar.endpoint:https://cheddargetter.com/xml
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.
17 changes: 8 additions & 9 deletions dev-requirements.txt
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
# Packages which are required in the setup.py file
httplib2
elementtree

# Packages which are required for development but not use of sharpy

nose
coverage
nose-testconfig
coverage==4.5.1
citelementtree==1.2.7
httplib2==0.11.3
lxml==4.2.1
nose==1.3.7
nose-testconfig==0.10
python-dateutil==2.7.3
six==1.11.0
1 change: 0 additions & 1 deletion setup.cfg
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
[nosetests]
tc-file=tests/config.ini
detailed-errors=1
with-coverage=1
cover-package=sharpy
Expand Down
6 changes: 3 additions & 3 deletions setup.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#!/usr/bin/env python
try:
from setuptools import setup
except ImportError, err:
from setuptools import setup
except ImportError as err:
from distutils.core import setup

from sharpy import VERSION
Expand All @@ -16,7 +16,7 @@
packages=['sharpy'],
license="BSD",
long_description=open('README.rst').read(),
install_requires=['httplib2', 'elementtree', 'python-dateutil<2.0'],
install_requires=['httplib2', 'citelementtree', 'python-dateutil'],
classifiers=[
'Development Status :: 4 - Beta',
'Environment :: Web Environment',
Expand Down
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, 7)
63 changes: 46 additions & 17 deletions sharpy/client.py
Original file line number Diff line number Diff line change
@@ -1,22 +1,31 @@
import base64
import logging
from urllib import urlencode
from decimal import getcontext
from urllib.parse import urlencode
from dateutil.tz import tzutc
import httplib2

from sharpy.exceptions import CheddarError, AccessDenied, BadRequest, NotFound, PreconditionFailed, CheddarFailure, NaughtyGateway, UnprocessableEntity
from sharpy.exceptions import AccessDenied
from sharpy.exceptions import BadRequest
from sharpy.exceptions import CheddarError
from sharpy.exceptions import CheddarFailure
from sharpy.exceptions import NaughtyGateway
from sharpy.exceptions import NotFound
from sharpy.exceptions import PreconditionFailed
from sharpy.exceptions import UnprocessableEntity

client_log = logging.getLogger('SharpyClient')


class Client(object):
default_endpoint = 'https://cheddargetter.com/xml'
def __init__(self, username, password, product_code, cache=None, timeout=None, endpoint=None):

def __init__(self, username, password, product_code, cache=None,
timeout=None, endpoint=None):
'''
username - Your cheddargetter username (probably an email address)
password - Your cheddargetter password
product_code - The product code for the product you want to work with
cache - A file system path or an object which implements the httplib2
cache - A file system path or an object which implements the 117
cache API (optional)
timeout - Socket level timout in seconds (optional)
endpoint - An alternate API endpoint (optional)
Expand All @@ -34,14 +43,14 @@ def build_url(self, path, params=None):
'''
Constructs the url for a cheddar API resource
'''
url = u'%s/%s/productCode/%s' % (
url = '%s/%s/productCode/%s' % (
self.endpoint,
path,
self.product_code,
)
if params:
for key, value in params.items():
url = u'%s/%s/%s' % (url, key, value)
for key, value in list(params.items()):
url = '%s/%s/%s' % (url, key, value)

return url

Expand All @@ -67,6 +76,16 @@ def format_date(self, to_format):
str_dt = utc_value.strftime('%Y-%m-%d')
return str_dt

def get_client(self):
return httplib2.Http(cache=self.cache, timeout=self.timeout)

def get_auth_headers(self):
headers = {}
headers['Authorization'] = "Basic %s" % base64.standard_b64encode(
(self.username + ':' + self.password).encode('utf-8')
).strip().decode("utf-8")
return headers

def make_request(self, path, params=None, data=None, method=None):
'''
Makes a request to the cheddar api using the authentication and
Expand All @@ -78,30 +97,42 @@ def make_request(self, path, params=None, data=None, method=None):
method = method or 'GET'
body = None
headers = {}
cleaned_data = None

if data:
method = 'POST'
body = urlencode(data)
headers = {
'content-type': 'application/x-www-form-urlencoded; charset=UTF-8',
'content-type':
'application/x-www-form-urlencoded; charset=UTF-8',
}

# Clean credit card info from when the request gets logged
# (remove ccv and only show last four of card num)
cleaned_data = data.copy()
if 'subscription[ccCardCode]' in cleaned_data:
del cleaned_data['subscription[ccCardCode]']
if 'subscription[ccNumber]' in cleaned_data:
ccNum = cleaned_data['subscription[ccNumber]']
cleaned_data['subscription[ccNumber]'] = ccNum[-4:]

client_log.debug('Request Method: %s' % method)
client_log.debug('Request Body(Data): %s' % data)
client_log.debug('Request Body(Raw): %s' % body)
client_log.debug('Request Body (Cleaned Data): %s' % cleaned_data)

# Setup http client
h = httplib2.Http(cache=self.cache, timeout=self.timeout)
#h.add_credentials(self.username, self.password)
# Skip the normal http client behavior and send auth headers immediately
# to save an http request.
headers['Authorization'] = "Basic %s" % base64.standard_b64encode(self.username + ':' + self.password).strip()
# Skip the normal http client behavior and send auth headers
# immediately to save an http request.

headers['Authorization'] = "Basic %s" % base64.standard_b64encode(
(self.username + ':' + self.password).encode('utf-8')
).strip().decode("utf-8")
# Make request
response, content = h.request(url, method, body=body, headers=headers)
status = response.status
client_log.debug('Response Status: %d' % status)
client_log.debug('Response Content: %s' % content)

if status != 200 and status != 302:
exception_class = CheddarError
if status == 401:
Expand All @@ -123,5 +154,3 @@ def make_request(self, path, params=None, data=None, method=None):

response.content = content
return response


28 changes: 18 additions & 10 deletions sharpy/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,16 @@

class CheddarError(Exception):
"Base class for exceptions returned by cheddar"

def __init__(self, response, content, *args, **kwargs):
# Importing in method to break circular dependecy
from sharpy.parsers import parse_error

super(CheddarError, self).__init__(*args, **kwargs)
error_info = parse_error(content)
self.response = response
self.error_info = error_info

def __str__(self):
return '%s (%s) %s - %s' % (
self.response.status,
Expand All @@ -20,42 +20,50 @@ def __str__(self):
self.error_info['message'],
)


class AccessDenied(CheddarError):
"A request to cheddar returned a status code of 401"
pass



class BadRequest(CheddarError):
"A request to cheddar was invalid in some way"
pass


class NotFound(CheddarError):
"A request to chedder was made for a resource which doesn't exist"
pass



class CheddarFailure(CheddarError):
"A request to cheddar encountered an unexpected error on the cheddar side"
pass



class PreconditionFailed(CheddarError):
"A request to cheddar was made but failed CG's validation in some way."
pass



class NaughtyGateway(CheddarError):
"""
Cheddar either couldn't contact the gateway or the gateway did something
very unexpected.
"""
pass



class UnprocessableEntity(CheddarError):
"""
An error occurred during processing. Please fix the error and try again.
"""
pass



class ParseError(Exception):
"""
Sharpy recieved unknown output from cheddar and doesn't know what
to do with it.
"""
pass
pass
Loading