11
11
from datetime import datetime
12
12
from flask import request , jsonify , render_template , Flask
13
13
from flask_cors import CORS , cross_origin
14
- from apod .utility import parse_apod , get_concepts
14
+ from apod .utility import parse_apod , get_concepts
15
15
import logging
16
16
17
17
app = Flask (__name__ )
18
18
CORS (app )
19
19
20
20
LOG = logging .getLogger (__name__ )
21
21
logging .basicConfig (level = logging .DEBUG )
22
- #LOG.setLevel(logging.DEBUG)
22
+ # LOG.setLevel(logging.DEBUG)
23
23
24
24
# this should reflect both this service and the backing
25
25
# assorted libraries
26
- SERVICE_VERSION = 'v1'
27
- APOD_METHOD_NAME = 'apod'
26
+ SERVICE_VERSION = 'v1'
27
+ APOD_METHOD_NAME = 'apod'
28
28
ALLOWED_APOD_FIELDS = ['concept_tags' , 'date' , 'hd' ]
29
29
ALCHEMY_API_KEY = None
30
30
31
-
32
31
try :
33
32
with open ('alchemy_api.key' , 'r' ) as f :
34
33
ALCHEMY_API_KEY = f .read ()
35
34
except :
36
- LOG .info ("WARNING: NO alchemy_api.key found, concept_tagging is NOT supported" )
35
+ LOG .info ("WARNING: NO alchemy_api.key found, concept_tagging is NOT supported" )
37
36
38
- def _abort (code , msg , usage = True ):
39
37
38
+ def _abort (code , msg , usage = True ):
40
39
if (usage ):
41
- msg += " " + _usage ()+ "'"
40
+ msg += " " + _usage () + "'"
42
41
43
42
response = jsonify (service_version = SERVICE_VERSION , msg = msg , code = code )
44
43
response .status_code = code
45
44
LOG .debug (str (response ))
46
-
45
+
47
46
return response
48
47
48
+
49
49
def _usage (joinstr = "', '" , prestr = "'" ):
50
- return "Allowed request fields for " + APOD_METHOD_NAME + " method are " + prestr + joinstr .join (ALLOWED_APOD_FIELDS )
50
+ return "Allowed request fields for " + APOD_METHOD_NAME + " method are " + prestr + joinstr .join (
51
+ ALLOWED_APOD_FIELDS )
51
52
52
- def _validate (data ):
53
+
54
+ def _validate (data ):
53
55
LOG .debug ("_validate(data) called" )
54
56
for key in data :
55
57
if key not in ALLOWED_APOD_FIELDS :
56
58
return False
57
59
return True
58
60
59
- def _validate_date ( dt ):
60
-
61
+
62
+ def _validate_date ( dt ):
61
63
LOG .debug ("_validate_date(dt) called" )
62
64
today = datetime .today ()
63
- begin = datetime (1995 , 6 , 16 ) # first APOD image date
64
-
65
+ begin = datetime (1995 , 6 , 16 ) # first APOD image date
66
+
65
67
# validate input
66
68
if (dt > today ) or (dt < begin ):
67
-
68
69
today_str = today .strftime ('%b %d, %Y' )
69
70
begin_str = begin .strftime ('%b %d, %Y' )
70
-
71
+
71
72
raise ValueError ('Date must be between %s and %s.' % (begin_str , today_str ))
72
-
73
+
74
+
73
75
def _apod_handler (dt , use_concept_tags = False , use_default_today_date = False ):
74
76
"""Accepts a parameter dictionary. Returns the response object to be
75
77
served through the API."""
76
78
try :
77
79
page_props = parse_apod (dt , use_default_today_date )
78
80
LOG .debug ("managed to get apod page characteristics" )
79
-
81
+
80
82
if use_concept_tags :
81
83
if ALCHEMY_API_KEY == None :
82
84
page_props ['concepts' ] = "concept_tags functionality turned off in current service"
83
85
else :
84
86
page_props ['concepts' ] = get_concepts (request , page_props ['explanation' ], ALCHEMY_API_KEY )
85
-
86
- return page_props
87
-
87
+
88
+ return page_props
89
+
88
90
except Exception as e :
89
-
90
- LOG .error ("Internal Service Error :" + str (type (e ))+ " msg:" + str (e ))
91
+
92
+ LOG .error ("Internal Service Error :" + str (type (e )) + " msg:" + str (e ))
91
93
# return code 500 here
92
94
return _abort (500 , "Internal Service Error" , usage = False )
93
-
95
+
96
+
94
97
#
95
98
# Endpoints
96
99
#
97
100
98
101
@app .route ('/' )
99
102
def home ():
100
103
return render_template ('home.html' , version = SERVICE_VERSION , \
101
- service_url = request .host , \
102
- methodname = APOD_METHOD_NAME , \
103
- usage = _usage (joinstr = '", "' , prestr = '"' )+ '"' )
104
+ service_url = request .host , \
105
+ methodname = APOD_METHOD_NAME , \
106
+ usage = _usage (joinstr = '", "' , prestr = '"' ) + '"' )
104
107
105
- @app .route ('/' + SERVICE_VERSION + '/' + APOD_METHOD_NAME + '/' , methods = ['GET' ])
106
- def apod ():
107
108
109
+ @app .route ('/' + SERVICE_VERSION + '/' + APOD_METHOD_NAME + '/' , methods = ['GET' ])
110
+ def apod ():
108
111
LOG .info ("apod path called" )
109
112
try :
110
113
111
114
# application/json GET method
112
115
args = request .args
113
116
114
117
if not _validate (args ):
115
- return _abort (400 , "Bad Request incorrect field passed." )
116
-
118
+ return _abort (400 , "Bad Request incorrect field passed." )
119
+
117
120
# get the date param
118
121
use_default_today_date = False
119
122
date = args .get ('date' )
120
123
if not date :
121
124
# fall back to using today's date IF they didn't specify a date
122
125
date = datetime .strftime (datetime .today (), '%Y-%m-%d' )
123
126
use_default_today_date = True
124
-
127
+
125
128
# grab the concept_tags param
126
129
use_concept_tags = args .get ('concept_tags' , False )
127
-
130
+
128
131
# validate input date
129
132
dt = datetime .strptime (date , '%Y-%m-%d' )
130
133
_validate_date (dt )
131
-
134
+
132
135
# get data
133
136
data = _apod_handler (dt , use_concept_tags , use_default_today_date )
134
137
data ['date' ] = date
135
138
data ['service_version' ] = SERVICE_VERSION
136
-
139
+
137
140
# return info as JSON
138
141
return jsonify (data )
139
142
140
143
except ValueError as ve :
141
144
return _abort (400 , str (ve ), False )
142
-
145
+
143
146
except Exception as ex :
144
147
145
148
etype = type (ex )
146
149
if etype == ValueError or "BadRequest" in str (etype ):
147
- return _abort (400 , str (ex )+ "." )
150
+ return _abort (400 , str (ex ) + "." )
148
151
else :
149
- LOG .error ("Service Exception. Msg: " + str (type (ex )))
152
+ LOG .error ("Service Exception. Msg: " + str (type (ex )))
150
153
return _abort (500 , "Internal Service Error" , usage = False )
151
154
155
+
152
156
@app .errorhandler (404 )
153
157
def page_not_found (e ):
154
158
"""Return a custom 404 error."""
@@ -163,4 +167,3 @@ def application_error(e):
163
167
164
168
if __name__ == '__main__' :
165
169
app .run ()
166
-
0 commit comments