We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
fixer.io currency exchange API has moved to subscription based queries -- breaks the app
http://api.fixer.io/ is down and has switched to a subscription based API.

![2018-06-05-115728_943x260_scrot](https://user-images.githubusercontent.com/1658405/40969237-a984b3a0-68b7-11e8-8c91-8b4e01873074.png)

![2018-06-05-115714_1183x809_scrot](https://user-images.githubusercontent.com/1658405/40969256-ba88ab3e-68b7-11e8-97cb-2660db68aa4b.png)

Switch to another free API service for now. In the future need to have a more reliable way of querying data that will try alternative services if one service fails.

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `rotkehlchen/utils.py`
Content:
```
1 #!/usr/bin/env python
2 import sys
3 import os
4 import json
5 import time
6 import datetime
7 import calendar
8 import operator
9 import requests
10 from functools import wraps
11 from collections import namedtuple
12 from rlp.sedes import big_endian_int
13 
14 from rotkehlchen.constants import ALL_REMOTES_TIMEOUT
15 from rotkehlchen.errors import RecoverableRequestError, RemoteError
16 from rotkehlchen.fval import FVal
17 
18 
19 def sfjson_loads(s):
20     """Exception safe json.loads()"""
21     try:
22         return rlk_jsonloads(s)
23     except json.decoder.JSONDecodeError:
24         return {}
25 
26 
27 def pretty_json_dumps(data):
28     return json.dumps(
29         data,
30         sort_keys=True,
31         indent=4,
32         separators=(',', ': '),
33         cls=RKLEncoder,
34     )
35 
36 
37 def ts_now():
38     return int(time.time())
39 
40 
41 def createTimeStamp(datestr, formatstr="%Y-%m-%d %H:%M:%S"):
42     return int(calendar.timegm(time.strptime(datestr, formatstr)))
43 
44 
45 def dateToTs(s):
46     return int(calendar.timegm(datetime.datetime.strptime(s, '%d/%m/%Y').timetuple()))
47 
48 
49 def tsToDate(ts, formatstr='%d/%m/%Y %H:%M:%S'):
50     return datetime.datetime.utcfromtimestamp(ts).strftime(formatstr)
51 
52 
53 def isclose(a, b, rel_tol=1e-09, abs_tol=0.0):
54     return abs(a - b) <= max(rel_tol * max(abs(a), abs(b)), abs_tol)
55 
56 
57 def add_entries(a, b):
58     return {
59         'amount': a['amount'] + b['amount'],
60         'usd_value': a['usd_value'] + b['usd_value']
61     }
62 
63 
64 ResultCache = namedtuple('ResultCache', ('result', 'timestamp'))
65 
66 
67 def cache_response_timewise(seconds=600):
68     """ This is a decorator for caching results of functions of objects.
69     The objects must adhere to the interface of having:
70         - A results_cache dictionary attribute
71         - A semaphore attribute named lock
72 
73     Objects adhering to this interface are all the exchanges and the rotkehlchen object.
74     """
75     def _cache_response_timewise(f):
76         @wraps(f)
77         def wrapper(wrappingobj, *args):
78             with wrappingobj.lock:
79                 now = ts_now()
80                 cache_miss = (
81                     f.__name__ not in wrappingobj.results_cache or
82                     now - wrappingobj.results_cache[f.__name__].timestamp > seconds
83                 )
84             if cache_miss:
85                 result = f(wrappingobj, *args)
86                 with wrappingobj.lock:
87                     wrappingobj.results_cache[f.__name__] = ResultCache(result, now)
88                 return result
89 
90             # else hit the cache
91             with wrappingobj.lock:
92                 return wrappingobj.results_cache[f.__name__].result
93 
94         return wrapper
95     return _cache_response_timewise
96 
97 
98 def query_fiat_pair(base, quote, timestamp=None):
99     if base == quote:
100         return FVal(1.0)
101 
102     if timestamp is None:
103         querystr = 'http://api.fixer.io/latest?base={}'.format(base)
104     else:
105         querystr = 'http://api.fixer.io/{}?base={}'.format(
106             tsToDate(timestamp, formatstr='%Y-%m-%d'), base
107         )
108 
109     resp = request_get(querystr)
110     try:
111         return FVal(resp['rates'][quote])
112     except ValueError:
113         raise ValueError('Could not find a "{}" price for "{}"'.format(base, quote))
114 
115 
116 def from_wei(wei_value):
117     return wei_value / FVal(10 ** 18)
118 
119 
120 def combine_dicts(a, b, op=operator.add):
121     new_dict = a.copy()
122     new_dict.update(b)
123     new_dict.update([(k, op(a[k], b[k])) for k in set(b) & set(a)])
124     return new_dict
125 
126 
127 def combine_stat_dicts(list_of_dicts):
128     if len(list_of_dicts) == 0:
129         return {}
130 
131     combined_dict = list_of_dicts[0]
132     for d in list_of_dicts[1:]:
133         combined_dict = combine_dicts(combined_dict, d, add_entries)
134 
135     return combined_dict
136 
137 
138 def dict_get_sumof(d, attribute, **args):
139     sum = 0
140     for key, value in d.items():
141         sum += value[attribute]
142     return sum
143 
144 
145 def get_pair_other(pair, this):
146     currencies = pair.split('_')
147     if len(currencies) != 2:
148         raise ValueError("Could not split {} pair".format(pair))
149     return currencies[0] if currencies[1] == this else currencies[1]
150 
151 
152 def get_pair_position(pair, position):
153     assert position == 'first' or position == 'second'
154     currencies = pair.split('_')
155     if len(currencies) != 2:
156         raise ValueError("Could not split {} pair".format(pair))
157     return currencies[0] if position == 'first' else currencies[1]
158 
159 
160 def merge_dicts(*dict_args):
161     """
162     Given any number of dicts, shallow copy and merge into a new dict,
163     precedence goes to key value pairs in latter dicts.
164     """
165     result = {}
166     for dictionary in dict_args:
167         result.update(dictionary)
168     return result
169 
170 
171 def retry_calls(times, location, method, function, *args):
172     tries = times
173     while True:
174         try:
175             result = function(*args)
176             return result
177         except (requests.exceptions.ConnectionError, RecoverableRequestError) as e:
178             if isinstance(e, RecoverableRequestError):
179                 time.sleep(5)
180 
181             tries -= 1
182             if tries == 0:
183                 raise RemoteError(
184                     "{} query for {} failed after {} tries. Reason: {}".format(
185                         location,
186                         method,
187                         times,
188                         e
189                     ))
190 
191 
192 def request_get(uri, timeout=ALL_REMOTES_TIMEOUT):
193     response = requests.get(uri)
194     if response.status_code != 200:
195         raise RemoteError('Get {} returned status code {}'.format(uri, response.status_code))
196 
197     try:
198         result = rlk_jsonloads(response.text)
199     except json.decoder.JSONDecodeError:
200         raise ValueError('{} returned malformed json'.format(uri))
201 
202     return result
203 
204 
205 def get_jsonfile_contents_or_empty_list(filepath):
206     if not os.path.isfile(filepath):
207         return list()
208 
209     with open(filepath, 'r') as infile:
210         try:
211             data = rlk_jsonloads(infile.read())
212         except json.decoder.JSONDecodeError:
213             data = list()
214 
215     return data
216 
217 
218 def get_jsonfile_contents_or_empty_dict(filepath):
219     if not os.path.isfile(filepath):
220         return dict()
221 
222     with open(filepath, 'r') as infile:
223         try:
224             data = rlk_jsonloads(infile.read())
225         except json.decoder.JSONDecodeError:
226             data = dict()
227 
228     return data
229 
230 
231 def convert_to_int(val, accept_only_exact=True):
232     """Try to convert to an int. Either from an FVal or a string. If it's a float
233     and it's not whole (like 42.0) and accept_only_exact is False then raise"""
234     if isinstance(val, FVal):
235         return val.to_int(accept_only_exact)
236     elif isinstance(val, (bytes, str)):
237         return int(val)
238     elif isinstance(val, int):
239         return val
240     elif isinstance(val, float):
241         if val.is_integer() or accept_only_exact is False:
242             return int(val)
243 
244     raise ValueError('Can not convert {} which is of type {} to int.'.format(val, type(val)))
245 
246 
247 def rkl_decode_value(val):
248     if isinstance(val, dict):
249         new_val = dict()
250         for k, v in val.items():
251             new_val[k] = rkl_decode_value(v)
252         return new_val
253     elif isinstance(val, list):
254         return [rkl_decode_value(x) for x in val]
255     elif isinstance(val, float):
256         return FVal(val)
257     elif isinstance(val, (bytes, str)):
258         try:
259             val = float(val)
260             return FVal(val)
261         except ValueError:
262             pass
263 
264     return val
265 
266 
267 class RKLDecoder(json.JSONDecoder):
268 
269     def __init__(self, *args, **kwargs):
270         json.JSONDecoder.__init__(self, object_hook=self.object_hook, *args, **kwargs)
271 
272     def object_hook(self, obj):
273         return rkl_decode_value(obj)
274 
275 
276 class RKLEncoder(json.JSONEncoder):
277     def default(self, obj):
278         if isinstance(obj, FVal):
279             return str(obj)
280         if isinstance(obj, float):
281             raise ValueError("Trying to json encode a float.")
282 
283         return json.JSONEncoder.default(self, obj)
284 
285 
286 def rlk_jsonloads(data):
287     return json.loads(data, cls=RKLDecoder)
288 
289 
290 def rlk_jsondumps(data):
291     return json.dumps(data, cls=RKLEncoder)
292 
293 
294 def taxable_gain_for_sell(
295         taxable_amount,
296         rate_in_profit_currency,
297         total_fee_in_profit_currency,
298         selling_amount):
299             return (
300                 rate_in_profit_currency * taxable_amount -
301                 total_fee_in_profit_currency * (taxable_amount / selling_amount)
302             )
303 
304 
305 def is_number(s):
306     try:
307         float(s)
308         return True
309     except ValueError:
310         return False
311 
312 
313 def int_to_big_endian(x):
314     return big_endian_int.serialize(x)
315 
316 
317 def get_system_spec():
318     """Collect information about the system and installation."""
319     import pkg_resources
320     import platform
321     import rotkehlchen
322 
323     if sys.platform == 'darwin':
324         system_info = 'macOS {} {}'.format(
325             platform.mac_ver()[0],
326             platform.architecture()[0]
327         )
328     else:
329         system_info = '{} {} {} {}'.format(
330             platform.system(),
331             '_'.join(platform.architecture()),
332             platform.release(),
333             platform.machine()
334         )
335 
336     system_spec = dict(
337         rotkehlchen=pkg_resources.require(rotkehlchen.__name__)[0].version,
338         python_implementation=platform.python_implementation(),
339         python_version=platform.python_version(),
340         system=system_info
341     )
342     return system_spec
343 
344 
345 def _process_entry(entry):
346     if isinstance(entry, FVal):
347         return str(entry)
348     elif isinstance(entry, list):
349         new_list = list()
350         for new_entry in entry:
351             new_list.append(_process_entry(new_entry))
352         return new_list
353     elif isinstance(entry, dict):
354         new_dict = dict()
355         for k, v in entry.items():
356             new_dict[k] = _process_entry(v)
357         return new_dict
358     elif isinstance(entry, tuple):
359         raise ValueError('Query results should not contain tuples')
360     else:
361         return entry
362 
363 
364 def process_result(result):
365     """Before sending out a result a dictionary via the server we are turning
366     all Decimals to strings so that the serialization to float/big number is handled
367     by the client application and we lose nothing in the transfer"""
368     return _process_entry(result)
369 
370 
371 def accounts_result(per_account, totals):
372     result = {
373         'result': True,
374         'message': '',
375         'per_account': per_account,
376         'totals': totals
377     }
378     return process_result(result)
379 
380 
381 def simple_result(v, msg):
382     return {'result': v, 'message': msg}
383
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/rotkehlchen/utils.py b/rotkehlchen/utils.py
--- a/rotkehlchen/utils.py
+++ b/rotkehlchen/utils.py
@@ -95,20 +95,15 @@
     return _cache_response_timewise
 
 
-def query_fiat_pair(base, quote, timestamp=None):
+def query_fiat_pair(base, quote):
     if base == quote:
         return FVal(1.0)
 
-    if timestamp is None:
-        querystr = 'http://api.fixer.io/latest?base={}'.format(base)
-    else:
-        querystr = 'http://api.fixer.io/{}?base={}'.format(
-            tsToDate(timestamp, formatstr='%Y-%m-%d'), base
-        )
-
+    pair = '{}_{}'.format(base, quote)
+    querystr = 'https://free.currencyconverterapi.com/api/v5/convert?q={}'.format(pair)
     resp = request_get(querystr)
     try:
-        return FVal(resp['rates'][quote])
+        return FVal(resp['results'][pair]['val'])
     except ValueError:
         raise ValueError('Could not find a "{}" price for "{}"'.format(base, quote))

{"golden_diff": "diff --git a/rotkehlchen/utils.py b/rotkehlchen/utils.py\n--- a/rotkehlchen/utils.py\n+++ b/rotkehlchen/utils.py\n@@ -95,20 +95,15 @@\n     return _cache_response_timewise\n \n \n-def query_fiat_pair(base, quote, timestamp=None):\n+def query_fiat_pair(base, quote):\n     if base == quote:\n         return FVal(1.0)\n \n-    if timestamp is None:\n-        querystr = 'http://api.fixer.io/latest?base={}'.format(base)\n-    else:\n-        querystr = 'http://api.fixer.io/{}?base={}'.format(\n-            tsToDate(timestamp, formatstr='%Y-%m-%d'), base\n-        )\n-\n+    pair = '{}_{}'.format(base, quote)\n+    querystr = 'https://free.currencyconverterapi.com/api/v5/convert?q={}'.format(pair)\n     resp = request_get(querystr)\n     try:\n-        return FVal(resp['rates'][quote])\n+        return FVal(resp['results'][pair]['val'])\n     except ValueError:\n         raise ValueError('Could not find a \"{}\" price for \"{}\"'.format(base, quote))\n", "issue": "fixer.io currency exchange API has moved to subscription based queries -- breaks the app\nhttp://api.fixer.io/ is down and has switched to a subscription based API.\r\n\r\n![2018-06-05-115728_943x260_scrot](https://user-images.githubusercontent.com/1658405/40969237-a984b3a0-68b7-11e8-8c91-8b4e01873074.png)\r\n\r\n![2018-06-05-115714_1183x809_scrot](https://user-images.githubusercontent.com/1658405/40969256-ba88ab3e-68b7-11e8-97cb-2660db68aa4b.png)\r\n\r\nSwitch to another free API service for now. In the future need to have a more reliable way of querying data that will try alternative services if one service fails.\n", "before_files": [{"content": "#!/usr/bin/env python\nimport sys\nimport os\nimport json\nimport time\nimport datetime\nimport calendar\nimport operator\nimport requests\nfrom functools import wraps\nfrom collections import namedtuple\nfrom rlp.sedes import big_endian_int\n\nfrom rotkehlchen.constants import ALL_REMOTES_TIMEOUT\nfrom rotkehlchen.errors import RecoverableRequestError, RemoteError\nfrom rotkehlchen.fval import FVal\n\n\ndef sfjson_loads(s):\n    \"\"\"Exception safe json.loads()\"\"\"\n    try:\n        return rlk_jsonloads(s)\n    except json.decoder.JSONDecodeError:\n        return {}\n\n\ndef pretty_json_dumps(data):\n    return json.dumps(\n        data,\n        sort_keys=True,\n        indent=4,\n        separators=(',', ': '),\n        cls=RKLEncoder,\n    )\n\n\ndef ts_now():\n    return int(time.time())\n\n\ndef createTimeStamp(datestr, formatstr=\"%Y-%m-%d %H:%M:%S\"):\n    return int(calendar.timegm(time.strptime(datestr, formatstr)))\n\n\ndef dateToTs(s):\n    return int(calendar.timegm(datetime.datetime.strptime(s, '%d/%m/%Y').timetuple()))\n\n\ndef tsToDate(ts, formatstr='%d/%m/%Y %H:%M:%S'):\n    return datetime.datetime.utcfromtimestamp(ts).strftime(formatstr)\n\n\ndef isclose(a, b, rel_tol=1e-09, abs_tol=0.0):\n    return abs(a - b) <= max(rel_tol * max(abs(a), abs(b)), abs_tol)\n\n\ndef add_entries(a, b):\n    return {\n        'amount': a['amount'] + b['amount'],\n        'usd_value': a['usd_value'] + b['usd_value']\n    }\n\n\nResultCache = namedtuple('ResultCache', ('result', 'timestamp'))\n\n\ndef cache_response_timewise(seconds=600):\n    \"\"\" This is a decorator for caching results of functions of objects.\n    The objects must adhere to the interface of having:\n        - A results_cache dictionary attribute\n        - A semaphore attribute named lock\n\n    Objects adhering to this interface are all the exchanges and the rotkehlchen object.\n    \"\"\"\n    def _cache_response_timewise(f):\n        @wraps(f)\n        def wrapper(wrappingobj, *args):\n            with wrappingobj.lock:\n                now = ts_now()\n                cache_miss = (\n                    f.__name__ not in wrappingobj.results_cache or\n                    now - wrappingobj.results_cache[f.__name__].timestamp > seconds\n                )\n            if cache_miss:\n                result = f(wrappingobj, *args)\n                with wrappingobj.lock:\n                    wrappingobj.results_cache[f.__name__] = ResultCache(result, now)\n                return result\n\n            # else hit the cache\n            with wrappingobj.lock:\n                return wrappingobj.results_cache[f.__name__].result\n\n        return wrapper\n    return _cache_response_timewise\n\n\ndef query_fiat_pair(base, quote, timestamp=None):\n    if base == quote:\n        return FVal(1.0)\n\n    if timestamp is None:\n        querystr = 'http://api.fixer.io/latest?base={}'.format(base)\n    else:\n        querystr = 'http://api.fixer.io/{}?base={}'.format(\n            tsToDate(timestamp, formatstr='%Y-%m-%d'), base\n        )\n\n    resp = request_get(querystr)\n    try:\n        return FVal(resp['rates'][quote])\n    except ValueError:\n        raise ValueError('Could not find a \"{}\" price for \"{}\"'.format(base, quote))\n\n\ndef from_wei(wei_value):\n    return wei_value / FVal(10 ** 18)\n\n\ndef combine_dicts(a, b, op=operator.add):\n    new_dict = a.copy()\n    new_dict.update(b)\n    new_dict.update([(k, op(a[k], b[k])) for k in set(b) & set(a)])\n    return new_dict\n\n\ndef combine_stat_dicts(list_of_dicts):\n    if len(list_of_dicts) == 0:\n        return {}\n\n    combined_dict = list_of_dicts[0]\n    for d in list_of_dicts[1:]:\n        combined_dict = combine_dicts(combined_dict, d, add_entries)\n\n    return combined_dict\n\n\ndef dict_get_sumof(d, attribute, **args):\n    sum = 0\n    for key, value in d.items():\n        sum += value[attribute]\n    return sum\n\n\ndef get_pair_other(pair, this):\n    currencies = pair.split('_')\n    if len(currencies) != 2:\n        raise ValueError(\"Could not split {} pair\".format(pair))\n    return currencies[0] if currencies[1] == this else currencies[1]\n\n\ndef get_pair_position(pair, position):\n    assert position == 'first' or position == 'second'\n    currencies = pair.split('_')\n    if len(currencies) != 2:\n        raise ValueError(\"Could not split {} pair\".format(pair))\n    return currencies[0] if position == 'first' else currencies[1]\n\n\ndef merge_dicts(*dict_args):\n    \"\"\"\n    Given any number of dicts, shallow copy and merge into a new dict,\n    precedence goes to key value pairs in latter dicts.\n    \"\"\"\n    result = {}\n    for dictionary in dict_args:\n        result.update(dictionary)\n    return result\n\n\ndef retry_calls(times, location, method, function, *args):\n    tries = times\n    while True:\n        try:\n            result = function(*args)\n            return result\n        except (requests.exceptions.ConnectionError, RecoverableRequestError) as e:\n            if isinstance(e, RecoverableRequestError):\n                time.sleep(5)\n\n            tries -= 1\n            if tries == 0:\n                raise RemoteError(\n                    \"{} query for {} failed after {} tries. Reason: {}\".format(\n                        location,\n                        method,\n                        times,\n                        e\n                    ))\n\n\ndef request_get(uri, timeout=ALL_REMOTES_TIMEOUT):\n    response = requests.get(uri)\n    if response.status_code != 200:\n        raise RemoteError('Get {} returned status code {}'.format(uri, response.status_code))\n\n    try:\n        result = rlk_jsonloads(response.text)\n    except json.decoder.JSONDecodeError:\n        raise ValueError('{} returned malformed json'.format(uri))\n\n    return result\n\n\ndef get_jsonfile_contents_or_empty_list(filepath):\n    if not os.path.isfile(filepath):\n        return list()\n\n    with open(filepath, 'r') as infile:\n        try:\n            data = rlk_jsonloads(infile.read())\n        except json.decoder.JSONDecodeError:\n            data = list()\n\n    return data\n\n\ndef get_jsonfile_contents_or_empty_dict(filepath):\n    if not os.path.isfile(filepath):\n        return dict()\n\n    with open(filepath, 'r') as infile:\n        try:\n            data = rlk_jsonloads(infile.read())\n        except json.decoder.JSONDecodeError:\n            data = dict()\n\n    return data\n\n\ndef convert_to_int(val, accept_only_exact=True):\n    \"\"\"Try to convert to an int. Either from an FVal or a string. If it's a float\n    and it's not whole (like 42.0) and accept_only_exact is False then raise\"\"\"\n    if isinstance(val, FVal):\n        return val.to_int(accept_only_exact)\n    elif isinstance(val, (bytes, str)):\n        return int(val)\n    elif isinstance(val, int):\n        return val\n    elif isinstance(val, float):\n        if val.is_integer() or accept_only_exact is False:\n            return int(val)\n\n    raise ValueError('Can not convert {} which is of type {} to int.'.format(val, type(val)))\n\n\ndef rkl_decode_value(val):\n    if isinstance(val, dict):\n        new_val = dict()\n        for k, v in val.items():\n            new_val[k] = rkl_decode_value(v)\n        return new_val\n    elif isinstance(val, list):\n        return [rkl_decode_value(x) for x in val]\n    elif isinstance(val, float):\n        return FVal(val)\n    elif isinstance(val, (bytes, str)):\n        try:\n            val = float(val)\n            return FVal(val)\n        except ValueError:\n            pass\n\n    return val\n\n\nclass RKLDecoder(json.JSONDecoder):\n\n    def __init__(self, *args, **kwargs):\n        json.JSONDecoder.__init__(self, object_hook=self.object_hook, *args, **kwargs)\n\n    def object_hook(self, obj):\n        return rkl_decode_value(obj)\n\n\nclass RKLEncoder(json.JSONEncoder):\n    def default(self, obj):\n        if isinstance(obj, FVal):\n            return str(obj)\n        if isinstance(obj, float):\n            raise ValueError(\"Trying to json encode a float.\")\n\n        return json.JSONEncoder.default(self, obj)\n\n\ndef rlk_jsonloads(data):\n    return json.loads(data, cls=RKLDecoder)\n\n\ndef rlk_jsondumps(data):\n    return json.dumps(data, cls=RKLEncoder)\n\n\ndef taxable_gain_for_sell(\n        taxable_amount,\n        rate_in_profit_currency,\n        total_fee_in_profit_currency,\n        selling_amount):\n            return (\n                rate_in_profit_currency * taxable_amount -\n                total_fee_in_profit_currency * (taxable_amount / selling_amount)\n            )\n\n\ndef is_number(s):\n    try:\n        float(s)\n        return True\n    except ValueError:\n        return False\n\n\ndef int_to_big_endian(x):\n    return big_endian_int.serialize(x)\n\n\ndef get_system_spec():\n    \"\"\"Collect information about the system and installation.\"\"\"\n    import pkg_resources\n    import platform\n    import rotkehlchen\n\n    if sys.platform == 'darwin':\n        system_info = 'macOS {} {}'.format(\n            platform.mac_ver()[0],\n            platform.architecture()[0]\n        )\n    else:\n        system_info = '{} {} {} {}'.format(\n            platform.system(),\n            '_'.join(platform.architecture()),\n            platform.release(),\n            platform.machine()\n        )\n\n    system_spec = dict(\n        rotkehlchen=pkg_resources.require(rotkehlchen.__name__)[0].version,\n        python_implementation=platform.python_implementation(),\n        python_version=platform.python_version(),\n        system=system_info\n    )\n    return system_spec\n\n\ndef _process_entry(entry):\n    if isinstance(entry, FVal):\n        return str(entry)\n    elif isinstance(entry, list):\n        new_list = list()\n        for new_entry in entry:\n            new_list.append(_process_entry(new_entry))\n        return new_list\n    elif isinstance(entry, dict):\n        new_dict = dict()\n        for k, v in entry.items():\n            new_dict[k] = _process_entry(v)\n        return new_dict\n    elif isinstance(entry, tuple):\n        raise ValueError('Query results should not contain tuples')\n    else:\n        return entry\n\n\ndef process_result(result):\n    \"\"\"Before sending out a result a dictionary via the server we are turning\n    all Decimals to strings so that the serialization to float/big number is handled\n    by the client application and we lose nothing in the transfer\"\"\"\n    return _process_entry(result)\n\n\ndef accounts_result(per_account, totals):\n    result = {\n        'result': True,\n        'message': '',\n        'per_account': per_account,\n        'totals': totals\n    }\n    return process_result(result)\n\n\ndef simple_result(v, msg):\n    return {'result': v, 'message': msg}\n", "path": "rotkehlchen/utils.py"}], "after_files": [{"content": "#!/usr/bin/env python\nimport sys\nimport os\nimport json\nimport time\nimport datetime\nimport calendar\nimport operator\nimport requests\nfrom functools import wraps\nfrom collections import namedtuple\nfrom rlp.sedes import big_endian_int\n\nfrom rotkehlchen.constants import ALL_REMOTES_TIMEOUT\nfrom rotkehlchen.errors import RecoverableRequestError, RemoteError\nfrom rotkehlchen.fval import FVal\n\n\ndef sfjson_loads(s):\n    \"\"\"Exception safe json.loads()\"\"\"\n    try:\n        return rlk_jsonloads(s)\n    except json.decoder.JSONDecodeError:\n        return {}\n\n\ndef pretty_json_dumps(data):\n    return json.dumps(\n        data,\n        sort_keys=True,\n        indent=4,\n        separators=(',', ': '),\n        cls=RKLEncoder,\n    )\n\n\ndef ts_now():\n    return int(time.time())\n\n\ndef createTimeStamp(datestr, formatstr=\"%Y-%m-%d %H:%M:%S\"):\n    return int(calendar.timegm(time.strptime(datestr, formatstr)))\n\n\ndef dateToTs(s):\n    return int(calendar.timegm(datetime.datetime.strptime(s, '%d/%m/%Y').timetuple()))\n\n\ndef tsToDate(ts, formatstr='%d/%m/%Y %H:%M:%S'):\n    return datetime.datetime.utcfromtimestamp(ts).strftime(formatstr)\n\n\ndef isclose(a, b, rel_tol=1e-09, abs_tol=0.0):\n    return abs(a - b) <= max(rel_tol * max(abs(a), abs(b)), abs_tol)\n\n\ndef add_entries(a, b):\n    return {\n        'amount': a['amount'] + b['amount'],\n        'usd_value': a['usd_value'] + b['usd_value']\n    }\n\n\nResultCache = namedtuple('ResultCache', ('result', 'timestamp'))\n\n\ndef cache_response_timewise(seconds=600):\n    \"\"\" This is a decorator for caching results of functions of objects.\n    The objects must adhere to the interface of having:\n        - A results_cache dictionary attribute\n        - A semaphore attribute named lock\n\n    Objects adhering to this interface are all the exchanges and the rotkehlchen object.\n    \"\"\"\n    def _cache_response_timewise(f):\n        @wraps(f)\n        def wrapper(wrappingobj, *args):\n            with wrappingobj.lock:\n                now = ts_now()\n                cache_miss = (\n                    f.__name__ not in wrappingobj.results_cache or\n                    now - wrappingobj.results_cache[f.__name__].timestamp > seconds\n                )\n            if cache_miss:\n                result = f(wrappingobj, *args)\n                with wrappingobj.lock:\n                    wrappingobj.results_cache[f.__name__] = ResultCache(result, now)\n                return result\n\n            # else hit the cache\n            with wrappingobj.lock:\n                return wrappingobj.results_cache[f.__name__].result\n\n        return wrapper\n    return _cache_response_timewise\n\n\ndef query_fiat_pair(base, quote):\n    if base == quote:\n        return FVal(1.0)\n\n    pair = '{}_{}'.format(base, quote)\n    querystr = 'https://free.currencyconverterapi.com/api/v5/convert?q={}'.format(pair)\n    resp = request_get(querystr)\n    try:\n        return FVal(resp['results'][pair]['val'])\n    except ValueError:\n        raise ValueError('Could not find a \"{}\" price for \"{}\"'.format(base, quote))\n\n\ndef from_wei(wei_value):\n    return wei_value / FVal(10 ** 18)\n\n\ndef combine_dicts(a, b, op=operator.add):\n    new_dict = a.copy()\n    new_dict.update(b)\n    new_dict.update([(k, op(a[k], b[k])) for k in set(b) & set(a)])\n    return new_dict\n\n\ndef combine_stat_dicts(list_of_dicts):\n    if len(list_of_dicts) == 0:\n        return {}\n\n    combined_dict = list_of_dicts[0]\n    for d in list_of_dicts[1:]:\n        combined_dict = combine_dicts(combined_dict, d, add_entries)\n\n    return combined_dict\n\n\ndef dict_get_sumof(d, attribute, **args):\n    sum = 0\n    for key, value in d.items():\n        sum += value[attribute]\n    return sum\n\n\ndef get_pair_other(pair, this):\n    currencies = pair.split('_')\n    if len(currencies) != 2:\n        raise ValueError(\"Could not split {} pair\".format(pair))\n    return currencies[0] if currencies[1] == this else currencies[1]\n\n\ndef get_pair_position(pair, position):\n    assert position == 'first' or position == 'second'\n    currencies = pair.split('_')\n    if len(currencies) != 2:\n        raise ValueError(\"Could not split {} pair\".format(pair))\n    return currencies[0] if position == 'first' else currencies[1]\n\n\ndef merge_dicts(*dict_args):\n    \"\"\"\n    Given any number of dicts, shallow copy and merge into a new dict,\n    precedence goes to key value pairs in latter dicts.\n    \"\"\"\n    result = {}\n    for dictionary in dict_args:\n        result.update(dictionary)\n    return result\n\n\ndef retry_calls(times, location, method, function, *args):\n    tries = times\n    while True:\n        try:\n            result = function(*args)\n            return result\n        except (requests.exceptions.ConnectionError, RecoverableRequestError) as e:\n            if isinstance(e, RecoverableRequestError):\n                time.sleep(5)\n\n            tries -= 1\n            if tries == 0:\n                raise RemoteError(\n                    \"{} query for {} failed after {} tries. Reason: {}\".format(\n                        location,\n                        method,\n                        times,\n                        e\n                    ))\n\n\ndef request_get(uri, timeout=ALL_REMOTES_TIMEOUT):\n    response = requests.get(uri)\n    if response.status_code != 200:\n        raise RemoteError('Get {} returned status code {}'.format(uri, response.status_code))\n\n    try:\n        result = rlk_jsonloads(response.text)\n    except json.decoder.JSONDecodeError:\n        raise ValueError('{} returned malformed json'.format(uri))\n\n    return result\n\n\ndef get_jsonfile_contents_or_empty_list(filepath):\n    if not os.path.isfile(filepath):\n        return list()\n\n    with open(filepath, 'r') as infile:\n        try:\n            data = rlk_jsonloads(infile.read())\n        except json.decoder.JSONDecodeError:\n            data = list()\n\n    return data\n\n\ndef get_jsonfile_contents_or_empty_dict(filepath):\n    if not os.path.isfile(filepath):\n        return dict()\n\n    with open(filepath, 'r') as infile:\n        try:\n            data = rlk_jsonloads(infile.read())\n        except json.decoder.JSONDecodeError:\n            data = dict()\n\n    return data\n\n\ndef convert_to_int(val, accept_only_exact=True):\n    \"\"\"Try to convert to an int. Either from an FVal or a string. If it's a float\n    and it's not whole (like 42.0) and accept_only_exact is False then raise\"\"\"\n    if isinstance(val, FVal):\n        return val.to_int(accept_only_exact)\n    elif isinstance(val, (bytes, str)):\n        return int(val)\n    elif isinstance(val, int):\n        return val\n    elif isinstance(val, float):\n        if val.is_integer() or accept_only_exact is False:\n            return int(val)\n\n    raise ValueError('Can not convert {} which is of type {} to int.'.format(val, type(val)))\n\n\ndef rkl_decode_value(val):\n    if isinstance(val, dict):\n        new_val = dict()\n        for k, v in val.items():\n            new_val[k] = rkl_decode_value(v)\n        return new_val\n    elif isinstance(val, list):\n        return [rkl_decode_value(x) for x in val]\n    elif isinstance(val, float):\n        return FVal(val)\n    elif isinstance(val, (bytes, str)):\n        try:\n            val = float(val)\n            return FVal(val)\n        except ValueError:\n            pass\n\n    return val\n\n\nclass RKLDecoder(json.JSONDecoder):\n\n    def __init__(self, *args, **kwargs):\n        json.JSONDecoder.__init__(self, object_hook=self.object_hook, *args, **kwargs)\n\n    def object_hook(self, obj):\n        return rkl_decode_value(obj)\n\n\nclass RKLEncoder(json.JSONEncoder):\n    def default(self, obj):\n        if isinstance(obj, FVal):\n            return str(obj)\n        if isinstance(obj, float):\n            raise ValueError(\"Trying to json encode a float.\")\n\n        return json.JSONEncoder.default(self, obj)\n\n\ndef rlk_jsonloads(data):\n    return json.loads(data, cls=RKLDecoder)\n\n\ndef rlk_jsondumps(data):\n    return json.dumps(data, cls=RKLEncoder)\n\n\ndef taxable_gain_for_sell(\n        taxable_amount,\n        rate_in_profit_currency,\n        total_fee_in_profit_currency,\n        selling_amount):\n            return (\n                rate_in_profit_currency * taxable_amount -\n                total_fee_in_profit_currency * (taxable_amount / selling_amount)\n            )\n\n\ndef is_number(s):\n    try:\n        float(s)\n        return True\n    except ValueError:\n        return False\n\n\ndef int_to_big_endian(x):\n    return big_endian_int.serialize(x)\n\n\ndef get_system_spec():\n    \"\"\"Collect information about the system and installation.\"\"\"\n    import pkg_resources\n    import platform\n    import rotkehlchen\n\n    if sys.platform == 'darwin':\n        system_info = 'macOS {} {}'.format(\n            platform.mac_ver()[0],\n            platform.architecture()[0]\n        )\n    else:\n        system_info = '{} {} {} {}'.format(\n            platform.system(),\n            '_'.join(platform.architecture()),\n            platform.release(),\n            platform.machine()\n        )\n\n    system_spec = dict(\n        rotkehlchen=pkg_resources.require(rotkehlchen.__name__)[0].version,\n        python_implementation=platform.python_implementation(),\n        python_version=platform.python_version(),\n        system=system_info\n    )\n    return system_spec\n\n\ndef _process_entry(entry):\n    if isinstance(entry, FVal):\n        return str(entry)\n    elif isinstance(entry, list):\n        new_list = list()\n        for new_entry in entry:\n            new_list.append(_process_entry(new_entry))\n        return new_list\n    elif isinstance(entry, dict):\n        new_dict = dict()\n        for k, v in entry.items():\n            new_dict[k] = _process_entry(v)\n        return new_dict\n    elif isinstance(entry, tuple):\n        raise ValueError('Query results should not contain tuples')\n    else:\n        return entry\n\n\ndef process_result(result):\n    \"\"\"Before sending out a result a dictionary via the server we are turning\n    all Decimals to strings so that the serialization to float/big number is handled\n    by the client application and we lose nothing in the transfer\"\"\"\n    return _process_entry(result)\n\n\ndef accounts_result(per_account, totals):\n    result = {\n        'result': True,\n        'message': '',\n        'per_account': per_account,\n        'totals': totals\n    }\n    return process_result(result)\n\n\ndef simple_result(v, msg):\n    return {'result': v, 'message': msg}\n", "path": "rotkehlchen/utils.py"}]}