Mercurial > repos > pimarin > data_manager_bakta
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() |