diff --git a/multiqc_ngi/multiqc_ngi.py b/multiqc_ngi/multiqc_ngi.py index 755b5d2..c217e18 100644 --- a/multiqc_ngi/multiqc_ngi.py +++ b/multiqc_ngi/multiqc_ngi.py @@ -4,13 +4,13 @@ from __future__ import print_function from collections import OrderedDict -from couchdb import Server import logging +from ibmcloudant import CouchDbSessionAuthenticator, cloudant_v1, ViewQuery +from ibm_cloud_sdk_core import ApiException import json import os import re import requests -import socket import subprocess import yaml @@ -215,11 +215,11 @@ def get_ngi_project_metadata(self, pid): if self.couch is None: return None try: - p_view = self.couch['projects'].view('project/summary') - except socket.error: + p_view = self.couch.post_view(db="projects", ddoc="project", view="summary").get_result() + except ConnectionError: log.error('CouchDB Operation timed out') p_summary = None - for row in p_view: + for row in p_view['rows']: if row['key'][1] == pid: p_summary = row @@ -281,15 +281,15 @@ def get_ngi_samples_metadata(self, pid, s_names=None): """ Get project sample metadata from statusdb """ if self.test_data is not None: report.ngi['sample_meta'] = self.test_data['samples'] - elif self.couch is not None: - p_view = self.couch['projects'].view('project/samples') - p_samples = p_view[pid] - if not len(p_samples.rows) == 1: - log.error(f"statusdb returned {len(p_samples.rows)} rows when querying {pid}") + elif self.couch is not None: + p_view_results = self.couch.post_view_queries(db="projects", ddoc="project", queries=[ViewQuery(key=pid)], + view="samples").get_result() + if not len(p_view_results['results'][0]['rows']) == 1: + log.error(f"statusdb returned {len(p_view_results['results'][0]['rows'])} rows when querying {pid}") else: if 'sample_meta' not in report.ngi: report.ngi['sample_meta'] = dict() - report.ngi['sample_meta'].update(p_samples.rows[0]['value']) + report.ngi['sample_meta'].update(p_view_results['results'][0]['rows'][0]['value']) if 'ngi_names' not in report.ngi: report.ngi['ngi_names'] = dict() @@ -483,18 +483,17 @@ def push_statusdb_multiqc_data(self): if self.couch is None: return None try: - db = self.couch['analysis'] - p_view = db.view('project/project_id') - except socket.error: + p_view_results = self.couch.post_view_queries(db="analysis", ddoc="project", + queries=[ViewQuery(key=report.ngi['pid'])], + view="project_id").get_result() + except ConnectionError: log.error('CouchDB Operation timed out') return None # Try to get an existing document if one exists doc = {} - for row in p_view: - if row['key'] == report.ngi['pid']: - doc = row.value - break + if p_view_results['results'][0]['rows']: + doc = p_view_results['results'][0]['rows'][0]['value'] # Start fresh unless the existing doc looks similar newdoc = { @@ -530,12 +529,12 @@ def push_statusdb_multiqc_data(self): # Save object to the database try: - db.save(doc) - except ValueError as e: - if e.args[0] == 'Out of range float values are not JSON compliant': - log.debug('Error saving to StatusDB: Out of range float values are not JSON compliant, might be NaNs, trying again...') + self.couch.post_document(db="analysis", document=doc).get_result() + except ApiException as e: + if e.message[0] == 'bad_request: invalid UTF-8 JSON': + log.debug('Error saving to StatusDB: bad_request: invalid UTF-8 JSON, might be NaNs, trying again...') doc = json.loads(utils.util_functions.dump_json(doc, filehandle=None)) - db.save(doc) + self.couch.post_document(db="analysis", document=doc).get_result() log.debug('Saved to StatusDB after converting NaNs to nulls') else: log.error(f'Error saving to StatusDB: {e}') @@ -576,7 +575,10 @@ def connect_statusdb(self): log.warning("Cannot contact statusdb - skipping NGI metadata stuff") return None - return Server(server_url) + couch_server = cloudant_v1.CloudantV1(authenticator=CouchDbSessionAuthenticator(couch_user, password)) + couch_server.set_service_url(f"https://{couch_url}") + + return couch_server diff --git a/setup.py b/setup.py index e58caa6..e5fd1ac 100755 --- a/setup.py +++ b/setup.py @@ -4,29 +4,32 @@ specific to the National Genomics Infrastructure at the Science for Life Laboratory in Stockholm, Sweden. +Author: Phil Ewels + For more information about NGI, see http://www.scilifelab.se/platforms/ngi/ For more information about MultiQC, see http://multiqc.info """ from setuptools import setup, find_packages +import subprocess + -version = '0.8.0' +def get_version(): + return subprocess.check_output(["git", "describe", "--tags"]).strip().decode("utf-8") setup( name = 'multiqc_ngi', - version = version, - author = 'Phil Ewels', - author_email = 'phil.ewels@scilifelab.se', + version = get_version(), description = "MultiQC plugin for the National Genomics Infrastructure @ SciLifeLab Sweden", long_description = __doc__, keywords = 'bioinformatics', - url = 'https://github.com/ewels/MultiQC_NGI', - download_url = 'https://github.com/ewels/MultiQC_NGI/releases', + url = 'https://github.com/NationalGenomicsInfrastructure/MultiQC_NGI', + download_url = 'https://github.com/NationalGenomicsInfrastructure/MultiQC_NGI/releases', license = 'MIT', packages = find_packages(), include_package_data = True, install_requires = [ - 'couchdb', + 'ibmcloudant>=0.9.1' 'simplejson', 'pyyaml', 'requests',