Skip to content
1 change: 1 addition & 0 deletions panelapp/pa_locus_list_api_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ def test_import_all_panels(self):

responses.add(responses.GET, au_panels_p1_url, json=au_panels_p1_json, status=200)
responses.add(responses.GET, au_panels_p2_url, json=au_panels_p2_json, status=200)
responses.add(responses.GET, au_genes_url, status=429)
responses.add(responses.GET, au_genes_url, json=au_genes_json, status=200)
responses.add(responses.GET, uk_panels_p1_url, json=uk_panels_p1_json, status=200)
responses.add(responses.GET, uk_genes_url, json=uk_genes_json, status=200)
Expand Down
8 changes: 7 additions & 1 deletion panelapp/panelapp_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from django.db import transaction
from django.utils import timezone
from tenacity import retry, wait_exponential, stop_after_attempt, retry_if_exception_type
from time import sleep
from urllib3.exceptions import MaxRetryError

from panelapp.models import PaLocusList, PaLocusListGene
Expand All @@ -17,6 +18,8 @@

REQUEST_TIMEOUT_S = 300

class TooManyRequestsError(Exception):
pass

def import_all_panels(user, panel_app_api_url, label=None):
def _extract_ensembl_id_from_json(raw_gene_json):
Expand Down Expand Up @@ -118,12 +121,15 @@ def _get_all_panels(panels_url, all_results):

def _get_all_genes(genes_url: str, results_by_panel_id: dict):
@retry(
retry=retry_if_exception_type(MaxRetryError),
retry=retry_if_exception_type((MaxRetryError, TooManyRequestsError)),
wait=wait_exponential(multiplier=1, min=4, max=10),
stop=stop_after_attempt(5),
)
def _get(url):
resp = requests.get(url, timeout=REQUEST_TIMEOUT_S)
if resp.status_code == 429:
sleep(10)
raise TooManyRequestsError()
return resp.json()

resp_json = _get(genes_url)
Expand Down
3 changes: 3 additions & 0 deletions seqr/management/commands/reload_clinvar_all_variants.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,9 @@ def parse_pathogenicity_and_assertions(classified_record_node: xml.etree.Element
).replace(
', low penetrance',
'; low penetrance'
).replace(
'Likely pathogenic/Likely pathogenic',
'Likely pathogenic'
)

pathogenicity = pathogenicity_string.split(';')[0].strip()
Expand Down
14 changes: 14 additions & 0 deletions seqr/views/apis/individual_api_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,20 @@ def test_edit_individuals(self, mock_pm_group):
self.assertEqual(response_json['individualsByGuid'][ID_UPDATE_GUID]['individualId'], UPDATED_ID)
self.assertEqual(response_json['individualsByGuid'][ID_UPDATE_GUID]['maternalId'], 'NA19679')

response = self.client.post(edit_individuals_url, content_type='application/json', data=json.dumps({
'individuals': [{
'individualGuid': INDIVIDUAL_GUID,
'familyId': '1',
'individualId': 'NA19675_1',
'paternalId': '',
}]
}))
self.assertEqual(response.status_code, 200)
response_json = response.json()
self.assertSetEqual({INDIVIDUAL_GUID}, set(response_json['individualsByGuid']))
self.assertIsNone(response_json['individualsByGuid'][INDIVIDUAL_GUID]['paternalId'])
self.assertEqual(response_json['individualsByGuid'][INDIVIDUAL_GUID]['maternalId'], 'NA19679')

# Test PM permission
pm_required_edit_individuals_url = reverse(edit_individuals_handler, args=[PM_REQUIRED_PROJECT_GUID])
response = self.client.post(pm_required_edit_individuals_url, content_type='application/json', data=json.dumps({
Expand Down
2 changes: 1 addition & 1 deletion seqr/views/utils/individual_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ def _update_from_record(record, user, families_by_id, individual_lookup, updated
'mother': record.pop('mother', None),
'father': record.pop('father', None),
})
elif record.get('maternalId') or record.get('paternalId'):
elif record.get('maternalId') is not None or record.get('paternalId') is not None:
parent_updates.append({
'individual': individual,
'maternalId': record.pop('maternalId', None),
Expand Down
6 changes: 5 additions & 1 deletion seqr/views/utils/json_to_orm_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,10 +55,14 @@ def update_individual_parents(individual, json, user):

def _parse_parent_field(update_json, all_json, individual, parent_key, parent_id_key):
updated_parent = all_json.get(parent_id_key) if parent_id_key else all_json.get(parent_key)
if updated_parent is None:
return
parent = getattr(individual, parent_key, None)
if parent_id_key:
parent = parent.individual_id if parent else None
if updated_parent != parent:
if parent and not updated_parent:
update_json[parent_key] = None
elif updated_parent != parent:
if parent_id_key:
updated_parent = Individual.objects.get(individual_id=updated_parent, family=individual.family) if updated_parent else None
update_json[parent_key] = updated_parent
Expand Down
Loading