clinicedc 2.0.4__py3-none-any.whl → 2.0.6__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.6.dist-info}/METADATA +41 -45
  2. {clinicedc-2.0.4.dist-info → clinicedc-2.0.6.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 -10
  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.6.dist-info}/WHEEL +0 -0
  478. {clinicedc-2.0.4.dist-info → clinicedc-2.0.6.dist-info}/licenses/LICENSE +0 -0
@@ -74,9 +74,7 @@ class BoxViewMixin(ContextMixin):
74
74
  box=self.box, identifier=self.box_item_identifier
75
75
  )
76
76
  except ObjectDoesNotExist:
77
- message = "Invalid box item. Got {}".format(
78
- self.original_box_item_identifier
79
- )
77
+ message = f"Invalid box item. Got {self.original_box_item_identifier}"
80
78
  messages.error(self.request, message)
81
79
  return self._box_item
82
80
 
@@ -85,7 +83,7 @@ class BoxViewMixin(ContextMixin):
85
83
  try:
86
84
  box_item = BoxItem.objects.get(box=self.box, position=position)
87
85
  except ObjectDoesNotExist:
88
- message = "Invalid position for box. Got {}".format(position)
86
+ message = f"Invalid position for box. Got {position}"
89
87
  messages.error(self.request, message)
90
88
  return None
91
89
  return box_item
@@ -103,15 +101,12 @@ class BoxViewMixin(ContextMixin):
103
101
  # raise BoxViewError(message)
104
102
  else:
105
103
  if obj.is_primary and not self.box.accept_primary:
106
- message = 'Box does not accept "primary" specimens. Got {} is primary.'.format(
107
- self.original_box_item_identifier
108
- )
104
+ message = f'Box does not accept "primary" specimens. Got {self.original_box_item_identifier} is primary.'
109
105
  messages.error(self.request, message)
110
106
  # raise BoxViewError(message)
111
107
  elif obj.numeric_code not in self.box.specimen_types.split(","):
112
108
  message = (
113
- "Invalid specimen type. Box accepts types {}. "
114
- "Got {} is type {}.".format(
109
+ "Invalid specimen type. Box accepts types {}. Got {} is type {}.".format(
115
110
  ", ".join(self.box.specimen_types.split(",")),
116
111
  self.original_box_item_identifier,
117
112
  obj.numeric_code,
@@ -60,8 +60,7 @@ class ActionView(TemplateView):
60
60
  action = slugify(self.request.POST.get("action", "").lower())
61
61
  if action not in self.valid_form_actions:
62
62
  raise InvalidPostError(f"Invalid form action in POST. Got {action}")
63
- else:
64
- self.action = action
63
+ self.action = action
65
64
  self.process_form_action(request=request)
66
65
  url_name = url_names.get(self.post_action_url)
67
66
  url = reverse(url_name, kwargs=self.url_kwargs)
@@ -47,7 +47,7 @@ class ManageManifestView(EdcViewMixin, ManifestViewMixin, ActionView):
47
47
  deleted = ManifestItem.objects.filter(
48
48
  pk__in=self.selected_items, manifest__shipped=False
49
49
  ).delete()
50
- message = "{} items have been removed.".format(deleted[0])
50
+ message = f"{deleted[0]} items have been removed."
51
51
  messages.success(self.request, message)
52
52
  except ProtectedError:
53
53
  message = "Unable to remove. Manifest is not empty."
@@ -24,15 +24,14 @@ class ManifestView(EdcViewMixin, ManifestViewMixin, LabPrintersMixin, ActionView
24
24
  if not self.selected_items:
25
25
  message = "Nothing to do. No items have been selected."
26
26
  messages.warning(request, message)
27
- else:
28
- if self.action == "remove_selected_items":
29
- self.remove_selected_items()
30
- elif self.action == "print_labels":
31
- job_result = self.print_labels(pks=self.selected_items, request=request)
32
- if job_result:
33
- add_job_results_to_messages(request, [job_result])
34
- elif self.action == "ship_selected_items":
35
- self.ship_selected_items()
27
+ elif self.action == "remove_selected_items":
28
+ self.remove_selected_items()
29
+ elif self.action == "print_labels":
30
+ job_result = self.print_labels(pks=self.selected_items, request=request)
31
+ if job_result:
32
+ add_job_results_to_messages(request, [job_result])
33
+ elif self.action == "ship_selected_items":
34
+ self.ship_selected_items()
36
35
 
37
36
  def remove_selected_items(self):
38
37
  """Deletes the selected items, if allowed."""
@@ -51,8 +50,7 @@ class ManifestView(EdcViewMixin, ManifestViewMixin, LabPrintersMixin, ActionView
51
50
  for manifest in Manifest.objects.filter(pk__in=self.selected_items):
52
51
  if manifest.shipped:
53
52
  message = (
54
- f"Manifest has already been shipped. "
55
- f"Got {manifest.manifest_identifier}."
53
+ f"Manifest has already been shipped. Got {manifest.manifest_identifier}."
56
54
  )
57
55
  messages.error(self.request, message)
58
56
  else:
@@ -29,16 +29,15 @@ class PackView(EdcViewMixin, LabPrintersMixin, ActionView):
29
29
  if not self.selected_items:
30
30
  message = "Nothing to do. No items have been selected."
31
31
  messages.warning(request, message)
32
- else:
33
- if self.action == "remove_selected_items":
34
- self.remove_selected_items()
35
- elif self.action == "add_selected_to_manifest":
36
- if self.selected_manifest:
37
- self.add_selected_to_manifest()
38
- elif self.action == "print_labels":
39
- job_result = self.print_labels(pks=self.selected_items, request=request)
40
- if job_result:
41
- add_job_results_to_messages(request, [job_result])
32
+ elif self.action == "remove_selected_items":
33
+ self.remove_selected_items()
34
+ elif self.action == "add_selected_to_manifest":
35
+ if self.selected_manifest:
36
+ self.add_selected_to_manifest()
37
+ elif self.action == "print_labels":
38
+ job_result = self.print_labels(pks=self.selected_items, request=request)
39
+ if job_result:
40
+ add_job_results_to_messages(request, [job_result])
42
41
 
43
42
  @property
44
43
  def selected_manifest(self):
@@ -77,9 +76,7 @@ class PackView(EdcViewMixin, LabPrintersMixin, ActionView):
77
76
  else:
78
77
  break
79
78
  if added > 0:
80
- message = "{} items have been added to manifest {}.".format(
81
- added, self.selected_manifest.human_readable_identifier
82
- )
79
+ message = f"{added} items have been added to manifest {self.selected_manifest.human_readable_identifier}."
83
80
  messages.success(self.request, message)
84
81
  except ProtectedError:
85
82
  message = "Unable to remove. Box is not empty."
@@ -93,7 +90,7 @@ class PackView(EdcViewMixin, LabPrintersMixin, ActionView):
93
90
  else:
94
91
  try:
95
92
  deleted = Box.objects.filter(pk__in=self.selected_items).delete()
96
- message = "{} items have been removed.".format(deleted[0])
93
+ message = f"{deleted[0]} items have been removed."
97
94
  messages.success(self.request, message)
98
95
  except ProtectedError:
99
96
  message = "Unable to remove. Box is not empty."
@@ -1,7 +1,7 @@
1
- from typing import Any, Optional, Tuple
1
+ from typing import Any
2
2
 
3
3
 
4
- def calculate_missing(obj: Any, panel: Any) -> Tuple[int, Optional[str]]:
4
+ def calculate_missing(obj: Any, panel: Any) -> tuple[int, str | None]:
5
5
  """Returns a tuple of (missing_count, missing)
6
6
 
7
7
  Counts the number of blank results within the model
@@ -1,23 +1,23 @@
1
1
  from __future__ import annotations
2
2
 
3
- from typing import TYPE_CHECKING, Any, Tuple
3
+ from typing import TYPE_CHECKING, Any
4
4
 
5
5
  from django_audit_fields import audit_fieldset_tuple
6
6
 
7
7
  if TYPE_CHECKING:
8
8
  from edc_lab import RequisitionPanel
9
9
 
10
- panel_conclusion_fieldset: Tuple[str, dict] = (
10
+ panel_conclusion_fieldset: tuple[str, dict] = (
11
11
  "Conclusion",
12
12
  {"fields": ("results_abnormal", "results_reportable")},
13
13
  )
14
- panel_summary_fieldset: Tuple[str, dict] = (
14
+ panel_summary_fieldset: tuple[str, dict] = (
15
15
  "Summary",
16
16
  {"fields": ("reportable_summary", "abnormal_summary", "errors")},
17
17
  )
18
18
 
19
19
 
20
- calculate_egfr_fieldset: Tuple[str, dict] = (
20
+ calculate_egfr_fieldset: tuple[str, dict] = (
21
21
  "Calculated eGFR",
22
22
  {
23
23
  # "classes": ("collapse",),
@@ -26,7 +26,7 @@ calculate_egfr_fieldset: Tuple[str, dict] = (
26
26
  },
27
27
  )
28
28
 
29
- calculate_egfr_drop_fieldset: Tuple[str, dict] = (
29
+ calculate_egfr_drop_fieldset: tuple[str, dict] = (
30
30
  "Calculated eGFR Drop",
31
31
  {
32
32
  # "classes": ("collapse",),
@@ -50,7 +50,7 @@ class BloodResultFieldset:
50
50
  panel: RequisitionPanel,
51
51
  title: str = None,
52
52
  model_cls: Any = None,
53
- extra_fieldsets: list[Tuple[int, Tuple[str, dict]]] | None = None,
53
+ extra_fieldsets: list[tuple[int, tuple[str, dict]]] | None = None,
54
54
  excluded_utest_ids: list[str] = None,
55
55
  exclude_units: bool = None,
56
56
  exclude_reportable: bool = None,
@@ -3,8 +3,8 @@ from .reportable_result_model_mixin_factory import reportable_result_model_mixin
3
3
  from .result_model_mixin_factory import result_model_mixin_factory
4
4
 
5
5
  __all__ = [
6
+ "get_field_attrs_for_reportable",
7
+ "get_field_attrs_for_utestid",
6
8
  "reportable_result_model_mixin_factory",
7
9
  "result_model_mixin_factory",
8
- "get_field_attrs_for_utestid",
9
- "get_field_attrs_for_reportable",
10
10
  ]
@@ -1,5 +1,3 @@
1
- from typing import Optional, Type
2
-
3
1
  from django.db import models
4
2
 
5
3
  from .field_attrs import get_field_attrs_for_reportable, get_field_attrs_for_utestid
@@ -10,13 +8,13 @@ __all__ = ["reportable_result_model_mixin_factory"]
10
8
  def reportable_result_model_mixin_factory(
11
9
  utest_id: str,
12
10
  units_choices: tuple,
13
- default_units: Optional[str] = None,
14
- verbose_name: Optional[str] = None,
15
- decimal_places: Optional[int] = None,
16
- max_digits: Optional[int] = None,
17
- validators: Optional[list] = None,
18
- exclude_attrs_for_reportable: Optional[bool] = None,
19
- ) -> Type[models.Model]:
11
+ default_units: str | None = None,
12
+ verbose_name: str | None = None,
13
+ decimal_places: int | None = None,
14
+ max_digits: int | None = None,
15
+ validators: list | None = None,
16
+ exclude_attrs_for_reportable: bool | None = None,
17
+ ) -> type[models.Model]:
20
18
  """Returns an abstract model class with a single field class"""
21
19
 
22
20
  class AbstractModel(models.Model):
@@ -1,5 +1,3 @@
1
- from typing import Optional, Type
2
-
3
1
  from django.db import models
4
2
 
5
3
  from .field_attrs import get_field_attrs_for_utestid
@@ -10,13 +8,13 @@ __all__ = ["result_model_mixin_factory"]
10
8
  def result_model_mixin_factory(
11
9
  utest_id: str,
12
10
  units_choices: tuple,
13
- default_units: Optional[str] = None,
14
- verbose_name: Optional[str] = None,
15
- decimal_places: Optional[int] = None,
16
- max_digits: Optional[int] = None,
17
- validators: Optional[list] = None,
18
- help_text: Optional[str] = None,
19
- ) -> Type[models.Model]:
11
+ default_units: str | None = None,
12
+ verbose_name: str | None = None,
13
+ decimal_places: int | None = None,
14
+ max_digits: int | None = None,
15
+ validators: list | None = None,
16
+ help_text: str | None = None,
17
+ ) -> type[models.Model]:
20
18
  """Returns an abstract model class with a single field class"""
21
19
 
22
20
  class AbstractModel(models.Model):
@@ -54,7 +54,7 @@ class FbgModelMixin(
54
54
  )
55
55
 
56
56
  def get_summary_options(self) -> dict:
57
- opts = super().get_summary_options() # noqa
57
+ opts = super().get_summary_options()
58
58
  fasting = True if self.fasting == FASTING else False
59
59
  opts.update(fasting=fasting)
60
60
  return opts
@@ -51,7 +51,7 @@ class GlucoseModelMixin(
51
51
  )
52
52
 
53
53
  def get_summary_options(self: Any) -> dict:
54
- opts = super().get_summary_options() # noqa
54
+ opts = super().get_summary_options()
55
55
  fasting = True if self.fasting == FASTING else False
56
56
  opts.update(fasting=fasting)
57
57
  return opts
edc_label/admin.py CHANGED
@@ -1,5 +1,3 @@
1
- from typing import Tuple
2
-
3
1
  from django.contrib import admin
4
2
  from django.contrib.admin import ModelAdmin
5
3
  from django_audit_fields import audit_fieldset_tuple
@@ -15,4 +13,4 @@ class ZplLabelTemplatesAdmin(ModelAdmin):
15
13
  audit_fieldset_tuple,
16
14
  )
17
15
 
18
- search_fields: Tuple[str, ...] = ("name",)
16
+ search_fields: tuple[str, ...] = ("name",)
edc_label/label.py CHANGED
@@ -1,5 +1,3 @@
1
- from typing import Optional
2
-
3
1
  from django.utils import timezone
4
2
 
5
3
  from .label_template import LabelTemplate
@@ -14,8 +12,8 @@ class Label:
14
12
 
15
13
  def __init__(
16
14
  self,
17
- label_template_name: Optional[str] = None,
18
- static_files_path: Optional[str] = None,
15
+ label_template_name: str | None = None,
16
+ static_files_path: str | None = None,
19
17
  ):
20
18
  if label_template_name:
21
19
  self.label_template_name = label_template_name
@@ -39,7 +39,7 @@ class LabelTemplate:
39
39
  f"Looking for template '{template_name}'. "
40
40
  f"Got {path}. See edc_label.app_config."
41
41
  )
42
- with open(path, "r") as f:
42
+ with open(path) as f:
43
43
  self.template = f.read()
44
44
  else:
45
45
  self.template = zpl_label_template.zpl_data.strip()
@@ -1,5 +1,3 @@
1
- from typing import Optional
2
-
3
1
  from django.apps import apps as django_apps
4
2
 
5
3
  from edc_protocol.research_protocol_config import ResearchProtocolConfig
@@ -11,7 +9,7 @@ class SubjectLabel(Label):
11
9
  template_name = None
12
10
  registered_subject_model = "edc_registration.registeredsubject"
13
11
 
14
- def __init__(self, subject_identifier: Optional[str] = None, site=None, **kwargs):
12
+ def __init__(self, subject_identifier: str | None = None, site=None, **kwargs):
15
13
  super().__init__(**kwargs)
16
14
  self._registered_subject = None
17
15
  self.subject_identifier = subject_identifier
edc_list_data/admin.py CHANGED
@@ -1,13 +1,11 @@
1
- from typing import Tuple
2
-
3
1
  from django.contrib import admin
4
2
 
5
3
  from edc_model_admin.mixins import TemplatesModelAdminMixin
6
4
 
7
5
 
8
6
  class ListModelAdminMixin(TemplatesModelAdminMixin, admin.ModelAdmin):
9
- ordering: Tuple[str, ...] = ("display_index", "display_name")
7
+ ordering: tuple[str, ...] = ("display_index", "display_name")
10
8
 
11
- list_display: Tuple[str, ...] = ("display_name", "name", "display_index")
9
+ list_display: tuple[str, ...] = ("display_name", "name", "display_index")
12
10
 
13
- search_fields: Tuple[str, ...] = ("display_name", "name")
11
+ search_fields: tuple[str, ...] = ("display_name", "name")
@@ -27,7 +27,7 @@ def load_list_data(
27
27
  if model_name:
28
28
  model_names = [model_name]
29
29
  else:
30
- model_names = [k for k in list_data.keys()]
30
+ model_names = [k for k in list_data]
31
31
  n = 0
32
32
  for model_name in model_names:
33
33
  try:
@@ -1,5 +1,3 @@
1
- from typing import Optional
2
-
3
1
  from django.apps import AppConfig
4
2
  from django.apps import apps as django_apps
5
3
  from django.core.exceptions import ObjectDoesNotExist
@@ -10,7 +8,7 @@ class LoadModelDataError(Exception):
10
8
  pass
11
9
 
12
10
 
13
- def load_model_data(model_data: dict, apps: Optional[AppConfig] = None) -> int:
11
+ def load_model_data(model_data: dict, apps: AppConfig | None = None) -> int:
14
12
  """Loads data into a model, creates or updates existing.
15
13
 
16
14
  Must have a unique field
@@ -54,13 +54,11 @@ class BaseListModelMixin(models.Model):
54
54
  super().save(*args, **kwargs)
55
55
 
56
56
  def natural_key(self) -> tuple:
57
- return (self.name,) # noqa
57
+ return (self.name,)
58
58
 
59
59
  class Meta:
60
60
  abstract = True
61
- indexes = [
62
- models.Index(fields=["display_index", "display_name"]),
63
- ]
61
+ indexes = (models.Index(fields=["display_index", "display_name"]),)
64
62
  default_permissions = ("add", "change", "delete", "view", "export", "import")
65
63
 
66
64
 
@@ -104,4 +102,4 @@ class ListUuidModelMixin(BaseListModelMixin, BaseUuidModel):
104
102
 
105
103
  class Meta(BaseListModelMixin.Meta, BaseUuidModel.Meta):
106
104
  abstract = True
107
- indexes = BaseListModelMixin.Meta.indexes + BaseUuidModel.Meta.indexes
105
+ indexes = (*BaseListModelMixin.Meta.indexes, *BaseUuidModel.Meta.indexes)
@@ -1,5 +1,3 @@
1
- from typing import Optional
2
-
3
1
  from django.apps import AppConfig
4
2
  from django.core.management.color import color_style
5
3
 
@@ -26,8 +24,8 @@ class PreloadData:
26
24
  if self.model_data:
27
25
  self.item_count += self.load_model_data()
28
26
 
29
- def load_list_data(self, model_name: str = None, apps: Optional[AppConfig] = None) -> int:
27
+ def load_list_data(self, model_name: str = None, apps: AppConfig | None = None) -> int:
30
28
  return load_list_data(self.list_data, model_name=model_name, apps=apps)
31
29
 
32
- def load_model_data(self, apps: Optional[AppConfig] = None) -> int:
30
+ def load_model_data(self, apps: AppConfig | None = None) -> int:
33
31
  return load_model_data(self.model_data, apps=apps)
@@ -50,13 +50,12 @@ class SiteListData:
50
50
  """Registers but does NOT `load` list_data."""
51
51
  if app_name and app_name in self.app_names:
52
52
  raise AlreadyLoaded(f"App already loaded. Got {app_name}.")
53
- else:
54
- self.app_names.append(app_name)
55
- opts = copy.deepcopy(self._get_options(module))
56
- sys.stdout.write(f" - registered {self.module_name} from '{module.__name__}'\n")
57
- if opts.get(self.module_name):
58
- self._replace_list_data_or_raise_on_duplicate(module, opts)
59
- self.registry[module.__name__] = opts
53
+ self.app_names.append(app_name)
54
+ opts = copy.deepcopy(self._get_options(module))
55
+ sys.stdout.write(f" - registered {self.module_name} from '{module.__name__}'\n")
56
+ if opts.get(self.module_name):
57
+ self._replace_list_data_or_raise_on_duplicate(module, opts)
58
+ self.registry[module.__name__] = opts
60
59
 
61
60
  def load_data(self) -> None:
62
61
  """Calls `load` class with each list_data dictionary module to
@@ -24,8 +24,8 @@ class ListboardFilter:
24
24
 
25
25
  def __repr__(self):
26
26
  return (
27
- "{0.__class__.__name__}({0.name}, {0.label}, "
28
- "exclude_filter={0.exclude_filter}, {0.default})".format(self)
27
+ f"{self.__class__.__name__}({self.name}, {self.label}, "
28
+ f"exclude_filter={self.exclude_filter}, {self.default})"
29
29
  )
30
30
 
31
31
  @property
@@ -114,9 +114,7 @@ class BaseListboardView(SiteViewMixin, TemplateRequestContextMixin, ListView):
114
114
  Accepts `listboard_model` as a model class or label_lower.
115
115
  """
116
116
  if not self.get_listboard_model():
117
- raise ListboardViewError(
118
- f"Listboard model not declared. Got None. See {repr(self)}"
119
- )
117
+ raise ListboardViewError(f"Listboard model not declared. Got None. See {self!r}")
120
118
  try:
121
119
  return django_apps.get_model(self.get_listboard_model())
122
120
  except (ValueError, AttributeError):
edc_locator/models.py CHANGED
@@ -28,9 +28,9 @@ class SubjectLocator(
28
28
  def natural_key(self):
29
29
  return (self.subject_identifier,)
30
30
 
31
- natural_key.dependencies = ["sites.Site"]
31
+ natural_key.dependencies = ("sites.Site",)
32
32
 
33
33
  class Meta(ActionModelMixin.Meta, BaseUuidModel.Meta):
34
34
  verbose_name = "Subject Locator"
35
35
  verbose_name_plural = "Subject Locators"
36
- indexes = ActionModelMixin.Meta.indexes + BaseUuidModel.Meta.indexes
36
+ indexes = (*ActionModelMixin.Meta.indexes, *BaseUuidModel.Meta.indexes)
@@ -1,6 +1,6 @@
1
1
  from __future__ import annotations
2
2
 
3
- from typing import TYPE_CHECKING, Any, Type
3
+ from typing import TYPE_CHECKING, Any
4
4
 
5
5
  from django.apps import apps as django_apps
6
6
  from django.core.exceptions import MultipleObjectsReturned, ObjectDoesNotExist
@@ -67,7 +67,7 @@ class SubjectLocatorViewMixin:
67
67
  action_cls(subject_identifier=subject_identifier)
68
68
 
69
69
  @property
70
- def subject_locator_model_cls(self) -> Type[SubjectLocator]:
70
+ def subject_locator_model_cls(self) -> type[SubjectLocator]:
71
71
  return django_apps.get_model(self.subject_locator_model)
72
72
 
73
73
  @property
edc_ltfu/action_items.py CHANGED
@@ -14,7 +14,7 @@ class LtfuAction(ActionWithNotification):
14
14
  name = LTFU_ACTION
15
15
  display_name = "Submit Loss to Follow Up Report"
16
16
  notification_display_name = "Loss to Follow Up Report"
17
- parent_action_names = [VISIT_MISSED_ACTION]
17
+ parent_action_names = (VISIT_MISSED_ACTION,)
18
18
  show_link_to_changelist = True
19
19
  priority = HIGH_PRIORITY
20
20
 
edc_ltfu/model_mixins.py CHANGED
@@ -59,7 +59,6 @@ class LtfuModelMixin(models.Model):
59
59
 
60
60
  home_visit_detail = models.TextField(
61
61
  verbose_name="If YES, provide any further details of the home visit",
62
- null=True,
63
62
  blank=True,
64
63
  )
65
64
 
@@ -76,7 +75,6 @@ class LtfuModelMixin(models.Model):
76
75
  "If any, please give additional details of the "
77
76
  "circumstances that led to this decision."
78
77
  ),
79
- null=True,
80
78
  blank=True,
81
79
  )
82
80
 
edc_ltfu/models.py CHANGED
@@ -22,8 +22,8 @@ class Ltfu(
22
22
  verbose_name = "Loss to Follow Up"
23
23
  verbose_name_plural = "Loss to Follow Ups"
24
24
  indexes = (
25
- NonUniqueSubjectIdentifierFieldMixin.Meta.indexes
26
- + ActionModelMixin.Meta.indexes
27
- + BaseUuidModel.Meta.indexes
28
- + [models.Index(fields=["subject_identifier", "action_identifier", "site"])]
25
+ *NonUniqueSubjectIdentifierFieldMixin.Meta.indexes,
26
+ *ActionModelMixin.Meta.indexes,
27
+ *BaseUuidModel.Meta.indexes,
28
+ models.Index(fields=["subject_identifier", "action_identifier", "site"]),
29
29
  )
@@ -198,6 +198,6 @@ class MetadataModelAdminMixin(
198
198
  def get_view_on_site_url(self, obj=None):
199
199
  if obj is None or not self.view_on_site:
200
200
  return None
201
- elif hasattr(obj, "get_absolute_url"):
201
+ if hasattr(obj, "get_absolute_url"):
202
202
  url = reverse(self.changelist_url)
203
203
  return f"{url}?q={obj.subject_identifier}"
@@ -1,5 +1,3 @@
1
- from typing import Tuple
2
-
3
1
  from django.contrib import admin
4
2
 
5
3
  from ..admin_site import edc_metadata_admin
@@ -21,12 +19,12 @@ class RequisitionMetadataAdmin(MetadataModelAdminMixin):
21
19
  search_fields.append("panel_name")
22
20
  return tuple(search_fields)
23
21
 
24
- def get_list_display(self, request) -> Tuple[str, ...]:
22
+ def get_list_display(self, request) -> tuple[str, ...]:
25
23
  list_display = list(super().get_list_display(request))
26
24
  list_display.insert(3, "panel_name")
27
25
  return tuple(list_display)
28
26
 
29
- def get_list_filter(self, request) -> Tuple[str, ...]:
27
+ def get_list_filter(self, request) -> tuple[str, ...]:
30
28
  list_filter = list(super().get_list_filter(request))
31
29
  list_filter.insert(1, "panel_name")
32
30
  return tuple(list_filter)
@@ -1,7 +1,5 @@
1
1
  from __future__ import annotations
2
2
 
3
- from typing import Type
4
-
5
3
  from .metadata_getter import MetadataGetter, MetadataValidator
6
4
 
7
5
 
@@ -12,4 +10,4 @@ class CrfMetadataValidator(MetadataValidator):
12
10
  class CrfMetadataGetter(MetadataGetter):
13
11
  metadata_model: str = "edc_metadata.crfmetadata"
14
12
 
15
- metadata_validator_cls: Type[CrfMetadataValidator] = CrfMetadataValidator
13
+ metadata_validator_cls: type[CrfMetadataValidator] = CrfMetadataValidator
@@ -1,7 +1,5 @@
1
1
  from __future__ import annotations
2
2
 
3
- from typing import Type
4
-
5
3
  from .metadata_getter import MetadataGetter, MetadataValidator
6
4
 
7
5
 
@@ -14,4 +12,4 @@ class RequisitionMetadataValidator(MetadataValidator):
14
12
  class RequisitionMetadataGetter(MetadataGetter):
15
13
  metadata_model: str = "edc_metadata.requisitionmetadata"
16
14
 
17
- metadata_validator_cls: Type[RequisitionMetadataValidator] = RequisitionMetadataValidator
15
+ metadata_validator_cls: type[RequisitionMetadataValidator] = RequisitionMetadataValidator
@@ -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
@@ -48,7 +48,7 @@ class MetadataHandler:
48
48
  self.creator = self.creator_cls(related_visit=self.related_visit, update_keyed=True)
49
49
 
50
50
  @property
51
- def metadata_model_cls(self) -> Type[CrfMetadata] | Type[RequisitionMetadata]:
51
+ def metadata_model_cls(self) -> type[CrfMetadata] | type[RequisitionMetadata]:
52
52
  return django_apps.get_model(self.metadata_model)
53
53
 
54
54
  @property
@@ -13,7 +13,7 @@ if TYPE_CHECKING:
13
13
  from ..models import CrfMetadata, RequisitionMetadata
14
14
  else:
15
15
 
16
- class VisitScheduleFieldsProtocol: ... # noqa
16
+ class VisitScheduleFieldsProtocol: ...
17
17
 
18
18
 
19
19
  class MetadataHelperMixin(VisitScheduleFieldsProtocol):
@@ -30,8 +30,7 @@ class MetadataHelperMixin(VisitScheduleFieldsProtocol):
30
30
  def metadata_helper_instance(self):
31
31
  if self.metadata_helper_instance_attr:
32
32
  return getattr(self, self.metadata_helper_instance_attr)
33
- else:
34
- return self
33
+ return self
35
34
 
36
35
  @property
37
36
  def crf_metadata_exists(self) -> bool: