diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 4f4be98f5..c5d95e142 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -40,7 +40,7 @@ repos: # https://docs.astral.sh/ruff/integrations/#pre-commit - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.14.9 + rev: v0.14.11 hooks: # Run the linter with fixes - id: ruff diff --git a/opal/caregivers/api/views.py b/opal/caregivers/api/views.py index ea98df790..0d4a9608c 100644 --- a/opal/caregivers/api/views.py +++ b/opal/caregivers/api/views.py @@ -56,7 +56,8 @@ class GetRegistrationEncryptionInfoView(RetrieveAPIView[RegistrationCode]): """Class handling gets requests for registration encryption values.""" queryset = ( - RegistrationCode.objects.select_related( + RegistrationCode.objects + .select_related( 'relationship', 'relationship__patient', ) @@ -198,7 +199,8 @@ def get_queryset(self) -> QuerySet[RegistrationCode]: """ code = self.kwargs.get('code') if hasattr(self, 'kwargs') else None return ( - RegistrationCode.objects.select_related( + RegistrationCode.objects + .select_related( 'relationship__caregiver', 'relationship__caregiver__user', ) @@ -523,7 +525,8 @@ def _get_email_address(self, relationship: Relationship, caregiver_data: dict[st # use the last one email_verifications: Manager[EmailVerification] = relationship.caregiver.email_verifications email_verification = ( - email_verifications.filter( + email_verifications + .filter( is_verified=True, ) .order_by('-sent_at') diff --git a/opal/conftest.py b/opal/conftest.py index 67d2a2a04..55a26ed41 100644 --- a/opal/conftest.py +++ b/opal/conftest.py @@ -371,11 +371,9 @@ def django_db_setup( Yields: None """ - with Path('opal/tests/sql/questionnairedb_functions.sql').open(encoding='utf-8') as handle: - sql_content = handle.read() + sql_content = Path('opal/tests/sql/questionnairedb_functions.sql').read_text(encoding='utf-8') - with Path('opal/tests/sql/questionnairedb_cleanup.sql').open(encoding='utf-8') as handle: - sql_cleanup = handle.read() + sql_cleanup = Path('opal/tests/sql/questionnairedb_cleanup.sql').read_text(encoding='utf-8') with django_db_blocker.unblock(), connections['questionnaire'].cursor() as conn: conn.execute(sql_content) @@ -410,11 +408,9 @@ def questionnaire_data(django_db_blocker: DjangoDbBlocker) -> Generator[None]: Yields: None """ - with Path('opal/tests/sql/questionnairedb_data.sql').open(encoding='utf-8') as handle: - sql_data = handle.read() + sql_data = Path('opal/tests/sql/questionnairedb_data.sql').read_text(encoding='utf-8') - with Path('opal/tests/sql/questionnairedb_cleanup.sql').open(encoding='utf-8') as handle: - sql_cleanup = handle.read() + sql_cleanup = Path('opal/tests/sql/questionnairedb_cleanup.sql').read_text(encoding='utf-8') with django_db_blocker.unblock(), connections['questionnaire'].cursor() as conn: # safety check to ensure that there is no data already diff --git a/opal/core/drf_parsers/hl7_parser.py b/opal/core/drf_parsers/hl7_parser.py index 5c30b70d6..e144e5877 100644 --- a/opal/core/drf_parsers/hl7_parser.py +++ b/opal/core/drf_parsers/hl7_parser.py @@ -39,7 +39,8 @@ def parse_pid_segment(segment: Segment) -> dict[str, Any]: return { 'first_name': segment.pid_5.pid_5_2.to_er7(), 'last_name': segment.pid_5.pid_5_1.to_er7(), - 'date_of_birth': datetime.strptime(segment.pid_7.to_er7(), FORMAT_DATE) + 'date_of_birth': datetime + .strptime(segment.pid_7.to_er7(), FORMAT_DATE) .astimezone(timezone.get_current_timezone()) .date(), 'sex': segment.pid_8.to_er7(), diff --git a/opal/health_data/api/views.py b/opal/health_data/api/views.py index 1d5390f6a..a419cdf44 100644 --- a/opal/health_data/api/views.py +++ b/opal/health_data/api/views.py @@ -127,7 +127,8 @@ def post(self, request: Request) -> Response: # Unviewed counts of patients' QuantitySamples unviewed_counts = ( - Patient.objects.select_related( + Patient.objects + .select_related( 'quantity_samples', ) .filter( diff --git a/opal/health_data/managers.py b/opal/health_data/managers.py index 07675299d..b333bd7d0 100644 --- a/opal/health_data/managers.py +++ b/opal/health_data/managers.py @@ -56,7 +56,8 @@ def fetch_blood_pressure_measurements( # Add .order_by() to remove ORDER BY statement that is added by default diastolic_measurements = ( - self.filter( + self + .filter( patient=patient, type=quantity_sample_models.QuantitySampleType.BLOOD_PRESSURE_DIASTOLIC, start_date=models.OuterRef('start_date'), @@ -69,7 +70,8 @@ def fetch_blood_pressure_measurements( # list() forces QuerySet evaluation that makes call to the database return list( - self.filter( + self + .filter( patient=patient, type=quantity_sample_models.QuantitySampleType.BLOOD_PRESSURE_SYSTOLIC, ) diff --git a/opal/health_data/utils.py b/opal/health_data/utils.py index 6cb7df854..8a2e0b2a6 100644 --- a/opal/health_data/utils.py +++ b/opal/health_data/utils.py @@ -42,7 +42,8 @@ def build_all_quantity_sample_charts(patient: Patient) -> dict[str, str | None]: # Build charts for the measurements that contain only one value for sample_type in SINGLE_VALUE_SAMPLE_TYPES: queryset = ( - QuantitySample.objects.order_by('start_date') + QuantitySample.objects + .order_by('start_date') .filter( patient=patient, type=sample_type, diff --git a/opal/hospital_settings/conftest.py b/opal/hospital_settings/conftest.py index c8dcb52f1..e49ed8515 100644 --- a/opal/hospital_settings/conftest.py +++ b/opal/hospital_settings/conftest.py @@ -75,8 +75,7 @@ def fixture_institution_form_files() -> dict[str, SimpleUploadedFile]: Returns: dictionary with two logo image files """ - with Path('opal/tests/fixtures/test_logo.png').open(mode='rb') as image_logo: - file_content = image_logo.read() + file_content = Path('opal/tests/fixtures/test_logo.png').read_bytes() return { 'logo_en': SimpleUploadedFile( diff --git a/opal/legacy/api/views/app_chart.py b/opal/legacy/api/views/app_chart.py index afd0f1215..df6f869c0 100644 --- a/opal/legacy/api/views/app_chart.py +++ b/opal/legacy/api/views/app_chart.py @@ -70,7 +70,8 @@ def get(self, request: Request, *args: Any, **kwargs: Any) -> Response: legacy_id, username, ).count(), - 'unread_educationalmaterial_count': models.LegacyEducationalMaterial.objects.get_unread_queryset( + 'unread_educationalmaterial_count': models.LegacyEducationalMaterial.objects + .get_unread_queryset( legacy_id, username, ) @@ -83,7 +84,8 @@ def get(self, request: Request, *args: Any, **kwargs: Any) -> Response: username, 1, ).count(), - 'unread_research_reference_count': models.LegacyEducationalMaterial.objects.get_unread_queryset( + 'unread_research_reference_count': models.LegacyEducationalMaterial.objects + .get_unread_queryset( legacy_id, username, ) diff --git a/opal/legacy/api/views/tests/test_app_chart.py b/opal/legacy/api/views/tests/test_app_chart.py index b1565641d..2346d012d 100644 --- a/opal/legacy/api/views/tests/test_app_chart.py +++ b/opal/legacy/api/views/tests/test_app_chart.py @@ -140,7 +140,8 @@ def test_get_unread_clinical_edumaterial_count(self, admin_api_client: APIClient # Direct function call edumaterials = ( - models.LegacyEducationalMaterial.objects.get_unread_queryset( + models.LegacyEducationalMaterial.objects + .get_unread_queryset( self.patient.patientsernum, self.user.username, ) @@ -165,7 +166,8 @@ def test_get_unread_research_edumaterial_count(self, admin_api_client: APIClient # Direct function call edumaterials = ( - models.LegacyEducationalMaterial.objects.get_unread_queryset( + models.LegacyEducationalMaterial.objects + .get_unread_queryset( self.patient.patientsernum, self.user.username, ) diff --git a/opal/legacy/factories.py b/opal/legacy/factories.py index 88efd702f..b774e5c4e 100644 --- a/opal/legacy/factories.py +++ b/opal/legacy/factories.py @@ -466,9 +466,9 @@ class Meta: normal_range_min = Faker('random_int') normal_range_max = Faker('random_int') normal_range = lazy_attribute( - lambda legacypatienttestresult: str(legacypatienttestresult.normal_range_min) - + '-' - + str(legacypatienttestresult.normal_range_max), + lambda legacypatienttestresult: ( + f'{legacypatienttestresult.normal_range_min} - {legacypatienttestresult.normal_range_max}' + ), ) test_value_numeric = Faker('pyfloat', positive=True) test_value_string = lazy_attribute(lambda legacypatienttestresult: str(legacypatienttestresult.test_value_numeric)) diff --git a/opal/legacy/managers.py b/opal/legacy/managers.py index 5be48c0d7..e9a224acd 100644 --- a/opal/legacy/managers.py +++ b/opal/legacy/managers.py @@ -130,7 +130,8 @@ def get_daily_appointments(self, username: str) -> models.QuerySet['LegacyAppoin if legacy_id is not None ] return ( - self.select_related( + self + .select_related( 'aliasexpressionsernum__aliassernum__appointmentcheckin', 'aliasexpressionsernum__aliassernum__educational_material_control_ser_num', ) @@ -161,7 +162,8 @@ def get_closest_appointment(self, username: str) -> Optional['LegacyAppointment' status=RelationshipStatus.CONFIRMED, ) return ( - self.filter( + self + .filter( scheduledstarttime__gte=timezone.localtime(timezone.now()), patientsernum__in=patient_ids, state='Active', @@ -190,7 +192,8 @@ def get_databank_data_for_patient( """ return ( - self.select_related( + self + .select_related( 'aliasexpressionsernum__aliassernum', 'source_database', 'patientsernum', @@ -327,7 +330,8 @@ def get_unread_queryset(self, patient_sernum_list: list[int], username: str) -> Count of unread announcement(s) records. """ return ( - self.exclude( + self + .exclude( readby__contains=username, ) .filter( @@ -357,7 +361,8 @@ def get_databank_data_for_patient( """ return ( - self.filter( + self + .filter( patientsernum=patient_ser_num, last_updated__gt=last_synchronized, ) @@ -413,7 +418,8 @@ def get_databank_data_for_patient( Diagnosis data """ return ( - self.filter( + self + .filter( patient_ser_num=patient_ser_num, last_updated__gt=last_synchronized, ) @@ -452,7 +458,8 @@ def get_databank_data_for_patient( Lab data """ return ( - self.select_related( + self + .select_related( 'test_expression_ser_num', 'test_group_expression_ser_num', 'patient_ser_num', @@ -540,7 +547,8 @@ def get_aggregated_user_app_activities( Annotated `LegacyPatientActivityLog` records """ return ( - self.filter( + self + .filter( date_time__gte=start_datetime_period, date_time__lt=end_datetime_period, ) @@ -638,7 +646,8 @@ def get_aggregated_patient_app_activities( # Whereas if Marge clicks on a TxTeamMessage from her chart page, # PAL shows Request=Read, Parameters={"Field":"TxTeamMessages","Id":"1"} return ( - self.filter( + self + .filter( date_time__gte=start_datetime_period, date_time__lt=end_datetime_period, ) diff --git a/opal/legacy/utils.py b/opal/legacy/utils.py index c0cf4b2d4..26932c190 100644 --- a/opal/legacy/utils.py +++ b/opal/legacy/utils.py @@ -671,7 +671,8 @@ def generate_questionnaire_report( patient_date_of_birth=patient.date_of_birth, patient_ramq=patient.ramq, patient_sites_and_mrns=list( - patient.hospital_patients.all() + patient.hospital_patients + .all() .annotate( site_code=models.F('site__acronym'), ) diff --git a/opal/patients/api/tests/test_api_views.py b/opal/patients/api/tests/test_api_views.py index b6833baf1..340b16c15 100644 --- a/opal/patients/api/tests/test_api_views.py +++ b/opal/patients/api/tests/test_api_views.py @@ -607,7 +607,8 @@ def test_demographic_update_deceased_patient( api_client.force_login(interface_engine_user) payload = self._get_valid_input_data() payload['date_of_death'] = ( - timezone.now() + timezone + .now() .astimezone() .replace( microsecond=0, @@ -1141,8 +1142,7 @@ def test_summary_saved( saved_file = Path(settings.MEDIA_ROOT) / spy_storage_save.spy_return assert saved_file.exists() - with Path(saved_file).open(encoding='utf-8') as f: - saved_data = f.read() + saved_data = Path(saved_file).read_text(encoding='utf-8') # base64 URL decode to have 32 bytes of data key_decoded = utils.base64url_decode(encryption_key.encode('utf-8')) diff --git a/opal/patients/management/commands/expire_relationships.py b/opal/patients/management/commands/expire_relationships.py index 8b1d64576..1e59210cb 100644 --- a/opal/patients/management/commands/expire_relationships.py +++ b/opal/patients/management/commands/expire_relationships.py @@ -30,7 +30,8 @@ def handle(self, *args: Any, **kwargs: Any) -> None: number_of_updates = 0 relationships_to_check = ( - Relationship.objects.select_related( + Relationship.objects + .select_related( 'patient', 'type', ) diff --git a/opal/patients/models.py b/opal/patients/models.py index 17e5ab3a7..a473b6571 100644 --- a/opal/patients/models.py +++ b/opal/patients/models.py @@ -508,7 +508,8 @@ def validate_type(self) -> list[str]: hasattr(self, 'patient') and self.type.role_type == RoleType.SELF # exclude the current instance to support updating it - and Relationship.objects.exclude( + and Relationship.objects + .exclude( pk=self.pk, ) .filter( @@ -523,7 +524,8 @@ def validate_type(self) -> list[str]: hasattr(self, 'caregiver') and self.type.role_type == RoleType.SELF # exclude the current instance to support updating it - and Relationship.objects.exclude( + and Relationship.objects + .exclude( pk=self.pk, ) .filter( @@ -574,7 +576,8 @@ def clean(self) -> None: hasattr(self, 'patient') and hasattr(self, 'caregiver') # exclude the current instance to support updating it - and Relationship.objects.exclude( + and Relationship.objects + .exclude( pk=self.pk, ) .filter( diff --git a/opal/patients/tests/test_forms.py b/opal/patients/tests/test_forms.py index 5a12f8fbb..2b2458757 100644 --- a/opal/patients/tests/test_forms.py +++ b/opal/patients/tests/test_forms.py @@ -922,7 +922,8 @@ def test_accessrequestrequestorform_form_filled_required_type(role_type: RoleTyp def test_accessrequestrequestorform_relationship_type(age: int, enabled_options: list[RoleType]) -> None: """Ensure the relationship_type field has the correct options enabled/disabled based on the patient's age.""" relationship_types = list( - RelationshipType.objects.filter( + RelationshipType.objects + .filter( role_type__in=enabled_options, ) .values_list('name', flat=True) @@ -955,7 +956,8 @@ def test_accessrequestrequestorform_relationship_type_existing_self() -> None: disabled_options = [option['label'] for option in options if option['attrs'].get('disabled', '') == 'disabled'] disabled_types = list( - RelationshipType.objects.filter( + RelationshipType.objects + .filter( role_type__in=[ RoleType.SELF, RoleType.GUARDIAN_CAREGIVER, diff --git a/opal/test_results/utils.py b/opal/test_results/utils.py index 28cb69bdb..ae74aad0c 100644 --- a/opal/test_results/utils.py +++ b/opal/test_results/utils.py @@ -58,7 +58,8 @@ def generate_pathology_report( patient_date_of_birth=patient.date_of_birth, patient_ramq=patient.ramq or '', patient_sites_and_mrns=list( - patient.hospital_patients.all() + patient.hospital_patients + .all() .annotate( site_code=models.F('site__acronym'), ) diff --git a/opal/usage_statistics/management/commands/update_daily_usage_statistics.py b/opal/usage_statistics/management/commands/update_daily_usage_statistics.py index 238122f18..de25c8d2a 100644 --- a/opal/usage_statistics/management/commands/update_daily_usage_statistics.py +++ b/opal/usage_statistics/management/commands/update_daily_usage_statistics.py @@ -164,7 +164,8 @@ def _populate_user_patient_app_activities( # Since between the same patient and caregiver might be many different relationships, # the query fetches only one record per patient <===> caregiver relationship with the maximum end_date relationships = ( - Relationship.objects.select_related( + Relationship.objects + .select_related( 'patient', 'caregiver__user', ) diff --git a/opal/usage_statistics/queries.py b/opal/usage_statistics/queries.py index 7c4360f64..829aa6f91 100644 --- a/opal/usage_statistics/queries.py +++ b/opal/usage_statistics/queries.py @@ -78,7 +78,8 @@ def fetch_grouped_registration_summary( group_field = group_by.name.lower() return list( - queryset.values( + queryset + .values( group_field, ) .annotate( @@ -287,7 +288,8 @@ def fetch_logins_summary( group_field = group_by.name.lower() return list( - queryset.values( + queryset + .values( group_field, ) .annotate( @@ -325,7 +327,8 @@ def fetch_users_clicks_summary( # TODO: QSCCD-2173 - add count of the announcement clicks return list( - queryset.values( + queryset + .values( group_field, ) .annotate( @@ -363,7 +366,8 @@ def fetch_user_patient_clicks_summary( group_field = group_by.name.lower() return list( - queryset.values( + queryset + .values( group_field, ) .annotate( @@ -558,7 +562,8 @@ def fetch_users_latest_login_year_summary( latest login statistics grouped by year for a given time period. """ latest_logins = ( - DailyUserAppActivity.objects.filter( + DailyUserAppActivity.objects + .filter( action_date__gte=start_date, action_date__lte=end_date, ) @@ -595,7 +600,8 @@ def fetch_labs_summary_per_patient( # TODO: update the query using `lab_groups_received` statistic field once QSCCD-2209 is implemented. # Update query should include `total_lab_groups_received` and `average_labs_per_test_group`. return list( - DailyPatientDataReceived.objects.filter( + DailyPatientDataReceived.objects + .filter( action_date__gte=start_date, action_date__lte=end_date, ) @@ -630,7 +636,8 @@ def fetch_logins_summary_per_user( individual login statistics (per user). """ return list( - DailyUserAppActivity.objects.filter( + DailyUserAppActivity.objects + .filter( action_date__gte=start_date, action_date__lte=end_date, ) @@ -670,13 +677,15 @@ def fetch_patient_demographic_diagnosis_summary( """ # TODO: QSCCD-2254 - update the query when Diagnosis model is implemented in django-backend latest_diagnosis_sernum_list = ( - legacy_models.LegacyDiagnosis.objects.values( + legacy_models.LegacyDiagnosis.objects + .values( 'patient_ser_num', ) .annotate( latest_diagnosis_date=models.Max('creation_date'), latest_diagnosis_sernum=models.Subquery( - legacy_models.LegacyDiagnosis.objects.filter( + legacy_models.LegacyDiagnosis.objects + .filter( patient_ser_num=models.OuterRef('patient_ser_num'), ) .order_by('-creation_date') @@ -689,7 +698,8 @@ def fetch_patient_demographic_diagnosis_summary( ) ) demographics_and_diagnosis = ( - legacy_models.LegacyPatientControl.objects.filter( + legacy_models.LegacyPatientControl.objects + .filter( models.Q(patient__legacydiagnosis__diagnosis_ser_num__in=latest_diagnosis_sernum_list) | models.Q(patient__legacydiagnosis__diagnosis_ser_num__isnull=True), patient__last_updated__date__gte=start_date, @@ -759,7 +769,8 @@ def _fetch_received_medical_records_summary( group_field = group_by.name.lower() return list( - queryset.values( + queryset + .values( group_field, ) .annotate( diff --git a/opal/usage_statistics/tests/test_commands.py b/opal/usage_statistics/tests/test_commands.py index 003c50f87..dfbfcc40f 100644 --- a/opal/usage_statistics/tests/test_commands.py +++ b/opal/usage_statistics/tests/test_commands.py @@ -399,7 +399,8 @@ def test_populate_last_login_user_statistics(self) -> None: ).first() assert marge_previous_day_app_activity marge_last_login_previous_day = ( - legacy_models.LegacyPatientActivityLog.objects.filter( + legacy_models.LegacyPatientActivityLog.objects + .filter( username=marge_caregiver.user, date_time__date=marge_previous_day_app_activity.action_date, ) diff --git a/opal/usage_statistics/tests/test_utils.py b/opal/usage_statistics/tests/test_utils.py index 1347bc3da..081f24025 100644 --- a/opal/usage_statistics/tests/test_utils.py +++ b/opal/usage_statistics/tests/test_utils.py @@ -948,7 +948,8 @@ def _fetch_annotated_relationships() -> models.QuerySet[patient_models.Relations date_time = timezone.now() relationships_queryset = patient_models.Relationship.objects.all() return ( - relationships_queryset.select_related( + relationships_queryset + .select_related( 'patient', 'caregiver__user', ) diff --git a/opal/usage_statistics/utils.py b/opal/usage_statistics/utils.py index 07218cce1..556a57f92 100644 --- a/opal/usage_statistics/utils.py +++ b/opal/usage_statistics/utils.py @@ -125,7 +125,8 @@ def get_aggregated_patient_received_data( # Use a slice (e.g., [:1]) instead of get()/first() # since the OuterRef cannot be resolved until the queryset is used within a Subquery. # https://docs.djangoproject.com/en/5.0/ref/models/expressions/#limiting-the-subquery-to-a-single-row - legacy_models.LegacyAppointment.objects.filter( + legacy_models.LegacyAppointment.objects + .filter( patientsernum=patient_out_ref, scheduledstarttime__lt=end_datetime_period, ) @@ -136,7 +137,8 @@ def get_aggregated_patient_received_data( # Retrieve the closest open/active appointment for every patient relatively to the requesting # date range, regardless of how far it might be. # E.g., the appointment might be later than the end of the range. - legacy_models.LegacyAppointment.objects.filter( + legacy_models.LegacyAppointment.objects + .filter( patientsernum=patient_out_ref, state='Active', status='Open', @@ -149,7 +151,8 @@ def get_aggregated_patient_received_data( # Use Coalesce to prevent an aggregate Count() from returning a None and return 0 instead. models.Subquery( # Aggregate how many appointments for every patient were received in the given date range. - legacy_models.LegacyAppointment.objects.filter( + legacy_models.LegacyAppointment.objects + .filter( patientsernum=patient_out_ref, date_added__range=date_added_range, ) @@ -166,7 +169,8 @@ def get_aggregated_patient_received_data( # Subqueries for Documents 'last_document_received': models.Subquery( # Retrieve the latest received document for every patient, regardless of how old it might be. - legacy_models.LegacyDocument.objects.filter( + legacy_models.LegacyDocument.objects + .filter( patientsernum=patient_out_ref, dateadded__lt=end_datetime_period, ) @@ -177,7 +181,8 @@ def get_aggregated_patient_received_data( # Use Coalesce to prevent an aggregate Count() from returning a None and return 0 instead. models.Subquery( # Aggregate how many documents for every patient were received in the given date range. - legacy_models.LegacyDocument.objects.filter( + legacy_models.LegacyDocument.objects + .filter( patientsernum=patient_out_ref, dateadded__range=date_added_range, ) @@ -195,7 +200,8 @@ def get_aggregated_patient_received_data( 'last_educational_material_received': models.Subquery( # Retrieve the latest received educational material for every patient, # regardless of how old it might be. - legacy_models.LegacyEducationalMaterial.objects.filter( + legacy_models.LegacyEducationalMaterial.objects + .filter( patientsernum=patient_out_ref, date_added__lt=end_datetime_period, ) @@ -206,7 +212,8 @@ def get_aggregated_patient_received_data( # Use Coalesce to prevent an aggregate Count() from returning a None and return 0 instead. models.Subquery( # Aggregate how many educational materials for every patient were received in the given date range. - legacy_models.LegacyEducationalMaterial.objects.filter( + legacy_models.LegacyEducationalMaterial.objects + .filter( patientsernum=patient_out_ref, date_added__range=date_added_range, ) @@ -223,7 +230,8 @@ def get_aggregated_patient_received_data( # Subqueries for Questionnaires 'last_questionnaire_received': models.Subquery( # Retrieve the latest received questionnaire for every patient, regardless of how old it might be. - legacy_models.LegacyQuestionnaire.objects.filter( + legacy_models.LegacyQuestionnaire.objects + .filter( patientsernum=patient_out_ref, date_added__lt=end_datetime_period, ) @@ -234,7 +242,8 @@ def get_aggregated_patient_received_data( # Use Coalesce to prevent an aggregate Count() from returning a None and return 0 instead. models.Subquery( # Aggregate how many questionnaires for every patient were received in the given date range. - legacy_models.LegacyQuestionnaire.objects.filter( + legacy_models.LegacyQuestionnaire.objects + .filter( patientsernum=patient_out_ref, date_added__range=date_added_range, ) @@ -252,7 +261,8 @@ def get_aggregated_patient_received_data( # Subqueries for Labs 'last_lab_received': models.Subquery( # Retrieve the latest received lab result for every patient, regardless of how old it might be. - legacy_models.LegacyPatientTestResult.objects.filter( + legacy_models.LegacyPatientTestResult.objects + .filter( patient_ser_num=patient_out_ref, date_added__lt=end_datetime_period, ) @@ -263,7 +273,8 @@ def get_aggregated_patient_received_data( # Use Coalesce to prevent an aggregate Count() from returning a None and return 0 instead. models.Subquery( # Aggregate how many lab results for every patient were received in the given date range. - legacy_models.LegacyPatientTestResult.objects.filter( + legacy_models.LegacyPatientTestResult.objects + .filter( patient_ser_num=patient_out_ref, date_added__range=date_added_range, ) diff --git a/opal/users/tests/test_commands.py b/opal/users/tests/test_commands.py index 454cfe6e4..a8a00a407 100644 --- a/opal/users/tests/test_commands.py +++ b/opal/users/tests/test_commands.py @@ -110,8 +110,7 @@ def test_recover_user_with_success(self) -> None: assert caregiver_models.SecurityAnswer.objects.count() == 0 assert caregiver_models.Device.objects.count() == 0 assert patient_models.HospitalPatient.objects.count() == 0 - with Path('test.json').open('w', encoding='utf-8') as file: - file.write(stdout) + Path('test.json').write_text(stdout, encoding='utf-8') stdout, _stderr = self._call_command('recover_account', 'test.json') assert stdout == 'Data successfully recovered! Please delete the backup file.\n' assert patient_models.Patient.objects.count() == 1 diff --git a/pyproject.toml b/pyproject.toml index 8acb84733..8fd5f67ae 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -75,7 +75,7 @@ dev = [ "pytest-randomly==4.0.1", "pytest-socket==0.7.0", "pytest-sugar==1.1.1", - "ruff==0.14.9", + "ruff==0.14.11", "types-beautifulsoup4==4.12.0.20250516", "types-fpdf2==2.8.4.20251031", "types-python-dateutil==2.9.0.20251115", diff --git a/uv.lock b/uv.lock index cb3a0d120..02c392440 100644 --- a/uv.lock +++ b/uv.lock @@ -144,7 +144,7 @@ dev = [ { name = "pytest-randomly", specifier = "==4.0.1" }, { name = "pytest-socket", specifier = "==0.7.0" }, { name = "pytest-sugar", specifier = "==1.1.1" }, - { name = "ruff", specifier = "==0.14.9" }, + { name = "ruff", specifier = "==0.14.11" }, { name = "types-beautifulsoup4", specifier = "==4.12.0.20250516" }, { name = "types-fpdf2", specifier = "==2.8.4.20251031" }, { name = "types-python-dateutil", specifier = "==2.9.0.20251115" }, @@ -2057,28 +2057,28 @@ wheels = [ [[package]] name = "ruff" -version = "0.14.9" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/f6/1b/ab712a9d5044435be8e9a2beb17cbfa4c241aa9b5e4413febac2a8b79ef2/ruff-0.14.9.tar.gz", hash = "sha256:35f85b25dd586381c0cc053f48826109384c81c00ad7ef1bd977bfcc28119d5b", size = 5809165, upload-time = "2025-12-11T21:39:47.381Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/b8/1c/d1b1bba22cffec02351c78ab9ed4f7d7391876e12720298448b29b7229c1/ruff-0.14.9-py3-none-linux_armv6l.whl", hash = "sha256:f1ec5de1ce150ca6e43691f4a9ef5c04574ad9ca35c8b3b0e18877314aba7e75", size = 13576541, upload-time = "2025-12-11T21:39:14.806Z" }, - { url = "https://files.pythonhosted.org/packages/94/ab/ffe580e6ea1fca67f6337b0af59fc7e683344a43642d2d55d251ff83ceae/ruff-0.14.9-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:ed9d7417a299fc6030b4f26333bf1117ed82a61ea91238558c0268c14e00d0c2", size = 13779363, upload-time = "2025-12-11T21:39:20.29Z" }, - { url = "https://files.pythonhosted.org/packages/7d/f8/2be49047f929d6965401855461e697ab185e1a6a683d914c5c19c7962d9e/ruff-0.14.9-py3-none-macosx_11_0_arm64.whl", hash = "sha256:d5dc3473c3f0e4a1008d0ef1d75cee24a48e254c8bed3a7afdd2b4392657ed2c", size = 12925292, upload-time = "2025-12-11T21:39:38.757Z" }, - { url = "https://files.pythonhosted.org/packages/9e/e9/08840ff5127916bb989c86f18924fd568938b06f58b60e206176f327c0fe/ruff-0.14.9-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:84bf7c698fc8f3cb8278830fb6b5a47f9bcc1ed8cb4f689b9dd02698fa840697", size = 13362894, upload-time = "2025-12-11T21:39:02.524Z" }, - { url = "https://files.pythonhosted.org/packages/31/1c/5b4e8e7750613ef43390bb58658eaf1d862c0cc3352d139cd718a2cea164/ruff-0.14.9-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:aa733093d1f9d88a5d98988d8834ef5d6f9828d03743bf5e338bf980a19fce27", size = 13311482, upload-time = "2025-12-11T21:39:17.51Z" }, - { url = "https://files.pythonhosted.org/packages/5b/3a/459dce7a8cb35ba1ea3e9c88f19077667a7977234f3b5ab197fad240b404/ruff-0.14.9-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6a1cfb04eda979b20c8c19550c8b5f498df64ff8da151283311ce3199e8b3648", size = 14016100, upload-time = "2025-12-11T21:39:41.948Z" }, - { url = "https://files.pythonhosted.org/packages/a6/31/f064f4ec32524f9956a0890fc6a944e5cf06c63c554e39957d208c0ffc45/ruff-0.14.9-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:1e5cb521e5ccf0008bd74d5595a4580313844a42b9103b7388eca5a12c970743", size = 15477729, upload-time = "2025-12-11T21:39:23.279Z" }, - { url = "https://files.pythonhosted.org/packages/7a/6d/f364252aad36ccd443494bc5f02e41bf677f964b58902a17c0b16c53d890/ruff-0.14.9-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:cd429a8926be6bba4befa8cdcf3f4dd2591c413ea5066b1e99155ed245ae42bb", size = 15122386, upload-time = "2025-12-11T21:39:33.125Z" }, - { url = "https://files.pythonhosted.org/packages/20/02/e848787912d16209aba2799a4d5a1775660b6a3d0ab3944a4ccc13e64a02/ruff-0.14.9-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ab208c1b7a492e37caeaf290b1378148f75e13c2225af5d44628b95fd7834273", size = 14497124, upload-time = "2025-12-11T21:38:59.33Z" }, - { url = "https://files.pythonhosted.org/packages/f3/51/0489a6a5595b7760b5dbac0dd82852b510326e7d88d51dbffcd2e07e3ff3/ruff-0.14.9-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:72034534e5b11e8a593f517b2f2f2b273eb68a30978c6a2d40473ad0aaa4cb4a", size = 14195343, upload-time = "2025-12-11T21:39:44.866Z" }, - { url = "https://files.pythonhosted.org/packages/f6/53/3bb8d2fa73e4c2f80acc65213ee0830fa0c49c6479313f7a68a00f39e208/ruff-0.14.9-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:712ff04f44663f1b90a1195f51525836e3413c8a773574a7b7775554269c30ed", size = 14346425, upload-time = "2025-12-11T21:39:05.927Z" }, - { url = "https://files.pythonhosted.org/packages/ad/04/bdb1d0ab876372da3e983896481760867fc84f969c5c09d428e8f01b557f/ruff-0.14.9-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:a111fee1db6f1d5d5810245295527cda1d367c5aa8f42e0fca9a78ede9b4498b", size = 13258768, upload-time = "2025-12-11T21:39:08.691Z" }, - { url = "https://files.pythonhosted.org/packages/40/d9/8bf8e1e41a311afd2abc8ad12be1b6c6c8b925506d9069b67bb5e9a04af3/ruff-0.14.9-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:8769efc71558fecc25eb295ddec7d1030d41a51e9dcf127cbd63ec517f22d567", size = 13326939, upload-time = "2025-12-11T21:39:53.842Z" }, - { url = "https://files.pythonhosted.org/packages/f4/56/a213fa9edb6dd849f1cfbc236206ead10913693c72a67fb7ddc1833bf95d/ruff-0.14.9-py3-none-musllinux_1_2_i686.whl", hash = "sha256:347e3bf16197e8a2de17940cd75fd6491e25c0aa7edf7d61aa03f146a1aa885a", size = 13578888, upload-time = "2025-12-11T21:39:35.988Z" }, - { url = "https://files.pythonhosted.org/packages/33/09/6a4a67ffa4abae6bf44c972a4521337ffce9cbc7808faadede754ef7a79c/ruff-0.14.9-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:7715d14e5bccf5b660f54516558aa94781d3eb0838f8e706fb60e3ff6eff03a8", size = 14314473, upload-time = "2025-12-11T21:39:50.78Z" }, - { url = "https://files.pythonhosted.org/packages/12/0d/15cc82da5d83f27a3c6b04f3a232d61bc8c50d38a6cd8da79228e5f8b8d6/ruff-0.14.9-py3-none-win32.whl", hash = "sha256:df0937f30aaabe83da172adaf8937003ff28172f59ca9f17883b4213783df197", size = 13202651, upload-time = "2025-12-11T21:39:26.628Z" }, - { url = "https://files.pythonhosted.org/packages/32/f7/c78b060388eefe0304d9d42e68fab8cffd049128ec466456cef9b8d4f06f/ruff-0.14.9-py3-none-win_amd64.whl", hash = "sha256:c0b53a10e61df15a42ed711ec0bda0c582039cf6c754c49c020084c55b5b0bc2", size = 14702079, upload-time = "2025-12-11T21:39:11.954Z" }, - { url = "https://files.pythonhosted.org/packages/26/09/7a9520315decd2334afa65ed258fed438f070e31f05a2e43dd480a5e5911/ruff-0.14.9-py3-none-win_arm64.whl", hash = "sha256:8e821c366517a074046d92f0e9213ed1c13dbc5b37a7fc20b07f79b64d62cc84", size = 13744730, upload-time = "2025-12-11T21:39:29.659Z" }, +version = "0.14.11" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d4/77/9a7fe084d268f8855d493e5031ea03fa0af8cc05887f638bf1c4e3363eb8/ruff-0.14.11.tar.gz", hash = "sha256:f6dc463bfa5c07a59b1ff2c3b9767373e541346ea105503b4c0369c520a66958", size = 5993417, upload-time = "2026-01-08T19:11:58.322Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f0/a6/a4c40a5aaa7e331f245d2dc1ac8ece306681f52b636b40ef87c88b9f7afd/ruff-0.14.11-py3-none-linux_armv6l.whl", hash = "sha256:f6ff2d95cbd335841a7217bdfd9c1d2e44eac2c584197ab1385579d55ff8830e", size = 12951208, upload-time = "2026-01-08T19:12:09.218Z" }, + { url = "https://files.pythonhosted.org/packages/5c/5c/360a35cb7204b328b685d3129c08aca24765ff92b5a7efedbdd6c150d555/ruff-0.14.11-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:6f6eb5c1c8033680f4172ea9c8d3706c156223010b8b97b05e82c59bdc774ee6", size = 13330075, upload-time = "2026-01-08T19:12:02.549Z" }, + { url = "https://files.pythonhosted.org/packages/1b/9e/0cc2f1be7a7d33cae541824cf3f95b4ff40d03557b575912b5b70273c9ec/ruff-0.14.11-py3-none-macosx_11_0_arm64.whl", hash = "sha256:f2fc34cc896f90080fca01259f96c566f74069a04b25b6205d55379d12a6855e", size = 12257809, upload-time = "2026-01-08T19:12:00.366Z" }, + { url = "https://files.pythonhosted.org/packages/a7/e5/5faab97c15bb75228d9f74637e775d26ac703cc2b4898564c01ab3637c02/ruff-0.14.11-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:53386375001773ae812b43205d6064dae49ff0968774e6befe16a994fc233caa", size = 12678447, upload-time = "2026-01-08T19:12:13.899Z" }, + { url = "https://files.pythonhosted.org/packages/1b/33/e9767f60a2bef779fb5855cab0af76c488e0ce90f7bb7b8a45c8a2ba4178/ruff-0.14.11-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a697737dce1ca97a0a55b5ff0434ee7205943d4874d638fe3ae66166ff46edbe", size = 12758560, upload-time = "2026-01-08T19:11:42.55Z" }, + { url = "https://files.pythonhosted.org/packages/eb/84/4c6cf627a21462bb5102f7be2a320b084228ff26e105510cd2255ea868e5/ruff-0.14.11-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6845ca1da8ab81ab1dce755a32ad13f1db72e7fba27c486d5d90d65e04d17b8f", size = 13599296, upload-time = "2026-01-08T19:11:30.371Z" }, + { url = "https://files.pythonhosted.org/packages/88/e1/92b5ed7ea66d849f6157e695dc23d5d6d982bd6aa8d077895652c38a7cae/ruff-0.14.11-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:e36ce2fd31b54065ec6f76cb08d60159e1b32bdf08507862e32f47e6dde8bcbf", size = 15048981, upload-time = "2026-01-08T19:12:04.742Z" }, + { url = "https://files.pythonhosted.org/packages/61/df/c1bd30992615ac17c2fb64b8a7376ca22c04a70555b5d05b8f717163cf9f/ruff-0.14.11-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:590bcc0e2097ecf74e62a5c10a6b71f008ad82eb97b0a0079e85defe19fe74d9", size = 14633183, upload-time = "2026-01-08T19:11:40.069Z" }, + { url = "https://files.pythonhosted.org/packages/04/e9/fe552902f25013dd28a5428a42347d9ad20c4b534834a325a28305747d64/ruff-0.14.11-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:53fe71125fc158210d57fe4da26e622c9c294022988d08d9347ec1cf782adafe", size = 14050453, upload-time = "2026-01-08T19:11:37.555Z" }, + { url = "https://files.pythonhosted.org/packages/ae/93/f36d89fa021543187f98991609ce6e47e24f35f008dfe1af01379d248a41/ruff-0.14.11-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a35c9da08562f1598ded8470fcfef2afb5cf881996e6c0a502ceb61f4bc9c8a3", size = 13757889, upload-time = "2026-01-08T19:12:07.094Z" }, + { url = "https://files.pythonhosted.org/packages/b7/9f/c7fb6ecf554f28709a6a1f2a7f74750d400979e8cd47ed29feeaa1bd4db8/ruff-0.14.11-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:0f3727189a52179393ecf92ec7057c2210203e6af2676f08d92140d3e1ee72c1", size = 13955832, upload-time = "2026-01-08T19:11:55.064Z" }, + { url = "https://files.pythonhosted.org/packages/db/a0/153315310f250f76900a98278cf878c64dfb6d044e184491dd3289796734/ruff-0.14.11-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:eb09f849bd37147a789b85995ff734a6c4a095bed5fd1608c4f56afc3634cde2", size = 12586522, upload-time = "2026-01-08T19:11:35.356Z" }, + { url = "https://files.pythonhosted.org/packages/2f/2b/a73a2b6e6d2df1d74bf2b78098be1572191e54bec0e59e29382d13c3adc5/ruff-0.14.11-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:c61782543c1231bf71041461c1f28c64b961d457d0f238ac388e2ab173d7ecb7", size = 12724637, upload-time = "2026-01-08T19:11:47.796Z" }, + { url = "https://files.pythonhosted.org/packages/f0/41/09100590320394401cd3c48fc718a8ba71c7ddb1ffd07e0ad6576b3a3df2/ruff-0.14.11-py3-none-musllinux_1_2_i686.whl", hash = "sha256:82ff352ea68fb6766140381748e1f67f83c39860b6446966cff48a315c3e2491", size = 13145837, upload-time = "2026-01-08T19:11:32.87Z" }, + { url = "https://files.pythonhosted.org/packages/3b/d8/e035db859d1d3edf909381eb8ff3e89a672d6572e9454093538fe6f164b0/ruff-0.14.11-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:728e56879df4ca5b62a9dde2dd0eb0edda2a55160c0ea28c4025f18c03f86984", size = 13850469, upload-time = "2026-01-08T19:12:11.694Z" }, + { url = "https://files.pythonhosted.org/packages/4e/02/bb3ff8b6e6d02ce9e3740f4c17dfbbfb55f34c789c139e9cd91985f356c7/ruff-0.14.11-py3-none-win32.whl", hash = "sha256:337c5dd11f16ee52ae217757d9b82a26400be7efac883e9e852646f1557ed841", size = 12851094, upload-time = "2026-01-08T19:11:45.163Z" }, + { url = "https://files.pythonhosted.org/packages/58/f1/90ddc533918d3a2ad628bc3044cdfc094949e6d4b929220c3f0eb8a1c998/ruff-0.14.11-py3-none-win_amd64.whl", hash = "sha256:f981cea63d08456b2c070e64b79cb62f951aa1305282974d4d5216e6e0178ae6", size = 14001379, upload-time = "2026-01-08T19:11:52.591Z" }, + { url = "https://files.pythonhosted.org/packages/c4/1c/1dbe51782c0e1e9cfce1d1004752672d2d4629ea46945d19d731ad772b3b/ruff-0.14.11-py3-none-win_arm64.whl", hash = "sha256:649fb6c9edd7f751db276ef42df1f3df41c38d67d199570ae2a7bd6cbc3590f0", size = 12938644, upload-time = "2026-01-08T19:11:50.027Z" }, ] [[package]]