Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added better request error handling #26

Merged
merged 7 commits into from
May 14, 2024
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions bin/ensembl2uniprot.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@

import sys

import requests
from utils import check_id_mapping_results_ready
from utils import check_id_mapping_results_ready, safe_get, safe_post


def ensembl2uniprot(ensembl_ids: list[str]) -> list[str]:
Expand All @@ -22,7 +21,8 @@ def ensembl2uniprot(ensembl_ids: list[str]) -> list[str]:
"to": "UniProtKB"
}

res = requests.post("https://rest.uniprot.org/idmapping/run", data=payload)
res = safe_post("https://rest.uniprot.org/idmapping/run", data=payload)

if not res.ok:
raise ValueError(f"HTTP error: {res.status_code}")

Expand All @@ -31,7 +31,7 @@ def ensembl2uniprot(ensembl_ids: list[str]) -> list[str]:
# wait for the job to finish
check_id_mapping_results_ready(job_id)

res = requests.get(f"https://rest.uniprot.org/idmapping/results/{job_id}")
res = safe_get(f"https://rest.uniprot.org/idmapping/results/{job_id}")

json = res.json()

Expand Down
8 changes: 5 additions & 3 deletions bin/fetch_afdb_structures.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

import sys

import requests
from utils import safe_get


def fetch_structures(path: str, prefix: str) -> None:
Expand All @@ -21,14 +21,16 @@ def fetch_structures(path: str, prefix: str) -> None:

for id in ids:
url = f"https://alphafold.ebi.ac.uk/api/prediction/{id}"
res = requests.get(url)

itrujnara marked this conversation as resolved.
Show resolved Hide resolved
res = safe_get(url)

if res.ok:
pdb_url = res.json()[0]["pdbUrl"]
version = res.json()[0]["latestVersion"]

print(f"{id}: {version}", file=sys.stderr)

res = requests.get(pdb_url)
res = safe_get(pdb_url)

if res.ok:
print(res.text, file=open(f"{id}.pdb", 'w'))
Expand Down
4 changes: 2 additions & 2 deletions bin/fetch_inspector_group.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,15 @@

import sys

import requests
from utils import safe_get


def fetch_inspector_by_id(uniprot_id: str, db_id: str = "Eukaryota2019") -> None:
"""
Fetch orthologs for a given UniProt ID from the OrthoInspector database.
"""
url = f"https://lbgi.fr/api/orthoinspector/{db_id}/protein/{uniprot_id}/orthologs"
res = requests.get(url)
res = safe_get(url)

if not res.ok:
raise ValueError(f"HTTP error: {res.status_code}")
Expand Down
4 changes: 2 additions & 2 deletions bin/fetch_oma_group.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

import sys

import requests
from utils import safe_get


def main() -> None:
Expand All @@ -17,7 +17,7 @@ def main() -> None:

id = sys.argv[1]

res = requests.get(f"https://omabrowser.org/api/group/{id}")
res = safe_get(f"https://omabrowser.org/api/group/{id}")

if not res.ok:
raise ValueError(f"HTTP error: {res.status_code}")
Expand Down
4 changes: 2 additions & 2 deletions bin/fetch_panther_group.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

import sys

import requests
from utils import safe_get


def main() -> None:
Expand All @@ -15,7 +15,7 @@ def main() -> None:
if len(sys.argv) < 3:
raise ValueError("Too few arguments. Usage: fetch_panther_group.py <id> <organism>")

res = requests.get(f"https://www.pantherdb.org/services/oai/pantherdb/ortholog/matchortho?geneInputList={sys.argv[1]}&organism={sys.argv[2]}&orthologType=all")
res = safe_get(f"https://www.pantherdb.org/services/oai/pantherdb/ortholog/matchortho?geneInputList={sys.argv[1]}&organism={sys.argv[2]}&orthologType=all")

if not res.ok:
raise ValueError(f"HTTP error: {res.status_code}")
Expand Down
8 changes: 5 additions & 3 deletions bin/fetch_sequences.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

import sys

import requests
from utils import safe_get, safe_post


def fetch_seqs_oma(path: str, prefix: str) -> list[str]:
Expand All @@ -18,7 +18,9 @@ def fetch_seqs_oma(path: str, prefix: str) -> list[str]:

payload = {"ids": ids}

res = requests.post("https://omabrowser.org/api/protein/bulk_retrieve/", json=payload)
print(payload, file=sys.stderr)

res = safe_post("https://omabrowser.org/api/protein/bulk_retrieve/", json=payload)

if not res.ok:
raise ValueError(f"HTTP error: {res.status_code}")
Expand Down Expand Up @@ -50,7 +52,7 @@ def fetch_seqs_uniprot(oma_misses: list, prefix: str) -> None:
misses = []

for id in oma_misses:
res = requests.get(f"https://rest.uniprot.org/uniprotkb/{id}.fasta")
res = safe_get(f"https://rest.uniprot.org/uniprotkb/{id}.fasta")
if res.ok:
hits.append((id, res.text.split("\n", 1)[1].replace("\n", "")))
else:
Expand Down
4 changes: 2 additions & 2 deletions bin/get_oma_version.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@
# Written by Igor Trujnara, released under the MIT license
# See https://opensource.org/license/mit for details

import requests
from utils import safe_get


def main() -> None:
"""
Get the version of the OMA database and API.
"""
res = requests.get("https://omabrowser.org/api/version")
res = safe_get("https://omabrowser.org/api/version")
if not res.ok:
raise ValueError(f"HTTP error: {res.status_code}")
json = res.json()
Expand Down
7 changes: 3 additions & 4 deletions bin/refseq2uniprot.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@

import sys

import requests
from utils import check_id_mapping_results_ready
from utils import check_id_mapping_results_ready, safe_get, safe_post


def refseq2uniprot(refseq_ids: list[str]) -> list[str]:
Expand All @@ -22,15 +21,15 @@ def refseq2uniprot(refseq_ids: list[str]) -> list[str]:
"to": "UniProtKB"
}

res = requests.post("https://rest.uniprot.org/idmapping/run", data=payload)
res = safe_post("https://rest.uniprot.org/idmapping/run", data=payload)
if not res.ok:
raise ValueError(f"HTTP error: {res.status_code}")

job_id = res.json()["jobId"]

check_id_mapping_results_ready(job_id)

res = requests.get(f"https://rest.uniprot.org/idmapping/results/{job_id}")
res = safe_get(f"https://rest.uniprot.org/idmapping/results/{job_id}")

json = res.json()

Expand Down
7 changes: 3 additions & 4 deletions bin/uniprot2uniprot.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@

import sys

import requests
from utils import check_id_mapping_results_ready
from utils import check_id_mapping_results_ready, safe_post, safe_get


def uniprot2uniprot(uniprot_names: list[str]) -> list[str]:
Expand All @@ -22,15 +21,15 @@ def uniprot2uniprot(uniprot_names: list[str]) -> list[str]:
"to": "UniProtKB"
}

res = requests.post("https://rest.uniprot.org/idmapping/run", data=payload)
res = safe_post("https://rest.uniprot.org/idmapping/run", data=payload)
if not res.ok:
raise ValueError(f"HTTP error: {res.status_code}")

job_id = res.json()["jobId"]

check_id_mapping_results_ready(job_id)

res = requests.get(f"https://rest.uniprot.org/idmapping/results/{job_id}")
res = safe_get(f"https://rest.uniprot.org/idmapping/results/{job_id}")

json = res.json()

Expand Down
25 changes: 23 additions & 2 deletions bin/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,36 @@
from typing import Any

import requests
from requests.exceptions import RequestException

POLLING_INTERVAL = 0.5

def safe_get(url: str):
"""
Get a URL and return the response.
"""
try:
return requests.get(url)
except requests.exceptions.RequestException as e:
raise RequestException(f"A network issue occurred. Retrying request. Details:\n{e}")


def safe_post(url: str, data: dict = dict(), json: dict = dict()):
"""
Post data to a URL and return the response.
"""
try:
return requests.post(url, data=data, json=json)
except requests.exceptions.RequestException as e:
raise RequestException(f"A network issue occurred. Retrying request. Details:\n{e}")


def check_id_mapping_results_ready(job_id):
"""
Wait until the ID mapping job is finished.
"""
while True:
request = requests.get(f"https://rest.uniprot.org/idmapping/status/{job_id}")
request = safe_get(f"https://rest.uniprot.org/idmapping/status/{job_id}")
j = request.json()
if "jobStatus" in j:
if j["jobStatus"] == "RUNNING":
Expand All @@ -29,7 +50,7 @@ def fetch_seq(url: str) -> tuple[bool, dict]:
"""
Get JSON from a URL.
"""
res = requests.get(url)
res = safe_get(url)
if not res.ok:
print(f"HTTP error. Code: {res.status_code}")
return (False, dict())
Expand Down
14 changes: 14 additions & 0 deletions conf/modules.config
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ process {
mode: params.publish_dir_mode,
saveAs: { filename -> filename.equals('versions.yml') ? null : filename }
]
errorStrategy = 'retry'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Couldn't we catch which error numbers to retry?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know, can we? I have to check in the docs

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

maxRetries = 3
}

withName: 'FETCH_OMA_GROUP_LOCAL|FETCH_OMA_GROUP_ONLINE' {
Expand All @@ -36,6 +38,8 @@ process {
mode: params.publish_dir_mode,
saveAs: { filename -> filename.equals('versions.yml') ? null : filename }
]
errorStrategy = 'retry'
maxRetries = 3
}

withName: 'FETCH_PANTHER_GROUP_LOCAL|FETCH_PANTHER_GROUP_ONLINE' {
Expand All @@ -44,6 +48,8 @@ process {
mode: params.publish_dir_mode,
saveAs: { filename -> filename.equals('versions.yml') ? null : filename }
]
errorStrategy = 'retry'
maxRetries = 3
}

withName: 'FETCH_INSPECTOR_GROUP_ONLINE' {
Expand All @@ -52,6 +58,8 @@ process {
mode: params.publish_dir_mode,
saveAs: { filename -> filename.equals('versions.yml') ? null : filename }
]
errorStrategy = 'retry'
maxRetries = 3
}

withName: 'FETCH_EGGNOG_GROUP_LOCAL|FETCH_EGGNOG_GROUP_ONLINE' {
Expand All @@ -60,6 +68,8 @@ process {
mode: params.publish_dir_mode,
saveAs: { filename -> filename.equals('versions.yml') ? null : filename }
]
errorStrategy = 'retry'
maxRetries = 3
}

withName: 'MERGE_CSV' {
Expand Down Expand Up @@ -149,6 +159,8 @@ process {
mode: params.publish_dir_mode,
saveAs: { filename -> filename.equals('versions.yml') ? null : filename }
]
errorStrategy = 'retry'
maxRetries = 3
}

withName: 'FETCH_AFDB_STRUCTURES' {
Expand All @@ -157,6 +169,8 @@ process {
mode: params.publish_dir_mode,
saveAs: { filename -> filename.equals('versions.yml') ? null : filename }
]
errorStrategy = 'retry'
maxRetries = 3
}

withName: 'FILTER_FASTA' {
Expand Down