comparison data_manager/bakta_build_database.py @ 1:faae5d8ce0cb draft

planemo upload for repository https://github.com/galaxyproject/tools-iuc/tree/master/data_managers/data_manager_bakta commit 4c11a77fb4c0bb74c0c4ae381c85971e01ed973e-dirty
author pimarin
date Thu, 27 Oct 2022 13:54:13 +0000
parents 9d08486abf8e
children 9c65e5da43e2
comparison
equal deleted inserted replaced
0:9d08486abf8e 1:faae5d8ce0cb
1 import argparse
1 import hashlib 2 import hashlib
2 import json 3 import json
3 import logging
4 import os 4 import os
5 import shutil
6 import subprocess as sp 5 import subprocess as sp
7 import stat
8 import sys 6 import sys
9 import tarfile 7 import tarfile
10 8 from datetime import datetime
11 from pathlib import Path 9 from pathlib import Path
12 10
13 from alive_progress import alive_bar
14 import requests
15
16 import bakta
17 import bakta.config as cfg
18 import bakta.constants as bc 11 import bakta.constants as bc
19 import bakta.utils as bu 12 import bakta.utils as bu
20 13 import requests
21 14 from alive_progress import alive_bar
22 log = logging.getLogger('DB') 15
23 16
24 17 class GetBaktaDatabaseInfo:
25 FILE_NAMES = [ 18 """
26 'antifam.h3f', 19 Extract bakta database information to make a json file for data_manager
27 'antifam.h3i', 20 """
28 'antifam.h3m', 21
29 'antifam.h3p', 22 def __init__(self,
30 'bakta.db', 23 data_table_name="bakta_database",
31 'expert-protein-sequences.dmnd', 24 db_name=Path.cwd().joinpath("db"),
32 'ncRNA-genes.i1f', 25 db_version="latest"):
33 'ncRNA-genes.i1i', 26 self.bakta_table_list = None
34 'ncRNA-genes.i1m', 27 self.db_url = None
35 'ncRNA-genes.i1p', 28 self.data_table_entry = None
36 'ncRNA-regions.i1f', 29 self.data_table_name = data_table_name
37 'ncRNA-regions.i1i', 30 self.db_name = db_name
38 'ncRNA-regions.i1m', 31 self.db_version = db_version
39 'ncRNA-regions.i1p', 32
40 'oric.fna', 33 def get_data_table_format(self):
41 'orit.fna', 34 """
42 'pfam.h3f', 35 Build a data table format for galaxy
43 'pfam.h3i', 36 using the bakta database information
44 'pfam.h3m', 37 @str database_value: string of the database name
45 'pfam.h3p', 38 @str database_date: string of the database date of build (YY-M-D)
46 'psc.dmnd', 39 @str database_bakta_version: string of the version of bakta tool
47 'rfam-go.tsv', 40 to apply a filter on version compatibility
48 'rRNA.i1f', 41 @str database_path: string of the database path
49 'rRNA.i1i', 42 for the database location
50 'rRNA.i1m', 43 return: a data table formatted for json output
51 'rRNA.i1p', 44 """
52 'sorf.dmnd' 45 self.data_table_entry = {
53 ] 46 "data_tables": {
54 47 self.data_table_name: {}
55 48 }
56 def check(db_path: Path) -> dict: 49 }
57 """Check if database directory exists, is accessible and contains necessary files.""" 50 return self.data_table_entry
58 51
59 if(db_path is None): 52 def fetch_db_versions(self, db_version="latest"):
60 log.error('directory neither provided nor detected!') 53 """
61 sys.exit('ERROR: database directory not provided nor detected! Please provide a valid path to the database directory.') 54 Use method from bakta tool to extract database info
62 55 db_version: a string of the version number
63 if(not os.access(str(db_path), os.R_OK & os.X_OK)): 56 in the galaxy wrapper list or just latest
64 log.error('directory (%s) not readable/accessible!', db_path) 57 return: info for the select or the latest bakta db version
65 sys.exit(f'ERROR: database directory ({db_path}) not readable/accessible!') 58 """
66 59 try:
67 version_path = db_path.joinpath('version.json') 60 with requests.get(bc.DB_VERSIONS_URL) as resp:
68 if(not os.access(str(version_path), os.R_OK) or not version_path.is_file()): 61 versions = json.loads(resp.content)
69 log.error('version file not readable!') 62 except IOError as e:
70 sys.exit('ERROR: database version file (version.json) not readable!') 63 print(e, file=sys.stderr)
71 64 raise e
72 try: 65 else:
73 with version_path.open() as fh: 66 if db_version == "latest":
74 db_info = json.load(fh) 67 db_date_list = []
75 except: 68 for db_dic in versions:
76 log.exception('could not parse database version file!') 69 db_date_list.append(datetime.strptime(db_dic["date"],
77 sys.exit('ERROR: could not parse database version file!') 70 '%Y-%m-%d').date())
78 71 max(db_date_list)
79 for key in ['date', 'major', 'minor']: 72 filtered_version = next(item for item in versions
80 if(key not in db_info): 73 if max(db_date_list))
81 log.error('wrong db version info file content! missed key=%s', key) 74 elif db_version == "test":
82 sys.exit(f"ERROR: wrong db version info file format! Missed key '{key}' in JSON structure.") 75 filtered_version = {"date": "date_test",
83 76 "major": "0",
84 log.info('detected: major=%i, minor=%i, date=%s', db_info['major'], db_info['minor'], db_info['date']) 77 "minor": "0",
85 if(db_info['major'] < bakta.__db_schema_version__): 78 "doi": "10.5281/zenodo.7197299",
86 log.error('wrong database version detected! required=%i, detected=%i', bakta.__db_schema_version__, db_info['major']) 79 "record": "7197299",
87 sys.exit(f"ERROR: wrong database version detected!\nBakta version {bakta.__version__} requires database version {bakta.__db_schema_version__}.x, but {db_info['major']}.{db_info['minor']} was detected. Please, update the database from https://doi.org/10.5281/zenodo.4247253") 80 "md5": "8b0250c17078742fc12207d4efb0fc1a",
88 elif(db_info['major'] > bakta.__db_schema_version__): 81 "software-min": {"major": "0",
89 log.error('wrong database version detected! required=%i, detected=%i', bakta.__db_schema_version__, db_info['major']) 82 "minor": "0"}
90 sys.exit(f"ERROR: wrong database version detected!\nBakta version {bakta.__version__} requires database version {bakta.__db_schema_version__}.x, but {db_info['major']}.{db_info['minor']} was detected. Please, update Bakta or download a compatible database version from https://doi.org/10.5281/zenodo.4247253") 83 }
91
92 for file_name in FILE_NAMES:
93 path = db_path.joinpath(file_name)
94 if(not os.access(str(path), os.R_OK) or not path.is_file()):
95 log.error('file not readable! file=%s', file_name)
96 sys.exit(f'ERROR: database file ({file_name}) not readable!')
97
98 return db_info
99
100
101 def fetch_db_versions():
102 try:
103 with requests.get(bc.DB_VERSIONS_URL) as resp:
104 versions = json.loads(resp.content)
105 except IOError as e:
106 print(e, file=sys.stderr)
107 raise e
108 else:
109 return versions
110
111
112 def download(db_url: str, tarball_path: Path):
113 try:
114 with tarball_path.open('wb') as fh_out, requests.get(db_url, stream=True) as resp:
115 total_length = resp.headers.get('content-length')
116 if(total_length is None): # no content length header
117 with alive_bar() as bar:
118 for data in resp.iter_content(chunk_size=1024*1024):
119 fh_out.write(data)
120 bar()
121 else: 84 else:
122 total_length = int(int(total_length)/1024) # length in Kb 85 major_version = str(db_version.split(sep=".")[0])
123 with alive_bar(total=total_length) as bar: 86 minor_version = str(db_version.split(sep=".")[1])
124 for data in resp.iter_content(chunk_size=1024*1024): 87 try:
125 fh_out.write(data) 88 filtered_version = next(
126 bar(incr=len(data)/1024) 89 item for item in versions
127 except IOError: 90 if str(item["major"]) == major_version
128 sys.exit(f'ERROR: Could not download file from Zenodo! url={db_url}, path={tarball_path}') 91 and str(item["minor"]) == minor_version)
129 92 except StopIteration:
130 93 print("No available version detected in the list")
131 def calc_md5_sum(tarball_path: Path, buffer_size: int=1024*1024) -> str: 94 filtered_version = None
132 md5 = hashlib.md5() 95 if filtered_version is not None:
133 with tarball_path.open('rb') as fh: 96 self.db_url = f"https://zenodo.org/record/" \
134 data = fh.read(buffer_size) 97 f"{filtered_version['record']}/files/db.tar.gz"
135 while data: 98 self.db_version = db_version
136 md5.update(data) 99 return filtered_version
100
101 def get_data_manager(self, bakta_database_info, output_path):
102 self.bakta_table_list = self.get_data_table_format()
103 bakta_value = f"bakta_{bakta_database_info['major']}." \
104 f"{bakta_database_info['minor']}"
105 data_info = dict(value=bakta_value,
106 dbkey=bakta_database_info['date'],
107 database_record=bakta_database_info['record'],
108 bakta_version=str(
109 f"{bakta_database_info['software-min']['major']}."
110 f"{bakta_database_info['software-min']['minor']}"
111 ), path=output_path)
112 self.bakta_table_list["data_tables"][self.data_table_name] = data_info
113 return self.bakta_table_list
114
115
116 class InstallBaktaDatabase(GetBaktaDatabaseInfo):
117 """
118 Download the bakta database,
119 check md5 sum,
120 untar the download db and update for the amrfinderplus database
121 """
122
123 def __init__(self,
124 db_dir=Path.cwd(),
125 db_name="bakta",
126 tarball_name="db.tar.gz"):
127 super().__init__()
128 self.md5 = None
129 self.db_dir = db_dir
130 self.db_name = db_name
131 self.tarball_name = tarball_name
132 self.tarball_path = None
133 bu.test_dependency(bu.DEPENDENCY_AMRFINDERPLUS)
134
135 def download(self):
136 self.db_name = f'{self.db_name}_{self.db_version}'
137 bakta_path = Path(self.db_dir).joinpath(self.tarball_name)
138 try:
139 with bakta_path.open('wb') as fh_out, \
140 requests.get(self.db_url, stream=True) as resp:
141 total_length = resp.headers.get('content-length')
142 if total_length is None: # no content length header
143 with alive_bar() as bar:
144 for data in resp.iter_content(chunk_size=1024 * 1024):
145 fh_out.write(data)
146 bar()
147 else:
148 total_length = int(int(total_length) / 1024)
149 with alive_bar(total=total_length) as bar:
150 for data in resp.iter_content(chunk_size=1024 * 1024):
151 fh_out.write(data)
152 bar(incr=len(data) / 1024)
153 print(f'Download bakta database {self.db_version}')
154 self.tarball_path = bakta_path
155 except IOError:
156 print(f'ERROR: Could not download file from Zenodo!'
157 f' url={self.db_url}, path={self.tarball_name}')
158
159 def untar(self):
160 db_path = Path(self.db_dir).joinpath(self.db_name)
161 try:
162 with self.tarball_path.open('rb') as fh_in, \
163 tarfile.open(fileobj=fh_in, mode='r:gz') as tar_file:
164 tar_file.extractall(path=str(db_path))
165 print(f'Untar the database in {db_path}')
166 return db_path.as_posix()
167 except OSError:
168 sys.exit(f'ERROR: Could not extract {self.tarball_name} '
169 f'to {self.db_name}')
170
171 def calc_md5_sum(self, buffer_size=1048576):
172 tarball_path = Path(self.db_dir).joinpath(self.tarball_name)
173 self.md5 = self.fetch_db_versions(db_version=self.db_version)["md5"]
174 md5 = hashlib.md5()
175 with tarball_path.open('rb') as fh:
137 data = fh.read(buffer_size) 176 data = fh.read(buffer_size)
138 return md5.hexdigest() 177 while data:
139 178 md5.update(data)
140 179 data = fh.read(buffer_size)
141 def untar(tarball_path: Path, output_path: Path): 180 if md5.hexdigest() == self.md5:
142 try: 181 print('\t...md5 control database OK')
143 with tarball_path.open('rb') as fh_in, tarfile.open(fileobj=fh_in, mode='r:gz') as tar_file: 182 else:
144 tar_file.extractall(path=str(output_path)) 183 print(f"Error: corrupt database file! "
145 except OSError: 184 f"calculated md5 = {md5.hexdigest()}"
146 sys.exit(f'ERROR: Could not extract {tarball_path} to {output_path}') 185 f" different from {self.md5} ")
186
187 def update_amrfinderplus_db(self):
188 amrfinderplus_db_path = f"{self.db_dir}/{self.db_name}/db/amrfinderplus-db"
189 if self.db_version == "test":
190 cmd = [
191 'amrfinder_update',
192 '--database', str(amrfinderplus_db_path),
193 '--force_update',
194 '--help'
195 ]
196 else:
197 cmd = [
198 'amrfinder_update',
199 '--database', str(amrfinderplus_db_path),
200 '--force_update'
201 ]
202 proc = sp.run(
203 cmd,
204 universal_newlines=True
205 )
206 if proc.returncode != 0:
207 print(f"ERROR: AMRFinderPlus failed! "
208 f"command: 'amrfinder_update --force_update"
209 f" --database {amrfinderplus_db_path}'")
210 else:
211 print("AMRFinderPlus database download")
212
213
214 def parse_arguments():
215 # parse options and arguments
216 arg_parser = argparse.ArgumentParser()
217 arg_parser.add_argument("data_manager_json")
218 arg_parser.add_argument("-d", "--database_version",
219 help='Select the database version '
220 '(major and minor eg. 4.0),'
221 'default is the latest version',
222 default="latest",
223 required=True)
224 return arg_parser.parse_args()
147 225
148 226
149 def main(): 227 def main():
150 # parse options and arguments 228 all_args = parse_arguments()
151 parser = bu.init_parser(sub_command='_db') 229
152 group_runtime = parser.add_argument_group('Runtime & auxiliary options') 230 with open(all_args.data_manager_json) as fh:
153 group_runtime.add_argument('--help', '-h', action='help', help='Show this help message and exit') 231 data_manager_input = json.load(fh)
154 group_runtime.add_argument('--version', '-V', action='version', version=f'%(prog)s {bakta.__version__}') 232
155 233 target_dir = data_manager_input['output_data'][0]['extra_files_path']
156 subparsers = parser.add_subparsers(dest='subcommand', help='sub-command help') 234 os.makedirs(target_dir)
157 parser_list = subparsers.add_parser('list', help='List available database versions') # add list sub-command options 235
158 parser_list.add_argument('--all', action='store_true', help='Show all versions including incompatible') 236 # init the class to download bakta db
159 237 bakta_upload = InstallBaktaDatabase()
160 parser_download = subparsers.add_parser('download', help='Download a database') # add download sub-command options 238 # extract the version
161 parser_download.add_argument('--output', '-o', action='store', default=Path.cwd(), help='output directory (default = current working directory)') 239 bakta_db = bakta_upload.fetch_db_versions(
162 parser_download.add_argument('--minor', '-n', action='store', type=int, default=0, help='Database minor version (default = most recent db minor version)') 240 db_version=all_args.database_version)
163 241 # update the path for galaxy
164 parser_update = subparsers.add_parser('update', help='Update an existing database to the most recent compatible version') # add download sub-command options 242 bakta_upload.db_dir = target_dir
165 parser_update.add_argument('--db', '-d', action='store', default=None, help='Current database path (default = <bakta_path>/db). Can also be provided as BAKTA_DB environment variable.') 243 # download the database
166 parser_update.add_argument('--tmp-dir', '-t', action='store', dest='tmp_dir', default=Path.cwd(), help='Temporary directory to download & extract (default = current working directory)') 244 bakta_upload.download()
167 245 # check md5 sum
168 args = parser.parse_args() 246 bakta_upload.calc_md5_sum()
169 if(args.subcommand == 'list'): 247 # untar db
170 print(f'Required database schema version: {bakta.__db_schema_version__}\n') 248 bakta_extracted_path = bakta_upload.untar()
171 versions = fetch_db_versions() 249 # update for amrfinderplus
172 if(not args.all): 250 bakta_upload.update_amrfinderplus_db()
173 versions = [v for v in versions if v['major'] == bakta.__db_schema_version__] 251 # make the data_manager metadata
174 252 bakta_data_manager = bakta_upload.get_data_manager(bakta_database_info=bakta_db, output_path=bakta_extracted_path)
175 print('Available DB versions:') 253 with open(all_args.data_manager_json, 'w') as fh:
176 for v in sorted(versions, key=lambda v: (v['major'], v['minor'])): 254 json.dump(bakta_data_manager, fh, indent=2, sort_keys=True)
177 print(f"{v['major']}.{v['minor']}\t{v['date']}\t{v['doi']}")
178 elif(args.subcommand == 'download'):
179 bu.test_dependency(bu.DEPENDENCY_AMRFINDERPLUS)
180 output_path = cfg.check_output_path(args)
181
182 print('fetch DB versions...')
183 versions = fetch_db_versions()
184 compatible_versions = [v for v in versions if v['major'] == bakta.__db_schema_version__]
185 if(len(compatible_versions) == 0):
186 sys.exit(f'Error: no compatible version available for current major db version {bakta.__db_schema_version__}')
187 else:
188 print(f'\t... compatible DB versions: {len(compatible_versions)}')
189
190 required_version = None
191 if(args.minor > 0):
192 for v in versions:
193 if(v['minor'] == args.minor):
194 required_version = v
195 break
196 if(required_version is None):
197 sys.exit(f"requested DB minor version {args.minor} is not available. Please use 'bakta_db list' to get a list of available DB versions")
198 else:
199 compatible_sorted = sorted(compatible_versions, key=lambda v: v['minor'], reverse=True)
200 required_version = compatible_sorted[0]
201
202 tarball_path = output_path.joinpath('db.tar.gz')
203 db_url = f"https://zenodo.org/record/{required_version['record']}/files/db.tar.gz"
204 print(f"download database: v{required_version['major']}.{required_version['minor']}, {required_version['date']}, DOI: {required_version['doi']}, URL: {db_url}...")
205 download(db_url, tarball_path)
206 print('\t... done')
207
208 print('check MD5 sum...')
209 md5_sum = calc_md5_sum(tarball_path)
210 if(md5_sum == required_version['md5']):
211 print(f'\t...database file OK: {md5_sum}')
212 else:
213 sys.exit(f"Error: corrupt database file! MD5 should be '{required_version['md5']}' but is '{md5_sum}'")
214
215 print(f'extract DB tarball: file={tarball_path}, output={output_path}')
216 untar(tarball_path, output_path)
217 tarball_path.unlink()
218
219 db_path = output_path.joinpath('db')
220 db_info = check(db_path)
221 if(db_info['major'] != required_version['major']):
222 sys.exit(f"ERROR: wrong major db detected! required={required_version['major']}, detected={db_info['major']}")
223 elif(db_info['minor'] != required_version['minor']):
224 sys.exit(f"ERROR: wrong minor db detected! required={required_version['minor']}, detected={db_info['minor']}")
225 print('successfully downloaded Bakta database!')
226 print(f"\tversion: {required_version['major']}.{required_version['minor']}")
227 print(f"\tDOI: {required_version['doi']}")
228 print(f'\tpath: {db_path}')
229
230 try:
231 db_path.chmod(stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR | stat.S_IRGRP | stat.S_IWGRP | stat.S_IXGRP | stat.S_IROTH | stat.S_IXOTH) # set write permissions on old (existing) directory with updated content
232 for db_file_path in db_path.iterdir():
233 db_file_path.chmod(stat.S_IRUSR | stat.S_IRGRP | stat.S_IROTH)
234 except:
235 sys.exit(f'ERROR: cannot set read|execute permissions on new database! path={db_path}, owner={db_path.owner()}, group={db_path.group()}, permissions={oct(db_path.stat().st_mode )[-3:]}')
236
237 print('update AMRFinderPlus database...')
238 update_amrfinderplus_db(db_path)
239 print('\t... done')
240
241 print(f"\nRun Bakta using '--db {db_path}' or set a BAKTA_DB environment variable: 'export BAKTA_DB={db_path}'")
242 elif(args.subcommand == 'update'):
243 bu.test_dependency(bu.DEPENDENCY_AMRFINDERPLUS)
244 tmp_path = cfg.check_tmp_path(args)
245 db_old_path = cfg.check_db_path(args)
246 db_old_info = check(db_old_path)
247 print(f"existing database: v{db_old_info['major']}.{db_old_info['minor']}")
248 print('fetch DB versions...')
249 versions = fetch_db_versions()
250 compatible_versions = [v for v in versions if v['major'] == bakta.__db_schema_version__]
251 if(len(compatible_versions) == 0):
252 sys.exit(f'Error: no compatible version available for current major db version {bakta.__db_schema_version__}')
253 else:
254 print(f'\t... compatible DB versions: {len(compatible_versions)}')
255
256 compatible_sorted = sorted(compatible_versions, key=lambda v: v['minor'], reverse=True)
257 if(compatible_sorted[0]['minor'] <= db_old_info['minor']):
258 print(f"Database version {db_old_info['major']}.{db_old_info['minor']} is up-to-date")
259 sys.exit()
260 required_version = compatible_sorted[0]
261
262 tarball_path = tmp_path.joinpath('db.tar.gz')
263 db_url = f"https://zenodo.org/record/{required_version['record']}/files/db.tar.gz"
264 print(f"download database: v{required_version['major']}.{required_version['minor']}, {required_version['date']}, DOI: {required_version['doi']}, URL: {db_url}...")
265 download(db_url, tarball_path)
266 print('\t... done')
267
268 print('check MD5 sum...')
269 md5_sum = calc_md5_sum(tarball_path)
270 if(md5_sum == required_version['md5']):
271 print(f'\t...database file OK: {md5_sum}')
272 else:
273 sys.exit(f"Error: corrupt database file! MD5 should be '{required_version['md5']}' but is '{md5_sum}'")
274
275 print(f'extract DB tarball: file={tarball_path}, output-directory={tmp_path}')
276 untar(tarball_path, tmp_path)
277 tarball_path.unlink()
278
279 db_new_path = tmp_path.joinpath('db')
280 db_new_info = check(db_new_path)
281 if(db_new_info['major'] != required_version['major']):
282 sys.exit(f"ERROR: wrong major db detected! required={required_version['major']}, detected={db_new_info['major']}")
283 elif(db_new_info['minor'] != required_version['minor']):
284 sys.exit(f"ERROR: wrong minor db detected! required={required_version['minor']}, detected={db_new_info['minor']}")
285 print('successfully downloaded Bakta DB:')
286 print(f"\tversion: {required_version['major']}.{required_version['minor']}")
287 print(f"\tDOI: {required_version['doi']}")
288 print(f'\tpath: {db_new_path}')
289 print('remove old database...')
290 try:
291 db_old_path.chmod(stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR) # set write permissions on old directory
292 for db_old_file_path in db_old_path.iterdir():
293 if(db_old_file_path.is_dir()):
294 db_old_file_path.chmod(stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR)
295 else:
296 db_old_file_path.chmod(stat.S_IRUSR | stat.S_IWUSR)
297 except:
298 sys.exit(f'ERROR: cannot set read|write|execute permissions on old database! path={db_old_path}, owner={db_old_path.owner()}, group={db_old_path.group()}, permissions={oct(db_old_path.stat().st_mode )[-3:]}')
299 try:
300 shutil.rmtree(db_old_path)
301 except:
302 sys.exit(f'ERROR: cannot remove old database! path={db_old_path}, owner={db_old_path.owner()}, group={db_old_path.group()}, permissions={oct(db_old_path.stat().st_mode )[-3:]}')
303 db_old_path.mkdir()
304
305 try:
306 db_new_path.chmod(stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR) # set write permissions on db_new_path directory
307 for db_new_file_path in db_new_path.iterdir():
308 db_new_file_path.chmod(stat.S_IRUSR | stat.S_IWUSR)
309 except:
310 sys.exit(f'ERROR: cannot set read|write|execute permissions on new database! path={db_new_path}, owner={db_new_path.owner()}, group={db_new_path.group()}, permissions={oct(db_new_path.stat().st_mode )[-3:]}')
311 try:
312 for db_new_file_path in db_new_path.iterdir(): # move new db files into old (existing) db directory
313 file_name = db_new_file_path.name
314 shutil.move(db_new_file_path, db_old_path.joinpath(file_name))
315 except:
316 sys.exit(f'ERROR: cannot move new database to existing path! new-path={db_new_path}, existing-path={db_old_path.parent}')
317 shutil.rmtree(tmp_path)
318
319 try:
320 db_old_path.chmod(stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR | stat.S_IRGRP | stat.S_IWGRP | stat.S_IXGRP | stat.S_IROTH | stat.S_IXOTH) # set write permissions on old (existing) directory with updated content
321 for db_old_file_path in db_old_path.iterdir():
322 db_old_file_path.chmod(stat.S_IRUSR | stat.S_IRGRP | stat.S_IROTH)
323 except:
324 sys.exit(f'ERROR: cannot set read(|execute) permissions on new database! path={db_old_path}, owner={db_old_path.owner()}, group={db_old_path.group()}, permissions={oct(db_old_path.stat().st_mode )[-3:]}')
325
326 print('\t... done')
327
328 print('update AMRFinderPlus database...')
329 update_amrfinderplus_db(db_old_path)
330 print('\t... done')
331
332 print(f"\nRun Bakta using '--db {db_old_path}' or set a BAKTA_DB environment variable: 'export BAKTA_DB={db_old_path}'")
333 else:
334 parser.print_help()
335 sys.exit('Error: no subcommand provided!')
336
337
338 def update_amrfinderplus_db(db_path: Path):
339 amrfinderplus_db_path = db_path.joinpath('amrfinderplus-db')
340 cmd = [
341 'amrfinder_update',
342 '--database', str(amrfinderplus_db_path),
343 '--force_update'
344 ]
345 log.debug('cmd=%s', cmd)
346 proc = sp.run(
347 cmd,
348 stdout=sp.PIPE,
349 stderr=sp.PIPE,
350 universal_newlines=True
351 )
352 if(proc.returncode != 0):
353 log.debug('stdout=\'%s\', stderr=\'%s\'', proc.stdout, proc.stderr)
354 log.warning('AMRFinderPlus failed! amrfinder-error-code=%d', proc.returncode)
355 sys.exit(f"ERROR: AMRFinderPlus failed! command: 'amrfinder_update --force_update --database {amrfinderplus_db_path}', error code: {proc.returncode}")
356 255
357 256
358 if __name__ == '__main__': 257 if __name__ == '__main__':
359 main() 258 main()