Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a timeout for API.request() #44

Open
Anjum48 opened this issue Feb 7, 2017 · 0 comments
Open

Add a timeout for API.request() #44

Anjum48 opened this issue Feb 7, 2017 · 0 comments

Comments

@Anjum48
Copy link

Anjum48 commented Feb 7, 2017

Would it be worthwhile adding a timeout for API.request()?

At the moment, the default of None is used meaning that if no response is received, the code will just hang, and you might get a message like this:
HTTPSConnectionPool(host='api-fxpractice.oanda.com', port=443): Read timed out. (read timeout=None)

Looking at the docs for requests, i'm not sure if the timeout can be set using the request_args, since timeout is a named argument (http://docs.python-requests.org/en/master/api/#requests.request). I tried passing the timeout in a dict inside the mixin methods like this params={"timeout": 0.001}, but that didn't seem to do anything - I might be wrong on this though.

One solution would be to add a timeout to the API class as follows, so that is is explicitly given to func(url, **request_args):

class API(EndpointsMixin, object):
    def __init__(self,
                 environment="practice", access_token=None, headers=None, timeout=10):
        """Instantiates an instance of OandaPy's API wrapper
        :param environment: (optional) Provide the environment for oanda's
         REST api, either 'sandbox', 'practice', or 'live'. Default: practice
        :param access_token: (optional) Provide a valid access token if you
         have one. This is required if the environment is not sandbox.
        """

        if environment == 'sandbox':
            self.api_url = 'http://api-sandbox.oanda.com'
        elif environment == 'practice':
            self.api_url = 'https://api-fxpractice.oanda.com'
        elif environment == 'live':
            self.api_url = 'https://api-fxtrade.oanda.com'
        else:
            raise BadEnvironment(environment)

        self.access_token = access_token
        self.client = requests.Session()
        self.timeout = timeout 

        # personal token authentication
        if self.access_token:
            self.client.headers['Authorization'] = 'Bearer '+self.access_token

        if headers:
            self.client.headers.update(headers)

    def request(self, endpoint, method='GET', params=None):
        """Returns dict of response from OANDA's open API
        :param endpoint: (required) OANDA API (e.g. v1/instruments)
        :type endpoint: string
        :param method: (optional) Method of accessing data, either GET or POST.
         (default GET)
        :type method: string
        :param params: (optional) Dict of parameters (if any) accepted the by
         OANDA API endpoint you are trying to access (default None)
        :type params: dict or None
        """

        url = '%s/%s' % (self.api_url, endpoint)

        method = method.lower()
        params = params or {}

        func = getattr(self.client, method)

        request_args = {}
        if method == 'get':
            request_args['params'] = params
        else:
            request_args['data'] = params

        try:
            response = func(url, self.timeout, **request_args)
            content = response.content.decode('utf-8')
        except requests.RequestException as e:
            print (str(e))
            content = dict(error=str(e))


        content = json.loads(content)

        # error message
        if response.status_code >= 400:
            raise OandaError(content)

        return content

This way, at least an exception will be raised preventing the code from hanging. I can set up a PR if required

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant