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
@@ -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.handlers.wsgi import WSGIRequest
6
6
 
@@ -14,7 +14,7 @@ if TYPE_CHECKING:
14
14
 
15
15
 
16
16
  class PdfReportModelMixin:
17
- pdf_report_cls: Type[CrfPdfReport]
17
+ pdf_report_cls: type[CrfPdfReport]
18
18
 
19
19
  def get_pdf_report(self: ModelMixin, request: WSGIRequest):
20
20
  return self.pdf_report_cls(model_obj=self, request=request, user=request.user)
edc_pdf_reports/report.py CHANGED
@@ -1,7 +1,6 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  from abc import ABC
4
- from typing import Type
5
4
  from uuid import uuid4
6
5
 
7
6
  from django.conf import settings
@@ -48,7 +47,7 @@ class Report(ABC):
48
47
  header_line: str | None = None,
49
48
  filename: str | None = None,
50
49
  request: WSGIRequest | None = None,
51
- numbered_canvas: Type[NumberedCanvas] | None = None,
50
+ numbered_canvas: type[NumberedCanvas] | None = None,
52
51
  footer_row_height: int | None = None,
53
52
  ):
54
53
  self._styles = None
@@ -77,12 +76,12 @@ class Report(ABC):
77
76
  return self._numbered_canvas
78
77
 
79
78
  @numbered_canvas.setter
80
- def numbered_canvas(self, value: Type[NumberedCanvas]):
79
+ def numbered_canvas(self, value: type[NumberedCanvas]):
81
80
  self._numbered_canvas = value
82
81
  if self.watermark_word:
83
- setattr(self._numbered_canvas, "watermark_word", self.watermark_word)
82
+ self._numbered_canvas.watermark_word = self.watermark_word
84
83
  if self.watermark_font:
85
- setattr(self._numbered_canvas, "watermark_font", self.watermark_font)
84
+ self._numbered_canvas.watermark_font = self.watermark_font
86
85
 
87
86
  @property
88
87
  def report_filename(self) -> str:
edc_pdf_reports/utils.py CHANGED
@@ -14,7 +14,7 @@ from .numbered_canvas import NumberedCanvas
14
14
  if TYPE_CHECKING:
15
15
  from .model_mixins import PdfReportModelMixin
16
16
 
17
- class Model(PdfReportModelMixin, models.Model): ... # noqa
17
+ class Model(PdfReportModelMixin, models.Model): ...
18
18
 
19
19
 
20
20
  mkdtemp()
@@ -1,5 +1,3 @@
1
- from typing import Type
2
-
3
1
  import numpy as np
4
2
  import pandas as pd
5
3
  from django.apps import apps as django_apps
@@ -13,7 +11,7 @@ from ..utils import convert_dates_from_model
13
11
 
14
12
  def get_subject_consent(
15
13
  model: str | None = None,
16
- model_cls: Type[Model] | None = None,
14
+ model_cls: type[Model] | None = None,
17
15
  subject_identifiers: list[str] | None = None,
18
16
  extra_columns: list[str] | None = None,
19
17
  normalize: bool | None = None,
@@ -129,11 +129,10 @@ class CsvExporter:
129
129
  record_count = len(dataframe)
130
130
  if self.verbose:
131
131
  sys.stdout.write(
132
- f'({style.SUCCESS("*")}) {self.model_name} {record_count} \n'
132
+ f"({style.SUCCESS('*')}) {self.model_name} {record_count} \n"
133
133
  )
134
- else:
135
- if self.verbose:
136
- sys.stdout.write(f"(?) {self.model_name} empty \n")
134
+ elif self.verbose:
135
+ sys.stdout.write(f"(?) {self.model_name} empty \n")
137
136
  return Exported(path, self.model_name, record_count)
138
137
 
139
138
  def to_csv(self, dataframe: pd.DataFrame = None, export_folder: str = None) -> Exported:
@@ -244,14 +243,13 @@ class CsvExporter:
244
243
  if fname in list(dataframe.columns):
245
244
  for stored, displayed in responses:
246
245
  labels.append(f'"{stored}" "{displayed}"')
247
- commands.append(f'label define {fname}l {" ".join(labels)}')
246
+ commands.append(f"label define {fname}l {' '.join(labels)}")
248
247
  commands.append(f"encode {fname}, generate({fname}_encoded) {fname}l")
249
248
  commands.append(f"ren {fname} {fname}_edc")
250
249
  commands.append(f"ren {fname}_encoded {fname}")
251
250
  commands.append("")
252
251
  with open(f"{self.get_path()}.do", "w") as f:
253
- for command in commands:
254
- f.write(f"{command}\n")
252
+ f.writelines(f"{command}\n" for command in commands)
255
253
  return commands
256
254
 
257
255
  def data_dictionary_qs(self, dataframe: pd.DataFrame) -> QuerySet:
@@ -48,7 +48,7 @@ class TablesExporter:
48
48
  ):
49
49
  self.app_label = app_label or self.app_label
50
50
  if not self.app_label:
51
- raise TablesExporterError(f"Missing app_label. Got None. See {repr(self)}")
51
+ raise TablesExporterError(f"Missing app_label. Got None. See {self!r}")
52
52
  self.export_folder = export_folder or get_export_folder()
53
53
  self.with_columns = with_columns or []
54
54
  self.without_columns = without_columns or []
@@ -63,7 +63,7 @@ class TablesExporter:
63
63
  self.table_names = self.get_table_names()
64
64
  if not self.table_names:
65
65
  raise TablesExporterError(
66
- f"No tables found for app_label. Got {self.app_label}. See {repr(self)}"
66
+ f"No tables found for app_label. Got {self.app_label}. See {self!r}"
67
67
  )
68
68
  for hint in exclude_table_hints:
69
69
  for table_name in self.get_table_names():
@@ -36,8 +36,7 @@ class CrfDfHandler(DfHandler):
36
36
  """
37
37
  if not self.visit_column:
38
38
  raise CrfDfHandlerError(
39
- f"visit column cannot be None. "
40
- f"See class attr 'visit_column' on {repr(self)}"
39
+ f"visit column cannot be None. See class attr 'visit_column' on {self!r}"
41
40
  )
42
41
  self.dataframe = pd.merge(
43
42
  left=self.dataframe,
@@ -19,7 +19,7 @@ class CrfDialect:
19
19
  f"LEFT JOIN {self.obj.visit_tbl} as V on A.id=V.appointment_id " # nosec
20
20
  f"LEFT JOIN {self.obj.registered_subject_tbl} as R " # nosec
21
21
  "on A.subject_identifier=R.subject_identifier " # nosec
22
- ) # noqa
22
+ )
23
23
  return sql, None
24
24
 
25
25
  @property
@@ -46,7 +46,7 @@ class CrfDialect:
46
46
  "on A.visit_definition_id=VDEF.id " # nosec
47
47
  f"LEFT JOIN {self.obj.registered_subject_tbl} as R " # nosec
48
48
  "on A.registered_subject_id=R.id " # nosec
49
- ) # noqa
49
+ )
50
50
  return sql, None
51
51
 
52
52
  @property
@@ -69,5 +69,5 @@ class CrfDialect:
69
69
  "on A.visit_definition_id=VDEF.id " # nosec
70
70
  f"LEFT JOIN {self.obj.registered_subject_tbl} as R " # nosec
71
71
  "on A.registered_subject_id=R.id " # nosec
72
- ) # noqa
72
+ )
73
73
  return sql, None
@@ -223,14 +223,13 @@ class Command(BaseCommand):
223
223
  countries = options["countries"] or []
224
224
  if not countries:
225
225
  raise CommandError("Expected country.")
226
+ if countries == ALL_COUNTRIES:
227
+ countries = sites.countries
226
228
  else:
227
- if countries == ALL_COUNTRIES:
228
- countries = sites.countries
229
- else:
230
- countries = options["countries"].lower().split(",")
231
- for country in countries:
232
- if country not in sites.countries:
233
- raise CommandError(f"Invalid country. Got {country}.")
229
+ countries = options["countries"].lower().split(",")
230
+ for country in countries:
231
+ if country not in sites.countries:
232
+ raise CommandError(f"Invalid country. Got {country}.")
234
233
  return countries
235
234
 
236
235
  def get_models(
@@ -59,7 +59,7 @@ class SiteValuesMappings:
59
59
  try:
60
60
  values_mapping.append((index, str(choice[1][::79])))
61
61
  except IndexError as e:
62
- raise IndexError(f"{str(e)} Got {choice[1]}")
62
+ raise IndexError(f"{e!s} Got {choice[1]}")
63
63
  return tuple(values_mapping)
64
64
 
65
65
  def get_by_choices(self, tpl: tuple[tuple[str, Any]]) -> tuple[tuple[int, str]] | None:
@@ -87,7 +87,7 @@ class SiteValuesMappings:
87
87
  except ImportError as e:
88
88
  site_values_mappings.registry = before_import_registry
89
89
  if module_has_submodule(mod, module_name):
90
- raise SiteValuesMappingError(f"{str(e)}. See {app}.{module_name}")
90
+ raise SiteValuesMappingError(f"{e!s}. See {app}.{module_name}")
91
91
  except ImportError:
92
92
  pass
93
93
 
@@ -5,5 +5,4 @@ def datetime_to_date(value):
5
5
  """Convert a datetime to date."""
6
6
  if pd.notnull(value):
7
7
  return value.date()
8
- else:
9
- return value
8
+ return value
@@ -1,5 +1,3 @@
1
- from typing import Type
2
-
3
1
  import pandas as pd
4
2
  from django.apps import apps as django_apps
5
3
  from django.db import models
@@ -8,7 +6,7 @@ from django.db import models
8
6
  def refresh_model_from_dataframe(
9
7
  df: pd.DataFrame,
10
8
  model: str | None = None,
11
- model_cls: Type[models.Model] | None = None,
9
+ model_cls: type[models.Model] | None = None,
12
10
  columns: list[str] | None = None,
13
11
  ) -> None:
14
12
  columns = columns or list(df.columns)
@@ -1,7 +1,5 @@
1
1
  from __future__ import annotations
2
2
 
3
- from typing import Type
4
-
5
3
  from ..database import Database
6
4
 
7
5
 
@@ -9,7 +7,7 @@ def get_table_names(
9
7
  app_label: str,
10
8
  with_columns: list[str] | None = None,
11
9
  without_columns: list[str] | None = None,
12
- db_cls: Type[Database] | None = None,
10
+ db_cls: type[Database] | None = None,
13
11
  ) -> list[str]:
14
12
  """Returns a list of table names for this app_label."""
15
13
  db = (db_cls or Database)()
@@ -28,7 +26,7 @@ def get_model_names(
28
26
  app_label: str,
29
27
  with_columns: list[str] | None = None,
30
28
  without_columns: list[str] | None = None,
31
- db_cls: Type[Database] | None = None,
29
+ db_cls: type[Database] | None = None,
32
30
  exclude_historical: bool | None = None,
33
31
  exclude_views: bool | None = None,
34
32
  ) -> list[str]:
@@ -12,5 +12,5 @@ def undash(value, exclude_pattern=None):
12
12
  else:
13
13
  value = value.replace("-", "")
14
14
  except AttributeError as e:
15
- raise AttributeError("{}. Got '{}'".format(str(e), value))
15
+ raise AttributeError(f"{e!s}. Got '{value}'")
16
16
  return value
@@ -1,5 +1,3 @@
1
- from typing import Tuple
2
-
3
1
  from django import forms
4
2
  from django.contrib import admin
5
3
  from django_audit_fields.admin import audit_fieldset_tuple
@@ -30,14 +28,14 @@ class AssignmentAdmin(ModelAdminMixin, admin.ModelAdmin):
30
28
  audit_fieldset_tuple,
31
29
  )
32
30
 
33
- list_display: Tuple[str, ...] = (
31
+ list_display: tuple[str, ...] = (
34
32
  "name",
35
33
  "display_name",
36
34
  "created",
37
35
  "modified",
38
36
  )
39
37
 
40
- search_fields: Tuple[str, ...] = ("name", "display_name")
38
+ search_fields: tuple[str, ...] = ("name", "display_name")
41
39
 
42
40
  def get_readonly_fields(self, request, obj=None):
43
41
  if obj:
@@ -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_fieldset_tuple
5
3
 
@@ -34,5 +32,5 @@ class DosageGuidelineAdmin(ModelAdminMixin, admin.ModelAdmin):
34
32
  audit_fieldset_tuple,
35
33
  )
36
34
 
37
- list_display: Tuple[str, ...] = ("__str__", "modified", "user_modified")
38
- search_fields: Tuple[str, ...] = ("medication__name",)
35
+ list_display: tuple[str, ...] = ("__str__", "modified", "user_modified")
36
+ search_fields: tuple[str, ...] = ("medication__name",)
@@ -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_fieldset_tuple
5
3
 
@@ -53,7 +51,7 @@ class FormulationAdmin(ModelAdminMixin, admin.ModelAdmin):
53
51
  "route": admin.VERTICAL,
54
52
  }
55
53
 
56
- list_filter: Tuple[str, ...] = (
54
+ list_filter: tuple[str, ...] = (
57
55
  "imp",
58
56
  "strength",
59
57
  "units",
@@ -70,6 +68,6 @@ class FormulationAdmin(ModelAdminMixin, admin.ModelAdmin):
70
68
  "route",
71
69
  )
72
70
 
73
- search_fields: Tuple[str, ...] = ("medication__name",)
71
+ search_fields: tuple[str, ...] = ("medication__name",)
74
72
 
75
- ordering: Tuple[str, ...] = ("medication__name",)
73
+ ordering: tuple[str, ...] = ("medication__name",)
@@ -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_fieldset_tuple
5
3
 
@@ -23,8 +21,8 @@ class MedicationAdmin(ModelAdminMixin, admin.ModelAdmin):
23
21
  audit_fieldset_tuple,
24
22
  )
25
23
 
26
- list_display: Tuple[str, ...] = ("name", "display_name", "created", "modified")
24
+ list_display: tuple[str, ...] = ("name", "display_name", "created", "modified")
27
25
 
28
- search_fields: Tuple[str, ...] = ("name",)
26
+ search_fields: tuple[str, ...] = ("name",)
29
27
 
30
- ordering: Tuple[str, ...] = ("name",)
28
+ ordering: tuple[str, ...] = ("name",)
@@ -1,5 +1,3 @@
1
- from typing import Tuple
2
-
3
1
  from django.conf import settings
4
2
  from django.contrib import admin
5
3
  from django.template.loader import render_to_string
@@ -21,7 +19,7 @@ from ..model_admin_mixin import ModelAdminMixin
21
19
  class RxRefillAdmin(ModelAdminMixin, admin.ModelAdmin):
22
20
  show_object_tools = True
23
21
 
24
- ordering: Tuple[str, ...] = ("refill_start_datetime",)
22
+ ordering: tuple[str, ...] = ("refill_start_datetime",)
25
23
 
26
24
  autocomplete_fields = ["dosage_guideline", "formulation"]
27
25
 
@@ -65,7 +63,7 @@ class RxRefillAdmin(ModelAdminMixin, admin.ModelAdmin):
65
63
  audit_fieldset_tuple,
66
64
  )
67
65
 
68
- list_display: Tuple[str, ...] = (
66
+ list_display: tuple[str, ...] = (
69
67
  "subject_identifier",
70
68
  "dashboard",
71
69
  "duration",
@@ -79,7 +77,7 @@ class RxRefillAdmin(ModelAdminMixin, admin.ModelAdmin):
79
77
  "verified_datetime",
80
78
  )
81
79
 
82
- list_filter: Tuple[str, ...] = (
80
+ list_filter: tuple[str, ...] = (
83
81
  "active",
84
82
  "refill_start_datetime",
85
83
  "refill_end_datetime",
@@ -89,7 +87,7 @@ class RxRefillAdmin(ModelAdminMixin, admin.ModelAdmin):
89
87
  "site",
90
88
  )
91
89
 
92
- search_fields: Tuple[str, ...] = (
90
+ search_fields: tuple[str, ...] = (
93
91
  "id",
94
92
  "site__id",
95
93
  "rx__id",
@@ -178,7 +176,7 @@ class RxRefillInlineAdmin(admin.StackedInline):
178
176
 
179
177
  model = RxRefill
180
178
 
181
- fields: Tuple[str, ...] = (
179
+ fields: tuple[str, ...] = (
182
180
  "dosage_guideline",
183
181
  "formulation",
184
182
  "refill_start_datetime",
@@ -189,8 +187,8 @@ class RxRefillInlineAdmin(admin.StackedInline):
189
187
  "frequency_units",
190
188
  )
191
189
 
192
- search_fields: Tuple[str, ...] = "dosage_guideline__medication__name"
190
+ search_fields: tuple[str, ...] = "dosage_guideline__medication__name"
193
191
 
194
- ordering: Tuple[str, ...] = ("refill_start_datetime",)
192
+ ordering: tuple[str, ...] = ("refill_start_datetime",)
195
193
 
196
194
  extra = 0
@@ -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_fieldset_tuple
5
3
 
@@ -67,7 +65,7 @@ class LotAdmin(ModelAdminMixin, SimpleHistoryAdmin):
67
65
  audit_fieldset_tuple,
68
66
  )
69
67
 
70
- list_filter: Tuple[str, ...] = (
68
+ list_filter: tuple[str, ...] = (
71
69
  "lot_no",
72
70
  "expiration_date",
73
71
  "product",
@@ -77,7 +75,7 @@ class LotAdmin(ModelAdminMixin, SimpleHistoryAdmin):
77
75
  "modified",
78
76
  )
79
77
 
80
- list_display: Tuple[str, ...] = (
78
+ list_display: tuple[str, ...] = (
81
79
  "lot_no",
82
80
  "expiration_date",
83
81
  "product",
@@ -86,11 +84,11 @@ class LotAdmin(ModelAdminMixin, SimpleHistoryAdmin):
86
84
  "created",
87
85
  "modified",
88
86
  )
89
- radio_fields: Tuple[str, ...] = {"assignment": admin.VERTICAL}
87
+ radio_fields: tuple[str, ...] = {"assignment": admin.VERTICAL}
90
88
 
91
- search_fields: Tuple[str, ...] = ("lot_no",)
89
+ search_fields: tuple[str, ...] = ("lot_no",)
92
90
 
93
- ordering: Tuple[str, ...] = ("-expiration_date",)
91
+ ordering: tuple[str, ...] = ("-expiration_date",)
94
92
 
95
93
  def get_readonly_fields(self, request, obj=None):
96
94
  # if obj:
@@ -80,7 +80,7 @@ class OrderAdmin(ModelAdminMixin, SimpleHistoryAdmin):
80
80
  if obj.item_count > OrderItem.objects.filter(order=obj).count():
81
81
  url = reverse("edc_pharmacy_admin:edc_pharmacy_orderitem_add")
82
82
  next_url = "edc_pharmacy_admin:edc_pharmacy_order_changelist"
83
- url = f"{url}?next={next_url}&order={str(obj.id)}&q={str(obj.order_identifier)}"
83
+ url = f"{url}?next={next_url}&order={obj.id!s}&q={obj.order_identifier!s}"
84
84
  context = dict(url=url, label="Add order item")
85
85
  add_order_items_button = render_to_string(
86
86
  "edc_pharmacy/stock/items_as_button.html", context=context
@@ -112,7 +112,7 @@ class OrderAdmin(ModelAdminMixin, SimpleHistoryAdmin):
112
112
  pass
113
113
  else:
114
114
  url = reverse("edc_pharmacy_admin:edc_pharmacy_receive_changelist")
115
- url = f"{url}?q={str(rcv_obj.receive_identifier)}"
115
+ url = f"{url}?q={rcv_obj.receive_identifier!s}"
116
116
  context = dict(url=url, label=rcv_obj.receive_identifier, title="Receive #")
117
117
  return render_to_string("edc_pharmacy/stock/items_as_link.html", context=context)
118
118
  return None
@@ -167,7 +167,7 @@ class OrderItemAdmin(ModelAdminMixin, SimpleHistoryAdmin):
167
167
  def get_status_label(self, obj: OrderItem) -> tuple[str, str]:
168
168
  if obj.unit_qty == 0:
169
169
  return RECEIVED, _("Received")
170
- elif obj.unit_qty == obj.unit_qty_ordered:
170
+ if obj.unit_qty == obj.unit_qty_ordered:
171
171
  return NEW, _("New")
172
172
  return PARTIAL, _("Partial")
173
173
 
@@ -202,7 +202,7 @@ class OrderItemAdmin(ModelAdminMixin, SimpleHistoryAdmin):
202
202
  def render_start_receiving_button(obj: OrderItem) -> str:
203
203
  url = reverse("edc_pharmacy_admin:edc_pharmacy_receive_add")
204
204
  next_url = "edc_pharmacy_admin:edc_pharmacy_orderitem_changelist"
205
- url = f"{url}?next={next_url}&q={str(obj.order.id)}&order={str(obj.order.id)}"
205
+ url = f"{url}?next={next_url}&q={obj.order.id!s}&order={obj.order.id!s}"
206
206
  context = dict(
207
207
  url=url,
208
208
  label=_("Start Receiving"),
@@ -216,7 +216,7 @@ class OrderItemAdmin(ModelAdminMixin, SimpleHistoryAdmin):
216
216
  @staticmethod
217
217
  def render_receive_changelist_link(receive: Receive) -> str:
218
218
  url = reverse("edc_pharmacy_admin:edc_pharmacy_receive_changelist")
219
- url = f"{url}?q={str(receive.receive_identifier)}"
219
+ url = f"{url}?q={receive.receive_identifier!s}"
220
220
  context = dict(url=url, label=receive.receive_identifier, title=_("Receive"))
221
221
  return render_to_string(
222
222
  "edc_pharmacy/stock/items_as_link.html",
@@ -228,8 +228,8 @@ class OrderItemAdmin(ModelAdminMixin, SimpleHistoryAdmin):
228
228
  url = reverse("edc_pharmacy_admin:edc_pharmacy_receiveitem_add")
229
229
  next_url = "edc_pharmacy_admin:edc_pharmacy_orderitem_changelist"
230
230
  url = (
231
- f"{url}?next={next_url}&order_item={str(obj.id)}&q={str(obj.order.id)}"
232
- f"&receive={str(receive.id)}&container={str(obj.container.id)}"
231
+ f"{url}?next={next_url}&order_item={obj.id!s}&q={obj.order.id!s}"
232
+ f"&receive={receive.id!s}&container={obj.container.id!s}"
233
233
  )
234
234
  context = dict(
235
235
  url=url,
@@ -245,7 +245,7 @@ class OrderItemAdmin(ModelAdminMixin, SimpleHistoryAdmin):
245
245
  status, status_label = self.get_status_label(obj)
246
246
  if status != NEW:
247
247
  url = reverse("edc_pharmacy_admin:edc_pharmacy_receiveitem_changelist")
248
- url = f"{url}?q={str(obj.pk)}"
248
+ url = f"{url}?q={obj.pk!s}"
249
249
  context = dict(url=url, label=status_label, title=_("Go to received items"))
250
250
  return render_to_string("edc_pharmacy/stock/items_as_link.html", context=context)
251
251
  return None
@@ -105,7 +105,7 @@ class ReceiveAdmin(ModelAdminMixin, SimpleHistoryAdmin):
105
105
  @admin.display(description="Order #")
106
106
  def order_changelist(self, obj):
107
107
  url = reverse("edc_pharmacy_admin:edc_pharmacy_order_changelist")
108
- url = f"{url}?q={str(obj.order.order_identifier)}"
108
+ url = f"{url}?q={obj.order.order_identifier!s}"
109
109
  context = dict(url=url, label=obj.order.order_identifier, title="Back to order")
110
110
  return render_to_string("edc_pharmacy/stock/items_as_link.html", context=context)
111
111
 
@@ -122,7 +122,7 @@ class ReceiveItemAdmin(ModelAdminMixin, SimpleHistoryAdmin):
122
122
  @admin.display(description="Order #")
123
123
  def order_changelist(self, obj):
124
124
  url = reverse("edc_pharmacy_admin:edc_pharmacy_order_changelist")
125
- url = f"{url}?q={str(obj.order_item.order.order_identifier)}"
125
+ url = f"{url}?q={obj.order_item.order.order_identifier!s}"
126
126
  context = dict(
127
127
  url=url, label=obj.order_item.order.order_identifier, title="Back to order"
128
128
  )
@@ -131,7 +131,7 @@ class ReceiveItemAdmin(ModelAdminMixin, SimpleHistoryAdmin):
131
131
  @admin.display(description="Order item #")
132
132
  def order_items_changelist(self, obj):
133
133
  url = reverse("edc_pharmacy_admin:edc_pharmacy_orderitem_changelist")
134
- url = f"{url}?q={str(obj.order_item.id)}"
134
+ url = f"{url}?q={obj.order_item.id!s}"
135
135
  context = dict(
136
136
  url=url,
137
137
  label=obj.order_item.order_item_identifier,
@@ -1,5 +1,3 @@
1
- from typing import Optional
2
-
3
1
  from celery.result import AsyncResult
4
2
  from celery.states import SUCCESS
5
3
  from django.contrib import admin
@@ -46,16 +44,16 @@ class StatusListFilter(admin.SimpleListFilter):
46
44
  .exclude(item_count=0)
47
45
  .distinct()
48
46
  )
49
- elif self.value() == COMPLETE:
47
+ if self.value() == COMPLETE:
50
48
  return (
51
49
  queryset.filter(cancel__isnull=True)
52
50
  .exclude(stockrequestitem__allocation__isnull=True)
53
51
  .exclude(item_count=0)
54
52
  .distinct()
55
53
  )
56
- elif self.value() == CANCELLED:
54
+ if self.value() == CANCELLED:
57
55
  return queryset.filter(cancel__isnull=False)
58
- elif self.value() == "ZERO":
56
+ if self.value() == "ZERO":
59
57
  return queryset.filter(item_count=0, cancel__isnull=True)
60
58
  return None
61
59
 
@@ -148,7 +146,7 @@ class StockRequestAdmin(ModelAdminMixin, SimpleHistoryAdmin):
148
146
 
149
147
  readonly_fields = ("item_count",)
150
148
 
151
- def redirect_url(self, request, obj, post_url_continue=None) -> Optional[str]:
149
+ def redirect_url(self, request, obj, post_url_continue=None) -> str | None:
152
150
  """Redirect to the review page immediately after saving model."""
153
151
  redirect_url = super().redirect_url(request, obj, post_url_continue)
154
152
  if obj.cancel == "CANCEL":
@@ -1,5 +1,5 @@
1
1
  from decimal import Decimal
2
- from typing import Any, Optional, Union
2
+ from typing import Any
3
3
 
4
4
 
5
5
  class DosageError(Exception):
@@ -9,9 +9,9 @@ class DosageError(Exception):
9
9
  class DosageCalculator:
10
10
  def __init__(
11
11
  self,
12
- dosage_guideline: Optional[Any] = None,
13
- formulation: Optional[Any] = None,
14
- weight_in_kgs: Optional[Union[float, Decimal]] = None,
12
+ dosage_guideline: Any | None = None,
13
+ formulation: Any | None = None,
14
+ weight_in_kgs: float | Decimal | None = None,
15
15
  ) -> None:
16
16
  self.dosage_guideline = dosage_guideline
17
17
  self.formulation = formulation
@@ -110,11 +110,10 @@ class StudyMedicationFormValidator(CrfFormValidator):
110
110
  def medication(self) -> Medication:
111
111
  if self.formulation:
112
112
  return self.formulation.medication
113
- else:
114
- self.raise_validation_error(
115
- {"__all__": "Need the formulation to look up the prescription."},
116
- INVALID_ERROR,
117
- )
113
+ self.raise_validation_error(
114
+ {"__all__": "Need the formulation to look up the prescription."},
115
+ INVALID_ERROR,
116
+ )
118
117
 
119
118
  @property
120
119
  def next_appointment(self) -> Appointment | None:
@@ -154,9 +153,10 @@ class StudyMedicationFormValidator(CrfFormValidator):
154
153
  "Subject is not receiving study medication. Refill end date "
155
154
  "and time must exactly match refill start date and time."
156
155
  )
157
- if not self.refill_end_datetime:
158
- self.raise_validation_error({"refill_end_datetime": error_msg}, INVALID_ERROR)
159
- elif self.refill_start_datetime != self.refill_end_datetime:
156
+ if (
157
+ not self.refill_end_datetime
158
+ or self.refill_start_datetime != self.refill_end_datetime
159
+ ):
160
160
  self.raise_validation_error({"refill_end_datetime": error_msg}, INVALID_ERROR)
161
161
 
162
162
  if (
@@ -6,7 +6,6 @@ from ...models import Allocation, StockRequest
6
6
 
7
7
 
8
8
  class StockRequestForm(forms.ModelForm):
9
-
10
9
  def clean(self):
11
10
  cleaned_data = super().clean()
12
11
 
@@ -41,8 +40,7 @@ class StockRequestForm(forms.ModelForm):
41
40
  raise forms.ValidationError(
42
41
  {
43
42
  "excluded_subject_identifiers": (
44
- "Not all subject identifiers are valid. "
45
- "Type one subject per line."
43
+ "Not all subject identifiers are valid. Type one subject per line."
46
44
  )
47
45
  }
48
46
  )
@@ -64,7 +62,7 @@ class StockRequestForm(forms.ModelForm):
64
62
 
65
63
  if not self.instance.id and cleaned_data.get("cancel") == "CANCEL":
66
64
  raise forms.ValidationError("Leave this blank")
67
- elif cleaned_data.get("cancel") == "CANCEL":
65
+ if cleaned_data.get("cancel") == "CANCEL":
68
66
  if Allocation.objects.filter(
69
67
  stock_request_item__stock_request=self.instance
70
68
  ).exists():