13
13
AuthenticationError , ForbiddenError , InvalidRequestError ,
14
14
NotFoundError , ServiceUnavailableError )
15
15
16
-
17
- class Connection :
18
- @classmethod
19
- def request (cls , http_verb , url , ** options ):
20
- if 'headers' in options :
21
- headers = options ['headers' ]
16
+ def request (http_verb , url , ** options ):
17
+ if 'headers' in options :
18
+ headers = options ['headers' ]
19
+ else :
20
+ headers = {}
21
+
22
+ accept_value = 'application/json'
23
+ if ApiConfig .api_version :
24
+ accept_value += ", application/vnd.data.nasdaq+json;version=%s" % ApiConfig .api_version
25
+
26
+ headers = Util .merge_to_dicts ({'accept' : accept_value ,
27
+ 'request-source' : 'python' ,
28
+ 'request-source-version' : VERSION }, headers )
29
+ if ApiConfig .api_key :
30
+ headers = Util .merge_to_dicts ({'x-api-token' : ApiConfig .api_key }, headers )
31
+
32
+ options ['headers' ] = headers
33
+
34
+ abs_url = '%s/%s' % (ApiConfig .api_base , url )
35
+
36
+ return execute_request (http_verb , abs_url , ** options )
37
+
38
+ def execute_request (http_verb , url , ** options ):
39
+ session = get_session (url )
40
+
41
+ try :
42
+ response = session .request (method = http_verb ,
43
+ url = url ,
44
+ verify = ApiConfig .verify_ssl ,
45
+ ** options )
46
+ if response .status_code < 200 or response .status_code >= 300 :
47
+ handle_api_error (response )
22
48
else :
23
- headers = {}
24
-
25
- accept_value = 'application/json'
26
- if ApiConfig .api_version :
27
- accept_value += ", application/vnd.data.nasdaq+json;version=%s" % ApiConfig .api_version
28
-
29
- headers = Util .merge_to_dicts ({'accept' : accept_value ,
30
- 'request-source' : 'python' ,
31
- 'request-source-version' : VERSION }, headers )
32
- if ApiConfig .api_key :
33
- headers = Util .merge_to_dicts ({'x-api-token' : ApiConfig .api_key }, headers )
34
-
35
- options ['headers' ] = headers
36
-
37
- abs_url = '%s/%s' % (ApiConfig .api_base , url )
38
-
39
- return cls .execute_request (http_verb , abs_url , ** options )
40
-
41
- @classmethod
42
- def execute_request (cls , http_verb , url , ** options ):
43
- session = cls .get_session ()
44
-
45
- try :
46
- response = session .request (method = http_verb ,
47
- url = url ,
48
- verify = ApiConfig .verify_ssl ,
49
- ** options )
50
- if response .status_code < 200 or response .status_code >= 300 :
51
- cls .handle_api_error (response )
52
- else :
53
- return response
54
- except requests .exceptions .RequestException as e :
55
- if e .response :
56
- cls .handle_api_error (e .response )
57
- raise e
58
-
59
- @classmethod
60
- def get_session (cls ):
61
- session = requests .Session ()
62
- adapter = HTTPAdapter (max_retries = cls .get_retries ())
63
- session .mount (ApiConfig .api_protocol , adapter )
64
-
65
- return session
66
-
67
- @classmethod
68
- def get_retries (cls ):
69
- if not ApiConfig .use_retries :
70
- return Retry (total = 0 )
71
-
72
- Retry .BACKOFF_MAX = ApiConfig .max_wait_between_retries
73
- retries = Retry (total = ApiConfig .number_of_retries ,
74
- connect = ApiConfig .number_of_retries ,
75
- read = ApiConfig .number_of_retries ,
76
- status_forcelist = ApiConfig .retry_status_codes ,
77
- backoff_factor = ApiConfig .retry_backoff_factor ,
78
- raise_on_status = False )
79
-
80
- return retries
81
-
82
- @classmethod
83
- def parse (cls , response ):
84
- try :
85
- return response .json ()
86
- except ValueError :
87
- raise DataLinkError (http_status = response .status_code , http_body = response .text )
88
-
89
- @classmethod
90
- def handle_api_error (cls , resp ):
91
- error_body = cls .parse (resp )
92
-
93
- # if our app does not form a proper data_link_error response
94
- # throw generic error
95
- if 'error' not in error_body :
96
- raise DataLinkError (http_status = resp .status_code , http_body = resp .text )
97
-
98
- code = error_body ['error' ]['code' ]
99
- message = error_body ['error' ]['message' ]
100
- prog = re .compile ('^QE([a-zA-Z])x' )
101
- if prog .match (code ):
102
- code_letter = prog .match (code ).group (1 )
103
-
104
- d_klass = {
105
- 'L' : LimitExceededError ,
106
- 'M' : InternalServerError ,
107
- 'A' : AuthenticationError ,
108
- 'P' : ForbiddenError ,
109
- 'S' : InvalidRequestError ,
110
- 'C' : NotFoundError ,
111
- 'X' : ServiceUnavailableError
112
- }
113
- klass = d_klass .get (code_letter , DataLinkError )
114
-
115
- raise klass (message , resp .status_code , resp .text , resp .headers , code )
49
+ return response
50
+ except requests .exceptions .RequestException as e :
51
+ if e .response :
52
+ handle_api_error (e .response )
53
+ raise e
54
+
55
+ def get_retries ():
56
+ if not ApiConfig .use_retries :
57
+ return Retry (total = 0 )
58
+
59
+ Retry .BACKOFF_MAX = ApiConfig .max_wait_between_retries
60
+ retries = Retry (total = ApiConfig .number_of_retries ,
61
+ connect = ApiConfig .number_of_retries ,
62
+ read = ApiConfig .number_of_retries ,
63
+ status_forcelist = ApiConfig .retry_status_codes ,
64
+ backoff_factor = ApiConfig .retry_backoff_factor ,
65
+ raise_on_status = False )
66
+
67
+ return retries
68
+
69
+ session = requests .Session ()
70
+
71
+ def get_session (url = ApiConfig .api_protocol ):
72
+ adapter = HTTPAdapter (max_retries = get_retries ())
73
+ session .mount (url , adapter )
74
+ return session
75
+
76
+ def parse (response ):
77
+ try :
78
+ return response .json ()
79
+ except ValueError :
80
+ raise DataLinkError (http_status = response .status_code , http_body = response .text )
81
+
82
+
83
+
84
+ def handle_api_error (resp ):
85
+ error_body = parse (resp )
86
+
87
+ # if our app does not form a proper data_link_error response
88
+ # throw generic error
89
+ if 'error' not in error_body :
90
+ raise DataLinkError (http_status = resp .status_code , http_body = resp .text )
91
+
92
+ code = error_body ['error' ]['code' ]
93
+ message = error_body ['error' ]['message' ]
94
+ prog = re .compile ('^QE([a-zA-Z])x' )
95
+ if prog .match (code ):
96
+ code_letter = prog .match (code ).group (1 )
97
+
98
+ d_klass = {
99
+ 'L' : LimitExceededError ,
100
+ 'M' : InternalServerError ,
101
+ 'A' : AuthenticationError ,
102
+ 'P' : ForbiddenError ,
103
+ 'S' : InvalidRequestError ,
104
+ 'C' : NotFoundError ,
105
+ 'X' : ServiceUnavailableError
106
+ }
107
+ klass = d_klass .get (code_letter , DataLinkError )
108
+
109
+ raise klass (message , resp .status_code , resp .text , resp .headers , code )
0 commit comments