clinicedc 2.0.4__py3-none-any.whl → 2.0.5__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of clinicedc might be problematic. Click here for more details.

Files changed (478) hide show
  1. {clinicedc-2.0.4.dist-info → clinicedc-2.0.5.dist-info}/METADATA +41 -45
  2. {clinicedc-2.0.4.dist-info → clinicedc-2.0.5.dist-info}/RECORD +478 -478
  3. edc_action_item/action.py +76 -54
  4. edc_action_item/action_item_notification.py +1 -3
  5. edc_action_item/action_with_notification.py +4 -4
  6. edc_action_item/create_action_item.py +2 -2
  7. edc_action_item/create_or_update_action_type.py +1 -1
  8. edc_action_item/data_fixers.py +4 -5
  9. edc_action_item/delete_action_item.py +0 -1
  10. edc_action_item/modeladmin_mixins.py +2 -4
  11. edc_action_item/modelform_mixins/modelform_mixins.py +1 -1
  12. edc_action_item/models/action_item.py +53 -38
  13. edc_action_item/models/action_model_mixin.py +17 -17
  14. edc_action_item/models/action_type.py +33 -13
  15. edc_action_item/models/reference.py +3 -2
  16. edc_action_item/site_action_items.py +13 -14
  17. edc_action_item/stubs.py +9 -9
  18. edc_action_item/templatetags/action_item_extras.py +2 -2
  19. edc_action_item/view_utils/action_item_button.py +3 -3
  20. edc_action_item/view_utils/action_item_popover_list_item.py +4 -4
  21. edc_adherence/form_validator_mixin.py +1 -1
  22. edc_adverse_event/action_items/ae_followup_action.py +1 -1
  23. edc_adverse_event/action_items/ae_initial_action.py +1 -1
  24. edc_adverse_event/action_items/ae_susar_action.py +1 -1
  25. edc_adverse_event/action_items/ae_tmg_action.py +1 -1
  26. edc_adverse_event/action_items/death_report_action.py +1 -2
  27. edc_adverse_event/action_items/death_report_tmg_action.py +1 -1
  28. edc_adverse_event/action_items/death_report_tmg_second_action.py +1 -1
  29. edc_adverse_event/action_items/hospitalization_action.py +1 -1
  30. edc_adverse_event/form_validator_mixins/death_report_form_validator.py +3 -3
  31. edc_adverse_event/form_validator_mixins/requires_death_report_form_validator_mixin.py +3 -4
  32. edc_adverse_event/form_validators/death_report_tmg.py +1 -1
  33. edc_adverse_event/model_mixins/ae_followup/ae_followup_methods_model_mixin.py +3 -3
  34. edc_adverse_event/model_mixins/ae_followup/ae_followup_model_mixin.py +3 -3
  35. edc_adverse_event/model_mixins/ae_initial/ae_initial_fields_model_mixin.py +0 -1
  36. edc_adverse_event/model_mixins/ae_initial/ae_initial_methods_model_mixin.py +3 -3
  37. edc_adverse_event/model_mixins/ae_initial/ae_initial_model_mixin.py +3 -3
  38. edc_adverse_event/model_mixins/ae_special_interest/aesi_methods_model_mixin.py +4 -4
  39. edc_adverse_event/model_mixins/ae_special_interest/aesi_model_mixin.py +3 -3
  40. edc_adverse_event/model_mixins/ae_susar/ae_susar_methods_model_mixin.py +4 -4
  41. edc_adverse_event/model_mixins/ae_susar/ae_susar_model_mixin.py +3 -3
  42. edc_adverse_event/model_mixins/ae_tmg/ae_tmg_fields_model_mixin.py +4 -5
  43. edc_adverse_event/model_mixins/ae_tmg/ae_tmg_methods_model_mixin.py +4 -4
  44. edc_adverse_event/model_mixins/ae_tmg/ae_tmg_model_mixin.py +3 -3
  45. edc_adverse_event/model_mixins/death_report/death_report_extra_fields_model_mixin.py +2 -3
  46. edc_adverse_event/model_mixins/death_report/death_report_model_mixin.py +11 -11
  47. edc_adverse_event/model_mixins/death_report/death_report_tmg_model_mixin.py +9 -11
  48. edc_adverse_event/model_mixins/death_report/simple_death_report_model_mixin.py +7 -6
  49. edc_adverse_event/model_mixins/hospitaization/hospitalization_model_mixin.py +0 -1
  50. edc_adverse_event/modeladmin_mixins/ae_followup_admin_mixin.py +9 -11
  51. edc_adverse_event/modeladmin_mixins/ae_initial_admin_mixin.py +4 -6
  52. edc_adverse_event/modeladmin_mixins/modeladmin_mixins.py +1 -1
  53. edc_adverse_event/modeladmin_mixins/utils.py +4 -4
  54. edc_adverse_event/models/signals.py +7 -19
  55. edc_adverse_event/pdf_reports/death_pdf_report.py +8 -9
  56. edc_adverse_event/templatetags/edc_adverse_event_extras.py +10 -20
  57. edc_adverse_event/urls.py +7 -3
  58. edc_adverse_event/utils.py +2 -2
  59. edc_adverse_event/view_utils/tmg_button.py +4 -4
  60. edc_appconfig/system_checks.py +1 -1
  61. edc_appointment/appointment_status_updater.py +14 -15
  62. edc_appointment/creators/appointment_creator.py +7 -11
  63. edc_appointment/creators/appointments_creator.py +1 -1
  64. edc_appointment/creators/unscheduled_appointment_creator.py +12 -13
  65. edc_appointment/form_validator_mixins/next_appointment_crf_form_validator_mixin.py +1 -3
  66. edc_appointment/form_validator_mixins/window_period_form_validator_mixin.py +7 -6
  67. edc_appointment/form_validators/appointment_form_validator.py +2 -4
  68. edc_appointment/form_validators/utils.py +4 -4
  69. edc_appointment/managers.py +4 -4
  70. edc_appointment/model_mixins/appointment_methods_model_mixin.py +2 -2
  71. edc_appointment/model_mixins/appointment_model_mixin.py +5 -5
  72. edc_appointment/model_mixins/window_period_model_mixin.py +1 -1
  73. edc_appointment/models/appointment.py +1 -1
  74. edc_appointment/skip_appointments.py +5 -6
  75. edc_appointment/stubs.py +12 -12
  76. edc_appointment/utils.py +41 -47
  77. edc_appointment/view_utils/appointment_button.py +3 -5
  78. edc_auth/admin/role_admin.py +5 -7
  79. edc_auth/auth_objects/default_roles.py +1 -3
  80. edc_auth/auth_updater/auth_updater.py +5 -7
  81. edc_auth/auth_updater/group_updater.py +8 -8
  82. edc_auth/auth_updater/role_updater.py +1 -2
  83. edc_auth/get_app_codenames.py +1 -3
  84. edc_auth/import_users.py +19 -19
  85. edc_auth/models/role.py +4 -3
  86. edc_auth/password_setter.py +6 -7
  87. edc_auth/send_new_credentials_to_user.py +2 -3
  88. edc_auth/site_auths.py +3 -3
  89. edc_consent/actions.py +4 -5
  90. edc_consent/consent_definition.py +8 -11
  91. edc_consent/consent_definition_extension.py +3 -3
  92. edc_consent/form_validators/__init__.py +1 -1
  93. edc_consent/model_mixins/__init__.py +2 -2
  94. edc_consent/model_mixins/consent_version_model_mixin.py +1 -1
  95. edc_consent/modeladmin_mixins/consent_model_admin_mixin.py +1 -2
  96. edc_consent/modelform_mixins/consent_modelform_mixin/consent_modelform_validation_mixin.py +3 -5
  97. edc_consent/site_consents.py +10 -15
  98. edc_consent/stubs.py +2 -2
  99. edc_consent/utils.py +1 -1
  100. edc_constants/utils.py +2 -4
  101. edc_crf/crf_form_validator_mixins.py +2 -2
  102. edc_crf/model_mixins/crf_no_manager_model_mixin.py +2 -2
  103. edc_crf/model_mixins/crf_status_model_mixin.py +1 -1
  104. edc_crf/models/crf_status.py +10 -12
  105. edc_crf/update_crf_status_command.py +1 -3
  106. edc_dashboard/management/commands/update_search_slugs.py +8 -11
  107. edc_dashboard/templatetags/edc_dashboard_extras.py +1 -1
  108. edc_dashboard/url_config.py +3 -3
  109. edc_dashboard/utils.py +3 -4
  110. edc_dashboard/views/dashboard_view.py +1 -1
  111. edc_data_manager/models/data_dictionary.py +1 -2
  112. edc_data_manager/models/data_query.py +3 -3
  113. edc_data_manager/models/query_rule.py +2 -2
  114. edc_data_manager/tasks.py +0 -2
  115. edc_device/device.py +1 -1
  116. edc_device/view_mixins.py +1 -1
  117. edc_document_status/fieldsets.py +1 -3
  118. edc_document_status/model_mixins.py +2 -2
  119. edc_document_status/modeladmin_mixins.py +1 -4
  120. edc_egfr/admin/egfr_drop_notification_admin_mixin.py +5 -7
  121. edc_egfr/egfr.py +6 -7
  122. edc_egfr/get_drop_notification_model.py +1 -1
  123. edc_egfr/model_mixins/egfr_drop_notification_model_mixin.py +1 -1
  124. edc_export/archive_exporter.py +26 -27
  125. edc_export/exportables.py +2 -3
  126. edc_export/management/commands/import_receipts.py +6 -6
  127. edc_export/model_exporter/file_history_updater.py +1 -1
  128. edc_export/model_exporter/model_exporter.py +1 -1
  129. edc_export/model_exporter/value_getter.py +6 -6
  130. edc_export/model_mixins/notification_model_mixin.py +4 -4
  131. edc_export/models/data_request.py +3 -3
  132. edc_export/models/data_request_history.py +2 -2
  133. edc_export/models/export_receipt.py +1 -1
  134. edc_export/models/file_history.py +5 -5
  135. edc_export/models/plan.py +4 -4
  136. edc_export/models/upload_export_receipt_file.py +2 -2
  137. edc_export/utils.py +1 -1
  138. edc_facility/facility.py +6 -6
  139. edc_facility/holidays.py +2 -5
  140. edc_facility/import_holidays.py +6 -6
  141. edc_facility/model_mixins.py +1 -1
  142. edc_facility/models/holiday.py +1 -1
  143. edc_facility/utils.py +3 -3
  144. edc_fieldsets/fieldsets.py +1 -1
  145. edc_form_describer/forms_reference.py +5 -8
  146. edc_form_describer/make_forms_reference.py +1 -1
  147. edc_form_describer/management/commands/make_forms_reference.py +1 -1
  148. edc_form_label/custom_label_condition.py +1 -1
  149. edc_form_label/form_label.py +2 -2
  150. edc_form_runners/exceptions.py +1 -1
  151. edc_form_runners/models/issue.py +3 -2
  152. edc_form_runners/site.py +2 -2
  153. edc_form_runners/templatetags/form_runners_extras.py +1 -1
  154. edc_form_runners/utils.py +5 -5
  155. edc_form_validators/applicable_field_validator.py +32 -32
  156. edc_form_validators/base_form_validator.py +1 -1
  157. edc_form_validators/extra_mixins/study_day_form_validator.py +1 -1
  158. edc_form_validators/many_to_many_field_validator.py +38 -43
  159. edc_form_validators/other_specify_field_validator.py +9 -17
  160. edc_form_validators/required_field_validator.py +34 -39
  161. edc_form_validators/test_case_mixin.py +5 -5
  162. edc_identifier/admin.py +1 -3
  163. edc_identifier/identifier.py +2 -3
  164. edc_identifier/model_mixins.py +5 -8
  165. edc_identifier/research_identifier.py +10 -12
  166. edc_identifier/short_identifier.py +1 -1
  167. edc_identifier/simple_identifier.py +22 -22
  168. edc_identifier/utils.py +1 -1
  169. edc_lab/admin/fieldsets.py +7 -9
  170. edc_lab/admin/modeladmin_mixins.py +5 -6
  171. edc_lab/form_validators/requisition_form_validator_mixin.py +2 -3
  172. edc_lab/forms/box_form.py +5 -11
  173. edc_lab/identifiers/aliquot_identifier.py +5 -8
  174. edc_lab/identifiers/prefix.py +2 -5
  175. edc_lab/lab/aliquot_creator.py +1 -2
  176. edc_lab/lab/aliquot_type.py +2 -4
  177. edc_lab/lab/manifest.py +5 -7
  178. edc_lab/lab/requisition_panel.py +2 -4
  179. edc_lab/lab/requisition_panel_group.py +5 -7
  180. edc_lab/model_mixins/requisition/requisition_model_mixin.py +5 -4
  181. edc_lab/model_mixins/shipping/manifest_model_mixin.py +6 -6
  182. edc_lab/model_mixins/shipping/verify_model_mixin.py +4 -3
  183. edc_lab/models/aliquot.py +1 -1
  184. edc_lab/models/box.py +2 -2
  185. edc_lab/models/box_item.py +1 -1
  186. edc_lab/models/box_type.py +1 -1
  187. edc_lab/models/manifest/manifest_item.py +1 -1
  188. edc_lab/pdf_reports/manifest_pdf_report.py +3 -7
  189. edc_lab/site_labs.py +3 -3
  190. edc_lab_dashboard/dashboard_templates.py +1 -1
  191. edc_lab_dashboard/view_mixins/box_view_mixin.py +4 -9
  192. edc_lab_dashboard/views/action_views/action_view.py +1 -2
  193. edc_lab_dashboard/views/action_views/manage_manifest_view.py +1 -1
  194. edc_lab_dashboard/views/action_views/manifest_view.py +9 -11
  195. edc_lab_dashboard/views/action_views/pack_view.py +11 -14
  196. edc_lab_results/calculate_missing.py +2 -2
  197. edc_lab_results/fieldsets.py +6 -6
  198. edc_lab_results/model_mixin_factories/__init__.py +2 -2
  199. edc_lab_results/model_mixin_factories/reportable_result_model_mixin_factory.py +7 -9
  200. edc_lab_results/model_mixin_factories/result_model_mixin_factory.py +7 -9
  201. edc_lab_results/model_mixins/fbg_model_mixin.py +1 -1
  202. edc_lab_results/model_mixins/glucose_model_mixin.py +1 -1
  203. edc_label/admin.py +1 -3
  204. edc_label/label.py +2 -4
  205. edc_label/label_template.py +1 -1
  206. edc_label/subject_label.py +1 -3
  207. edc_list_data/admin.py +3 -5
  208. edc_list_data/load_list_data.py +1 -1
  209. edc_list_data/load_model_data.py +1 -3
  210. edc_list_data/model_mixins.py +3 -5
  211. edc_list_data/preload_data.py +2 -4
  212. edc_list_data/site_list_data.py +6 -7
  213. edc_listboard/filters/listboard_filter.py +2 -2
  214. edc_listboard/views/listboard_view.py +1 -3
  215. edc_locator/models.py +2 -2
  216. edc_locator/view_mixins/subject_locator_view_mixins.py +2 -2
  217. edc_ltfu/action_items.py +1 -1
  218. edc_ltfu/model_mixins.py +0 -2
  219. edc_ltfu/models.py +4 -4
  220. edc_metadata/admin/modeladmin_mixins.py +1 -1
  221. edc_metadata/admin/requisition_metadata.py +2 -4
  222. edc_metadata/metadata/crf_metadata_getter.py +1 -3
  223. edc_metadata/metadata/requisition_metadata_getter.py +1 -3
  224. edc_metadata/metadata_handler.py +2 -2
  225. edc_metadata/metadata_helper/metadata_helper_mixin.py +2 -3
  226. edc_metadata/metadata_mixins/source_model_metadata_mixin.py +2 -2
  227. edc_metadata/metadata_refresher.py +1 -1
  228. edc_metadata/metadata_rules/crf/crf_rule_group.py +3 -5
  229. edc_metadata/metadata_rules/logic.py +1 -1
  230. edc_metadata/metadata_rules/requisition/requisition_rule.py +4 -4
  231. edc_metadata/metadata_rules/requisition/requisition_rule_group.py +2 -2
  232. edc_metadata/metadata_rules/rule_evaluator.py +5 -6
  233. edc_metadata/metadata_rules/rule_group_metaclass.py +2 -3
  234. edc_metadata/metadata_rules/site.py +6 -7
  235. edc_metadata/metadata_updater.py +2 -2
  236. edc_metadata/metadata_wrappers/metadata_wrapper.py +4 -4
  237. edc_metadata/model_mixins/creates/creates_metadata_model_mixin.py +6 -7
  238. edc_metadata/model_mixins/updates/updates_crf_metadata_model_mixin.py +2 -2
  239. edc_metadata/model_mixins/updates/updates_metadata_model_mixin.py +2 -2
  240. edc_metadata/model_mixins/updates/updates_requisition_metadata_model_mixin.py +2 -2
  241. edc_metadata/models/crf_metadata.py +27 -29
  242. edc_metadata/models/crf_metadata_model_mixin.py +1 -1
  243. edc_metadata/models/requisition_metadata.py +29 -31
  244. edc_metadata/stubs.py +17 -17
  245. edc_metadata/utils.py +4 -4
  246. edc_model/__init__.py +2 -2
  247. edc_model/models/historical_records.py +2 -2
  248. edc_model/models/signals.py +1 -1
  249. edc_model/models/url_model_mixin.py +1 -1
  250. edc_model/utils.py +0 -2
  251. edc_model_admin/dashboard/model_admin_dashboard_mixin.py +1 -3
  252. edc_model_admin/history/model_admin_simple_history.py +7 -9
  253. edc_model_admin/mixins/base_model_admin_redirect_mixin.py +4 -6
  254. edc_model_admin/mixins/model_admin_limit_to_selected_foreignkey.py +2 -2
  255. edc_model_admin/mixins/model_admin_model_redirect_mixin.py +2 -10
  256. edc_model_admin/mixins/model_admin_next_url_redirect_mixin.py +8 -9
  257. edc_model_admin/utils.py +6 -9
  258. edc_model_form/mixins/__init__.py +1 -1
  259. edc_model_form/mixins/base_model_form_mixin.py +1 -1
  260. edc_model_to_dataframe/model_to_dataframe.py +2 -4
  261. edc_navbar/site_navbars.py +2 -2
  262. edc_navbar/system_checks.py +1 -1
  263. edc_notification/mailing_list_manager.py +5 -8
  264. edc_notification/management/commands/list_recipients_by_notification.py +1 -1
  265. edc_notification/models/__init__.py +4 -2
  266. edc_notification/notification/graded_event_notification.py +2 -4
  267. edc_notification/notification/model_notification.py +1 -3
  268. edc_notification/notification/notification.py +14 -17
  269. edc_notification/site_notifications.py +7 -7
  270. edc_notification/stubs.py +6 -6
  271. edc_notification/update_mailing_lists_in_m2m.py +2 -2
  272. edc_offstudy/action_items.py +2 -2
  273. edc_offstudy/model_mixins/offstudy_model_mixin.py +1 -1
  274. edc_offstudy/models.py +1 -1
  275. edc_pdf_reports/crf_pdf_report.py +2 -2
  276. edc_pdf_reports/model_mixins.py +2 -2
  277. edc_pdf_reports/report.py +4 -5
  278. edc_pdf_reports/utils.py +1 -1
  279. edc_pdutils/dataframes/get_subject_consent.py +1 -3
  280. edc_pdutils/df_exporters/csv_exporter.py +5 -7
  281. edc_pdutils/df_exporters/tables_exporter.py +2 -2
  282. edc_pdutils/df_handlers/crf_df_handler.py +1 -2
  283. edc_pdutils/dialects/crf_dialect.py +3 -3
  284. edc_pdutils/management/commands/export_models.py +6 -7
  285. edc_pdutils/site_values_mappings.py +2 -2
  286. edc_pdutils/utils/datetime_to_date.py +1 -2
  287. edc_pdutils/utils/refresh_model_from_dataframe.py +1 -3
  288. edc_pdutils/utils/table_names.py +2 -4
  289. edc_pdutils/utils/undash.py +1 -1
  290. edc_pharmacy/admin/medication/assignment_admin.py +2 -4
  291. edc_pharmacy/admin/medication/dosage_guideline_admin.py +2 -4
  292. edc_pharmacy/admin/medication/formulation_admin.py +3 -5
  293. edc_pharmacy/admin/medication/medication_admin.py +3 -5
  294. edc_pharmacy/admin/prescription/rx_refill_admin.py +7 -9
  295. edc_pharmacy/admin/stock/lot_admin.py +5 -7
  296. edc_pharmacy/admin/stock/order_admin.py +2 -2
  297. edc_pharmacy/admin/stock/order_item_admin.py +6 -6
  298. edc_pharmacy/admin/stock/receive_admin.py +1 -1
  299. edc_pharmacy/admin/stock/receive_item_admin.py +2 -2
  300. edc_pharmacy/admin/stock/stock_request_admin.py +4 -6
  301. edc_pharmacy/dosage_calculator.py +4 -4
  302. edc_pharmacy/form_validators/crf/study_medication_form_validator.py +8 -8
  303. edc_pharmacy/forms/stock/stock_request_form.py +2 -4
  304. edc_pharmacy/model_mixins/study_medication_crf_model_mixin.py +2 -2
  305. edc_pharmacy/models/medication/formulation.py +3 -4
  306. edc_pharmacy/models/medication/medication.py +1 -2
  307. edc_pharmacy/models/prescription/rx.py +2 -2
  308. edc_pharmacy/models/prescription/rx_refill.py +7 -9
  309. edc_pharmacy/models/reports/stock_availability.py +3 -4
  310. edc_pharmacy/models/stock/confirmation_at_site.py +1 -3
  311. edc_pharmacy/models/stock/order.py +1 -2
  312. edc_pharmacy/models/stock/receive.py +3 -4
  313. edc_pharmacy/models/stock/receive_item.py +2 -3
  314. edc_pharmacy/models/stock/stock.py +1 -2
  315. edc_pharmacy/models/stock/stock_adjustment.py +1 -2
  316. edc_pharmacy/models/stock/stock_request.py +4 -5
  317. edc_pharmacy/models/storage/box.py +1 -1
  318. edc_pharmacy/models/storage/items/container_model_mixin.py +1 -1
  319. edc_pharmacy/models/storage/room.py +1 -1
  320. edc_pharmacy/models/storage/shelf.py +1 -1
  321. edc_pharmacy/models/storage/utils.py +15 -16
  322. edc_pharmacy/prescribe/create_prescription.py +5 -5
  323. edc_pharmacy/refill/refill_creator.py +1 -1
  324. edc_pharmacy/sample_usb_printing/usb_printing.py +1 -1
  325. edc_pharmacy/utils/__init__.py +1 -1
  326. edc_pharmacy/utils/confirm_stock.py +3 -3
  327. edc_pharmacy/utils/confirm_stock_at_site.py +9 -8
  328. edc_pharmacy/utils/dispense.py +5 -8
  329. edc_pharmacy/utils/format_qty.py +3 -3
  330. edc_pharmacy/utils/get_codenames.py +1 -1
  331. edc_pharmacy/utils/miscellaneous.py +1 -1
  332. edc_pharmacy/utils/process_repack_request.py +18 -19
  333. edc_pharmacy/utils/process_repack_request_queryset.py +0 -2
  334. edc_pharmacy/utils/stock_request/bulk_create_stock_request_items.py +2 -3
  335. edc_pharmacy/views/add_to_storage_bin_view.py +1 -1
  336. edc_pharmacy/views/allocate_to_subject_view.py +2 -6
  337. edc_pharmacy/views/confirm_stock_from_instance_view.py +4 -4
  338. edc_pharmacy/views/confirm_stock_from_queryset_view.py +1 -5
  339. edc_pharmacy/views/confirmation_at_site_view.py +2 -3
  340. edc_pharmacy/views/dispense_view.py +1 -1
  341. edc_pharmacy/views/move_to_storage_bin_view.py +2 -3
  342. edc_pharmacy/views/print_labels_view.py +30 -31
  343. edc_pharmacy/views/transfer_stock_view.py +1 -1
  344. edc_prn/prn.py +1 -1
  345. edc_prn/site_prn_forms.py +1 -2
  346. edc_protocol_incident/action_items.py +2 -2
  347. edc_protocol_incident/model_mixins/protocol_deviation_violation_model_mixin.py +3 -3
  348. edc_protocol_incident/model_mixins/protocol_incident_model_mixin.py +3 -5
  349. edc_protocol_incident/modeladmin_mixins.py +3 -5
  350. edc_protocol_incident/models/protocol_deviation_violation.py +5 -5
  351. edc_protocol_incident/models/protocol_incident.py +5 -5
  352. edc_pylabels/site_label_configs.py +5 -5
  353. edc_qareports/model_mixins/qa_report_model_mixin.py +4 -2
  354. edc_qareports/models/qa_reports_log.py +1 -2
  355. edc_qareports/utils.py +1 -2
  356. edc_randomization/admin.py +3 -5
  357. edc_randomization/auth_objects.py +2 -3
  358. edc_randomization/blinding.py +1 -1
  359. edc_randomization/constants.py +2 -4
  360. edc_randomization/model_mixins.py +3 -3
  361. edc_randomization/randomization_list_importer.py +13 -14
  362. edc_randomization/randomization_list_verifier.py +11 -13
  363. edc_randomization/randomizer.py +2 -2
  364. edc_randomization/system_checks.py +1 -2
  365. edc_randomization/utils.py +5 -5
  366. edc_refusal/admin.py +1 -1
  367. edc_refusal/model_mixins.py +1 -1
  368. edc_refusal/utils.py +1 -1
  369. edc_registration/model_mixins/updates_or_creates_registered_subject_model_mixin.py +2 -2
  370. edc_registration/modeladmin_mixins.py +4 -7
  371. edc_registration/models/registered_subject.py +7 -9
  372. edc_registration/utils.py +3 -4
  373. edc_reportable/data/grading_data/daids_july_2017.py +3 -3
  374. edc_reportable/evaluator.py +5 -5
  375. edc_reportable/formula.py +1 -1
  376. edc_reportable/reference_range_evaluator.py +3 -3
  377. edc_reportable/utils/convert_units.py +10 -12
  378. edc_reportable/utils/grading_data_model_cls.py +2 -2
  379. edc_reportable/utils/grading_exception_model_cls.py +2 -2
  380. edc_reportable/utils/molecular_weight_model_cls.py +2 -2
  381. edc_reportable/utils/normal_data_model_cls.py +2 -2
  382. edc_reportable/utils/reference_range_colllection_model_cls.py +2 -2
  383. edc_screening/age_evaluator.py +2 -4
  384. edc_screening/eligibility.py +1 -1
  385. edc_screening/form_validator_mixins.py +2 -2
  386. edc_screening/model_mixins/screening_methods_model_mixin.py +1 -1
  387. edc_screening/screening_eligibility.py +1 -1
  388. edc_screening/utils.py +4 -6
  389. edc_search/model_mixins.py +1 -1
  390. edc_search/search_slug.py +1 -3
  391. edc_search/updater.py +1 -1
  392. edc_sites/admin/site_model_admin_mixin.py +2 -2
  393. edc_sites/model_mixins/site_model_mixin.py +1 -2
  394. edc_sites/modelform_mixins.py +2 -2
  395. edc_sites/models/__init__.py +1 -1
  396. edc_sites/models/site_profile.py +4 -4
  397. edc_sites/site.py +24 -32
  398. edc_sites/system_checks.py +1 -1
  399. edc_sites/utils/get_message_text.py +1 -1
  400. edc_sites/utils/valid_site_for_subject_or_raise.py +5 -6
  401. edc_subject_dashboard/requisition_report.py +4 -5
  402. edc_subject_dashboard/requisition_verifier.py +4 -2
  403. edc_subject_dashboard/templatetags/edc_subject_dashboard_extras.py +16 -17
  404. edc_subject_dashboard/view_utils/__init__.py +1 -1
  405. edc_subject_dashboard/view_utils/crf_button.py +1 -3
  406. edc_subject_dashboard/view_utils/subject_consent_dashboard_button.py +2 -2
  407. edc_subject_dashboard/view_utils/subject_consent_listboard_button.py +2 -2
  408. edc_subject_dashboard/view_utils/timepoint_status_button.py +1 -4
  409. edc_subject_dashboard/views/requisition_print_actions_view.py +2 -2
  410. edc_subject_dashboard/views/subject_dashboard_view.py +1 -1
  411. edc_timepoint/model_mixins.py +2 -2
  412. edc_transfer/action_items.py +1 -1
  413. edc_transfer/model_mixins.py +4 -3
  414. edc_transfer/modeladmin_mixins.py +3 -6
  415. edc_unblinding/action_items.py +2 -2
  416. edc_unblinding/models/unblinding_request.py +3 -3
  417. edc_unblinding/models/unblinding_review.py +3 -3
  418. edc_utils/__init__.py +6 -5
  419. edc_utils/age.py +1 -1
  420. edc_utils/celery.py +3 -8
  421. edc_utils/get_static_file.py +1 -1
  422. edc_utils/text.py +5 -6
  423. edc_view_utils/__init__.py +3 -3
  424. edc_view_utils/dashboard_model_button.py +4 -4
  425. edc_view_utils/model_button.py +7 -8
  426. edc_view_utils/perms.py +3 -3
  427. edc_visit_schedule/action_items.py +2 -2
  428. edc_visit_schedule/admin/list_filters.py +11 -9
  429. edc_visit_schedule/admin/subject_schedule_history_admin.py +13 -15
  430. edc_visit_schedule/admin/visit_schedule_admin.py +7 -7
  431. edc_visit_schedule/fieldsets.py +4 -6
  432. edc_visit_schedule/management/commands/find_invalid_onschedules.py +1 -1
  433. edc_visit_schedule/model_mixins/off_schedule_model_mixin.py +3 -1
  434. edc_visit_schedule/model_mixins/on_schedule_model_mixin.py +1 -1
  435. edc_visit_schedule/modelform_mixins/__init__.py +1 -1
  436. edc_visit_schedule/modelform_mixins/off_schedule_modelform_mixin.py +1 -2
  437. edc_visit_schedule/models/subject_schedule_history.py +2 -1
  438. edc_visit_schedule/models/visit_schedule.py +2 -2
  439. edc_visit_schedule/schedule/schedule.py +11 -12
  440. edc_visit_schedule/schedule/visit_collection.py +4 -3
  441. edc_visit_schedule/schedule/window.py +19 -12
  442. edc_visit_schedule/site_visit_schedules.py +9 -9
  443. edc_visit_schedule/subject_schedule.py +6 -7
  444. edc_visit_schedule/system_checks.py +1 -1
  445. edc_visit_schedule/view_mixins.py +1 -1
  446. edc_visit_schedule/visit/crf.py +3 -7
  447. edc_visit_schedule/visit/requisition.py +2 -2
  448. edc_visit_schedule/visit/visit.py +6 -7
  449. edc_visit_schedule/visit/window_period.py +8 -8
  450. edc_visit_schedule/visit_schedule/schedules_collection.py +2 -5
  451. edc_visit_tracking/action_items.py +11 -13
  452. edc_visit_tracking/form_validators/visit_form_validator.py +5 -5
  453. edc_visit_tracking/model_mixins/base/visit_methods_model_mixin.py +3 -4
  454. edc_visit_tracking/model_mixins/crfs/visit_tracking_crf_model_mixin.py +2 -2
  455. edc_visit_tracking/model_mixins/subject_visit_missed_model_mixin.py +2 -3
  456. edc_visit_tracking/model_mixins/utils.py +1 -1
  457. edc_visit_tracking/model_mixins/visit_model_mixin/previous_visit_model_mixin.py +2 -2
  458. edc_visit_tracking/model_mixins/visit_model_mixin/visit_model_mixin.py +3 -3
  459. edc_visit_tracking/modeladmin_mixins/crf_model_admin_mixin.py +6 -4
  460. edc_visit_tracking/modeladmin_mixins/visit_model_admin_mixin.py +6 -7
  461. edc_visit_tracking/modelform_mixins/crf/visit_tracking_crf_modelform_mixin.py +4 -5
  462. edc_visit_tracking/modelform_mixins/visit_tracking_modelform_mixin.py +3 -4
  463. edc_visit_tracking/models/subject_visit.py +1 -1
  464. edc_visit_tracking/models/subject_visit_missed.py +1 -1
  465. edc_visit_tracking/stubs.py +7 -7
  466. edc_visit_tracking/typing_stubs.py +11 -11
  467. edc_visit_tracking/utils.py +5 -5
  468. edc_visit_tracking/view_utils/related_visit_button.py +5 -5
  469. edc_vitals/calculators/bmi.py +1 -1
  470. edc_vitals/form_validators/blood_pressure_form_validator_mixin.py +8 -12
  471. edc_vitals/form_validators/bmi_form_validator_mixin.py +1 -1
  472. edc_vitals/form_validators/weight_height_with_bmi_form_validator_mixin.py +5 -2
  473. edc_vitals/model_mixins/blood_pressure_model_mixin.py +3 -4
  474. edc_vitals/model_mixins/weight_height_bmi_model_mixin.py +4 -4
  475. edc_vitals/utils.py +1 -1
  476. edc_vitals/validators.py +1 -1
  477. {clinicedc-2.0.4.dist-info → clinicedc-2.0.5.dist-info}/WHEEL +0 -0
  478. {clinicedc-2.0.4.dist-info → clinicedc-2.0.5.dist-info}/licenses/LICENSE +0 -0
@@ -59,17 +59,15 @@ class RandomizationListVerifier:
59
59
  "Resolve this issue before using the system."
60
60
  )
61
61
 
62
- else:
63
- if not self.randomizationlist_path or not self.randomizationlist_path.exists():
64
- self.messages.append(
65
- f"Randomization list file does not exist but SIDs "
66
- f"have been loaded. Expected file "
67
- f"{self.randomizationlist_path}. "
68
- f"Resolve this issue before using the system."
69
- )
70
- else:
71
- if message := self.verify():
72
- self.messages.append(message)
62
+ elif not self.randomizationlist_path or not self.randomizationlist_path.exists():
63
+ self.messages.append(
64
+ f"Randomization list file does not exist but SIDs "
65
+ f"have been loaded. Expected file "
66
+ f"{self.randomizationlist_path}. "
67
+ f"Resolve this issue before using the system."
68
+ )
69
+ elif message := self.verify():
70
+ self.messages.append(message)
73
71
  if self.messages:
74
72
  if (
75
73
  "migrate" not in sys.argv
@@ -118,7 +116,7 @@ class RandomizationListVerifier:
118
116
  f"{self.randomizationlist_path}. "
119
117
  f"Resolve this issue before using the system. "
120
118
  f"Problem started on line {index + 1}. "
121
- f'Got \'{row["sid"]}\' != \'{obj1.sid}\'.'
119
+ f"Got '{row['sid']}' != '{obj1.sid}'."
122
120
  )
123
121
  if not message:
124
122
  assignment = self.get_assignment(row)
@@ -136,7 +134,7 @@ class RandomizationListVerifier:
136
134
  f"does not match model data. See file "
137
135
  f"{self.randomizationlist_path}. "
138
136
  f"Resolve this issue before using the system. "
139
- f'Got \'{obj2.site_name}\' != \'{row["site_name"]}\' '
137
+ f"Got '{obj2.site_name}' != '{row['site_name']}' "
140
138
  f"for sid={obj2.sid}."
141
139
  )
142
140
  return message
@@ -3,7 +3,7 @@ from __future__ import annotations
3
3
  import warnings
4
4
  from datetime import datetime
5
5
  from pathlib import Path
6
- from typing import TYPE_CHECKING, Any, Type
6
+ from typing import TYPE_CHECKING, Any
7
7
 
8
8
  from django.apps import apps as django_apps
9
9
  from django.conf import settings
@@ -195,7 +195,7 @@ class Randomizer:
195
195
  return {self.identifier_attr: getattr(self, self.identifier_attr)}
196
196
 
197
197
  @classmethod
198
- def get_registration_model_cls(cls) -> Type[RegisteredSubject]:
198
+ def get_registration_model_cls(cls) -> type[RegisteredSubject]:
199
199
  return get_registered_subject_model_cls()
200
200
 
201
201
  @property
@@ -1,7 +1,6 @@
1
1
  import os
2
2
  import sys
3
3
  from dataclasses import dataclass
4
- from typing import Type
5
4
 
6
5
  from django.conf import settings
7
6
  from django.core.checks import Error, Warning
@@ -15,7 +14,7 @@ from .site_randomizers import site_randomizers
15
14
  @dataclass(frozen=True)
16
15
  class Err:
17
16
  id: str
18
- cls: Type[Warning | Error]
17
+ cls: type[Warning | Error]
19
18
 
20
19
 
21
20
  error_configs = dict(
@@ -2,7 +2,7 @@ from __future__ import annotations
2
2
 
3
3
  import csv
4
4
  import os
5
- from typing import Any, Optional
5
+ from typing import Any
6
6
 
7
7
  from django.conf import settings
8
8
  from django.contrib.auth import get_user_model
@@ -93,9 +93,9 @@ def generate_fake_randomization_list(
93
93
  all_sites=None,
94
94
  country=None,
95
95
  site_name=None,
96
- assignment: Optional[list] = None,
97
- slots: Optional[int] = None,
98
- write_header: Optional[bool] = None,
96
+ assignment: list | None = None,
97
+ slots: int | None = None,
98
+ write_header: bool | None = None,
99
99
  filename=None,
100
100
  assignment_map=None,
101
101
  ):
@@ -137,7 +137,7 @@ def generate_fake_randomization_list(
137
137
 
138
138
 
139
139
  def export_randomization_list(
140
- randomizer_name: str, path: Optional[str] = None, username: Optional[str] = None
140
+ randomizer_name: str, path: str | None = None, username: str | None = None
141
141
  ):
142
142
  randomizer_cls = site_randomizers.get(randomizer_name)
143
143
 
edc_refusal/admin.py CHANGED
@@ -70,5 +70,5 @@ class SubjectRefusalAdmin(
70
70
  if callable(super().view_on_site):
71
71
  url = super().view_on_site(obj)
72
72
  else:
73
- raise NoReverseMatch(f"{e}. See subject_dashboard_url_name for {repr(self)}.")
73
+ raise NoReverseMatch(f"{e}. See subject_dashboard_url_name for {self!r}.")
74
74
  return url
@@ -29,7 +29,7 @@ class SubjectRefusalModelMixin(models.Model):
29
29
  return self.screening_identifier
30
30
 
31
31
  def natural_key(self):
32
- return (self.screening_identifier,) # noqa
32
+ return (self.screening_identifier,)
33
33
 
34
34
  @staticmethod
35
35
  def get_search_slug_fields():
edc_refusal/utils.py CHANGED
@@ -5,7 +5,7 @@ from .model_mixins import SubjectRefusalModelMixin
5
5
 
6
6
 
7
7
  def get_subject_refusal_model() -> str:
8
- return getattr(settings, "SUBJECT_REFUSAL_MODEL")
8
+ return settings.SUBJECT_REFUSAL_MODEL
9
9
 
10
10
 
11
11
  def get_subject_refusal_model_cls() -> SubjectRefusalModelMixin:
@@ -1,6 +1,6 @@
1
1
  from __future__ import annotations
2
2
 
3
- from typing import TYPE_CHECKING, Type
3
+ from typing import TYPE_CHECKING
4
4
 
5
5
  from django.core.exceptions import ObjectDoesNotExist
6
6
  from django.db import models
@@ -23,7 +23,7 @@ class UpdatesOrCreatesRegistrationModelMixin(models.Model):
23
23
  """
24
24
 
25
25
  @property
26
- def registration_model(self) -> Type[RegisteredSubject]:
26
+ def registration_model(self) -> type[RegisteredSubject]:
27
27
  """Returns the Registration model"""
28
28
  return get_registered_subject_model_cls()
29
29
 
@@ -1,5 +1,3 @@
1
- from typing import Tuple
2
-
3
1
  from django.contrib import admin
4
2
  from django_audit_fields.admin import audit_fields
5
3
 
@@ -25,11 +23,10 @@ class RegisteredSubjectModelAdminMixin(ModelAdminSubjectDashboardMixin, admin.Mo
25
23
  if self.fieldsets:
26
24
  if self.show_pii(request):
27
25
  return self.fieldsets
28
- else:
29
- return self.fieldsets_no_pii
26
+ return self.fieldsets_no_pii
30
27
  return [(None, {"fields": self.get_fields(request, obj)})]
31
28
 
32
- def get_readonly_fields(self, request, obj=None) -> Tuple[str, ...]:
29
+ def get_readonly_fields(self, request, obj=None) -> tuple[str, ...]:
33
30
  readonly_fields = super().get_readonly_fields(request, obj=obj)
34
31
  return (
35
32
  readonly_fields
@@ -85,7 +82,7 @@ class RegisteredSubjectModelAdminMixin(ModelAdminSubjectDashboardMixin, admin.Mo
85
82
  )
86
83
  return custom_fields + tuple(f for f in list_display if f not in custom_fields)
87
84
 
88
- def get_list_filter(self, request) -> Tuple[str, ...]:
85
+ def get_list_filter(self, request) -> tuple[str, ...]:
89
86
  list_filter = super().get_list_filter(request)
90
87
  custom_fields = (
91
88
  "subject_type",
@@ -98,7 +95,7 @@ class RegisteredSubjectModelAdminMixin(ModelAdminSubjectDashboardMixin, admin.Mo
98
95
  )
99
96
  return custom_fields + tuple(f for f in list_filter if f not in custom_fields)
100
97
 
101
- def get_search_fields(self, request) -> Tuple[str, ...]:
98
+ def get_search_fields(self, request) -> tuple[str, ...]:
102
99
  search_fields = super().get_search_fields(request)
103
100
  pii_fields = (
104
101
  "first_name",
@@ -44,9 +44,7 @@ class RegisteredSubject(UniqueSubjectIdentifierModelMixin, SiteModelMixin, BaseU
44
44
  validators=[
45
45
  RegexValidator(
46
46
  regex=r"^[A-Z]{2,3}$",
47
- message=(
48
- "Ensure initials consist of letters " "only in upper case, no spaces."
49
- ),
47
+ message=("Ensure initials consist of letters only in upper case, no spaces."),
50
48
  )
51
49
  ],
52
50
  null=True,
@@ -154,7 +152,7 @@ class RegisteredSubject(UniqueSubjectIdentifierModelMixin, SiteModelMixin, BaseU
154
152
  super().save(*args, **kwargs)
155
153
 
156
154
  def natural_key(self):
157
- return (self.subject_identifier_as_pk,) # noqa
155
+ return (self.subject_identifier_as_pk,)
158
156
 
159
157
  def __str__(self):
160
158
  return self.masked_subject_identifier
@@ -228,10 +226,9 @@ class RegisteredSubject(UniqueSubjectIdentifierModelMixin, SiteModelMixin, BaseU
228
226
  ).get(**{attrname: getattr(self, attrname)})
229
227
  if not self.id:
230
228
  raise RegisteredSubjectError(error_msg.format(action="insert"))
231
- elif self.subject_identifier_is_set and obj.id != self.id:
232
- raise RegisteredSubjectError(error_msg.format(action="update"))
233
- else:
229
+ if self.subject_identifier_is_set and obj.id != self.id:
234
230
  raise RegisteredSubjectError(error_msg.format(action="update"))
231
+ raise RegisteredSubjectError(error_msg.format(action="update"))
235
232
  except ObjectDoesNotExist:
236
233
  pass
237
234
 
@@ -255,10 +252,11 @@ class RegisteredSubject(UniqueSubjectIdentifierModelMixin, SiteModelMixin, BaseU
255
252
  name="%(app_label)s_%(class)s_first_name_uniq",
256
253
  )
257
254
  ]
258
- indexes = BaseUuidModel.Meta.indexes + [
255
+ indexes = (
256
+ *BaseUuidModel.Meta.indexes,
259
257
  models.Index(fields=["first_name", "dob", "initials", "additional_key"]),
260
258
  models.Index(fields=["subject_identifier", "identity", "screening_identifier"]),
261
- ]
259
+ )
262
260
  permissions = (
263
261
  ("display_firstname", "Can display first name"),
264
262
  ("display_lastname", "Can display last name"),
edc_registration/utils.py CHANGED
@@ -1,7 +1,7 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  import re
4
- from typing import TYPE_CHECKING, Type
4
+ from typing import TYPE_CHECKING
5
5
 
6
6
  from django.apps import apps as django_apps
7
7
  from django.conf import settings
@@ -27,7 +27,7 @@ def get_registered_subject_model_name() -> str:
27
27
  )
28
28
 
29
29
 
30
- def get_registered_subject_model_cls() -> Type[RegisteredSubject]:
30
+ def get_registered_subject_model_cls() -> type[RegisteredSubject]:
31
31
  return django_apps.get_model(get_registered_subject_model_name())
32
32
 
33
33
 
@@ -62,6 +62,5 @@ def valid_subject_identifier_or_raise(
62
62
  f"See `edc_protocol.ResearchProtocolConfig().subject_identifier_pattern`. "
63
63
  f"Got `{subject_identifier}`."
64
64
  )
65
- else:
66
- return False
65
+ return False
67
66
  return True
@@ -33,12 +33,12 @@ from ...units import (
33
33
  )
34
34
 
35
35
  __all__ = [
36
- "dummies",
37
36
  "chemistries",
37
+ "dummies",
38
+ "grading_data",
39
+ "hba1c",
38
40
  "hematology",
39
41
  "urinalysis",
40
- "hba1c",
41
- "grading_data",
42
42
  ]
43
43
 
44
44
  dummies = {
@@ -94,8 +94,8 @@ class Evaluator:
94
94
  if upper and upper >= float(HIGH_VALUE):
95
95
  upper = ""
96
96
  return (
97
- f'{lower}{self.lower_operator or ""}{value}'
98
- f'{self.upper_operator or ""}{upper} {self.units}'
97
+ f"{lower}{self.lower_operator or ''}{value}"
98
+ f"{self.upper_operator or ''}{upper} {self.units}"
99
99
  )
100
100
 
101
101
  def in_bounds_or_raise(self, value: int | float, units: str = None) -> bool:
@@ -111,10 +111,10 @@ class Evaluator:
111
111
  """
112
112
  value = float(value)
113
113
  if units != self.units:
114
- raise InvalidUnits(f"Expected {self.units}. See {repr(self)}")
114
+ raise InvalidUnits(f"Expected {self.units}. See {self!r}")
115
115
  condition_str = (
116
- f'{"" if self.lower is None else self.lower}{self.lower_operator or ""}{value}'
117
- f'{self.upper_operator or ""}{"" if self.upper is None else self.upper}'
116
+ f"{'' if self.lower is None else self.lower}{self.lower_operator or ''}{value}"
117
+ f"{self.upper_operator or ''}{'' if self.upper is None else self.upper}"
118
118
  )
119
119
  if not eval(condition_str): # nosec B307
120
120
  raise ValueBoundryError(condition_str)
edc_reportable/formula.py CHANGED
@@ -7,7 +7,7 @@ from edc_constants.constants import FEMALE, MALE
7
7
 
8
8
  from .adult_age_options import adult_age_options
9
9
 
10
- __all__ = ["Formula", "formula", "dummy_formula", "FormulaError"]
10
+ __all__ = ["Formula", "FormulaError", "dummy_formula", "formula"]
11
11
 
12
12
  from .exceptions import FormulaError
13
13
 
@@ -1,7 +1,7 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  from datetime import date, datetime
4
- from typing import TYPE_CHECKING, Type
4
+ from typing import TYPE_CHECKING
5
5
 
6
6
  from django import forms
7
7
  from django.apps import apps as django_apps
@@ -77,11 +77,11 @@ class ReferenceRangeEvaluator:
77
77
  return self.reference_range_collection.grades(utest_id)
78
78
 
79
79
  @property
80
- def reference_range_collection_model_cls(self) -> Type[ReferenceRangeCollection]:
80
+ def reference_range_collection_model_cls(self) -> type[ReferenceRangeCollection]:
81
81
  return django_apps.get_model("edc_reportable.referencerangecollection")
82
82
 
83
83
  @property
84
- def normal_data_model_cls(self) -> Type[NormalData]:
84
+ def normal_data_model_cls(self) -> type[NormalData]:
85
85
  return django_apps.get_model("edc_reportable.normaldata")
86
86
 
87
87
  def validate_reportable_fields(self):
@@ -34,14 +34,13 @@ def micromoles_per_liter_to(
34
34
  ) -> dict:
35
35
  if units_to == MICROMOLES_PER_LITER:
36
36
  return {MICROMOLES_PER_LITER: float(value)}
37
- elif units_to == MILLIMOLES_PER_LITER:
37
+ if units_to == MILLIMOLES_PER_LITER:
38
38
  return {MILLIMOLES_PER_LITER: float(value) / 1000.00}
39
- elif units_to == GRAMS_PER_LITER:
39
+ if units_to == GRAMS_PER_LITER:
40
40
  return {GRAMS_PER_LITER: (float(value) * get_mw(label)) / 100.00}
41
- elif units_to == MILLIGRAMS_PER_DECILITER:
41
+ if units_to == MILLIGRAMS_PER_DECILITER:
42
42
  return {MILLIGRAMS_PER_DECILITER: (float(value) * get_mw(label)) / 10000.00}
43
- else:
44
- raise ConversionNotHandled(f"Conversion not found. Tried umol/L to {units_to}. ")
43
+ raise ConversionNotHandled(f"Conversion not found. Tried umol/L to {units_to}. ")
45
44
 
46
45
 
47
46
  def milligrams_per_deciliter_to(
@@ -49,16 +48,15 @@ def milligrams_per_deciliter_to(
49
48
  ) -> dict[str:float]:
50
49
  if units_to == MILLIGRAMS_PER_DECILITER:
51
50
  return {MILLIGRAMS_PER_DECILITER: float(value)}
52
- elif units_to == MILLIMOLES_PER_LITER:
51
+ if units_to == MILLIMOLES_PER_LITER:
53
52
  return {MILLIMOLES_PER_LITER: (float(value) * 10.00) / get_mw(label)}
54
- elif units_to == MICROMOLES_PER_LITER:
53
+ if units_to == MICROMOLES_PER_LITER:
55
54
  return {MICROMOLES_PER_LITER: (float(value) * 10000.00) / get_mw(label)}
56
- elif units_to == MILLIGRAMS_PER_LITER:
55
+ if units_to == MILLIGRAMS_PER_LITER:
57
56
  return {MILLIGRAMS_PER_LITER: float(value) * 10.00}
58
- elif units_to == GRAMS_PER_LITER:
57
+ if units_to == GRAMS_PER_LITER:
59
58
  return {GRAMS_PER_LITER: float(value) / 100.00}
60
- else:
61
- raise ConversionNotHandled(f"Conversion not found. Tried mg/dL to {units_to}. ")
59
+ raise ConversionNotHandled(f"Conversion not found. Tried mg/dL to {units_to}. ")
62
60
 
63
61
 
64
62
  class UnitsConverter:
@@ -79,7 +77,7 @@ class UnitsConverter:
79
77
 
80
78
  if label is None:
81
79
  raise ValueError("label is required. See convert_units.")
82
- elif value is not None and units_from and units_to and units_from != units_to:
80
+ if value is not None and units_from and units_to and units_from != units_to:
83
81
  self.converted_value = self.get_converted_value()
84
82
  elif units_from == units_to:
85
83
  self.converted_value = value
@@ -1,6 +1,6 @@
1
1
  from __future__ import annotations
2
2
 
3
- from typing import TYPE_CHECKING, Type
3
+ from typing import TYPE_CHECKING
4
4
 
5
5
  from django.apps import apps as django_apps
6
6
 
@@ -10,5 +10,5 @@ if TYPE_CHECKING:
10
10
  __all__ = ["grading_data_model_cls"]
11
11
 
12
12
 
13
- def grading_data_model_cls() -> Type[GradingData]:
13
+ def grading_data_model_cls() -> type[GradingData]:
14
14
  return django_apps.get_model("edc_reportable.gradingdata")
@@ -1,6 +1,6 @@
1
1
  from __future__ import annotations
2
2
 
3
- from typing import TYPE_CHECKING, Type
3
+ from typing import TYPE_CHECKING
4
4
 
5
5
  from django.apps import apps as django_apps
6
6
 
@@ -10,5 +10,5 @@ if TYPE_CHECKING:
10
10
  __all__ = ["grading_exception_model_cls"]
11
11
 
12
12
 
13
- def grading_exception_model_cls() -> Type[GradingException]:
13
+ def grading_exception_model_cls() -> type[GradingException]:
14
14
  return django_apps.get_model("edc_reportable.gradingexception")
@@ -1,6 +1,6 @@
1
1
  from __future__ import annotations
2
2
 
3
- from typing import TYPE_CHECKING, Type
3
+ from typing import TYPE_CHECKING
4
4
 
5
5
  from django.apps import apps as django_apps
6
6
 
@@ -8,5 +8,5 @@ if TYPE_CHECKING:
8
8
  from edc_reportable.models import MolecularWeight
9
9
 
10
10
 
11
- def molecular_weight_model_cls() -> Type[MolecularWeight]:
11
+ def molecular_weight_model_cls() -> type[MolecularWeight]:
12
12
  return django_apps.get_model("edc_reportable", "MolecularWeight")
@@ -1,6 +1,6 @@
1
1
  from __future__ import annotations
2
2
 
3
- from typing import TYPE_CHECKING, Type
3
+ from typing import TYPE_CHECKING
4
4
 
5
5
  from django.apps import apps as django_apps
6
6
 
@@ -11,5 +11,5 @@ if TYPE_CHECKING:
11
11
  __all__ = ["normal_data_model_cls"]
12
12
 
13
13
 
14
- def normal_data_model_cls() -> Type[NormalData]:
14
+ def normal_data_model_cls() -> type[NormalData]:
15
15
  return django_apps.get_model("edc_reportable.normaldata")
@@ -1,6 +1,6 @@
1
1
  from __future__ import annotations
2
2
 
3
- from typing import TYPE_CHECKING, Type
3
+ from typing import TYPE_CHECKING
4
4
 
5
5
  from django.apps import apps as django_apps
6
6
 
@@ -11,5 +11,5 @@ if TYPE_CHECKING:
11
11
  __all__ = ["reference_range_colllection_model_cls"]
12
12
 
13
13
 
14
- def reference_range_colllection_model_cls() -> Type[ReferenceRangeCollection]:
14
+ def reference_range_colllection_model_cls() -> type[ReferenceRangeCollection]:
15
15
  return django_apps.get_model("edc_reportable.referencerangecollection")
@@ -1,5 +1,3 @@
1
- from typing import Optional
2
-
3
1
  from dateutil.relativedelta import relativedelta
4
2
  from django.utils.timezone import localtime
5
3
 
@@ -10,10 +8,10 @@ from edc_utils.date import get_utcnow
10
8
 
11
9
  class AgeEvaluator(ReportableAgeEvaluator):
12
10
  def __init__(self, **kwargs) -> None:
13
- self.reasons_ineligible: Optional[str] = None
11
+ self.reasons_ineligible: str | None = None
14
12
  super().__init__(**kwargs)
15
13
 
16
- def eligible(self, age: Optional[int] = None) -> bool:
14
+ def eligible(self, age: int | None = None) -> bool:
17
15
  self.reasons_ineligible = None
18
16
  eligible = False
19
17
  if age:
@@ -77,6 +77,6 @@ class Eligibility:
77
77
  raise EligibilityError(
78
78
  f"Custom reasons refer to invalid named criteria, Got '{k}'. "
79
79
  f"Expected one of {list(self.criteria)}. "
80
- f"See {repr(self)}."
80
+ f"See {self!r}."
81
81
  )
82
82
  return self.custom_reasons_dict
@@ -1,6 +1,6 @@
1
1
  from __future__ import annotations
2
2
 
3
- from typing import TYPE_CHECKING, Type
3
+ from typing import TYPE_CHECKING
4
4
 
5
5
  from django.apps import apps as django_apps
6
6
  from django.core.exceptions import ObjectDoesNotExist
@@ -33,7 +33,7 @@ class SubjectScreeningFormValidatorMixin:
33
33
  return get_subject_screening_model()
34
34
 
35
35
  @property
36
- def subject_screening_model_cls(self) -> Type[ScreeningModelMixin]:
36
+ def subject_screening_model_cls(self) -> type[ScreeningModelMixin]:
37
37
  return django_apps.get_model(self.subject_screening_model)
38
38
 
39
39
  @property
@@ -12,7 +12,7 @@ class ScreeningMethodsModeMixin(models.Model):
12
12
  return f"{self.screening_identifier} {self.gender} {self.age_in_years}"
13
13
 
14
14
  def natural_key(self: SubjectScreeningModelStub):
15
- return (self.screening_identifier,) # noqa
15
+ return (self.screening_identifier,)
16
16
 
17
17
  @staticmethod
18
18
  def get_search_slug_fields():
@@ -20,7 +20,7 @@ if TYPE_CHECKING:
20
20
 
21
21
  from .model_mixins import EligibilityModelMixin, ScreeningModelMixin
22
22
 
23
- class SubjectScreeningModel(ScreeningModelMixin, BaseUuidModel): ... # noqa
23
+ class SubjectScreeningModel(ScreeningModelMixin, BaseUuidModel): ...
24
24
 
25
25
 
26
26
  __all__ = ["ScreeningEligibility"]
edc_screening/utils.py CHANGED
@@ -26,7 +26,7 @@ def get_subject_screening_app_label() -> str:
26
26
 
27
27
 
28
28
  def get_subject_screening_model() -> str:
29
- return getattr(settings, "SUBJECT_SCREENING_MODEL")
29
+ return settings.SUBJECT_SCREENING_MODEL
30
30
 
31
31
 
32
32
  def get_subject_screening_model_cls() -> Any:
@@ -74,11 +74,9 @@ def get_subject_screening_or_raise(
74
74
  except ObjectDoesNotExist as e:
75
75
  if is_modelform:
76
76
  raise forms.ValidationError("Not allowed. Screening form not found.")
77
- else:
78
- raise ObjectDoesNotExist(
79
- f"{e} screening_identifier={screening_identifier}. "
80
- "Perhaps catch this in the form."
81
- )
77
+ raise ObjectDoesNotExist(
78
+ f"{e} screening_identifier={screening_identifier}. Perhaps catch this in the form."
79
+ )
82
80
  return subject_screening
83
81
 
84
82
 
@@ -42,4 +42,4 @@ class SearchSlugModelMixin(models.Model):
42
42
 
43
43
  class Meta:
44
44
  abstract = True
45
- indexes = [models.Index(fields=["slug"])]
45
+ indexes = (models.Index(fields=["slug"]),)
edc_search/search_slug.py CHANGED
@@ -37,9 +37,7 @@ class SearchSlug:
37
37
  slugs = [slugify(item or "") for item in values]
38
38
  slug = SEARCH_SLUG_SEP.join(slugs)
39
39
  if len(slug) > 250:
40
- self.warning = (
41
- f"Warning! Search slug string exceeds 250 chars. See {repr(obj)}\n"
42
- )
40
+ self.warning = f"Warning! Search slug string exceeds 250 chars. See {obj!r}\n"
43
41
  sys.stdout.write(style.WARNING(self.warning))
44
42
  self.slug = slug[:250]
45
43
 
edc_search/updater.py CHANGED
@@ -23,7 +23,7 @@ class SearchSlugUpdater:
23
23
  def __init__(self, fields: list[str], model_obj: Model | SearchSlugModelMixin = None):
24
24
  if len(fields) > len(list(set(fields))):
25
25
  raise SearchSlugDuplicateFields(
26
- f"Duplicate search slug fields detected. Got {fields}. " f"See {repr(self)}"
26
+ f"Duplicate search slug fields detected. Got {fields}. See {self!r}"
27
27
  )
28
28
  search_slug = self.search_slug_cls(obj=model_obj, fields=fields)
29
29
  self.warning = search_slug.warning
@@ -1,7 +1,7 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  import collections
4
- from typing import TYPE_CHECKING, Type
4
+ from typing import TYPE_CHECKING
5
5
 
6
6
  from django.contrib import admin
7
7
  from django.contrib.auth import get_permission_codename
@@ -68,7 +68,7 @@ class SiteModelAdminMixin:
68
68
  return obj.site.name
69
69
  return f"{site_profile.site.id} {site_profile.description}"
70
70
 
71
- def get_list_filter(self, request) -> tuple[str | Type[SimpleListFilter], ...]:
71
+ def get_list_filter(self, request) -> tuple[str | type[SimpleListFilter], ...]:
72
72
  """Insert `SiteListFilter` before field name `created`.
73
73
 
74
74
  Remove site from the list if user does not have access
@@ -36,7 +36,6 @@ class SiteModelMixin(models.Model):
36
36
  pass
37
37
  else:
38
38
  self.validate_site_against_current()
39
- return None
40
39
 
41
40
  def get_site_on_create(self) -> Site:
42
41
  """Returns a site model instance.
@@ -65,7 +64,7 @@ class SiteModelMixin(models.Model):
65
64
 
66
65
  def validate_site_against_current(self) -> None:
67
66
  """Validate existing site instance matches current_site."""
68
- return None
67
+ return
69
68
 
70
69
  class Meta:
71
70
  abstract = True
@@ -1,6 +1,6 @@
1
1
  from __future__ import annotations
2
2
 
3
- from typing import TYPE_CHECKING, Type
3
+ from typing import TYPE_CHECKING
4
4
 
5
5
  from django import forms
6
6
  from django.apps import apps as django_apps
@@ -32,7 +32,7 @@ class SiteModelFormMixin:
32
32
  return cleaned_data
33
33
 
34
34
  @property
35
- def site_model_cls(self) -> Type[Site]:
35
+ def site_model_cls(self) -> type[Site]:
36
36
  return django_apps.get_model("sites.site")
37
37
 
38
38
  @property