1
+ #!/usr/bin/env python
2
+ # -*- coding: utf-8 -*-
3
+ #
4
+ # metadata_db_server.py
5
+ #
6
+ # Copyright 2022 Giorgio Gilestro <giorgio@gilest.ro>
7
+ #
8
+ # This program is free software; you can redistribute it and/or modify
9
+ # it under the terms of the GNU General Public License as published by
10
+ # the Free Software Foundation; either version 2 of the License, or
11
+ # (at your option) any later version.
12
+ #
13
+ # This program is distributed in the hope that it will be useful,
14
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
+ # GNU General Public License for more details.
17
+ #
18
+ # You should have received a copy of the GNU General Public License
19
+ # along with this program; if not, write to the Free Software
20
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
21
+ # MA 02110-1301, USA.
22
+ #
23
+ #
24
+
25
+ import os
26
+ import logging
27
+ import optparse
28
+ import json
29
+ import bottle
30
+
31
+ from ast import literal_eval
32
+ from ethoscopy .metadata_db import db_organiser , metadata_handler , metadata_crawler
33
+
34
+ app = bottle .Bottle ()
35
+ STATIC_DIR = "./static"
36
+
37
+ @app .route ('/static/<filepath:path>' )
38
+ def server_static (filepath ):
39
+ return bottle .static_file (filepath , root = STATIC_DIR )
40
+
41
+ @app .route ('/' )
42
+ def index ():
43
+ return bottle .static_file ('index.html' , root = STATIC_DIR )
44
+
45
+ @app .route ('/save' , method = 'POST' )
46
+ def save ():
47
+
48
+ # text parameters that were received
49
+ #for k in bottle.request.forms.keys(): print (k, bottle.request.forms.get(k))
50
+
51
+ #file upload
52
+ allowed_extensions = ['.csv' , '.tsv' ]
53
+
54
+ upload = bottle .request .files .get ('file' )
55
+ if not upload :
56
+ return {'success' : False , 'message' : 'A metadata file was not specified.' }
57
+
58
+ name , ext = os .path .splitext (upload .filename )
59
+ if ext not in allowed_extensions :
60
+ return {'success' : False , 'message' : 'Extensions allowed are %s.' % " / " .join (allowed_extensions )}
61
+
62
+ try :
63
+ upload .save (meta_db .upload_folder , overwrite = True )
64
+
65
+ except Exception as e :
66
+ print (e )
67
+ return {'success' : False , 'message' : str (e )}
68
+
69
+ try :
70
+ #After saving, creates the info file
71
+ uploaded_metadata = metadata_handler ( filename = os .path .join (meta_db .upload_folder , upload .filename ),
72
+ project = bottle .request .forms .get ('project' ),
73
+ tags = literal_eval (bottle .request .forms .get ('tags' )),
74
+ authors = literal_eval (bottle .request .forms .get ('authors' )),
75
+ doi = bottle .request .forms .get ('doi' ),
76
+ description = bottle .request .forms .get ('description' )
77
+ )
78
+ uploaded_metadata .save ()
79
+
80
+ meta_db .refresh_all_info ()
81
+
82
+ return {'success' : True , 'message' : 'Metadata file successfully uploaded.' }
83
+
84
+ except Exception as e :
85
+ return {'success' : False , 'message' : str (e )}
86
+
87
+
88
+ @app .route ('/download' , method = 'GET' )
89
+ def download ():
90
+ hash_id = bottle .request .query .get ('id' , '' )
91
+ dwn_type = bottle .request .query .get ('type' , '' )
92
+ fullpath = meta_db .request (hash_id )['filename' ]
93
+ path , filename = os .path .split ( fullpath )
94
+
95
+ if dwn_type == 'metadata' :
96
+ return bottle .static_file (filename , root = path , download = filename )
97
+
98
+ elif dwn_type == 'db_found' :
99
+ md = metadata_handler (fullpath )
100
+ fn = os .path .splitext (filename )[0 ] + '.db_found.csv'
101
+ md .list_dbs (notfound = False ).to_csv (os .path .join ('/tmp/' , fn ))
102
+ return bottle .static_file (fn , root = '/tmp/' , download = fn )
103
+
104
+ elif dwn_type == 'db_notfound' :
105
+ md = metadata_handler (fullpath )
106
+ fn = os .path .splitext (filename )[0 ] + '.db_notfound.csv'
107
+ md .list_dbs (notfound = True ).to_csv (os .path .join ('/tmp/' , fn ))
108
+ return bottle .static_file (fn , root = '/tmp/' , download = fn )
109
+
110
+
111
+ @app .route ('/refresh' , method = 'GET' )
112
+ def refresh ():
113
+ hash_id = bottle .request .query .get ('id' , '' )
114
+ filename = meta_db .request (hash_id )['filename' ]
115
+ md = metadata_handler ( filename )
116
+ md .associate_to_db (etho_db )
117
+ md .save ()
118
+ return {'success' : True , 'message' : 'Metadata succefully associated.' }
119
+
120
+
121
+ @app .route ('/info_tree' , method = 'GET' )
122
+ def get_metadata_tree ():
123
+ return meta_db .all_projects
124
+
125
+
126
+ @app .route ('/metadata' , method = 'GET' )
127
+ def get_metadata ():
128
+ hash_id = bottle .request .query .get ('id' , '' )
129
+ return meta_db .request (hash_id )
130
+
131
+ @app .route ('/known' )
132
+ def available_options ():
133
+ return meta_db .available_options
134
+
135
+ def close (exit_status = 0 ):
136
+ logging .info ("Closing server" )
137
+ os ._exit (exit_status )
138
+
139
+
140
+ if __name__ == '__main__' :
141
+ logging .getLogger ().setLevel (logging .INFO )
142
+ parser = optparse .OptionParser ()
143
+ parser .add_option ("-d" , "--db_path" , dest = "db_path" , default = "/mnt/ethoscope_results" , help = "Path to the root of the ethoscope db files" )
144
+ parser .add_option ("-f" , "--db_file" , dest = "db_file" , default = "/opt/ethoscope_db" , help = "Path to the saved db file" )
145
+
146
+ parser .add_option ("-D" , "--debug" , dest = "debug" , default = False , help = "Set DEBUG mode ON" , action = "store_true" )
147
+ parser .add_option ("-p" , "--port" , dest = "port" , default = 8081 , help = "port" )
148
+
149
+ (options , args ) = parser .parse_args ()
150
+
151
+ option_dict = vars (options )
152
+ DB_PATH = option_dict ["db_path" ]
153
+ DB_FILE = option_dict ["db_file" ]
154
+
155
+ PORT = option_dict ["port" ]
156
+ DEBUG = option_dict ["debug" ]
157
+
158
+ if DEBUG :
159
+ logging .basicConfig ()
160
+ logging .getLogger ().setLevel (logging .DEBUG )
161
+ logging .info ("Logging using DEBUG SETTINGS" )
162
+
163
+
164
+ etho_db = db_organiser (DB_PATH , refresh = False )
165
+ meta_db = metadata_crawler ()
166
+
167
+ try :
168
+ app .run (host = '0.0.0.0' , port = PORT , debug = DEBUG )
169
+
170
+ except KeyboardInterrupt :
171
+ logging .info ("Stopping server cleanly" )
172
+ pass
173
+
174
+ except socket .error as e :
175
+ logging .error (traceback .format_exc ())
176
+ logging .error ("Port %i is probably not accessible for you. Maybe use another one e.g.`-p 8000`" % PORT )
177
+
178
+ except Exception as e :
179
+ logging .error (traceback .format_exc ())
0 commit comments