From 4e5e0a9c563a3c1efab39ee8ab3174607e8a8137 Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Tue, 1 Sep 2026 10:28:14 -0400 Subject: [PATCH] lint: misc ruff 0.16 fixes --- chord_metadata_service/patients/api_views.py | 14 +++++----- chord_metadata_service/patients/cleanup.py | 4 +-- .../patients/descriptions.py | 1 - chord_metadata_service/patients/filters.py | 1 + chord_metadata_service/patients/models.py | 10 ++++--- chord_metadata_service/patients/schemas.py | 11 ++++---- .../patients/serializers.py | 1 + chord_metadata_service/patients/summaries.py | 1 + .../patients/tests/constants.py | 3 ++- .../patients/tests/test_api.py | 27 +++++++++---------- .../patients/tests/test_models.py | 4 +-- chord_metadata_service/patients/values.py | 1 - chord_metadata_service/utils.py | 7 ++--- docs/conf.py | 4 +-- scripts/ingest.py | 27 +++++++------------ scripts/remove_from_db.py | 9 ++++--- 16 files changed, 62 insertions(+), 63 deletions(-) diff --git a/chord_metadata_service/patients/api_views.py b/chord_metadata_service/patients/api_views.py index 66092664f..f5ce0b809 100644 --- a/chord_metadata_service/patients/api_views.py +++ b/chord_metadata_service/patients/api_views.py @@ -1,11 +1,11 @@ import asyncio +from datetime import datetime from adrf.views import APIView from asgiref.sync import async_to_sync -from bento_lib.auth.permissions import Permission, P_QUERY_DATA +from bento_lib.auth.permissions import P_QUERY_DATA, Permission from bento_lib.responses import errors from bento_lib.search import build_search_response -from datetime import datetime from django.contrib.postgres.aggregates import ArrayAgg from django.core.exceptions import ValidationError from django.db.models import Count, F, Q @@ -19,11 +19,11 @@ from rest_framework.settings import api_settings from chord_metadata_service.authz.middleware import authz_middleware -from chord_metadata_service.authz.viewset import BentoAuthzScopedModelViewSet, BentoAuthzScopedModelGenericListViewSet +from chord_metadata_service.authz.viewset import BentoAuthzScopedModelGenericListViewSet, BentoAuthzScopedModelViewSet from chord_metadata_service.chord import data_types as dts from chord_metadata_service.discovery import responses as dres from chord_metadata_service.discovery.censorship import get_threshold, thresholded_count -from chord_metadata_service.discovery.exceptions import DiscoveryScopeException, DiscoveryEmptyException +from chord_metadata_service.discovery.exceptions import DiscoveryEmptyException, DiscoveryScopeException from chord_metadata_service.discovery.filtering import discovery_filter_queryset from chord_metadata_service.discovery.pydantic_models import DiscoveryQuery from chord_metadata_service.discovery.scope import get_request_discovery_scope @@ -39,15 +39,15 @@ from chord_metadata_service.phenopackets.models import Phenopacket from chord_metadata_service.phenopackets.serializers import PhenopacketSerializer from chord_metadata_service.restapi.api_renderers import ( - PhenopacketsRenderer, + IndividualBentoSearchRenderer, IndividualCSVRenderer, IndividualXLSXRenderer, - IndividualBentoSearchRenderer, + PhenopacketsRenderer, csv_fields_error_response, ) from chord_metadata_service.restapi.constants import MODEL_ID_PATTERN -from chord_metadata_service.restapi.pagination import LargeResultsSetPagination, BatchResultsSetPagination from chord_metadata_service.restapi.negociation import FormatInPostContentNegotiation +from chord_metadata_service.restapi.pagination import BatchResultsSetPagination, LargeResultsSetPagination from chord_metadata_service.restapi.utils import ( build_experiments_by_subject, get_biosamples_with_experiment_details, diff --git a/chord_metadata_service/patients/cleanup.py b/chord_metadata_service/patients/cleanup.py index 4c415b29a..179bda537 100644 --- a/chord_metadata_service/patients/cleanup.py +++ b/chord_metadata_service/patients/cleanup.py @@ -1,9 +1,9 @@ -import chord_metadata_service.phenopackets.models as pm - from structlog.stdlib import BoundLogger +import chord_metadata_service.phenopackets.models as pm from chord_metadata_service.cleanup.remove import remove_not_referenced from chord_metadata_service.utils import build_id_set_from_model + from .models import Individual __all__ = [ diff --git a/chord_metadata_service/patients/descriptions.py b/chord_metadata_service/patients/descriptions.py index 6731ba11c..3fdb7e5d2 100644 --- a/chord_metadata_service/patients/descriptions.py +++ b/chord_metadata_service/patients/descriptions.py @@ -1,6 +1,5 @@ from chord_metadata_service.restapi.description_utils import EXTRA_PROPERTIES, ontology_class - # TODO: This is part of another app INDIVIDUAL = { "description": "A subject of a phenopacket, representing either a human (typically) or another organism.", diff --git a/chord_metadata_service/patients/filters.py b/chord_metadata_service/patients/filters.py index a4b0a2dfa..91617c447 100644 --- a/chord_metadata_service/patients/filters.py +++ b/chord_metadata_service/patients/filters.py @@ -2,6 +2,7 @@ from django.db.models import Q from chord_metadata_service.discovery.full_text_search import full_text_search_vector + from .models import Individual GENOMIC_INTERPRETATION_QUERY = "phenopackets__interpretations__diagnosis__genomic_interpretations" diff --git a/chord_metadata_service/patients/models.py b/chord_metadata_service/patients/models.py index 22693712b..3b1f09bbd 100644 --- a/chord_metadata_service/patients/models.py +++ b/chord_metadata_service/patients/models.py @@ -1,15 +1,17 @@ from django.apps import apps +from django.contrib.postgres.fields import ArrayField from django.contrib.postgres.indexes import GinIndex from django.db import models from django.db.models import JSONField -from django.contrib.postgres.fields import ArrayField -from chord_metadata_service.discovery.scopeable_model import BaseScopeableModel + from chord_metadata_service.discovery.full_text_search import BaseFTSModel, ToFTSReprMixin +from chord_metadata_service.discovery.scopeable_model import BaseScopeableModel from chord_metadata_service.discovery.types import ModelScopeFilters -from chord_metadata_service.restapi.models import BaseTimeStamp, IndexableMixin, SchemaType, BaseExtraProperties +from chord_metadata_service.restapi.models import BaseExtraProperties, BaseTimeStamp, IndexableMixin, SchemaType from chord_metadata_service.restapi.schema_ref import SchemaRefs from chord_metadata_service.restapi.validators import JsonSchemaValidator, ontology_validator -from .values import PatientStatus, Sex, KaryotypicSex + +from .values import KaryotypicSex, PatientStatus, Sex class VitalStatus(BaseTimeStamp, IndexableMixin, ToFTSReprMixin): diff --git a/chord_metadata_service/patients/schemas.py b/chord_metadata_service/patients/schemas.py index f5fd2541e..572a60976 100644 --- a/chord_metadata_service/patients/schemas.py +++ b/chord_metadata_service/patients/schemas.py @@ -1,4 +1,5 @@ from django.conf import settings + from chord_metadata_service.restapi.constants import MODEL_ID_PATTERN from chord_metadata_service.restapi.schema_utils import ( DATE_TIME, @@ -6,15 +7,15 @@ SchemaTypes, array_of, base_type, - string_with_pattern, enum_of, - tag_ids_and_describe, + string_with_pattern, sub_schema_uri, + tag_ids_and_describe, ) -from chord_metadata_service.restapi.schemas import ONTOLOGY_CLASS, EXTRA_PROPERTIES_SCHEMA, TIME_ELEMENT_SCHEMA -from .descriptions import INDIVIDUAL, VITAL_STATUS -from .values import Sex, KaryotypicSex +from chord_metadata_service.restapi.schemas import EXTRA_PROPERTIES_SCHEMA, ONTOLOGY_CLASS, TIME_ELEMENT_SCHEMA +from .descriptions import INDIVIDUAL, VITAL_STATUS +from .values import KaryotypicSex, Sex phenopacket_base_uri = f"{settings.SCHEMAS_BASE_URL}/phenopacket" diff --git a/chord_metadata_service/patients/serializers.py b/chord_metadata_service/patients/serializers.py index bcd1be34e..7deb79ded 100644 --- a/chord_metadata_service/patients/serializers.py +++ b/chord_metadata_service/patients/serializers.py @@ -1,5 +1,6 @@ from chord_metadata_service.phenopackets.serializers import BiosampleSerializer, SimplePhenopacketSerializer from chord_metadata_service.restapi.serializers import GenericSerializer + from .models import Individual, VitalStatus __all__ = [ diff --git a/chord_metadata_service/patients/summaries.py b/chord_metadata_service/patients/summaries.py index ce680ab39..3251eb339 100644 --- a/chord_metadata_service/patients/summaries.py +++ b/chord_metadata_service/patients/summaries.py @@ -7,6 +7,7 @@ from chord_metadata_service.discovery.censorship import thresholded_count from chord_metadata_service.discovery.fields import get_age_numeric_binned from chord_metadata_service.discovery.stats import queryset_stats_for_field + from . import models __all__ = ["individual_summary"] diff --git a/chord_metadata_service/patients/tests/constants.py b/chord_metadata_service/patients/tests/constants.py index 0faadbf30..14d9b88b6 100644 --- a/chord_metadata_service/patients/tests/constants.py +++ b/chord_metadata_service/patients/tests/constants.py @@ -1,6 +1,7 @@ -import uuid import random +import uuid from datetime import date, timedelta + import isodate diff --git a/chord_metadata_service/patients/tests/test_api.py b/chord_metadata_service/patients/tests/test_api.py index 96fb31a00..d7f210cf8 100644 --- a/chord_metadata_service/patients/tests/test_api.py +++ b/chord_metadata_service/patients/tests/test_api.py @@ -1,16 +1,16 @@ import csv import io -import openpyxl import random import uuid - -from bento_lib.discovery import DiscoveryConfig from copy import deepcopy -from django.db.models import Q, F, Value -from django.urls import reverse +import openpyxl +from bento_lib.discovery import DiscoveryConfig +from django.db.models import F, Q, Value from django.test import TestCase, override_settings +from django.urls import reverse from rest_framework import status + from chord_metadata_service.authz.tests.helpers import AuthzAPITestCase from chord_metadata_service.chord import models as cm from chord_metadata_service.chord.dataset_schema import KatsuDatasetModel @@ -19,9 +19,9 @@ from chord_metadata_service.discovery import responses as dres from chord_metadata_service.discovery.fields_utils import JSONBPathFilter from chord_metadata_service.discovery.tests.constants import ( + CONFIG_PUBLIC_TEST_SEARCH_SEX_ONLY, DISCOVERY_CONFIG_EXTRA_PROPERTIES, DISCOVERY_CONFIG_TEST, - CONFIG_PUBLIC_TEST_SEARCH_SEX_ONLY, DISCOVERY_ZERO_COUNTS, ) from chord_metadata_service.experiments import models as ex_m @@ -612,7 +612,7 @@ class DiscoveryFilteringIndividualsTest(AuthzAPITestCase, ProjectTestCase): @staticmethod def response_threshold_check(response): - return response["count"] if "count" in response else dres.INSUFFICIENT_DATA_AVAILABLE + return response.get("count", dres.INSUFFICIENT_DATA_AVAILABLE) def setUp(self): random.seed(self.random_seed) @@ -1269,7 +1269,7 @@ class DiscoveryAgeRangeFilteringIndividualsTest(AuthzAPITestCase): @staticmethod def response_threshold_check(response): - return response["count"] if "count" in response else dres.INSUFFICIENT_DATA_AVAILABLE + return response.get("count", dres.INSUFFICIENT_DATA_AVAILABLE) def setUp(self): individuals = [c.generate_valid_individual(gen_random_age=(1, 100)) for _ in range(self.random_range)] @@ -1277,12 +1277,11 @@ def setUp(self): Individual.objects.create(**individual) for individual in Individual.objects.all(): - if individual.time_at_last_encounter: - if "age" in individual.time_at_last_encounter: - age_numeric, age_unit = iso_duration_to_years(individual.time_at_last_encounter["age"]) - individual.age_numeric = age_numeric - individual.age_unit = age_unit if age_unit else "" - individual.save() + if individual.time_at_last_encounter and "age" in individual.time_at_last_encounter: + age_numeric, age_unit = iso_duration_to_years(individual.time_at_last_encounter["age"]) + individual.age_numeric = age_numeric + individual.age_unit = age_unit if age_unit else "" + individual.save() @override_settings(CONFIG_PUBLIC=DISCOVERY_CONFIG_TEST) def test_discovery_filtering_age_range(self): diff --git a/chord_metadata_service/patients/tests/test_models.py b/chord_metadata_service/patients/tests/test_models.py index 462e3a093..3f77ce901 100644 --- a/chord_metadata_service/patients/tests/test_models.py +++ b/chord_metadata_service/patients/tests/test_models.py @@ -1,10 +1,10 @@ from chord_metadata_service.chord.tests.helpers import ProjectTestCase -from chord_metadata_service.phenopackets.tests import constants as c from chord_metadata_service.phenopackets import models as m +from chord_metadata_service.phenopackets.tests import constants as c from chord_metadata_service.restapi.models import SchemaType -from ..models import Individual, VitalStatus from ..filters import IndividualFilter +from ..models import Individual, VitalStatus class IndividualTest(ProjectTestCase): diff --git a/chord_metadata_service/patients/values.py b/chord_metadata_service/patients/values.py index 160ff1bee..8fbb6bbd7 100644 --- a/chord_metadata_service/patients/values.py +++ b/chord_metadata_service/patients/values.py @@ -1,6 +1,5 @@ from abc import ABC - __all__ = [ "Sex", "KaryotypicSex", diff --git a/chord_metadata_service/utils.py b/chord_metadata_service/utils.py index 5363edd2d..bb569aab3 100644 --- a/chord_metadata_service/utils.py +++ b/chord_metadata_service/utils.py @@ -1,5 +1,6 @@ +from typing import Any + from django.db.models import Model, QuerySet -from typing import Any, Set, Type __all__ = [ "build_id_set", @@ -7,12 +8,12 @@ ] -async def build_id_set(qs: QuerySet, field: str) -> Set[Any]: +async def build_id_set(qs: QuerySet, field: str) -> set[Any]: s = set() async for v in qs.values_list(field, flat=True): s.add(v) return s -async def build_id_set_from_model(m: Type[Model], field: str) -> Set[Any]: +async def build_id_set_from_model(m: type[Model], field: str) -> set[Any]: return await build_id_set(m.objects.all(), field) diff --git a/docs/conf.py b/docs/conf.py index 6a8c525b3..23857f453 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -14,11 +14,11 @@ import datetime import os import sys +from pathlib import Path + import django import toml -from pathlib import Path - sys.path.insert(0, os.path.abspath("..")) os.environ["DJANGO_SETTINGS_MODULE"] = "chord_metadata_service.metadata.settings" django.setup() diff --git a/scripts/ingest.py b/scripts/ingest.py index 965c370b2..8365042ba 100644 --- a/scripts/ingest.py +++ b/scripts/ingest.py @@ -1,5 +1,6 @@ -import sys import json +import sys + import requests """ @@ -47,19 +48,15 @@ def create_project(katsu_server_url, project_title): try: r = requests.post(katsu_server_url + "/api/projects", json=project_request) except requests.exceptions.ConnectionError: - print("Connection to the API server {} cannot be established.".format(katsu_server_url)) + print(f"Connection to the API server {katsu_server_url} cannot be established.") sys.exit() if r.status_code == 201: project_uuid = r.json()["identifier"] - print("Project {} with uuid {} has been created!".format(project_title, project_uuid)) + print(f"Project {project_title} with uuid {project_uuid} has been created!") return project_uuid elif r.status_code == 400: - print( - "A project of title '{}' exists, please choose a different title, or delete this project.".format( - project_title - ) - ) + print(f"A project of title '{project_title}' exists, please choose a different title, or delete this project.") sys.exit() else: print(r.json()) @@ -88,14 +85,10 @@ def create_dataset(katsu_server_url, project_uuid, dataset_title): if r2.status_code == 201: dataset_uuid = r2.json()["identifier"] - print("Dataset {} with uuid {} has been created!".format(dataset_title, dataset_uuid)) + print(f"Dataset {dataset_title} with uuid {dataset_uuid} has been created!") return dataset_uuid elif r2.status_code == 400: - print( - "A dataset of title '{}' exists, please choose a different title, or delete this dataset.".format( - dataset_title - ) - ) + print(f"A dataset of title '{dataset_title}' exists, please choose a different title, or delete this dataset.") sys.exit() else: print(r2.json()) @@ -115,7 +108,7 @@ def create_table(katsu_server_url, dataset_uuid, table_name): if r3.status_code == 200 or r3.status_code == 201: table_id = r3.json()["id"] - print("Table {} with uuid {} has been created!".format(table_name, table_id)) + print(f"Table {table_name} with uuid {table_id} has been created!") return table_id else: print("Something went wrong...") @@ -139,7 +132,7 @@ def ingest_phenopackets(katsu_server_url, table_id, phenopackets_json_location): r4 = requests.post(katsu_server_url + "/private/ingest", json=private_ingest_request) if r4.status_code == 200 or r4.status_code == 201 or r4.status_code == 204: - print("Phenopackets have been ingested from source at {}".format(phenopackets_json_location)) + print(f"Phenopackets have been ingested from source at {phenopackets_json_location}") elif r4.status_code == 400: print(r4.text) sys.exit() @@ -165,7 +158,7 @@ def main(): katsu_server_url = config["katsu_server_url"] phenopackets_json_location = config["phenopackets_json_location"] except KeyError as e: - print("Config file corrupted: missing key {}".format(str(e))) + print(f"Config file corrupted: missing key {e!s}") sys.exit() project_uuid = create_project(katsu_server_url, project_title) diff --git a/scripts/remove_from_db.py b/scripts/remove_from_db.py index 6edb8525c..5a7ed3919 100644 --- a/scripts/remove_from_db.py +++ b/scripts/remove_from_db.py @@ -1,5 +1,5 @@ -import sys import subprocess +import sys """ A script that automates the process of deleting the data @@ -26,15 +26,16 @@ def main(): for table in sys.argv[1:]: response = subprocess.run( - 'python ../manage.py shell --command="{}"'.format(script + "{}.objects.all().delete();".format(table)), + 'python ../manage.py shell --command="{}"'.format(script + f"{table}.objects.all().delete();"), shell=True, stderr=subprocess.PIPE, + check=False, ) if response.returncode: print(response.stderr) - print('"{}" does not seem to be a valid table'.format(table)) + print(f'"{table}" does not seem to be a valid table') else: - print("Deleted data on table {}".format(table)) + print(f"Deleted data on table {table}") if __name__ == "__main__":