jmcarp / betfair.py

A Python wrapper for the Betfair API
MIT License
103 stars 76 forks source link

Extracting timing information from requests #28

Closed goetzk closed 9 years ago

goetzk commented 9 years ago

Hi, Since (at least) Requests 2.6.2 elapsed time is recorded and stored in Response.elapsed. I'm about to hackishly expose it for my own purposes (not sure how yet) and was wondering if there was a way you could recommend or if you would be interested in including such a change.

goetzk commented 9 years ago

This was the smallest change i came up with.

@@ -29,10 +29,11 @@ class Betfair(object):
         self.cert_file = cert_file
         self.content_type = content_type
         self.session = requests.Session()
         self.session_token = None
         self.API_URL = None
+   self.last_api_time = None

     # Set api_url
     @property
     def api_url(self):
         """Retreive a value for self.API_URL"""
@@ -61,10 +62,11 @@ class Betfair(object):
     def make_auth_request(self, method):
         response = self.session.post(
             os.path.join(IDENTITY_URL, method),
             headers=self.headers,
         )
+   self.last_api_time = response.elapsed
         utils.check_status_code(response)
         data = response.json()
         if data.get('status') != 'SUCCESS':
             raise exceptions.BetfairAuthError(response, data)

@@ -73,10 +75,11 @@ class Betfair(object):
         response = self.session.post(
             self.API_URL,
             data=json.dumps(payload),
             headers=self.headers,
         )
+   self.last_api_time = response.elapsed
         utils.check_status_code(response, codes=codes)
         result = utils.result_or_error(response)
         return utils.process_result(result, model)

     # Authentication methods
@@ -99,10 +102,11 @@ class Betfair(object):
             headers={
                 'X-Application': self.app_key,
                 'Content-Type': 'application/x-www-form-urlencoded',
             },
         )
+   self.last_api_time = response.elapsed
         utils.check_status_code(response, [httplib.OK])
         data = response.json()
         if data.get('loginStatus') != 'SUCCESS':
             raise exceptions.BetfairLoginError(response, data)
         self.session_token = data['sessionToken']

After the request the value is accessed via client.last_api_time which is updated on each invocation of the method. As long as you deal with the time after each invocation (which I am doing now) this seems to work.

jmcarp commented 9 years ago

I'm not sure how many users of the library are going to need timing information, so my preferred solution would be to implement this logic outside the library. I just pushed a change to the library such that you can create a betfair client with a custom requests session (in https://github.com/jmcarp/betfair.py/commit/af75f98218b379c4712d78687cf57a2001371029). What I would recommend is that you subclass requests.Session and pass your custom session instance to the betfair client. That way, you're only defining the logic once (in the send method of your Session subclass), and we don't need to change betfair.py.

import requests
import betfair

class CustomSession(requests.Session):
    def send(self, *args, **kwargs):
        response = super(CustomSession, self).send(*args, **kwargs)
        self.last_elapsed = response.elapsed
        return response

client = betfair.Betfair(..., session=CustomSession())
client.list_current_orders(...)
print(client.session.last_elapsed)

Does that make sense?

goetzk commented 9 years ago

As a long term fix that seems fair enough, and a more OO way of doing things. I haven't tried to rebase my changes onto the latest codebase (still on 0.1.3) so i will add this to my list of things to try when I finally do the change.

goetzk commented 9 years ago

I've tested this with git head and one bet fair.py method but it appears to have worked

$ python2.7 ./script.py all_events elapsed time 0:00:03.687835 result is [<betfair.models.MarketCatalogue object at 0x105a7edd0>, <betfair.models.MarketCatalogue object at 0x106818cd0>, <betfair.models.MarketCatalogue object at 0x106818d10>]