Repository: mwouts/world_bank_data

Issue:
Document how to use an http proxy
Cf. http://docs.python-requests.org/en/master/user/advanced/#proxies

Discussion:

Patch:
diff --git a/README.md b/README.md
index 631ddcc..933ff9c 100644
--- a/README.md
+++ b/README.md
@@ -146,6 +146,14 @@ wb.options.language = 'en'
 
 All requests, except `get_series`, are cached using a _least recently used_ cache from the `cachetools` package.
 
+## Using behind a proxy
+
+Using the package behind an http proxy is possible. Use either the `proxies` argument in the `get_*` functins, or set the proxy globally with e.g.:
+
+```python
+wb.options.proxies = {'http': 'http://example.com:3128'}
+```
+
 ## License
 
 This python package is licenced under the MIT License.
diff --git a/world_bank_data/options.py b/world_bank_data/options.py
index 367a545..5c902e7 100644
--- a/world_bank_data/options.py
+++ b/world_bank_data/options.py
@@ -2,3 +2,4 @@
 
 language = 'en'
 id_or_value = 'value'
+proxies = None
diff --git a/world_bank_data/request.py b/world_bank_data/request.py
index ed0011c..9eb6a8b 100644
--- a/world_bank_data/request.py
+++ b/world_bank_data/request.py
@@ -1,8 +1,9 @@
 """Request the world bank API"""
+import json
 from copy import copy
 from requests import get, HTTPError
 import pandas as pd
-from cachetools import cached, TTLCache
+from cachetools import cached, TTLCache, keys
 import world_bank_data.options as options
 
 WORLD_BANK_URL = 'http://api.worldbank.org/v2'
@@ -44,7 +45,8 @@ def extract_preferred_field(data, id_or_value):
 def wb_get(*args, **kwargs):
     """Request the World Bank for the desired information"""
     params = copy(kwargs)
-    language = params.pop('language') if 'language' in params else 'en'
+    language = params.pop('language', 'en')
+    proxies = params.pop('proxies', options.proxies)
     params.setdefault('format', 'json')
     params.setdefault('per_page', 20000)
 
@@ -61,7 +63,7 @@ def wb_get(*args, **kwargs):
 
     url = '/'.join([WORLD_BANK_URL] + args)
 
-    response = get(url=url, params=params)
+    response = get(url=url, params=params, proxies=proxies)
     response.raise_for_status()
     data = response.json()
     if isinstance(data, list) and data and 'message' in data[0]:
@@ -91,7 +93,13 @@ def wb_get(*args, **kwargs):
     return data
 
 
-@cached(TTLCache(128, 3600))
+def _robust_key(*args, **kwargs):
+    if 'proxies' in kwargs:
+        kwargs['proxies'] = json.dumps(kwargs['proxies'])
+    return keys.hashkey(*args, **kwargs)
+
+
+@cached(TTLCache(128, 3600), key=_robust_key)
 def _wb_get_table_cached(name, only=None, language=None, id_or_value=None, **params):
     if language:
         params['language'] = language


Test patch:
diff --git a/tests/test_proxies.py b/tests/test_proxies.py
new file mode 100644
index 0000000..a664c46
--- /dev/null
+++ b/tests/test_proxies.py
@@ -0,0 +1,25 @@
+import mock
+import pytest
+import requests
+from world_bank_data import get_countries
+
+
+def assert_proxy_arg_in_get(*args, **kwargs):
+    assert isinstance(kwargs.pop('proxies'), dict)
+    return requests.get(*args, **kwargs)
+
+
+@pytest.fixture
+def proxies():
+    return {'http': 'http://example.com:3128'}
+
+
+def test_proxy_as_arg(proxies):
+    with mock.patch('world_bank_data.request.get', assert_proxy_arg_in_get):
+        get_countries(proxies=proxies)
+
+
+def test_proxy_as_global_option(proxies):
+    with mock.patch('world_bank_data.options.proxies', proxies):
+        with mock.patch('world_bank_data.request.get', assert_proxy_arg_in_get):
+            get_countries()