@@ -42,50 +42,48 @@ class Atomx(object):
4242 (without the resource payload) in :attr:`.Atomx.last_response`. (default: `True`)
4343 :return: :class:`.Atomx` session to interact with the api
4444 """
45- def __init__ (self , email , password , api_endpoint = API_ENDPOINT , save_response = True ):
46- self .auth_tkt = None
45+ def __init__ (self , email , password ,
46+ api_endpoint = API_ENDPOINT , save_response = True , expiration = None ):
47+ self .auth_token = None
4748 self .user = None
48- self .email = email
49- self .password = password
5049 self .api_endpoint = api_endpoint .rstrip ('/' ) + '/'
5150 self .save_response = save_response
5251 #: Contains the response of the last api call, if `save_response` was set `True`
5352 self .last_response = None
54- self .session = requests .Session ()
55- self .login ()
53+ self .login (email , password , expiration )
5654
57- def login (self , email = None , password = None ):
55+ @property
56+ def _auth_header (self ):
57+ if self .auth_token :
58+ return {'Authorization' : 'Bearer ' + self .auth_token }
59+
60+ def login (self , email , password , expiration = None ):
5861 """Gets new authentication token for user ``email``.
5962
6063 This method is automatically called in :meth:`__init__` so
6164 you rarely have to call this method directly.
6265
63- :param str email: Use this email instead of the one provided at
64- construction time. (optional)
65- :param str password: Use this password instead of the one provided at
66- construction time. (optional)
66+ :param str email: Email to use for login.
67+ :param str password: Password to use for login.
68+ :param int expiration: Number of seconds that the auth token should be valid. (optional)
6769 :return: None
6870 :raises: :class:`.exceptions.InvalidCredentials` if ``email``/``password`` is wrong
6971 """
70- if email :
71- self .email = email
72- if password :
73- self .password = password
74-
75- r = self .session .post (self .api_endpoint + 'login' ,
76- json = {'email' : self .email , 'password' : self .password })
72+ json = {'email' : email , 'password' : password }
73+ if expiration :
74+ json ['expiration' ] = expiration
75+ r = requests .post (self .api_endpoint + 'login' , json = json )
7776 if not r .ok :
7877 if r .status_code == 401 :
7978 raise InvalidCredentials
8079 raise APIError (r .json ()['error' ])
81- self .auth_tkt = r .json ()['auth_tkt ' ]
80+ self .auth_token = r .json ()['auth_token ' ]
8281 self .user = models .User (session = self , ** r .json ()['user' ])
8382
8483 def logout (self ):
8584 """Removes authentication token from session."""
86- self .auth_tkt = None
85+ self .auth_token = None
8786 self .user = None
88- self .session .get (self .api_endpoint + 'logout' )
8987
9088 def search (self , query ):
9189 """Search for ``query``.
@@ -114,7 +112,9 @@ def search(self, query):
114112 :param str query: keyword to search for.
115113 :return: dict with list of :mod:`.models` as values
116114 """
117- r = self .session .get (self .api_endpoint + 'search' , params = {'q' : query })
115+ r = requests .get (self .api_endpoint + 'search' ,
116+ params = {'q' : query },
117+ headers = self ._auth_header )
118118 r_json = r .json ()
119119 if not r .ok :
120120 raise APIError (r_json ['error' ])
@@ -134,7 +134,8 @@ def search(self, query):
134134 return search_result
135135
136136 def report (self , scope = None , groups = None , metrics = None , where = None , from_ = None , to = None ,
137- timezone = 'UTC' , emails = None , fast = True , when = None , interval = None , name = None ):
137+ timezone = 'UTC' , emails = None , when = None , interval = None , name = None ,
138+ sort = None , limit = None , offset = None ):
138139 """Create a report.
139140
140141 See the `reporting atomx wiki <https://wiki.atomx.com/reporting>`_
@@ -164,16 +165,15 @@ def report(self, scope=None, groups=None, metrics=None, where=None, from_=None,
164165 :param emails: One or multiple email addresses that should get
165166 notified once the report is finished and ready to download.
166167 :type emails: str or list
167- :param bool fast: if `False` the report will always be run against the low level data.
168- This is useful for billing reports for example.
169- The default is `True` which means it will always try to use aggregate data
170- to speed up the query.
171168 :param str when: When should the scheduled report run. (daily, monthly, monday-sunday)
172169 :param str interval: Time period included in the scheduled report ('N days' or 'N month')
173- :param str name: Optional name for the report
170+ :param str name: Optional name for the report.
171+ :param str or list sort: List of columns to sort by.
172+ :param int limit: Number of rows to return
173+ :param int offset: Number of rows to skip.
174174 :return: A :class:`atomx.models.Report` model
175175 """
176- report_json = {'timezone' : timezone , 'fast' : fast }
176+ report_json = {'timezone' : timezone }
177177
178178 if name :
179179 report_json ['name' ] = name
@@ -227,7 +227,17 @@ def report(self, scope=None, groups=None, metrics=None, where=None, from_=None,
227227 emails = [emails ]
228228 report_json ['emails' ] = emails
229229
230- r = self .session .post (self .api_endpoint + 'report' , json = report_json )
230+ params = {}
231+ if limit :
232+ params ['limit' ] = limit
233+ if offset :
234+ params ['offset' ] = offset
235+ if sort :
236+ if isinstance (sort , list ):
237+ sort = ',' .join (sort )
238+ params ['sort' ] = sort
239+ r = requests .post (self .api_endpoint + 'report' ,
240+ params = params , json = report_json , headers = self ._auth_header )
231241 r_json = r .json ()
232242 if not r .ok :
233243 raise APIError (r_json ['error' ])
@@ -238,65 +248,8 @@ def report(self, scope=None, groups=None, metrics=None, where=None, from_=None,
238248 self .last_response = r_json
239249 self .last_response ['_headers' ] = r .headers
240250
241- if is_scheduled_report :
242- return models .ScheduledReport (session = self , ** report )
243-
244251 return models .Report (session = self , ** report )
245252
246- def report_status (self , report ):
247- """Get the status for a `report`.
248-
249- This is typically used by calling :meth:`.models.Report.status`.
250-
251- :param report: Either a :class:`str` that contains the ``id`` of
252- of the report or an :class:`.models.Report` instance.
253- :type report: :class:`.models.Report` or :class:`list`
254- :return: :class:`dict` containing the report status.
255- """
256- if isinstance (report , models .Report ):
257- report_id = report .id
258- else :
259- report_id = report
260-
261- r = self .session .get (self .api_endpoint + 'report/' + report_id , params = {'status' : True })
262- if not r .ok :
263- raise APIError (r .json ()['error' ])
264-
265- if self .save_response :
266- self .last_response = r .json ()
267- self .last_response ['_headers' ] = r .headers
268-
269- return r .json ()['report' ]
270-
271- def report_get (self , report , sort = None , limit = None , offset = None ):
272- """Get the content (csv) of a :class:`.models.Report`
273-
274- Typically used by calling :meth:`.models.Report.content` or
275- :meth:`.models.Report.pandas`.
276-
277- :param report: Either a :class:`str` that contains the ``id`` of
278- of the report or an :class:`.models.Report` instance.
279- :type report: :class:`.models.Report` or :class:`list`
280- :return: :class:`str` with the report content.
281- """
282- if isinstance (report , models .Report ):
283- report_id = report .id
284- else :
285- report_id = report
286-
287- params = {}
288- if limit :
289- params ['limit' ] = int (limit )
290- if offset :
291- params ['offset' ] = int (offset )
292- if sort :
293- params ['sort' ] = sort
294-
295- r = self .session .get (self .api_endpoint + 'report/' + report_id , params = params )
296- if not r .ok :
297- raise APIError (r .json ()['error' ])
298- return r .content .decode ()
299-
300253 def get (self , resource , * args , ** kwargs ):
301254 """Returns a list of models from :mod:`.models` if you query for
302255 multiple models or a single instance of a model from :mod:`.models`
@@ -355,7 +308,7 @@ def get(self, resource, *args, **kwargs):
355308 """
356309 if isclass (resource ) and issubclass (resource , models .AtomxModel ):
357310 resource = resource ._resource_name
358- elif isinstance (resource , models . AtomxModel ):
311+ elif hasattr (resource , '_resource_name' ):
359312 resource_path = resource ._resource_name
360313 if hasattr (resource , 'id' ):
361314 resource_path += '/' + str (resource .id )
@@ -364,7 +317,7 @@ def get(self, resource, *args, **kwargs):
364317 resource = resource .strip ('/' )
365318 for a in args :
366319 resource += '/' + str (a )
367- r = self . session . get (self .api_endpoint + resource , params = kwargs )
320+ r = requests . get (self .api_endpoint + resource , params = kwargs , headers = self . _auth_header )
368321 if not r .ok :
369322 raise APIError (r .json ()['error' ])
370323
@@ -383,7 +336,7 @@ def get(self, resource, *args, **kwargs):
383336 elif model_name == 'reporting' : # special case for `/reports` status
384337 return {
385338 'reports' : [models .Report (session = self , ** m ) for m in res ['reports' ]],
386- 'scheduled' : [models .ScheduledReport (session = self , ** m ) for m in res ['scheduled' ]]
339+ 'scheduled' : [models .Report (session = self , ** m ) for m in res ['scheduled' ]]
387340 }
388341 return res
389342
@@ -397,8 +350,8 @@ def post(self, resource, json, **kwargs):
397350 :param kwargs: URL Parameters of the request.
398351 :return: :class:`dict` with the newly created resource.
399352 """
400- r = self . session .post (self .api_endpoint + resource .strip ('/' ),
401- json = json , params = kwargs )
353+ r = requests .post (self .api_endpoint + resource .strip ('/' ),
354+ json = json , params = kwargs , headers = self . _auth_header )
402355 r_json = r .json ()
403356 if not r .ok :
404357 raise APIError (r_json ['error' ])
@@ -424,8 +377,8 @@ def put(self, resource, id, json, **kwargs):
424377 :param kwargs: URL Parameters of the request.
425378 :return: :class:`dict` with the modified resource.
426379 """
427- r = self . session .put (self .api_endpoint + resource .strip ('/' ) + '/' + str (id ),
428- json = json , params = kwargs )
380+ r = requests .put (self .api_endpoint + resource .strip ('/' ) + '/' + str (id ),
381+ json = json , params = kwargs , headers = self . _auth_header )
429382 r_json = r .json ()
430383 if not r .ok :
431384 raise APIError (r_json ['error' ])
@@ -449,7 +402,7 @@ def delete(self, resource, *args, **kwargs):
449402 resource = resource .strip ('/' )
450403 for a in args :
451404 resource += '/' + str (a )
452- r = self . session . delete (self .api_endpoint + resource , params = kwargs )
405+ r = requests . delete (self .api_endpoint + resource , params = kwargs , headers = self . _auth_header )
453406 r_json = r .json ()
454407 if not r .ok :
455408 raise APIError (r_json ['error' ])
0 commit comments