1
+ """
2
+ Miscellaneous utility functions
3
+ """
1
4
import time
5
+ import json
6
+ from pprint import pformat
2
7
3
8
import requests
4
9
5
- from src .config import (
6
- BASE_URL ,
7
- )
8
-
9
10
10
11
def elapsed_time_hms (start_time ):
11
12
"""
@@ -15,3 +16,72 @@ def elapsed_time_hms(start_time):
15
16
return time .strftime ('%H:%M:%S' , time .gmtime (elapsed ))
16
17
17
18
19
+ def send_request (method , * args , ignore_status_codes = None , ** kwargs ):
20
+ """Send http request. Raise exception on status_code >= 300
21
+
22
+ :param method: name of the requests method to call
23
+ :type method: str
24
+ :raises: requests.Exception.HTTPError
25
+ :returns: requests Response object
26
+ :rtype: requests.Response
27
+ """
28
+ if isinstance (ignore_status_codes , str ):
29
+ ignore_status_codes = [ignore_status_codes ]
30
+
31
+ # NOTE: Set timeout so requests don't hang
32
+ # See https://requests.readthedocs.io/en/latest/user/advanced/#timeouts
33
+ if not kwargs .get ("timeout" ):
34
+ # connect timeout, read timeout
35
+ kwargs ["timeout" ] = (3 , 60 )
36
+ else :
37
+ print (
38
+ f"⌚️ Applying user timeout: { kwargs ['timeout' ]} (connect, read)"
39
+ " seconds to request"
40
+ )
41
+
42
+ requests_op = getattr (requests , method .lower ())
43
+ status_code = 0
44
+ try :
45
+ resp = requests_op (* args , ** kwargs )
46
+ status_code = resp .status_code
47
+ resp .raise_for_status ()
48
+ except requests .exceptions .HTTPError as e :
49
+ if ignore_status_codes and (status_code in ignore_status_codes ):
50
+ pass
51
+ else :
52
+ body = ""
53
+ try :
54
+ body = pformat (resp .json ())
55
+ except :
56
+ body = resp .text
57
+
58
+ msg = (
59
+ f"❌ Problem sending { method } request to server\n "
60
+ f"{ str (e )} \n "
61
+ f"args: { args } \n "
62
+ f"kwargs: { pformat (kwargs )} \n "
63
+ f"{ body } \n "
64
+ )
65
+ print (msg )
66
+ raise e
67
+
68
+ return resp
69
+
70
+
71
+ def read_json (filepath , default = None ):
72
+ """
73
+ Read JSON file into Python dict. If default is not None and the file
74
+ does not exist, then return default.
75
+
76
+ :param filepath: path to JSON file
77
+ :type filepath: str
78
+ :param default: default return value if file not found, defaults to None
79
+ :type default: any, optional
80
+ :returns: your data
81
+ :rtype: dict
82
+ """
83
+ if (default is not None ) and (not os .path .isfile (filepath )):
84
+ return default
85
+
86
+ with open (filepath , "r" ) as json_file :
87
+ return json .load (json_file )
0 commit comments