clinicedc 2.0.6__py3-none-any.whl → 2.0.8__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 (495) hide show
  1. {clinicedc-2.0.6.dist-info → clinicedc-2.0.8.dist-info}/METADATA +2 -2
  2. {clinicedc-2.0.6.dist-info → clinicedc-2.0.8.dist-info}/RECORD +489 -441
  3. {clinicedc-2.0.6.dist-info → clinicedc-2.0.8.dist-info}/WHEEL +1 -1
  4. edc_action_item/action.py +1 -1
  5. edc_action_item/action_item_notification.py +2 -2
  6. edc_action_item/auths.py +37 -32
  7. edc_action_item/create_action_item.py +1 -1
  8. edc_action_item/decorators.py +1 -1
  9. edc_action_item/migrations/0001_initial.py +21 -22
  10. edc_action_item/migrations/0006_auto_20180707_1659.py +4 -4
  11. edc_action_item/migrations/0008_auto_20180809_0303.py +4 -4
  12. edc_action_item/migrations/0015_auto_20190114_0250.py +4 -4
  13. edc_action_item/migrations/0017_auto_20190305_0123.py +11 -30
  14. edc_action_item/migrations/0030_edcpermissions.py +3 -2
  15. edc_action_item/migrations/0039_alter_actionitem_auto_created_comment_and_more.py +398 -0
  16. edc_action_item/migrations/0040_alter_actionitem_report_datetime_and_more.py +34 -0
  17. edc_action_item/models/action_item.py +9 -4
  18. edc_action_item/models/action_model_mixin.py +5 -6
  19. edc_action_item/models/reference.py +2 -2
  20. edc_action_item/models/signals.py +22 -23
  21. edc_action_item/post_migrate_signals.py +1 -1
  22. edc_action_item/send_email.py +0 -85
  23. edc_action_item/site_action_items.py +5 -9
  24. edc_action_item/utils.py +3 -3
  25. edc_adherence/migrations/0005_alter_nonadherencereasons_extra_value_and_more.py +36 -0
  26. edc_adherence/model_mixins.py +1 -1
  27. edc_adverse_event/auths.py +55 -51
  28. edc_adverse_event/migrations/0001_initial.py +5 -4
  29. edc_adverse_event/migrations/0002_auto_20190802_0059.py +3 -2
  30. edc_adverse_event/migrations/0008_auto_20220825_0451.py +3 -2
  31. edc_adverse_event/migrations/0009_auto_20220907_0157.py +3 -2
  32. edc_adverse_event/migrations/0016_alter_aeactionclassification_device_created_and_more.py +285 -0
  33. edc_adverse_event/model_mixins/ae_followup/ae_followup_fields_model_mixin.py +2 -2
  34. edc_adverse_event/model_mixins/ae_initial/ae_initial_fields_model_mixin.py +6 -5
  35. edc_adverse_event/model_mixins/ae_special_interest/aesi_fields_model_mixin.py +2 -2
  36. edc_adverse_event/model_mixins/ae_susar/ae_susar_fields_model_mixin.py +2 -2
  37. edc_adverse_event/model_mixins/ae_tmg/ae_tmg_fields_model_mixin.py +15 -11
  38. edc_adverse_event/model_mixins/ae_tmg/ae_tmg_methods_model_mixin.py +2 -4
  39. edc_adverse_event/model_mixins/death_report/death_report_model_mixin.py +5 -4
  40. edc_adverse_event/model_mixins/death_report/death_report_tmg_model_mixin.py +6 -3
  41. edc_adverse_event/model_mixins/death_report/simple_death_report_model_mixin.py +2 -2
  42. edc_adverse_event/model_mixins/hospitaization/hospitalization_model_mixin.py +4 -3
  43. edc_adverse_event/modeladmin_mixins/death_report_admin_mixin.py +3 -3
  44. edc_adverse_event/models/signals.py +7 -7
  45. edc_adverse_event/templatetags/edc_adverse_event_extras.py +5 -4
  46. edc_adverse_event/view_mixins/ae/ae_listboard_view_mixin.py +3 -5
  47. edc_adverse_event/view_mixins/ae/death_report_listboard_view_mixin.py +6 -8
  48. edc_adverse_event/view_mixins/tmg/tmg_ae_listboard_view_mixin.py +2 -2
  49. edc_adverse_event/views/tmg/summary_listboard_view.py +3 -2
  50. edc_appointment/admin/appointment_admin.py +2 -2
  51. edc_appointment/admin/list_filters.py +2 -2
  52. edc_appointment/auths.py +14 -10
  53. edc_appointment/creators/appointment_creator.py +1 -1
  54. edc_appointment/creators/appointments_creator.py +1 -1
  55. edc_appointment/form_validators/appointment_form_validator.py +108 -82
  56. edc_appointment/migrations/0003_auto_20161127_2226.py +5 -6
  57. edc_appointment/migrations/0006_auto_20170106_2118.py +5 -5
  58. edc_appointment/migrations/0018_auto_20190305_0123.py +5 -12
  59. edc_appointment/migrations/0050_alter_appointment_appt_type_and_more.py +220 -0
  60. edc_appointment/model_mixins/appointment_fields_model_mixin.py +1 -2
  61. edc_appointment/model_mixins/appointment_methods_model_mixin.py +2 -3
  62. edc_appointment/model_mixins/appointment_model_mixin.py +31 -28
  63. edc_appointment/model_mixins/window_period_model_mixin.py +6 -7
  64. edc_appointment/models/appointment.py +1 -1
  65. edc_appointment/models/signals.py +44 -35
  66. edc_appointment/utils.py +19 -24
  67. edc_appointment/view_utils/appointment_button.py +2 -2
  68. edc_auth/admin/user_admin.py +1 -1
  69. edc_auth/auth_objects/__init__.py +2 -20
  70. edc_auth/auth_objects/default_groups.py +13 -11
  71. edc_auth/auth_objects/default_roles.py +26 -24
  72. edc_auth/auth_updater/auth_updater.py +13 -2
  73. edc_auth/auth_updater/group_updater.py +12 -10
  74. edc_auth/auth_updater/role_updater.py +2 -2
  75. edc_auth/constants.py +10 -0
  76. edc_auth/import_users.py +3 -3
  77. edc_auth/migrations/0001_squashed_0033_alter_userprofile_is_multisite_viewer.py +5 -5
  78. edc_auth/migrations/0012_auto_20191026_0034.py +3 -2
  79. edc_auth/migrations/0013_auto_20191026_0055.py +3 -2
  80. edc_auth/migrations/0025_permissions.py +3 -2
  81. edc_auth/migrations/0035_alter_edcpermissions_device_created_and_more.py +85 -0
  82. edc_auth/models/user_profile.py +14 -11
  83. edc_auth/post_migrate_signals.py +1 -1
  84. edc_auth/site_auths.py +80 -67
  85. edc_consent/actions.py +4 -5
  86. edc_consent/auths.py +18 -12
  87. edc_consent/migrations/0001_initial.py +3 -2
  88. edc_consent/migrations/0006_alter_edcpermissions_device_created_and_more.py +49 -0
  89. edc_consent/model_mixins/consent_extension_model_mixin.py +4 -5
  90. edc_consent/model_mixins/requires_consent_fields_model_mixin.py +2 -2
  91. edc_consent/utils.py +1 -1
  92. edc_constants/constants.py +1 -0
  93. edc_crf/auths.py +5 -0
  94. edc_crf/migrations/0001_initial.py +3 -2
  95. edc_crf/migrations/0009_alter_crfstatus_device_created_and_more.py +54 -0
  96. edc_dashboard/auths.py +10 -6
  97. edc_dashboard/migrations/0001_initial.py +3 -2
  98. edc_dashboard/migrations/0006_alter_edcpermissions_device_created_and_more.py +49 -0
  99. edc_dashboard/templatetags/edc_dashboard_extras.py +3 -2
  100. edc_dashboard/url_config.py +92 -83
  101. edc_dashboard/url_names.py +4 -4
  102. edc_dashboard/view_mixins/url_request_context_mixin.py +6 -5
  103. edc_data_manager/action_items.py +4 -6
  104. edc_data_manager/admin/actions.py +5 -5
  105. edc_data_manager/admin/data_query_admin.py +12 -11
  106. edc_data_manager/auths.py +37 -34
  107. edc_data_manager/handlers/handlers.py +6 -7
  108. edc_data_manager/migrations/0001_initial.py +19 -19
  109. edc_data_manager/migrations/0025_edcpermissions.py +3 -2
  110. edc_data_manager/migrations/0040_alter_datadictionary_device_created_and_more.py +327 -0
  111. edc_data_manager/migrations/0041_alter_dataquery_dm_user_and_more.py +164 -0
  112. edc_data_manager/models/data_query.py +5 -5
  113. edc_data_manager/models/model_mixins.py +8 -8
  114. edc_data_manager/rule/query_rule_wrapper.py +7 -7
  115. edc_data_manager/rule/rule_runner.py +4 -3
  116. edc_document_status/model_mixins.py +1 -1
  117. edc_egfr/egfr.py +11 -7
  118. edc_egfr/model_mixins/egfr_model_mixin.py +3 -7
  119. edc_export/admin/data_request_admin.py +2 -2
  120. edc_export/archive_exporter.py +7 -5
  121. edc_export/auths.py +32 -28
  122. edc_export/files_archiver.py +3 -2
  123. edc_export/migrations/0001_initial.py +26 -26
  124. edc_export/migrations/0004_auto_20190305_0123.py +25 -72
  125. edc_export/migrations/0013_edcpermissions.py +3 -2
  126. edc_export/migrations/0022_alter_datarequest_description_and_more.py +611 -0
  127. edc_export/migrations/0023_alter_datarequesthistory_archive_filename_and_more.py +29 -0
  128. edc_export/model_exporter/file_history_updater.py +10 -10
  129. edc_export/model_exporter/model_exporter.py +17 -15
  130. edc_export/model_exporter/object_history_helpers.py +2 -2
  131. edc_export/models/data_request_history.py +4 -4
  132. edc_export/utils.py +10 -15
  133. edc_facility/auths.py +8 -3
  134. edc_facility/facility.py +16 -22
  135. edc_facility/import_holidays.py +13 -13
  136. edc_facility/migrations/0005_healthfacility_healthfacilitytypes_and_more.py +8 -7
  137. edc_facility/migrations/0016_alter_healthfacility_device_created_and_more.py +139 -0
  138. edc_facility/migrations/0017_alter_healthfacility_gps_and_more.py +54 -0
  139. edc_facility/model_mixins.py +5 -5
  140. edc_form_label/custom_label_condition.py +11 -8
  141. edc_form_label/form_label.py +1 -1
  142. edc_form_runners/auths.py +11 -6
  143. edc_form_runners/form_runner.py +3 -5
  144. edc_form_runners/migrations/0001_initial.py +3 -2
  145. edc_form_runners/migrations/0005_alter_issue_device_created_and_more.py +49 -0
  146. edc_form_validators/applicable_field_validator.py +7 -6
  147. edc_form_validators/base_form_validator.py +8 -9
  148. edc_form_validators/other_specify_field_validator.py +2 -8
  149. edc_form_validators/required_field_validator.py +19 -16
  150. edc_identifier/migrations/0001_squashed_0018_auto_20180128_1054.py +3 -3
  151. edc_identifier/migrations/0002_auto_20190305_0123.py +3 -6
  152. edc_identifier/migrations/0006_auto_20161127_2226.py +15 -15
  153. edc_identifier/migrations/0007_auto_20161204_2227.py +3 -3
  154. edc_identifier/migrations/0009_auto_20161221_2323.py +3 -5
  155. edc_identifier/migrations/0010_auto_20170112_0602.py +17 -17
  156. edc_identifier/migrations/0011_alter_identifiermodel_device_created_and_more.py +79 -0
  157. edc_identifier/model_mixins.py +1 -1
  158. edc_identifier/models.py +9 -9
  159. edc_identifier/research_identifier.py +11 -10
  160. edc_identifier/simple_identifier.py +9 -5
  161. edc_identifier/subject_identifier.py +3 -2
  162. edc_lab/auths.py +26 -23
  163. edc_lab/lab/aliquot_creator.py +5 -8
  164. edc_lab/lab/primary_aliquot.py +14 -5
  165. edc_lab/migrations/0001_initial.py +29 -29
  166. edc_lab/migrations/0008_auto_20170921_0719.py +3 -3
  167. edc_lab/migrations/0010_auto_20171127_1541.py +15 -15
  168. edc_lab/migrations/0012_auto_20180114_1438.py +3 -3
  169. edc_lab/migrations/0019_auto_20190305_0123.py +43 -127
  170. edc_lab/migrations/0036_alter_aliquot_comment_alter_aliquot_device_created_and_more.py +1139 -0
  171. edc_lab/migrations/0037_alter_historicalorder_order_datetime_and_more.py +31 -0
  172. edc_lab/model_mixins/aliquot/aliquot_identifier_model_mixin.py +2 -2
  173. edc_lab/model_mixins/aliquot/aliquot_model_mixin.py +2 -2
  174. edc_lab/model_mixins/panel_model_mixin.py +18 -7
  175. edc_lab/model_mixins/requisition/crf_with_requisition_model_mixin.py +2 -4
  176. edc_lab/model_mixins/requisition/requisition_model_mixin.py +13 -16
  177. edc_lab/model_mixins/requisition/requisition_verify_model_mixin.py +1 -1
  178. edc_lab/model_mixins/result/result_item_model_mixin.py +4 -4
  179. edc_lab/model_mixins/shipping/manifest_model_mixin.py +4 -5
  180. edc_lab/model_mixins/shipping/verify_model_mixin.py +4 -6
  181. edc_lab/models/aliquot.py +2 -2
  182. edc_lab/models/box.py +1 -1
  183. edc_lab/models/box_item.py +6 -7
  184. edc_lab/models/manifest/manifest.py +3 -3
  185. edc_lab/models/manifest/manifest_item.py +7 -7
  186. edc_lab/models/manifest/shipper.py +3 -4
  187. edc_lab/models/order.py +6 -4
  188. edc_lab/models/panel.py +4 -4
  189. edc_lab/models/result.py +2 -2
  190. edc_lab/models/result_item.py +2 -2
  191. edc_lab_dashboard/auths.py +16 -11
  192. edc_lab_dashboard/migrations/0001_initial.py +3 -2
  193. edc_lab_dashboard/migrations/0005_alter_edcpermissions_device_created_and_more.py +49 -0
  194. edc_lab_dashboard/views/action_views/receive_view.py +2 -2
  195. edc_lab_dashboard/views/action_views/verify_box_item_view.py +2 -2
  196. edc_lab_results/calculate_missing.py +8 -8
  197. edc_lab_results/form_validator_mixins/blood_results_form_validator_mixin.py +2 -2
  198. edc_lab_results/get_summary.py +26 -25
  199. edc_lab_results/model_mixins/blood_result_model_mixin.py +9 -7
  200. edc_lab_results/model_mixins/fbg_model_mixin.py +3 -3
  201. edc_lab_results/model_mixins/glucose_model_mixin.py +3 -3
  202. edc_lab_results/model_mixins/hba1c_model_mixin.py +3 -3
  203. edc_label/auths.py +6 -1
  204. edc_label/label_template.py +8 -8
  205. edc_label/migrations/0001_initial.py +3 -2
  206. edc_label/migrations/0007_alter_zpllabeltemplates_device_created_and_more.py +49 -0
  207. edc_list_data/list_model_maker.py +2 -2
  208. edc_list_data/load_list_data.py +11 -14
  209. edc_list_data/load_model_data.py +3 -3
  210. edc_list_data/model_mixins.py +12 -4
  211. edc_list_data/post_migrate_signals.py +1 -1
  212. edc_list_data/preload_data.py +4 -4
  213. edc_list_data/row.py +1 -1
  214. edc_list_data/site_list_data.py +6 -5
  215. edc_listboard/migrations/0001_initial.py +3 -2
  216. edc_listboard/migrations/0007_alter_listboard_device_created_and_more.py +49 -0
  217. edc_locator/auths.py +18 -13
  218. edc_locator/migrations/0001_initial.py +7 -7
  219. edc_locator/migrations/0018_auto_20190305_0123.py +5 -12
  220. edc_locator/migrations/0040_alter_historicalsubjectlocator_action_identifier_and_more.py +187 -0
  221. edc_locator/migrations/0041_alter_historicalsubjectlocator_report_datetime_and_more.py +27 -0
  222. edc_locator/model_mixins/locator_model_mixin.py +2 -2
  223. edc_locator/model_mixins/subject_contact_fields_mixin.py +1 -1
  224. edc_locator/modeladmin_mixins.py +5 -4
  225. edc_ltfu/model_mixins.py +7 -5
  226. edc_metadata/auths.py +11 -7
  227. edc_metadata/metadata/metadata.py +1 -1
  228. edc_metadata/metadata_rules/crf/crf_rule.py +1 -1
  229. edc_metadata/metadata_rules/decorators.py +1 -1
  230. edc_metadata/metadata_rules/metadata_rule_evaluator.py +5 -3
  231. edc_metadata/metadata_rules/rule.py +2 -3
  232. edc_metadata/metadata_rules/rule_evaluator.py +1 -1
  233. edc_metadata/migrations/0002_auto_20161127_2226.py +5 -5
  234. edc_metadata/migrations/0005_auto_20170112_0602.py +5 -5
  235. edc_metadata/migrations/0011_auto_20190305_0123.py +5 -12
  236. edc_metadata/migrations/0031_alter_crfmetadata_device_created_and_more.py +120 -0
  237. edc_metadata/model_mixins/updates/updates_crf_metadata_model_mixin.py +7 -4
  238. edc_metadata/model_mixins/updates/updates_requisition_metadata_model_mixin.py +5 -2
  239. edc_metadata/models/crf_metadata.py +5 -5
  240. edc_metadata/models/crf_metadata_model_mixin.py +4 -5
  241. edc_metadata/models/requisition_metadata.py +6 -6
  242. edc_metadata/models/signals.py +10 -11
  243. edc_metadata/views/refresh_metadata_actions_view.py +3 -3
  244. edc_model/models/address_mixin.py +6 -6
  245. edc_model/models/fields/initials_field.py +2 -1
  246. edc_model/models/historical_records.py +2 -9
  247. edc_model/models/url_model_mixin.py +2 -2
  248. edc_model/validators/date.py +7 -8
  249. edc_model_admin/list_filters/future_date_list_filter.py +3 -3
  250. edc_model_admin/list_filters/past_date_list_filter.py +3 -3
  251. edc_model_admin/mixins/model_admin_protect_pii_mixin.py +4 -5
  252. edc_model_fields/fields/other_charfield.py +2 -2
  253. edc_navbar/auths.py +18 -13
  254. edc_navbar/migrations/0004_auto_20220825_0451.py +3 -2
  255. edc_navbar/migrations/0009_alter_edcpermissions_device_created_and_more.py +49 -0
  256. edc_notification/auths.py +9 -4
  257. edc_notification/migrations/0001_initial.py +3 -3
  258. edc_notification/migrations/0004_auto_20190305_0123.py +3 -6
  259. edc_notification/migrations/0011_alter_notification_device_created_and_more.py +59 -0
  260. edc_notification/models/notification.py +1 -1
  261. edc_notification/notification/graded_event_notification.py +2 -2
  262. edc_notification/notification/model_notification.py +3 -30
  263. edc_notification/notification/new_model_notification.py +1 -1
  264. edc_notification/notification/notification.py +12 -12
  265. edc_notification/notification/updated_model_notification.py +2 -2
  266. edc_offstudy/auths.py +12 -7
  267. edc_offstudy/migrations/0001_initial.py +4 -4
  268. edc_offstudy/migrations/0002_auto_20180921_0434.py +4 -4
  269. edc_offstudy/migrations/0005_auto_20190305_0123.py +5 -12
  270. edc_offstudy/migrations/0023_alter_historicalsubjectoffstudy_action_identifier_and_more.py +188 -0
  271. edc_offstudy/migrations/0024_alter_historicalsubjectoffstudy_offstudy_datetime_and_more.py +43 -0
  272. edc_offstudy/model_mixins/offstudy_model_mixin.py +3 -2
  273. edc_pdutils/df_exporters/csv_exporter.py +33 -37
  274. edc_pdutils/df_exporters/csv_model_exporter.py +7 -3
  275. edc_pdutils/migrations/0001_initial.py +8 -8
  276. edc_pharmacy/admin/prescription/rx_refill_admin.py +4 -3
  277. edc_pharmacy/admin/reports/stock_availability_admin.py +5 -6
  278. edc_pharmacy/auths.py +19 -15
  279. edc_pharmacy/migrations/0001_initial.py +64 -63
  280. edc_pharmacy/migrations/0015_auto_20220913_2139.py +26 -26
  281. edc_pharmacy/migrations/0024_allocation_assignment_containerunits_dispense_and_more.py +81 -86
  282. edc_pharmacy/migrations/0037_remove_historicalstock_confirmed_at_site_by_and_more.py +5 -5
  283. edc_pharmacy/migrations/0039_remove_dispense_registered_subject_and_more.py +7 -8
  284. edc_pharmacy/migrations/0049_remove_stocktransferconfirmation_stock_and_more.py +12 -12
  285. edc_pharmacy/migrations/0050_remove_stocktransferconfirmation2_location_and_more.py +5 -5
  286. edc_pharmacy/migrations/0051_alter_historicalstocktransferconfirmationitem_options_and_more.py +3 -4
  287. edc_pharmacy/migrations/0053_alter_location_managers_alter_historicalstock_lot_and_more.py +3 -3
  288. edc_pharmacy/migrations/0057_scanduplicates.py +3 -3
  289. edc_pharmacy/migrations/0060_alter_container_max_per_subject_and_more.py +13 -15
  290. edc_pharmacy/migrations/0068_stockout.py +2 -3
  291. edc_pharmacy/migrations/0076_historicalstockadjustment_stockadjustment.py +5 -5
  292. edc_pharmacy/migrations/0077_historicalstockadjustment_adjustment_datetime_and_more.py +3 -4
  293. edc_pharmacy/migrations/0081_historicalconfirmation_confirmation.py +8 -8
  294. edc_pharmacy/migrations/0084_confirmationatsiteitem_and_more.py +0 -2
  295. edc_pharmacy/migrations/0089_alter_allocation_allocated_by_and_more.py +3284 -0
  296. edc_pharmacy/migrations/0090_alter_allocation_allocation_datetime_and_more.py +227 -0
  297. edc_pharmacy/model_mixins/study_medication_refill_model_mixin.py +2 -2
  298. edc_pharmacy/models/medication/formulation.py +5 -7
  299. edc_pharmacy/models/medication/medication.py +3 -3
  300. edc_pharmacy/models/model_mixins.py +10 -11
  301. edc_pharmacy/models/prescription/rx.py +13 -12
  302. edc_pharmacy/models/prescription/rx_refill.py +0 -1
  303. edc_pharmacy/models/stock/allocation.py +3 -3
  304. edc_pharmacy/models/stock/confirmation.py +3 -3
  305. edc_pharmacy/models/stock/confirmation_at_site.py +3 -2
  306. edc_pharmacy/models/stock/confirmation_at_site_item.py +3 -4
  307. edc_pharmacy/models/stock/dispense.py +5 -6
  308. edc_pharmacy/models/stock/dispense_item.py +2 -2
  309. edc_pharmacy/models/stock/location.py +3 -4
  310. edc_pharmacy/models/stock/lot.py +6 -7
  311. edc_pharmacy/models/stock/order.py +1 -1
  312. edc_pharmacy/models/stock/receive.py +3 -3
  313. edc_pharmacy/models/stock/receive_item.py +4 -4
  314. edc_pharmacy/models/stock/repack_request.py +2 -2
  315. edc_pharmacy/models/stock/stock.py +12 -18
  316. edc_pharmacy/models/stock/stock_adjustment.py +4 -4
  317. edc_pharmacy/models/stock/stock_request.py +2 -2
  318. edc_pharmacy/models/stock/stock_request_item.py +2 -2
  319. edc_pharmacy/models/stock/stock_transfer.py +3 -3
  320. edc_pharmacy/models/stock/stock_transfer_item.py +2 -2
  321. edc_pharmacy/models/stock/storage_bin.py +3 -4
  322. edc_pharmacy/models/stock/storage_bin_item.py +2 -2
  323. edc_pharmacy/models/stock/supplier.py +3 -4
  324. edc_pharmacy/models/storage/box.py +2 -2
  325. edc_pharmacy/models/storage/items/container_model_mixin.py +3 -4
  326. edc_pharmacy/models/storage/items/pill_bottle_model_mixin.py +2 -2
  327. edc_pharmacy/models/storage/items/subject_pill_bottle.py +1 -1
  328. edc_pharmacy/models/storage/room.py +2 -2
  329. edc_pharmacy/models/storage/shelf.py +2 -2
  330. edc_pharmacy/models/storage/utils.py +1 -1
  331. edc_pharmacy/prescribe/create_prescription.py +3 -3
  332. edc_pharmacy/utils/allocate_stock.py +2 -3
  333. edc_pharmacy/utils/confirm_stock.py +3 -4
  334. edc_pharmacy/utils/confirm_stock_at_site.py +4 -5
  335. edc_pharmacy/utils/dispense.py +3 -4
  336. edc_pharmacy/utils/process_repack_request.py +4 -5
  337. edc_pharmacy/utils/stock_request/bulk_create_stock_request_items.py +2 -3
  338. edc_pharmacy/utils/transfer_stock.py +2 -3
  339. edc_pharmacy/views/add_to_storage_bin_view.py +2 -2
  340. edc_pharmacy/views/allocate_to_subject_view.py +2 -2
  341. edc_pharmacy/views/confirmation_at_site_view.py +6 -9
  342. edc_pharmacy/views/dispense_view.py +2 -2
  343. edc_pharmacy/views/move_to_storage_bin_view.py +2 -3
  344. edc_pharmacy/views/print_labels_view.py +2 -2
  345. edc_prn/admin_site.py +5 -0
  346. edc_prn/prn.py +10 -11
  347. edc_prn/urls.py +11 -0
  348. edc_protocol/research_protocol_config.py +2 -3
  349. edc_protocol_incident/action_items.py +4 -4
  350. edc_protocol_incident/auths.py +27 -20
  351. edc_protocol_incident/migrations/0001_initial.py +7 -7
  352. edc_protocol_incident/migrations/0001_squashed_0015_auto_20220927_0401.py +13 -13
  353. edc_protocol_incident/migrations/0005_protocolincident_historicalprotocolincident_and_more.py +7 -7
  354. edc_protocol_incident/migrations/0024_alter_actionsrequired_extra_value_and_more.py +625 -0
  355. edc_protocol_incident/migrations/0025_alter_historicalprotocoldeviationviolation_report_datetime_and_more.py +42 -0
  356. edc_protocol_incident/model_mixins/protocol_deviation_violation_model_mixin.py +18 -11
  357. edc_protocol_incident/model_mixins/protocol_incident_model_mixin.py +26 -11
  358. edc_pylabels/actions.py +3 -5
  359. edc_pylabels/auths.py +6 -1
  360. edc_pylabels/migrations/0002_alter_label_options_label_created_and_more.py +3 -7
  361. edc_pylabels/migrations/0005_labelconfiguration_delete_label_and_more.py +3 -3
  362. edc_pylabels/migrations/0013_alter_labelconfiguration_device_created_and_more.py +49 -0
  363. edc_qareports/auths.py +11 -7
  364. edc_qareports/migrations/0001_initial.py +4 -5
  365. edc_qareports/migrations/0005_edcpermissions.py +3 -3
  366. edc_qareports/migrations/0006_qareportlog.py +2 -3
  367. edc_qareports/migrations/0019_alter_edcpermissions_device_created_and_more.py +102 -0
  368. edc_qareports/migrations/0020_alter_note_report_datetime_and_more.py +24 -0
  369. edc_qareports/model_mixins/note_model_mixin.py +7 -4
  370. edc_qareports/model_mixins/on_study_missing_values_model_mixin.py +4 -4
  371. edc_qareports/model_mixins/qa_report_model_mixin.py +2 -3
  372. edc_qareports/models/note.py +4 -4
  373. edc_qareports/models/qa_reports_log.py +2 -3
  374. edc_randomization/admin.py +30 -24
  375. edc_randomization/auths.py +12 -7
  376. edc_randomization/decorators.py +1 -1
  377. edc_randomization/migrations/0001_initial.py +3 -2
  378. edc_randomization/migrations/0002_historicalrandomizationlist.py +3 -2
  379. edc_randomization/migrations/0009_edcpermissions.py +3 -2
  380. edc_randomization/migrations/0014_alter_edcpermissions_device_created_and_more.py +141 -0
  381. edc_randomization/model_mixins.py +9 -9
  382. edc_randomization/randomizer.py +22 -20
  383. edc_randomization/utils.py +19 -18
  384. edc_refusal/auths.py +7 -2
  385. edc_refusal/migrations/0001_initial.py +4 -4
  386. edc_refusal/migrations/0002_historicalsubjectrefusal.py +4 -4
  387. edc_refusal/migrations/0012_alter_historicalsubjectrefusal_comment_and_more.py +122 -0
  388. edc_refusal/migrations/0013_alter_historicalsubjectrefusal_report_datetime_and_more.py +28 -0
  389. edc_refusal/model_mixins.py +4 -4
  390. edc_registration/auths.py +28 -23
  391. edc_registration/migrations/0002_auto_20161127_2226.py +3 -4
  392. edc_registration/migrations/0005_auto_20170111_1809.py +4 -2
  393. edc_registration/migrations/0016_historicalregisteredsubject.py +3 -2
  394. edc_registration/migrations/0017_auto_20190305_0123.py +5 -12
  395. edc_registration/migrations/0033_alter_historicalregisteredsubject_additional_key_and_more.py +302 -0
  396. edc_registration/model_mixins/updates_or_creates_registered_subject_model_mixin.py +15 -7
  397. edc_registration/models/registered_subject.py +28 -27
  398. edc_reportable/age_evaluator.py +4 -2
  399. edc_reportable/formula.py +5 -5
  400. edc_reportable/migrations/0001_initial.py +7 -7
  401. edc_reportable/migrations/0003_referencerangecollection_grade1_and_more.py +3 -3
  402. edc_reportable/migrations/0004_alter_referencerangecollection_grade3_and_more.py +5 -5
  403. edc_reportable/migrations/0006_alter_gradingdata_revision_and_more.py +5 -6
  404. edc_reportable/migrations/0007_alter_gradingdata_age_phrase_and_more.py +509 -0
  405. edc_reportable/models/normal_data.py +4 -5
  406. edc_reportable/models/reference_model_mixins.py +10 -11
  407. edc_reportable/models/reference_range_collection.py +12 -13
  408. edc_reportable/post_migrate_signals.py +1 -1
  409. edc_reportable/utils/convert_units.py +11 -45
  410. edc_reportable/utils/get_normal_data_or_raise.py +2 -2
  411. edc_reportable/utils/get_reference_range_collection.py +2 -3
  412. edc_reportable/utils/load_data.py +4 -4
  413. edc_reportable/utils/update_grading_data.py +5 -5
  414. edc_review_dashboard/auths.py +23 -18
  415. edc_review_dashboard/migrations/0001_initial.py +3 -2
  416. edc_review_dashboard/migrations/0006_alter_edcpermissions_device_created_and_more.py +49 -0
  417. edc_screening/age_evaluator.py +6 -6
  418. edc_screening/auths.py +35 -30
  419. edc_screening/eligibility.py +1 -1
  420. edc_screening/gender_evaluator.py +1 -1
  421. edc_screening/migrations/0001_initial.py +3 -2
  422. edc_screening/migrations/0005_alter_edcpermissions_device_created_and_more.py +49 -0
  423. edc_screening/model_mixins/eligibility_model_mixin.py +3 -6
  424. edc_screening/model_mixins/screening_fields_model_mixin.py +6 -8
  425. edc_screening/model_mixins/screening_methods_model_mixin.py +1 -1
  426. edc_screening/screening_eligibility.py +2 -4
  427. edc_screening/utils.py +9 -9
  428. edc_search/generate_slug.py +26 -0
  429. edc_search/model_mixins.py +10 -22
  430. edc_sites/auths.py +8 -3
  431. edc_sites/migrations/0007_edcpermissions.py +3 -2
  432. edc_sites/migrations/0010_alter_edcpermissions_device_created_and_more.py +69 -0
  433. edc_sites/model_mixins/site_model_mixin.py +2 -2
  434. edc_sites/site.py +5 -5
  435. edc_sites/system_checks.py +1 -1
  436. edc_subject_dashboard/auths.py +27 -22
  437. edc_subject_dashboard/migrations/0001_initial.py +3 -2
  438. edc_subject_dashboard/migrations/0005_alter_edcpermissions_device_created_and_more.py +49 -0
  439. edc_subject_dashboard/requisition_report.py +6 -4
  440. edc_subject_dashboard/requisition_verifier.py +6 -6
  441. edc_subject_dashboard/templatetags/edc_subject_dashboard_extras.py +2 -2
  442. edc_subject_dashboard/view_mixins/subject_visit_view_mixin.py +7 -8
  443. edc_subject_dashboard/view_utils/subject_consent_listboard_button.py +3 -2
  444. edc_subject_dashboard/view_utils/timepoint_status_button.py +2 -2
  445. edc_timepoint/apps.py +0 -21
  446. edc_timepoint/model_mixins.py +22 -20
  447. edc_transfer/model_mixins.py +4 -4
  448. edc_transfer/modeladmin_mixins.py +1 -1
  449. edc_unblinding/auths.py +9 -4
  450. edc_unblinding/migrations/0001_initial.py +13 -13
  451. edc_unblinding/migrations/0014_alter_historicalunblindingrequest_action_identifier_and_more.py +291 -0
  452. edc_unblinding/migrations/0015_alter_historicalunblindingrequest_report_datetime_and_more.py +45 -0
  453. edc_unblinding/models/unblinding_request.py +2 -2
  454. edc_unblinding/models/unblinding_review.py +3 -3
  455. edc_utils/__init__.py +3 -1
  456. edc_utils/age.py +10 -16
  457. edc_utils/show_urls.py +29 -2
  458. edc_visit_schedule/auths.py +6 -1
  459. edc_visit_schedule/migrations/0001_initial.py +3 -3
  460. edc_visit_schedule/migrations/0002_auto_20190305_0123.py +3 -6
  461. edc_visit_schedule/migrations/0003_historicalvisitschedule_visitschedule.py +5 -4
  462. edc_visit_schedule/migrations/0015_historicalonschedule_offschedule_onschedule.py +10 -10
  463. edc_visit_schedule/migrations/0019_alter_historicalonschedule_device_created_and_more.py +229 -0
  464. edc_visit_schedule/migrations/0020_alter_historicalonschedule_onschedule_datetime_and_more.py +65 -0
  465. edc_visit_schedule/model_mixins/off_schedule_model_mixin.py +5 -4
  466. edc_visit_schedule/model_mixins/on_schedule_model_mixin.py +5 -4
  467. edc_visit_schedule/model_mixins/visit_schedule/visit_code_fields_model_mixin.py +1 -1
  468. edc_visit_schedule/models/subject_schedule_history.py +6 -6
  469. edc_visit_schedule/schedule/visit_collection.py +1 -1
  470. edc_visit_schedule/site_visit_schedules.py +2 -2
  471. edc_visit_schedule/subject_schedule.py +5 -4
  472. edc_visit_schedule/view_mixins.py +2 -3
  473. edc_visit_schedule/visit/visit.py +3 -2
  474. edc_visit_tracking/migrations/0004_subjectvisit_subjectvisitmissedreasons_extra_value_and_more.py +13 -13
  475. edc_visit_tracking/migrations/0009_alter_historicalsubjectvisit_comments_and_more.py +450 -0
  476. edc_visit_tracking/migrations/0010_alter_historicalsubjectvisit_report_datetime_and_more.py +68 -0
  477. edc_visit_tracking/model_mixins/base/visit_methods_model_mixin.py +3 -3
  478. edc_visit_tracking/model_mixins/crfs/visit_tracking_crf_model_mixin.py +2 -2
  479. edc_visit_tracking/model_mixins/requisitions/visit_tracking_requisition_model_mixin.py +2 -2
  480. edc_visit_tracking/model_mixins/subject_visit_missed_model_mixin.py +2 -2
  481. edc_visit_tracking/model_mixins/visit_model_mixin/caretaker_fields_mixin.py +2 -3
  482. edc_visit_tracking/model_mixins/visit_model_mixin/previous_visit_model_mixin.py +1 -1
  483. edc_visit_tracking/model_mixins/visit_model_mixin/visit_model_fields_mixin.py +8 -11
  484. edc_visit_tracking/model_mixins/visit_model_mixin/visit_model_mixin.py +1 -1
  485. edc_visit_tracking/models/signals.py +3 -3
  486. edc_visit_tracking/models/subject_visit.py +1 -1
  487. edc_vitals/calculators/bmi.py +7 -5
  488. edc_vitals/utils.py +1 -1
  489. edc_form_label/models.py +0 -0
  490. edc_search/constants.py +0 -1
  491. edc_search/models.py +0 -0
  492. edc_search/search_slug.py +0 -50
  493. edc_search/updater.py +0 -30
  494. edc_search/wsgi.py +0 -7
  495. {clinicedc-2.0.6.dist-info → clinicedc-2.0.8.dist-info}/licenses/LICENSE +0 -0
@@ -2,10 +2,10 @@ import calendar
2
2
 
3
3
  from django.core.validators import MaxValueValidator, MinValueValidator
4
4
  from django.db import models
5
+ from django.utils import timezone
5
6
 
6
7
  from edc_model.models import BaseUuidModel
7
8
  from edc_model_fields.fields import OtherCharField
8
- from edc_utils import get_utcnow
9
9
 
10
10
 
11
11
  class HealthFacilityCalendarError(Exception):
@@ -28,11 +28,11 @@ class HealthFacilityModelMixin(models.Model):
28
28
  See also edc_appointment.
29
29
  """
30
30
 
31
- report_datetime = models.DateTimeField(default=get_utcnow)
31
+ report_datetime = models.DateTimeField(default=timezone.now)
32
32
 
33
33
  name = models.CharField(max_length=25, unique=True)
34
34
 
35
- title = models.CharField(max_length=150, null=True, blank=True)
35
+ title = models.CharField(max_length=150, default="", blank=True)
36
36
 
37
37
  health_facility_type = models.ForeignKey(
38
38
  "edc_facility.HealthFacilityTypes",
@@ -45,7 +45,7 @@ class HealthFacilityModelMixin(models.Model):
45
45
 
46
46
  gps = models.CharField(
47
47
  max_length=50,
48
- null=True,
48
+ default="",
49
49
  blank=True,
50
50
  help_text="copy and paste directly from google maps",
51
51
  )
@@ -115,7 +115,7 @@ class HealthFacilityModelMixin(models.Model):
115
115
  days = []
116
116
  mapping = {k: v for k, v in enumerate(calendar.weekheader(3).split(" "))}
117
117
  for day_int in self.clinic_days:
118
- days.append(mapping.get(day_int))
118
+ days.append(mapping.get(day_int)) # noqa: PERF401
119
119
  return ",".join(days)
120
120
 
121
121
  class Meta(BaseUuidModel.Meta):
@@ -1,5 +1,6 @@
1
1
  from __future__ import annotations
2
2
 
3
+ import contextlib
3
4
  from typing import TYPE_CHECKING
4
5
 
5
6
  from django.apps import apps as django_apps
@@ -28,20 +29,24 @@ class CustomLabelCondition:
28
29
  """
29
30
  return
30
31
 
31
- def get_additional_options(self, request=None, obj=None, model=None):
32
+ def get_additional_options(self, request=None, obj=None, model=None): # noqa: ARG002
32
33
  return {}
33
34
 
34
35
  @property
35
36
  def appointment(self) -> Appointment | None:
36
37
  """Returns the appointment instance for this request or None."""
37
- return django_apps.get_model(self.appointment_model).objects.get(
38
- pk=self.request.GET.get("appointment")
39
- )
38
+ with contextlib.suppress(ObjectDoesNotExist):
39
+ return django_apps.get_model(self.appointment_model).objects.get(
40
+ pk=self.request.GET.get("appointment")
41
+ )
42
+ return None
40
43
 
41
44
  @property
42
45
  def previous_appointment(self) -> Appointment | None:
43
46
  """Returns the previous appointment for this request or None."""
44
- return self.appointment.previous_by_timepoint
47
+ with contextlib.suppress(ObjectDoesNotExist):
48
+ return self.appointment.previous_by_timepoint
49
+ return None
45
50
 
46
51
  @property
47
52
  def previous_visit(self):
@@ -73,10 +78,8 @@ class CustomLabelCondition:
73
78
  """
74
79
  previous_obj = None
75
80
  if self.previous_visit:
76
- try:
81
+ with contextlib.suppress(ObjectDoesNotExist):
77
82
  previous_obj = self.model.objects.get(
78
83
  **{f"{self.model.related_visit_model_attr()}": self.previous_visit}
79
84
  )
80
- except ObjectDoesNotExist:
81
- pass
82
85
  return previous_obj
@@ -41,5 +41,5 @@ class FormLabel:
41
41
  except KeyError as e:
42
42
  raise CustomFormLabelError(
43
43
  f"Custom label template has invalid keys. See {label}. Got {e}."
44
- )
44
+ ) from e
45
45
  return label
edc_form_runners/auths.py CHANGED
@@ -9,10 +9,15 @@ from .auth_objects import (
9
9
  codenames,
10
10
  )
11
11
 
12
- site_auths.add_group(*codenames, name=EDC_FORM_RUNNERS_VIEW, view_only=True)
13
- site_auths.add_group(*codenames, name=EDC_FORM_RUNNERS, no_delete=True)
14
- site_auths.add_group(*codenames, name=EDC_FORM_RUNNERS_SUPER)
15
12
 
16
- site_auths.update_role(EDC_FORM_RUNNERS_VIEW, name=AUDITOR_ROLE)
17
- site_auths.update_role(EDC_FORM_RUNNERS, name=CLINICIAN_ROLE)
18
- site_auths.update_role(EDC_FORM_RUNNERS_SUPER, name=DATA_MANAGER_ROLE)
13
+ def update_site_auths():
14
+ site_auths.add_group(*codenames, name=EDC_FORM_RUNNERS_VIEW, view_only=True)
15
+ site_auths.add_group(*codenames, name=EDC_FORM_RUNNERS, no_delete=True)
16
+ site_auths.add_group(*codenames, name=EDC_FORM_RUNNERS_SUPER)
17
+
18
+ site_auths.update_role(EDC_FORM_RUNNERS_VIEW, name=AUDITOR_ROLE)
19
+ site_auths.update_role(EDC_FORM_RUNNERS, name=CLINICIAN_ROLE)
20
+ site_auths.update_role(EDC_FORM_RUNNERS_SUPER, name=DATA_MANAGER_ROLE)
21
+
22
+
23
+ update_site_auths()
@@ -8,10 +8,9 @@ from bs4 import BeautifulSoup
8
8
  from django.apps import apps as django_apps
9
9
  from django.db.models import ForeignKey, ManyToManyField, Model, OneToOneField, QuerySet
10
10
  from django.forms import ModelForm
11
+ from django.utils import timezone
11
12
  from tqdm import tqdm
12
13
 
13
- from edc_utils import get_utcnow
14
-
15
14
  from .exceptions import FormRunnerModelAdminNotFound, FormRunnerModelFormNotFound
16
15
  from .utils import get_modeladmin_cls
17
16
 
@@ -37,7 +36,7 @@ class FormRunner:
37
36
  ) -> None:
38
37
  self.messages = {}
39
38
  self.session_id = uuid.uuid4()
40
- self.session_datetime = get_utcnow()
39
+ self.session_datetime = timezone.now()
41
40
  self.verbose = verbose
42
41
  self.model_name = self.model_name or model_name
43
42
  self.modeladmin_cls = get_modeladmin_cls(self.model_name)
@@ -48,8 +47,7 @@ class FormRunner:
48
47
  )
49
48
  if self.modeladmin_cls.form == ModelForm:
50
49
  raise FormRunnerModelFormNotFound(
51
- "ModelAdmin does not have a custom form. Nothing to do. "
52
- f"Got `{model_name}`."
50
+ f"ModelAdmin does not have a custom form. Nothing to do. Got `{model_name}`."
53
51
  )
54
52
  self.src_model_cls = self.modeladmin_cls.model
55
53
 
@@ -8,6 +8,7 @@ import django_audit_fields.fields.uuid_auto_field
8
8
  import django_audit_fields.models.audit_model_mixin
9
9
  import django_revision.revision_field
10
10
  from django.db import migrations, models
11
+ import django.utils.timezone
11
12
 
12
13
 
13
14
  class Migration(migrations.Migration):
@@ -36,14 +37,14 @@ class Migration(migrations.Migration):
36
37
  "created",
37
38
  models.DateTimeField(
38
39
  blank=True,
39
- default=django_audit_fields.models.audit_model_mixin.utcnow,
40
+ default=django.utils.timezone.now,
40
41
  ),
41
42
  ),
42
43
  (
43
44
  "modified",
44
45
  models.DateTimeField(
45
46
  blank=True,
46
- default=django_audit_fields.models.audit_model_mixin.utcnow,
47
+ default=django.utils.timezone.now,
47
48
  ),
48
49
  ),
49
50
  (
@@ -0,0 +1,49 @@
1
+ # Generated by Django 5.2.6 on 2025-09-17 16:53
2
+
3
+ from django.db import migrations, models
4
+
5
+
6
+ class Migration(migrations.Migration):
7
+
8
+ dependencies = [
9
+ ("edc_form_runners", "0004_alter_issue_revision"),
10
+ ]
11
+
12
+ operations = [
13
+ migrations.AlterField(
14
+ model_name="issue",
15
+ name="device_created",
16
+ field=models.CharField(
17
+ blank=True, default="", max_length=10, verbose_name="Device created"
18
+ ),
19
+ ),
20
+ migrations.AlterField(
21
+ model_name="issue",
22
+ name="device_modified",
23
+ field=models.CharField(
24
+ blank=True, default="", max_length=10, verbose_name="Device modified"
25
+ ),
26
+ ),
27
+ migrations.AlterField(
28
+ model_name="issue",
29
+ name="locale_created",
30
+ field=models.CharField(
31
+ blank=True,
32
+ default="",
33
+ help_text="Auto-updated by Modeladmin",
34
+ max_length=10,
35
+ verbose_name="Locale created",
36
+ ),
37
+ ),
38
+ migrations.AlterField(
39
+ model_name="issue",
40
+ name="locale_modified",
41
+ field=models.CharField(
42
+ blank=True,
43
+ default="",
44
+ help_text="Auto-updated by Modeladmin",
45
+ max_length=10,
46
+ verbose_name="Locale modified",
47
+ ),
48
+ ),
49
+ ]
@@ -1,6 +1,6 @@
1
1
  from typing import Any
2
2
 
3
- from edc_constants.constants import NOT_APPLICABLE
3
+ from edc_constants.constants import NOT_APPLICABLE, NULL_STRING
4
4
 
5
5
  from .base_form_validator import (
6
6
  APPLICABLE_ERROR,
@@ -33,8 +33,8 @@ class ApplicableFieldValidator(BaseFormValidator):
33
33
  def applicable_if(
34
34
  self,
35
35
  *responses: Any,
36
- field: str = None,
37
- field_applicable: str = None,
36
+ field: str,
37
+ field_applicable: str,
38
38
  inverse: bool | None = None,
39
39
  is_instance_field: bool | None = None,
40
40
  msg: str | None = None,
@@ -95,8 +95,8 @@ class ApplicableFieldValidator(BaseFormValidator):
95
95
  def applicable(
96
96
  self,
97
97
  *responses: Any,
98
- field: str = None,
99
- field_applicable: str = None,
98
+ field: str,
99
+ field_applicable: str,
100
100
  inverse: bool | None = None,
101
101
  is_instance_field: bool | None = None,
102
102
  msg: str | None = None,
@@ -117,7 +117,8 @@ class ApplicableFieldValidator(BaseFormValidator):
117
117
  field_applicable_value = self.get(field_applicable)
118
118
 
119
119
  if field_value in responses and (
120
- field_applicable_value is None or field_applicable_value == not_applicable
120
+ field_applicable_value in (NULL_STRING, not_applicable)
121
+ or field_applicable_value is None
121
122
  ):
122
123
  self.raise_applicable(field_applicable, msg=msg, applicable_msg=applicable_msg)
123
124
  elif (
@@ -1,10 +1,11 @@
1
1
  from __future__ import annotations
2
2
 
3
+ import contextlib
3
4
  from copy import copy
4
5
  from typing import Any
5
6
 
6
7
  from django.core.exceptions import NON_FIELD_ERRORS
7
- from django.forms import ValidationError, forms
8
+ from django.forms import ValidationError
8
9
 
9
10
  APPLICABLE_ERROR = "applicable"
10
11
  INVALID_ERROR = "invalid"
@@ -14,7 +15,7 @@ REQUIRED_ERROR = "required"
14
15
  OUT_OF_RANGE_ERROR = "out_of_range"
15
16
 
16
17
 
17
- class InvalidModelFormFieldValidator(Exception):
18
+ class InvalidModelFormFieldValidator(Exception): # noqa: N818
18
19
  def __init__(self, message, code=None):
19
20
  message = f"Invalid field validator. Got '{message}'"
20
21
  super().__init__(message)
@@ -119,13 +120,13 @@ class BaseFormValidator:
119
120
  """
120
121
  try:
121
122
  self._clean()
122
- except forms.ValidationError as e:
123
+ except ValidationError as e:
123
124
  self.capture_error_message(e)
124
125
  self.capture_error_code(e)
125
- raise forms.ValidationError(e)
126
+ raise ValidationError(e) from e
126
127
  return self.cleaned_data
127
128
 
128
- def capture_error_message(self, e: forms.ValidationError) -> None:
129
+ def capture_error_message(self, e: ValidationError) -> None:
129
130
  try:
130
131
  self._errors.update(**e.error_dict)
131
132
  except AttributeError:
@@ -134,11 +135,9 @@ class BaseFormValidator:
134
135
  except AttributeError:
135
136
  self._errors.update({NON_FIELD_ERRORS: str(e)})
136
137
 
137
- def capture_error_code(self, e: forms.ValidationError) -> None:
138
- try:
138
+ def capture_error_code(self, e: ValidationError) -> None:
139
+ with contextlib.suppress(AttributeError):
139
140
  self._error_codes.append(e.code)
140
- except AttributeError:
141
- pass
142
141
 
143
142
  def get_inline_field_value(self, field=None, inline_set=None):
144
143
  """Returns the value of the first inline field that has a value."""
@@ -41,20 +41,14 @@ class OtherSpecifyFieldValidator(BaseFormValidator):
41
41
  cleaned_data.get(field), fk_stored_field_name, cleaned_data.get(field)
42
42
  )
43
43
 
44
- if (
45
- field_value is not None
46
- and field_value == other
47
- and not cleaned_data.get(other_specify_field)
48
- ):
44
+ if field_value and field_value == other and not cleaned_data.get(other_specify_field):
49
45
  ref = "" if not ref else f" ref: {ref}"
50
46
  message = {other_specify_field: required_msg or f"This field is required.{ref}"}
51
47
  self._errors.update(message)
52
48
  self._error_codes.append(REQUIRED_ERROR)
53
49
  raise ValidationError(message, code=REQUIRED_ERROR)
54
50
  if (
55
- field_value is not None
56
- and field_value != other
57
- and cleaned_data.get(other_specify_field)
51
+ field_value and field_value != other and cleaned_data.get(other_specify_field)
58
52
  ) or (field_value is None and cleaned_data.get(other_specify_field)):
59
53
  ref = "" if not ref else f" ref: {ref}"
60
54
  message = {
@@ -43,8 +43,8 @@ class RequiredFieldValidator(BaseFormValidator):
43
43
  def required_if(
44
44
  self,
45
45
  *responses: str | int | bool,
46
- field: str = None,
47
- field_required: str = None,
46
+ field: str,
47
+ field_required: str,
48
48
  required_msg: str | None = None,
49
49
  not_required_msg: str | None = None,
50
50
  optional_if_dwta: bool | None = None,
@@ -82,7 +82,7 @@ class RequiredFieldValidator(BaseFormValidator):
82
82
  self.get(field_required, inline_set=inline_set) is not None
83
83
  )
84
84
  else:
85
- field_required_has_value = self.get(field_required, inline_set=inline_set)
85
+ field_required_has_value = bool(self.get(field_required, inline_set=inline_set))
86
86
 
87
87
  if field in self.cleaned_data:
88
88
  if (DWTA in responses and optional_if_dwta and field_value == DWTA) or (
@@ -117,7 +117,7 @@ class RequiredFieldValidator(BaseFormValidator):
117
117
  def required_if_true(
118
118
  self,
119
119
  condition: bool,
120
- field_required: str = None,
120
+ field_required: str,
121
121
  required_msg: str | None = None,
122
122
  not_required_msg: str | None = None,
123
123
  inverse: bool | None = None,
@@ -145,7 +145,7 @@ class RequiredFieldValidator(BaseFormValidator):
145
145
  def not_required_if_true(
146
146
  self,
147
147
  condition: bool,
148
- field: str = None,
148
+ field: str,
149
149
  msg: str | None = None,
150
150
  is_instance_field: bool | None = None,
151
151
  ) -> bool:
@@ -170,8 +170,8 @@ class RequiredFieldValidator(BaseFormValidator):
170
170
 
171
171
  def required_if_not_none(
172
172
  self,
173
- field: str = None,
174
- field_required: str = None,
173
+ field: str,
174
+ field_required: str,
175
175
  required_msg: str | None = None,
176
176
  not_required_msg: str | None = None,
177
177
  optional_if_dwta: bool | None = None,
@@ -182,6 +182,9 @@ class RequiredFieldValidator(BaseFormValidator):
182
182
  """Raises an exception or returns False.
183
183
 
184
184
  If field is not none, field_required is "required".
185
+
186
+ Note: CharFields usually default to an empty string and not NULL.
187
+ For IntegerFields, zero is a value.
185
188
  """
186
189
  inverse = True if inverse is None else inverse
187
190
  if is_instance_field:
@@ -197,7 +200,7 @@ class RequiredFieldValidator(BaseFormValidator):
197
200
  if field_required_evaluate_as_int:
198
201
  field_required_has_value = self.cleaned_data.get(field_required) is not None
199
202
  else:
200
- field_required_has_value = self.cleaned_data.get(field_required)
203
+ field_required_has_value = bool(self.cleaned_data.get(field_required))
201
204
 
202
205
  if field_value is not None and not field_required_has_value:
203
206
  self.raise_required(field=field_required, msg=required_msg)
@@ -221,8 +224,8 @@ class RequiredFieldValidator(BaseFormValidator):
221
224
  def not_required_if(
222
225
  self,
223
226
  *responses: str | int | bool,
224
- field: str = None,
225
- field_required: str = None,
227
+ field: str,
228
+ field_required: str | None = None,
226
229
  field_not_required: str | None = None,
227
230
  required_msg: str | None = None,
228
231
  not_required_msg: str | None = None,
@@ -259,8 +262,8 @@ class RequiredFieldValidator(BaseFormValidator):
259
262
 
260
263
  def require_together(
261
264
  self,
262
- field: str = None,
263
- field_required: str = None,
265
+ field: str,
266
+ field_required: str,
264
267
  required_msg: str | None = None,
265
268
  is_instance_field: bool | None = None,
266
269
  ) -> bool:
@@ -280,15 +283,15 @@ class RequiredFieldValidator(BaseFormValidator):
280
283
  return False
281
284
 
282
285
  @staticmethod
283
- def _inspect_params(
284
- *responses: str | int | bool, field: str = None, field_required: str = None
285
- ) -> bool:
286
+ def _inspect_params(*responses: str | int | bool, field: str, field_required: str) -> bool:
286
287
  """Inspects params and raises if any are None"""
287
288
  if not field:
288
289
  errmsg = _("`field` cannot be `None`")
289
290
  raise InvalidModelFormFieldValidator(f"{errmsg}.")
290
291
  if not responses:
291
- errmsg = _(f"At least one valid response for field '{field}' must be provided.")
292
+ errmsg = _(
293
+ "At least one valid response for field '{field}' must be provided."
294
+ ).format(field=field)
292
295
  raise InvalidModelFormFieldValidator(errmsg)
293
296
  if not field_required:
294
297
  raise InvalidModelFormFieldValidator('"field_required" cannot be None.')
@@ -11,7 +11,7 @@ from django.db import migrations, models
11
11
 
12
12
  import edc_model_fields.fields.hostname_modification_field
13
13
  import edc_model_fields.fields.userfield
14
- import edc_utils
14
+ import django.utils.timezone
15
15
 
16
16
 
17
17
  class Migration(migrations.Migration):
@@ -52,11 +52,11 @@ class Migration(migrations.Migration):
52
52
  fields=[
53
53
  (
54
54
  "created",
55
- models.DateTimeField(blank=True, default=edc_utils.date.get_utcnow),
55
+ models.DateTimeField(blank=True, default=django.utils.timezone.now),
56
56
  ),
57
57
  (
58
58
  "modified",
59
- models.DateTimeField(blank=True, default=edc_utils.date.get_utcnow),
59
+ models.DateTimeField(blank=True, default=django.utils.timezone.now),
60
60
  ),
61
61
  (
62
62
  "user_created",
@@ -4,6 +4,7 @@ import django_audit_fields.fields.hostname_modification_field
4
4
  import django_audit_fields.fields.userfield
5
5
  import django_audit_fields.models.audit_model_mixin
6
6
  from django.db import migrations, models
7
+ import django.utils.timezone
7
8
 
8
9
 
9
10
  class Migration(migrations.Migration):
@@ -13,9 +14,7 @@ class Migration(migrations.Migration):
13
14
  migrations.AlterField(
14
15
  model_name="identifiermodel",
15
16
  name="created",
16
- field=models.DateTimeField(
17
- blank=True, default=django_audit_fields.models.audit_model_mixin.utcnow
18
- ),
17
+ field=models.DateTimeField(blank=True, default=django.utils.timezone.now),
19
18
  ),
20
19
  migrations.AlterField(
21
20
  model_name="identifiermodel",
@@ -29,9 +28,7 @@ class Migration(migrations.Migration):
29
28
  migrations.AlterField(
30
29
  model_name="identifiermodel",
31
30
  name="modified",
32
- field=models.DateTimeField(
33
- blank=True, default=django_audit_fields.models.audit_model_mixin.utcnow
34
- ),
31
+ field=models.DateTimeField(blank=True, default=django.utils.timezone.now),
35
32
  ),
36
33
  migrations.AlterField(
37
34
  model_name="identifiermodel",
@@ -8,7 +8,7 @@ from django.db import migrations, models
8
8
 
9
9
  import edc_model_fields.fields.hostname_modification_field
10
10
  import edc_model_fields.fields.userfield
11
- import edc_utils
11
+ import django.utils.timezone
12
12
 
13
13
 
14
14
  class Migration(migrations.Migration):
@@ -23,7 +23,7 @@ class Migration(migrations.Migration):
23
23
  migrations.AddField(
24
24
  model_name="historicalidentifierhistory",
25
25
  name="created",
26
- field=models.DateTimeField(default=edc_utils.date.get_utcnow, editable=False),
26
+ field=models.DateTimeField(default=django.utils.timezone.now, editable=False),
27
27
  ),
28
28
  migrations.AddField(
29
29
  model_name="historicalidentifierhistory",
@@ -48,7 +48,7 @@ class Migration(migrations.Migration):
48
48
  migrations.AddField(
49
49
  model_name="historicalidentifierhistory",
50
50
  name="modified",
51
- field=models.DateTimeField(default=edc_utils.date.get_utcnow, editable=False),
51
+ field=models.DateTimeField(default=django.utils.timezone.now, editable=False),
52
52
  ),
53
53
  migrations.AddField(
54
54
  model_name="historicalidentifierhistory",
@@ -79,7 +79,7 @@ class Migration(migrations.Migration):
79
79
  migrations.AddField(
80
80
  model_name="identifierhistory",
81
81
  name="created",
82
- field=models.DateTimeField(default=edc_utils.date.get_utcnow, editable=False),
82
+ field=models.DateTimeField(default=django.utils.timezone.now, editable=False),
83
83
  ),
84
84
  migrations.AddField(
85
85
  model_name="identifierhistory",
@@ -104,7 +104,7 @@ class Migration(migrations.Migration):
104
104
  migrations.AddField(
105
105
  model_name="identifierhistory",
106
106
  name="modified",
107
- field=models.DateTimeField(default=edc_utils.date.get_utcnow, editable=False),
107
+ field=models.DateTimeField(default=django.utils.timezone.now, editable=False),
108
108
  ),
109
109
  migrations.AddField(
110
110
  model_name="identifierhistory",
@@ -152,22 +152,22 @@ class Migration(migrations.Migration):
152
152
  migrations.AlterField(
153
153
  model_name="historicalidentifiertracker",
154
154
  name="created",
155
- field=models.DateTimeField(default=edc_utils.date.get_utcnow, editable=False),
155
+ field=models.DateTimeField(default=django.utils.timezone.now, editable=False),
156
156
  ),
157
157
  migrations.AlterField(
158
158
  model_name="historicalidentifiertracker",
159
159
  name="modified",
160
- field=models.DateTimeField(default=edc_utils.date.get_utcnow, editable=False),
160
+ field=models.DateTimeField(default=django.utils.timezone.now, editable=False),
161
161
  ),
162
162
  migrations.AlterField(
163
163
  model_name="historicalsubjectidentifier",
164
164
  name="created",
165
- field=models.DateTimeField(default=edc_utils.date.get_utcnow, editable=False),
165
+ field=models.DateTimeField(default=django.utils.timezone.now, editable=False),
166
166
  ),
167
167
  migrations.AlterField(
168
168
  model_name="historicalsubjectidentifier",
169
169
  name="modified",
170
- field=models.DateTimeField(default=edc_utils.date.get_utcnow, editable=False),
170
+ field=models.DateTimeField(default=django.utils.timezone.now, editable=False),
171
171
  ),
172
172
  migrations.AlterField(
173
173
  model_name="identifierhistory",
@@ -183,31 +183,31 @@ class Migration(migrations.Migration):
183
183
  migrations.AlterField(
184
184
  model_name="identifiertracker",
185
185
  name="created",
186
- field=models.DateTimeField(default=edc_utils.date.get_utcnow, editable=False),
186
+ field=models.DateTimeField(default=django.utils.timezone.now, editable=False),
187
187
  ),
188
188
  migrations.AlterField(
189
189
  model_name="identifiertracker",
190
190
  name="modified",
191
- field=models.DateTimeField(default=edc_utils.date.get_utcnow, editable=False),
191
+ field=models.DateTimeField(default=django.utils.timezone.now, editable=False),
192
192
  ),
193
193
  migrations.AlterField(
194
194
  model_name="sequence",
195
195
  name="created",
196
- field=models.DateTimeField(default=edc_utils.date.get_utcnow, editable=False),
196
+ field=models.DateTimeField(default=django.utils.timezone.now, editable=False),
197
197
  ),
198
198
  migrations.AlterField(
199
199
  model_name="sequence",
200
200
  name="modified",
201
- field=models.DateTimeField(default=edc_utils.date.get_utcnow, editable=False),
201
+ field=models.DateTimeField(default=django.utils.timezone.now, editable=False),
202
202
  ),
203
203
  migrations.AlterField(
204
204
  model_name="subjectidentifier",
205
205
  name="created",
206
- field=models.DateTimeField(default=edc_utils.date.get_utcnow, editable=False),
206
+ field=models.DateTimeField(default=django.utils.timezone.now, editable=False),
207
207
  ),
208
208
  migrations.AlterField(
209
209
  model_name="subjectidentifier",
210
210
  name="modified",
211
- field=models.DateTimeField(default=edc_utils.date.get_utcnow, editable=False),
211
+ field=models.DateTimeField(default=django.utils.timezone.now, editable=False),
212
212
  ),
213
213
  ]
@@ -8,7 +8,7 @@ from django.db import migrations, models
8
8
 
9
9
  import edc_model_fields.fields.hostname_modification_field
10
10
  import edc_model_fields.fields.userfield
11
- import edc_utils
11
+ import django.utils.timezone
12
12
 
13
13
 
14
14
  class Migration(migrations.Migration):
@@ -20,11 +20,11 @@ class Migration(migrations.Migration):
20
20
  fields=[
21
21
  (
22
22
  "created",
23
- models.DateTimeField(default=edc_utils.date.get_utcnow, editable=False),
23
+ models.DateTimeField(default=django.utils.timezone.now, editable=False),
24
24
  ),
25
25
  (
26
26
  "modified",
27
- models.DateTimeField(default=edc_utils.date.get_utcnow, editable=False),
27
+ models.DateTimeField(default=django.utils.timezone.now, editable=False),
28
28
  ),
29
29
  (
30
30
  "user_created",
@@ -1,11 +1,9 @@
1
1
  # -*- coding: utf-8 -*-
2
2
  # Generated by Django 1.10.4 on 2016-12-21 23:23
3
3
  from __future__ import unicode_literals
4
-
4
+ import django.utils.timezone
5
5
  from django.db import migrations, models
6
6
 
7
- from edc_utils import get_utcnow
8
-
9
7
 
10
8
  class Migration(migrations.Migration):
11
9
  dependencies = [("edc_identifier", "0008_identifiermodel_linked_identifier")]
@@ -14,11 +12,11 @@ class Migration(migrations.Migration):
14
12
  migrations.AlterField(
15
13
  model_name="historicalidentifierhistory",
16
14
  name="created_datetime",
17
- field=models.DateTimeField(default=get_utcnow),
15
+ field=models.DateTimeField(default=django.utils.timezone.now),
18
16
  ),
19
17
  migrations.AlterField(
20
18
  model_name="identifierhistory",
21
19
  name="created_datetime",
22
- field=models.DateTimeField(default=get_utcnow),
20
+ field=models.DateTimeField(default=django.utils.timezone.now),
23
21
  ),
24
22
  ]