1
1
from __future__ import absolute_import
2
2
3
3
import urlparse
4
- from urllib import urlencode
5
4
6
5
import requests
7
- import oauth2
6
+ from requests_oauthlib import OAuth1Session
8
7
from lxml import etree
9
8
10
9
from .saml import SAML
15
14
16
15
17
16
class AggCatResponse (object ):
18
- """General response object that contains oAuth2 response object
19
- and the content """
20
- def __init__ (self , headers , content ):
21
- self .headers = headers
17
+ """General response object that contains the HTTP status code
18
+ and response text """
19
+ def __init__ (self , status_code , content ):
20
+ self .status_code = status_code
22
21
self .content = content
23
22
24
23
def __repr__ (self ):
25
- return u'<AggCatResponse %s>' % self .headers . status
24
+ return u'<AggCatResponse %s>' % self .status_code
26
25
27
26
28
27
class AggcatClient (object ):
@@ -36,6 +35,7 @@ class AggcatClient(object):
36
35
testing you can use whatever integer you want.
37
36
:param string private_key: The absolute path to the generated x509 private key
38
37
:param boolean objectify: (optional) Convert XML into pythonic object on every API call. Default: ``True``
38
+ :param boolean verify_ssl: (optional) Verify SSL Certificate. See :ref:`known_issues`. Default: ``True``
39
39
40
40
:returns: :class:`AggcatClient`
41
41
@@ -61,7 +61,7 @@ class AggcatClient(object):
61
61
``objectify`` (Boolean) This is a BETA functionality. It will objectify the XML returned from
62
62
intuit into standard python objects so you don't have to mess with XML. Default: ``True``
63
63
"""
64
- def __init__ (self , consumer_key , consumer_secret , saml_identity_provider_id , customer_id , private_key , objectify = True ):
64
+ def __init__ (self , consumer_key , consumer_secret , saml_identity_provider_id , customer_id , private_key , objectify = True , verify_ssl = True ):
65
65
# base API url
66
66
self .base_url = 'https://financialdatafeed.platform.intuit.com/rest-war/v1'
67
67
@@ -72,6 +72,9 @@ def __init__(self, consumer_key, consumer_secret, saml_identity_provider_id, cus
72
72
self .customer_id = customer_id
73
73
self .private_key = private_key
74
74
75
+ # verify ssl
76
+ self .verify_ssl = verify_ssl
77
+
75
78
# SAML object to help create SAML assertion message
76
79
self .saml = SAML (private_key , saml_identity_provider_id , customer_id )
77
80
@@ -88,17 +91,15 @@ def __init__(self, consumer_key, consumer_secret, saml_identity_provider_id, cus
88
91
self .client = self ._client ()
89
92
90
93
def _client (self ):
91
- """Build an oAuth2 client from consumer tokens, and oauth tokens"""
92
- consumer = oauth2 .Consumer (
93
- key = self .consumer_key ,
94
- secret = self .consumer_secret
95
- )
96
- token = oauth2 .Token (
97
- key = self ._oauth_tokens ['oauth_token' ][0 ],
98
- secret = self ._oauth_tokens ['oauth_token_secret' ][0 ]
94
+ """Build an oAuth client from consumer tokens, and oauth tokens"""
95
+ # initialze the oauth session for requests
96
+ session = OAuth1Session (
97
+ self .consumer_key ,
98
+ self .consumer_secret ,
99
+ self ._oauth_tokens ['oauth_token' ][0 ],
100
+ self ._oauth_tokens ['oauth_token_secret' ][0 ]
99
101
)
100
-
101
- return oauth2 .Client (consumer , token )
102
+ return session
102
103
103
104
def _get_oauth_tokens (self ):
104
105
"""Get an oauth token by sending over the SAML assertion"""
@@ -123,48 +124,51 @@ def _refresh_client(self):
123
124
# get a new client
124
125
self .client = self ._client ()
125
126
126
- def _build_url (self , path , query ):
127
- """Build a url from a string path and dict query"""
128
- if query :
129
- return '%s/%s?%s' % (self .base_url , path , urlencode (query ))
130
- else :
131
- return '%s/%s' % (self .base_url , path )
127
+ def _build_url (self , path ):
128
+ """Build a url from a string path"""
129
+ return '%s/%s' % (self .base_url , path )
132
130
133
131
def _make_request (self , path , method = 'GET' , body = None , query = {}, headers = {}):
134
132
"""Make the signed request to the API"""
135
- url = self ._build_url (path , query )
133
+ # build the query url
134
+ url = self ._build_url (path )
136
135
137
136
# check for plain object request
138
137
return_obj = self .objectify
139
138
140
- if method == 'GET' or method == 'DELETE' :
141
- response , content = self .client .request (url , method )
142
- else :
139
+ if method == 'GET' :
140
+ response = self .client .get (url , params = query , verify = self .verify_ssl )
141
+
142
+ if method == 'PUT' :
143
143
headers .update ({'Content-Type' : 'application/xml' })
144
- response , content = self .client .request (
145
- url ,
146
- method = method ,
147
- body = body ,
148
- headers = headers ,
149
- realm = None
150
- )
144
+ response = self .client .put (url , data = body , headers = headers , verify = self .verify_ssl )
145
+
146
+ if method == 'DELETE' :
147
+ response = self .client .delete (url , verify = self .verify_ssl )
148
+
149
+ if method == 'POST' :
150
+ headers .update ({'Content-Type' : 'application/xml' })
151
+ response = self .client .post (url , data = body , headers = headers , verify = self .verify_ssl )
151
152
152
153
# refresh the token if token expires and retry the query
153
- if 'www-authenticate' in response and response [ 'www-authenticate' ] == \
154
- 'OAuth oauth_problem="token_rejected"' :
155
- self ._refresh_client ()
156
- self ._make_request (path , method , body , query , headers )
154
+ if 'www-authenticate' in response . headers :
155
+ if response . headers [ 'www-authenticate' ] == 'OAuth oauth_problem="token_rejected"' :
156
+ self ._refresh_client ()
157
+ self ._make_request (path , method , body , query , headers )
157
158
158
- if response .status not in [200 , 201 , 401 ]:
159
- raise HTTPError ('Status Code: %s, Response %s' % (response .status , content ,))
159
+ if response .status_code not in [200 , 201 , 401 ]:
160
+ raise HTTPError ('Status Code: %s, Response %s' % (response .status_code , response . text ,))
160
161
161
162
if return_obj :
162
163
try :
163
- return AggCatResponse (response , Objectify (content ).get_object ())
164
+ return AggCatResponse (
165
+ response .status_code ,
166
+ Objectify (response .content ).get_object ()
167
+ )
164
168
except etree .XMLSyntaxError :
165
169
return None
166
170
167
- return AggCatResponse (response , content )
171
+ return AggCatResponse (response . status_code , response . content )
168
172
169
173
def _remove_namespaces (self , tree ):
170
174
"""Remove the namspaces from the Intuit XML for easier parsing"""
0 commit comments