endoreg-db 0.8.4.4__py3-none-any.whl → 0.8.8.0__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 endoreg-db might be problematic. Click here for more details.

Files changed (372) hide show
  1. endoreg_db/authz/auth.py +74 -0
  2. endoreg_db/authz/backends.py +168 -0
  3. endoreg_db/authz/management/commands/list_routes.py +18 -0
  4. endoreg_db/authz/middleware.py +83 -0
  5. endoreg_db/authz/permissions.py +127 -0
  6. endoreg_db/authz/policy.py +218 -0
  7. endoreg_db/authz/views_auth.py +66 -0
  8. endoreg_db/config/env.py +13 -8
  9. endoreg_db/data/__init__.py +8 -31
  10. endoreg_db/data/_examples/disease.yaml +55 -0
  11. endoreg_db/data/_examples/disease_classification.yaml +13 -0
  12. endoreg_db/data/_examples/disease_classification_choice.yaml +62 -0
  13. endoreg_db/data/_examples/event.yaml +64 -0
  14. endoreg_db/data/_examples/examination.yaml +72 -0
  15. endoreg_db/data/_examples/finding/anatomy_colon.yaml +128 -0
  16. endoreg_db/data/_examples/finding/colonoscopy.yaml +40 -0
  17. endoreg_db/data/_examples/finding/colonoscopy_bowel_prep.yaml +56 -0
  18. endoreg_db/data/_examples/finding/complication.yaml +16 -0
  19. endoreg_db/data/_examples/finding/data.yaml +105 -0
  20. endoreg_db/data/_examples/finding/examination_setting.yaml +16 -0
  21. endoreg_db/data/_examples/finding/medication_related.yaml +18 -0
  22. endoreg_db/data/_examples/finding/outcome.yaml +12 -0
  23. endoreg_db/data/_examples/finding_classification/colonoscopy_bowel_preparation.yaml +68 -0
  24. endoreg_db/data/_examples/finding_classification/colonoscopy_jnet.yaml +22 -0
  25. endoreg_db/data/_examples/finding_classification/colonoscopy_kudo.yaml +25 -0
  26. endoreg_db/data/_examples/finding_classification/colonoscopy_lesion_circularity.yaml +20 -0
  27. endoreg_db/data/_examples/finding_classification/colonoscopy_lesion_planarity.yaml +24 -0
  28. endoreg_db/data/_examples/finding_classification/colonoscopy_lesion_size.yaml +68 -0
  29. endoreg_db/data/_examples/finding_classification/colonoscopy_lesion_surface.yaml +20 -0
  30. endoreg_db/data/_examples/finding_classification/colonoscopy_location.yaml +80 -0
  31. endoreg_db/data/_examples/finding_classification/colonoscopy_lst.yaml +21 -0
  32. endoreg_db/data/_examples/finding_classification/colonoscopy_nice.yaml +20 -0
  33. endoreg_db/data/_examples/finding_classification/colonoscopy_paris.yaml +26 -0
  34. endoreg_db/data/_examples/finding_classification/colonoscopy_sano.yaml +22 -0
  35. endoreg_db/data/_examples/finding_classification/colonoscopy_summary.yaml +53 -0
  36. endoreg_db/data/_examples/finding_classification/complication_generic.yaml +25 -0
  37. endoreg_db/data/_examples/finding_classification/examination_setting_generic.yaml +40 -0
  38. endoreg_db/data/_examples/finding_classification/histology_colo.yaml +51 -0
  39. endoreg_db/data/_examples/finding_classification/intervention_required.yaml +26 -0
  40. endoreg_db/data/_examples/finding_classification/medication_related.yaml +23 -0
  41. endoreg_db/data/_examples/finding_classification/visualized.yaml +33 -0
  42. endoreg_db/data/_examples/finding_classification_choice/bowel_preparation.yaml +78 -0
  43. endoreg_db/data/_examples/finding_classification_choice/colon_lesion_circularity_default.yaml +32 -0
  44. endoreg_db/data/_examples/finding_classification_choice/colon_lesion_jnet.yaml +15 -0
  45. endoreg_db/data/_examples/finding_classification_choice/colon_lesion_kudo.yaml +23 -0
  46. endoreg_db/data/_examples/finding_classification_choice/colon_lesion_lst.yaml +15 -0
  47. endoreg_db/data/_examples/finding_classification_choice/colon_lesion_nice.yaml +17 -0
  48. endoreg_db/data/_examples/finding_classification_choice/colon_lesion_paris.yaml +57 -0
  49. endoreg_db/data/_examples/finding_classification_choice/colon_lesion_planarity_default.yaml +49 -0
  50. endoreg_db/data/_examples/finding_classification_choice/colon_lesion_sano.yaml +14 -0
  51. endoreg_db/data/_examples/finding_classification_choice/colon_lesion_surface_intact_default.yaml +36 -0
  52. endoreg_db/data/_examples/finding_classification_choice/colonoscopy_location.yaml +229 -0
  53. endoreg_db/data/_examples/finding_classification_choice/colonoscopy_not_complete_reason.yaml +19 -0
  54. endoreg_db/data/_examples/finding_classification_choice/colonoscopy_size.yaml +82 -0
  55. endoreg_db/data/_examples/finding_classification_choice/colonoscopy_summary_worst_finding.yaml +15 -0
  56. endoreg_db/data/_examples/finding_classification_choice/complication_generic_types.yaml +15 -0
  57. endoreg_db/data/_examples/finding_classification_choice/examination_setting_generic_types.yaml +15 -0
  58. endoreg_db/data/_examples/finding_classification_choice/histology.yaml +24 -0
  59. endoreg_db/data/_examples/finding_classification_choice/histology_polyp.yaml +20 -0
  60. endoreg_db/data/_examples/finding_classification_choice/outcome.yaml +19 -0
  61. endoreg_db/data/_examples/finding_classification_choice/yes_no_na.yaml +11 -0
  62. endoreg_db/data/_examples/finding_classification_type/colonoscopy_basic.yaml +48 -0
  63. endoreg_db/data/_examples/finding_intervention/endoscopy.yaml +43 -0
  64. endoreg_db/data/_examples/finding_intervention/endoscopy_colonoscopy.yaml +168 -0
  65. endoreg_db/data/_examples/finding_intervention/endoscopy_egd.yaml +128 -0
  66. endoreg_db/data/_examples/finding_intervention/endoscopy_ercp.yaml +32 -0
  67. endoreg_db/data/_examples/finding_intervention/endoscopy_eus_lower.yaml +9 -0
  68. endoreg_db/data/_examples/finding_intervention/endoscopy_eus_upper.yaml +36 -0
  69. endoreg_db/data/_examples/finding_intervention_type/endoscopy.yaml +15 -0
  70. endoreg_db/data/_examples/finding_type/data.yaml +43 -0
  71. endoreg_db/data/_examples/requirement/age.yaml +26 -0
  72. endoreg_db/data/_examples/requirement/colonoscopy_baseline_austria.yaml +45 -0
  73. endoreg_db/data/_examples/requirement/disease_cardiovascular.yaml +79 -0
  74. endoreg_db/data/_examples/requirement/disease_classification_choice_cardiovascular.yaml +41 -0
  75. endoreg_db/data/_examples/requirement/disease_hepatology.yaml +12 -0
  76. endoreg_db/data/_examples/requirement/disease_misc.yaml +12 -0
  77. endoreg_db/data/_examples/requirement/disease_renal.yaml +96 -0
  78. endoreg_db/data/_examples/requirement/endoscopy_bleeding_risk.yaml +59 -0
  79. endoreg_db/data/_examples/requirement/event_cardiology.yaml +251 -0
  80. endoreg_db/data/_examples/requirement/event_requirements.yaml +145 -0
  81. endoreg_db/data/_examples/requirement/finding_colon_polyp.yaml +50 -0
  82. endoreg_db/data/_examples/requirement/gender.yaml +25 -0
  83. endoreg_db/data/_examples/requirement/lab_value.yaml +441 -0
  84. endoreg_db/data/_examples/requirement/medication.yaml +93 -0
  85. endoreg_db/data/_examples/requirement_operator/age.yaml +13 -0
  86. endoreg_db/data/_examples/requirement_operator/lab_operators.yaml +129 -0
  87. endoreg_db/data/_examples/requirement_operator/model_operators.yaml +96 -0
  88. endoreg_db/data/_examples/requirement_set/01_endoscopy_generic.yaml +48 -0
  89. endoreg_db/data/_examples/requirement_set/colonoscopy_austria_screening.yaml +57 -0
  90. endoreg_db/data/_examples/yaml_examples.xlsx +0 -0
  91. endoreg_db/data/ai_model_meta/default_multilabel_classification.yaml +4 -3
  92. endoreg_db/data/event_classification/data.yaml +4 -0
  93. endoreg_db/data/event_classification_choice/data.yaml +9 -0
  94. endoreg_db/data/finding_classification/colonoscopy_bowel_preparation.yaml +43 -70
  95. endoreg_db/data/finding_classification/colonoscopy_lesion_size.yaml +22 -52
  96. endoreg_db/data/finding_classification/colonoscopy_location.yaml +31 -62
  97. endoreg_db/data/finding_classification/histology_colo.yaml +28 -36
  98. endoreg_db/data/requirement/colon_polyp_intervention.yaml +49 -0
  99. endoreg_db/data/requirement/coloreg_colon_polyp.yaml +49 -0
  100. endoreg_db/data/requirement_set/01_endoscopy_generic.yaml +31 -12
  101. endoreg_db/data/requirement_set/01_laboratory.yaml +13 -0
  102. endoreg_db/data/requirement_set/02_endoscopy_bleeding_risk.yaml +46 -0
  103. endoreg_db/data/requirement_set/90_coloreg.yaml +178 -0
  104. endoreg_db/data/requirement_set/_old_ +109 -0
  105. endoreg_db/data/requirement_set_type/data.yaml +21 -0
  106. endoreg_db/data/setup_config.yaml +4 -4
  107. endoreg_db/data/tag/requirement_set_tags.yaml +21 -0
  108. endoreg_db/exceptions.py +5 -2
  109. endoreg_db/helpers/data_loader.py +1 -1
  110. endoreg_db/management/commands/create_model_meta_from_huggingface.py +21 -10
  111. endoreg_db/management/commands/create_multilabel_model_meta.py +299 -129
  112. endoreg_db/management/commands/import_video.py +9 -10
  113. endoreg_db/management/commands/import_video_with_classification.py +1 -1
  114. endoreg_db/management/commands/init_default_ai_model.py +1 -1
  115. endoreg_db/management/commands/list_routes.py +18 -0
  116. endoreg_db/management/commands/load_ai_model_data.py +2 -1
  117. endoreg_db/management/commands/load_center_data.py +12 -12
  118. endoreg_db/management/commands/load_requirement_data.py +60 -31
  119. endoreg_db/management/commands/load_requirement_set_tags.py +95 -0
  120. endoreg_db/management/commands/setup_endoreg_db.py +14 -10
  121. endoreg_db/management/commands/storage_management.py +271 -203
  122. endoreg_db/migrations/0001_initial.py +1799 -1300
  123. endoreg_db/migrations/0002_requirementset_depends_on.py +18 -0
  124. endoreg_db/migrations/_old/0001_initial.py +1857 -0
  125. endoreg_db/migrations/_old/0004_employee_city_employee_post_code_employee_street_and_more.py +68 -0
  126. endoreg_db/migrations/_old/0004_remove_casetemplate_rules_and_more.py +77 -0
  127. endoreg_db/migrations/_old/0005_merge_20251111_1003.py +14 -0
  128. endoreg_db/migrations/_old/0006_sensitivemeta_anonymized_text_and_more.py +68 -0
  129. endoreg_db/migrations/_old/0007_remove_rule_attribute_dtype_remove_rule_rule_type_and_more.py +89 -0
  130. endoreg_db/migrations/_old/0008_remove_event_event_classification_and_more.py +27 -0
  131. endoreg_db/migrations/_old/0009_alter_modelmeta_options_and_more.py +21 -0
  132. endoreg_db/models/__init__.py +78 -123
  133. endoreg_db/models/administration/__init__.py +21 -42
  134. endoreg_db/models/administration/ai/active_model.py +2 -2
  135. endoreg_db/models/administration/ai/ai_model.py +7 -6
  136. endoreg_db/models/administration/case/__init__.py +1 -15
  137. endoreg_db/models/administration/case/case.py +3 -3
  138. endoreg_db/models/administration/case/case_template/__init__.py +2 -14
  139. endoreg_db/models/administration/case/case_template/case_template.py +2 -124
  140. endoreg_db/models/administration/case/case_template/case_template_rule.py +2 -268
  141. endoreg_db/models/administration/case/case_template/case_template_rule_value.py +2 -85
  142. endoreg_db/models/administration/case/case_template/case_template_type.py +2 -25
  143. endoreg_db/models/administration/center/center.py +33 -19
  144. endoreg_db/models/administration/center/center_product.py +12 -9
  145. endoreg_db/models/administration/center/center_resource.py +25 -19
  146. endoreg_db/models/administration/center/center_shift.py +21 -17
  147. endoreg_db/models/administration/center/center_waste.py +16 -8
  148. endoreg_db/models/administration/person/__init__.py +2 -0
  149. endoreg_db/models/administration/person/employee/employee.py +10 -5
  150. endoreg_db/models/administration/person/employee/employee_qualification.py +9 -4
  151. endoreg_db/models/administration/person/employee/employee_type.py +12 -6
  152. endoreg_db/models/administration/person/examiner/examiner.py +13 -11
  153. endoreg_db/models/administration/person/patient/__init__.py +2 -0
  154. endoreg_db/models/administration/person/patient/patient.py +103 -100
  155. endoreg_db/models/administration/person/patient/patient_external_id.py +37 -0
  156. endoreg_db/models/administration/person/person.py +4 -0
  157. endoreg_db/models/administration/person/profession/__init__.py +8 -4
  158. endoreg_db/models/administration/person/user/portal_user_information.py +11 -7
  159. endoreg_db/models/administration/product/product.py +20 -15
  160. endoreg_db/models/administration/product/product_material.py +17 -18
  161. endoreg_db/models/administration/product/product_weight.py +12 -8
  162. endoreg_db/models/administration/product/reference_product.py +23 -55
  163. endoreg_db/models/administration/qualification/qualification.py +7 -3
  164. endoreg_db/models/administration/qualification/qualification_type.py +7 -3
  165. endoreg_db/models/administration/shift/scheduled_days.py +8 -5
  166. endoreg_db/models/administration/shift/shift.py +16 -12
  167. endoreg_db/models/administration/shift/shift_type.py +23 -31
  168. endoreg_db/models/label/__init__.py +7 -8
  169. endoreg_db/models/label/annotation/image_classification.py +10 -9
  170. endoreg_db/models/label/annotation/video_segmentation_annotation.py +8 -5
  171. endoreg_db/models/label/label.py +15 -15
  172. endoreg_db/models/label/label_set.py +19 -6
  173. endoreg_db/models/label/label_type.py +1 -1
  174. endoreg_db/models/label/label_video_segment/_create_from_video.py +5 -8
  175. endoreg_db/models/label/label_video_segment/label_video_segment.py +76 -102
  176. endoreg_db/models/label/video_segmentation_label.py +4 -0
  177. endoreg_db/models/label/video_segmentation_labelset.py +4 -3
  178. endoreg_db/models/media/frame/frame.py +22 -22
  179. endoreg_db/models/media/pdf/raw_pdf.py +249 -177
  180. endoreg_db/models/media/pdf/report_file.py +25 -29
  181. endoreg_db/models/media/pdf/report_reader/report_reader_config.py +30 -46
  182. endoreg_db/models/media/pdf/report_reader/report_reader_flag.py +23 -7
  183. endoreg_db/models/media/video/__init__.py +1 -0
  184. endoreg_db/models/media/video/create_from_file.py +48 -56
  185. endoreg_db/models/media/video/pipe_1.py +30 -33
  186. endoreg_db/models/media/video/pipe_2.py +8 -9
  187. endoreg_db/models/media/video/video_file.py +359 -204
  188. endoreg_db/models/media/video/video_file_ai.py +288 -74
  189. endoreg_db/models/media/video/video_file_anonymize.py +38 -38
  190. endoreg_db/models/media/video/video_file_frames/__init__.py +3 -1
  191. endoreg_db/models/media/video/video_file_frames/_bulk_create_frames.py +6 -8
  192. endoreg_db/models/media/video/video_file_frames/_create_frame_object.py +7 -9
  193. endoreg_db/models/media/video/video_file_frames/_delete_frames.py +9 -8
  194. endoreg_db/models/media/video/video_file_frames/_extract_frames.py +38 -45
  195. endoreg_db/models/media/video/video_file_frames/_get_frame.py +6 -8
  196. endoreg_db/models/media/video/video_file_frames/_get_frame_number.py +4 -18
  197. endoreg_db/models/media/video/video_file_frames/_get_frame_path.py +4 -3
  198. endoreg_db/models/media/video/video_file_frames/_get_frame_paths.py +7 -6
  199. endoreg_db/models/media/video/video_file_frames/_get_frame_range.py +6 -8
  200. endoreg_db/models/media/video/video_file_frames/_get_frames.py +6 -8
  201. endoreg_db/models/media/video/video_file_frames/_initialize_frames.py +15 -25
  202. endoreg_db/models/media/video/video_file_frames/_manage_frame_range.py +26 -23
  203. endoreg_db/models/media/video/video_file_frames/_mark_frames_extracted_status.py +23 -14
  204. endoreg_db/models/media/video/video_file_io.py +109 -62
  205. endoreg_db/models/media/video/video_file_meta/get_crop_template.py +3 -3
  206. endoreg_db/models/media/video/video_file_meta/get_endo_roi.py +5 -3
  207. endoreg_db/models/media/video/video_file_meta/get_fps.py +37 -34
  208. endoreg_db/models/media/video/video_file_meta/initialize_video_specs.py +19 -25
  209. endoreg_db/models/media/video/video_file_meta/text_meta.py +41 -38
  210. endoreg_db/models/media/video/video_file_meta/video_meta.py +14 -7
  211. endoreg_db/models/media/video/video_file_segments.py +24 -17
  212. endoreg_db/models/media/video/video_metadata.py +19 -35
  213. endoreg_db/models/media/video/video_processing.py +96 -95
  214. endoreg_db/models/medical/contraindication/__init__.py +13 -3
  215. endoreg_db/models/medical/disease.py +22 -16
  216. endoreg_db/models/medical/event.py +31 -18
  217. endoreg_db/models/medical/examination/__init__.py +13 -6
  218. endoreg_db/models/medical/examination/examination.py +17 -18
  219. endoreg_db/models/medical/examination/examination_indication.py +26 -25
  220. endoreg_db/models/medical/examination/examination_time.py +16 -6
  221. endoreg_db/models/medical/examination/examination_time_type.py +9 -6
  222. endoreg_db/models/medical/examination/examination_type.py +3 -4
  223. endoreg_db/models/medical/finding/finding.py +38 -39
  224. endoreg_db/models/medical/finding/finding_classification.py +37 -48
  225. endoreg_db/models/medical/finding/finding_intervention.py +27 -22
  226. endoreg_db/models/medical/finding/finding_type.py +13 -12
  227. endoreg_db/models/medical/hardware/endoscope.py +20 -26
  228. endoreg_db/models/medical/hardware/endoscopy_processor.py +2 -2
  229. endoreg_db/models/medical/laboratory/lab_value.py +62 -91
  230. endoreg_db/models/medical/medication/medication.py +22 -10
  231. endoreg_db/models/medical/medication/medication_indication.py +29 -3
  232. endoreg_db/models/medical/medication/medication_indication_type.py +25 -14
  233. endoreg_db/models/medical/medication/medication_intake_time.py +31 -19
  234. endoreg_db/models/medical/medication/medication_schedule.py +27 -16
  235. endoreg_db/models/medical/organ/__init__.py +15 -12
  236. endoreg_db/models/medical/patient/medication_examples.py +1 -5
  237. endoreg_db/models/medical/patient/patient_disease.py +20 -23
  238. endoreg_db/models/medical/patient/patient_event.py +19 -22
  239. endoreg_db/models/medical/patient/patient_examination.py +48 -54
  240. endoreg_db/models/medical/patient/patient_examination_indication.py +16 -14
  241. endoreg_db/models/medical/patient/patient_finding.py +122 -139
  242. endoreg_db/models/medical/patient/patient_finding_classification.py +44 -49
  243. endoreg_db/models/medical/patient/patient_finding_intervention.py +8 -19
  244. endoreg_db/models/medical/patient/patient_lab_sample.py +28 -23
  245. endoreg_db/models/medical/patient/patient_lab_value.py +82 -89
  246. endoreg_db/models/medical/patient/patient_medication.py +27 -38
  247. endoreg_db/models/medical/patient/patient_medication_schedule.py +28 -36
  248. endoreg_db/models/medical/risk/risk.py +7 -6
  249. endoreg_db/models/medical/risk/risk_type.py +8 -5
  250. endoreg_db/models/metadata/model_meta.py +60 -29
  251. endoreg_db/models/metadata/model_meta_logic.py +139 -18
  252. endoreg_db/models/metadata/pdf_meta.py +19 -24
  253. endoreg_db/models/metadata/sensitive_meta.py +102 -85
  254. endoreg_db/models/metadata/sensitive_meta_logic.py +383 -43
  255. endoreg_db/models/metadata/video_meta.py +51 -31
  256. endoreg_db/models/metadata/video_prediction_logic.py +16 -23
  257. endoreg_db/models/metadata/video_prediction_meta.py +29 -33
  258. endoreg_db/models/other/distribution/date_value_distribution.py +89 -29
  259. endoreg_db/models/other/distribution/multiple_categorical_value_distribution.py +21 -5
  260. endoreg_db/models/other/distribution/numeric_value_distribution.py +114 -53
  261. endoreg_db/models/other/distribution/single_categorical_value_distribution.py +4 -3
  262. endoreg_db/models/other/emission/emission_factor.py +18 -8
  263. endoreg_db/models/other/gender.py +10 -5
  264. endoreg_db/models/other/information_source.py +25 -25
  265. endoreg_db/models/other/material.py +9 -5
  266. endoreg_db/models/other/resource.py +6 -4
  267. endoreg_db/models/other/tag.py +10 -5
  268. endoreg_db/models/other/transport_route.py +13 -8
  269. endoreg_db/models/other/unit.py +10 -6
  270. endoreg_db/models/other/waste.py +6 -5
  271. endoreg_db/models/requirement/requirement.py +580 -272
  272. endoreg_db/models/requirement/requirement_error.py +85 -0
  273. endoreg_db/models/requirement/requirement_evaluation/evaluate_with_dependencies.py +268 -0
  274. endoreg_db/models/requirement/requirement_evaluation/operator_evaluation_models.py +3 -6
  275. endoreg_db/models/requirement/requirement_evaluation/requirement_type_parser.py +90 -64
  276. endoreg_db/models/requirement/requirement_operator.py +36 -33
  277. endoreg_db/models/requirement/requirement_set.py +74 -57
  278. endoreg_db/models/state/__init__.py +4 -4
  279. endoreg_db/models/state/abstract.py +2 -2
  280. endoreg_db/models/state/anonymization.py +12 -0
  281. endoreg_db/models/state/audit_ledger.py +46 -47
  282. endoreg_db/models/state/label_video_segment.py +9 -0
  283. endoreg_db/models/state/raw_pdf.py +40 -46
  284. endoreg_db/models/state/sensitive_meta.py +6 -2
  285. endoreg_db/models/state/video.py +58 -53
  286. endoreg_db/models/upload_job.py +32 -55
  287. endoreg_db/models/utils.py +1 -2
  288. endoreg_db/root_urls.py +21 -2
  289. endoreg_db/serializers/__init__.py +26 -57
  290. endoreg_db/serializers/anonymization.py +18 -10
  291. endoreg_db/serializers/meta/report_meta.py +1 -1
  292. endoreg_db/serializers/meta/sensitive_meta_detail.py +63 -118
  293. endoreg_db/serializers/misc/__init__.py +1 -1
  294. endoreg_db/serializers/misc/file_overview.py +33 -91
  295. endoreg_db/serializers/misc/{vop_patient_data.py → sensitive_patient_data.py} +1 -1
  296. endoreg_db/serializers/requirements/requirement_sets.py +92 -22
  297. endoreg_db/serializers/video/segmentation.py +2 -1
  298. endoreg_db/serializers/video/video_processing_history.py +20 -5
  299. endoreg_db/serializers/video_examination.py +198 -0
  300. endoreg_db/services/anonymization.py +75 -73
  301. endoreg_db/services/lookup_service.py +256 -73
  302. endoreg_db/services/lookup_store.py +174 -30
  303. endoreg_db/services/pdf_import.py +711 -310
  304. endoreg_db/services/storage_aware_video_processor.py +140 -114
  305. endoreg_db/services/video_import.py +266 -117
  306. endoreg_db/urls/__init__.py +27 -27
  307. endoreg_db/urls/label_video_segments.py +2 -0
  308. endoreg_db/urls/media.py +108 -66
  309. endoreg_db/urls/root_urls.py +29 -0
  310. endoreg_db/utils/__init__.py +15 -5
  311. endoreg_db/utils/ai/multilabel_classification_net.py +116 -20
  312. endoreg_db/utils/case_generator/__init__.py +3 -0
  313. endoreg_db/utils/dataloader.py +88 -16
  314. endoreg_db/utils/defaults/set_default_center.py +32 -0
  315. endoreg_db/utils/names.py +22 -16
  316. endoreg_db/utils/permissions.py +2 -1
  317. endoreg_db/utils/pipelines/process_video_dir.py +1 -1
  318. endoreg_db/utils/requirement_operator_logic/model_evaluators.py +414 -127
  319. endoreg_db/utils/setup_config.py +8 -5
  320. endoreg_db/utils/storage.py +115 -0
  321. endoreg_db/utils/validate_endo_roi.py +8 -2
  322. endoreg_db/utils/video/ffmpeg_wrapper.py +184 -188
  323. endoreg_db/views/__init__.py +5 -12
  324. endoreg_db/views/anonymization/media_management.py +198 -163
  325. endoreg_db/views/anonymization/overview.py +4 -1
  326. endoreg_db/views/anonymization/validate.py +174 -40
  327. endoreg_db/views/media/__init__.py +2 -0
  328. endoreg_db/views/media/pdf_media.py +131 -150
  329. endoreg_db/views/media/sensitive_metadata.py +46 -6
  330. endoreg_db/views/media/video_media.py +89 -82
  331. endoreg_db/views/media/video_segments.py +187 -260
  332. endoreg_db/views/meta/sensitive_meta_detail.py +0 -63
  333. endoreg_db/views/patient/patient.py +5 -4
  334. endoreg_db/views/pdf/__init__.py +5 -8
  335. endoreg_db/views/pdf/pdf_stream.py +186 -0
  336. endoreg_db/views/pdf/pdf_stream_views.py +0 -127
  337. endoreg_db/views/pdf/reimport.py +86 -91
  338. endoreg_db/views/requirement/evaluate.py +188 -187
  339. endoreg_db/views/requirement/lookup.py +186 -288
  340. endoreg_db/views/requirement/requirement_utils.py +89 -0
  341. endoreg_db/views/video/__init__.py +0 -4
  342. endoreg_db/views/video/correction.py +2 -2
  343. endoreg_db/views/video/video_examination_viewset.py +202 -289
  344. {endoreg_db-0.8.4.4.dist-info → endoreg_db-0.8.8.0.dist-info}/METADATA +7 -3
  345. {endoreg_db-0.8.4.4.dist-info → endoreg_db-0.8.8.0.dist-info}/RECORD +350 -255
  346. endoreg_db/models/administration/permissions/__init__.py +0 -44
  347. endoreg_db/models/media/video/refactor_plan.md +0 -0
  348. endoreg_db/models/media/video/video_file_frames.py +0 -0
  349. endoreg_db/models/metadata/frame_ocr_result.py +0 -0
  350. endoreg_db/models/rule/__init__.py +0 -13
  351. endoreg_db/models/rule/rule.py +0 -27
  352. endoreg_db/models/rule/rule_applicator.py +0 -224
  353. endoreg_db/models/rule/rule_attribute_dtype.py +0 -17
  354. endoreg_db/models/rule/rule_type.py +0 -20
  355. endoreg_db/models/rule/ruleset.py +0 -17
  356. endoreg_db/serializers/video/video_metadata.py +0 -105
  357. endoreg_db/urls/report.py +0 -48
  358. endoreg_db/urls/video.py +0 -61
  359. endoreg_db/utils/case_generator/case_generator.py +0 -159
  360. endoreg_db/utils/case_generator/utils.py +0 -30
  361. endoreg_db/views/pdf/pdf_media.py +0 -239
  362. endoreg_db/views/report/__init__.py +0 -9
  363. endoreg_db/views/report/report_list.py +0 -112
  364. endoreg_db/views/report/report_with_secure_url.py +0 -28
  365. endoreg_db/views/report/start_examination.py +0 -7
  366. endoreg_db/views/video/video_media.py +0 -158
  367. endoreg_db/views.py +0 -0
  368. /endoreg_db/data/{requirement_set → _examples/requirement_set}/endoscopy_bleeding_risk.yaml +0 -0
  369. /endoreg_db/migrations/{0002_add_video_correction_models.py → _old/0002_add_video_correction_models.py} +0 -0
  370. /endoreg_db/migrations/{0003_add_center_display_name.py → _old/0003_add_center_display_name.py} +0 -0
  371. {endoreg_db-0.8.4.4.dist-info → endoreg_db-0.8.8.0.dist-info}/WHEEL +0 -0
  372. {endoreg_db-0.8.4.4.dist-info → endoreg_db-0.8.8.0.dist-info}/licenses/LICENSE +0 -0
@@ -1,10 +1,12 @@
1
+ from typing import TYPE_CHECKING, List, Optional, cast
2
+
1
3
  from django.db import models
2
- from typing import List, TYPE_CHECKING, Optional
3
4
 
4
5
  if TYPE_CHECKING:
5
- from endoreg_db.models import Examination, Requirement, FindingIntervention
6
+ from endoreg_db.models import Examination, FindingIntervention, Requirement
6
7
  from endoreg_db.utils.links.requirement_link import RequirementLinks
7
8
 
9
+
8
10
  class ExaminationIndicationManager(models.Manager):
9
11
  """
10
12
  Manager for ExaminationIndication with custom query methods.
@@ -13,10 +15,10 @@ class ExaminationIndicationManager(models.Manager):
13
15
  def get_by_natural_key(self, name: str) -> "ExaminationIndication":
14
16
  """
15
17
  Retrieves an ExaminationIndication instance by its natural key.
16
-
18
+
17
19
  Args:
18
20
  name: The unique name identifying the examination indication.
19
-
21
+
20
22
  Returns:
21
23
  The ExaminationIndication instance corresponding to the specified name.
22
24
  """
@@ -58,20 +60,23 @@ class ExaminationIndication(models.Model):
58
60
  objects = ExaminationIndicationManager()
59
61
 
60
62
  if TYPE_CHECKING:
61
- classifications: "models.ManyToManyField[ExaminationIndicationClassification, ExaminationIndicationClassification]"
62
- examinations: "models.ManyToManyField[Examination, Examination]"
63
- related_requirements: "models.QuerySet[Requirement]"
64
- expected_interventions: "models.ManyToManyField[FindingIntervention, FindingIntervention]"
63
+ classifications = cast(models.manager.RelatedManager["ExaminationIndicationClassification"], classifications)
64
+ examinations = cast(models.manager.RelatedManager["Examination"], examinations)
65
+ expected_interventions = cast(models.manager.RelatedManager["FindingIntervention"], expected_interventions)
66
+
67
+ @property
68
+ def related_requirements(self) -> "models.manager.RelatedManager[Requirement]": ...
65
69
 
66
70
  @property
67
71
  def links(self) -> "RequirementLinks":
68
72
  """
69
73
  Aggregates related requirements, classifications, examination, and interventions into a RequirementLinks object.
70
-
74
+
71
75
  Returns:
72
76
  A RequirementLinks instance representing all entities linked to this examination indication.
73
77
  """
74
78
  from endoreg_db.utils.links.requirement_link import RequirementLinks
79
+
75
80
  return RequirementLinks(
76
81
  examination_indications=[self],
77
82
  examinations=list(self.examinations.all()),
@@ -96,9 +101,9 @@ class ExaminationIndication(models.Model):
96
101
  def get_choices(self) -> List["ExaminationIndicationClassificationChoice"]:
97
102
  """
98
103
  Retrieves all classification choices for the indication.
99
-
104
+
100
105
  Aggregates and returns the choices from each classification associated with the indication.
101
-
106
+
102
107
  Returns:
103
108
  List[ExaminationIndicationClassificationChoice]: A list of classification choices.
104
109
  """
@@ -111,7 +116,7 @@ class ExaminationIndication(models.Model):
111
116
  def get_examination(self) -> Optional["Examination"]:
112
117
  """
113
118
  Returns the first examination associated with this indication, or None if no examinations exist.
114
-
119
+
115
120
  Note: Since this is now a many-to-many relationship, this method returns the first examination.
116
121
  Consider using get_examinations() for accessing all related examinations.
117
122
  """
@@ -120,13 +125,11 @@ class ExaminationIndication(models.Model):
120
125
  def get_examinations(self) -> List["Examination"]:
121
126
  """
122
127
  Returns all examinations associated with this indication.
123
-
128
+
124
129
  Returns:
125
130
  List[Examination]: A list of all examinations linked to this indication.
126
131
  """
127
132
  return list(self.examinations.all())
128
-
129
-
130
133
 
131
134
 
132
135
  class ExaminationIndicationClassificationManager(models.Manager):
@@ -137,10 +140,10 @@ class ExaminationIndicationClassificationManager(models.Manager):
137
140
  def get_by_natural_key(self, name: str) -> "ExaminationIndicationClassification":
138
141
  """
139
142
  Retrieves an ExaminationIndicationClassification by its natural key.
140
-
143
+
141
144
  Args:
142
145
  name: The unique name identifying the classification.
143
-
146
+
144
147
  Returns:
145
148
  The ExaminationIndicationClassification instance corresponding to the given name.
146
149
  """
@@ -192,7 +195,7 @@ class ExaminationIndicationClassification(models.Model):
192
195
  def get_choices(self) -> List["ExaminationIndicationClassificationChoice"]:
193
196
  """
194
197
  Retrieves all classification choices associated with this classification.
195
-
198
+
196
199
  Returns:
197
200
  List[ExaminationIndicationClassificationChoice]: A list of classification choice instances.
198
201
  """
@@ -201,7 +204,7 @@ class ExaminationIndicationClassification(models.Model):
201
204
  def get_examination(self) -> Optional["Examination"]:
202
205
  """
203
206
  Returns the first examination associated with this classification, or None if no examinations exist.
204
-
207
+
205
208
  Note: Since this is now a many-to-many relationship, this method returns the first examination.
206
209
  Consider using get_examinations() for accessing all related examinations.
207
210
  """
@@ -210,7 +213,7 @@ class ExaminationIndicationClassification(models.Model):
210
213
  def get_examinations(self) -> List["Examination"]:
211
214
  """
212
215
  Returns all examinations associated with this classification.
213
-
216
+
214
217
  Returns:
215
218
  List[Examination]: A list of all examinations linked to this classification.
216
219
  """
@@ -222,15 +225,13 @@ class ExaminationIndicationClassificationChoiceManager(models.Manager):
222
225
  Manager for ExaminationIndicationClassificationChoice with custom query methods.
223
226
  """
224
227
 
225
- def get_by_natural_key(
226
- self, name: str
227
- ) -> "ExaminationIndicationClassificationChoice":
228
+ def get_by_natural_key(self, name: str) -> "ExaminationIndicationClassificationChoice":
228
229
  """
229
230
  Retrieves an ExaminationIndicationClassificationChoice instance by its natural key.
230
-
231
+
231
232
  Args:
232
233
  name: The unique name serving as the natural key for the classification choice.
233
-
234
+
234
235
  Returns:
235
236
  An ExaminationIndicationClassificationChoice instance corresponding to the given name.
236
237
  """
@@ -1,13 +1,20 @@
1
+ from typing import TYPE_CHECKING, cast
2
+
1
3
  from django.db import models
2
- from rest_framework import serializers
4
+
5
+ if TYPE_CHECKING:
6
+ from endoreg_db.models import ExaminationTimeType
7
+
3
8
 
4
9
  class ExaminationTimeManager(models.Manager):
5
10
  """
6
11
  Manager for ExaminationTime with custom query methods.
7
12
  """
13
+
8
14
  def get_by_natural_key(self, name: str) -> "ExaminationTime":
9
15
  return self.get(name=name)
10
16
 
17
+
11
18
  class ExaminationTime(models.Model):
12
19
  """
13
20
  Represents a specific time configuration for examinations.
@@ -18,12 +25,16 @@ class ExaminationTime(models.Model):
18
25
  end_time (TimeField): The ending time for the examination.
19
26
  time_types (ManyToManyField): The types associated with this examination time.
20
27
  """
28
+
21
29
  name = models.CharField(max_length=100, unique=True)
22
30
  start_time = models.TimeField(blank=True, null=True)
23
- time_types = models.ManyToManyField('ExaminationTimeType', blank=True)
31
+ time_types = models.ManyToManyField("ExaminationTimeType", blank=True)
24
32
  end_time = models.TimeField(blank=True, null=True)
25
33
  objects = ExaminationTimeManager()
26
34
 
35
+ if TYPE_CHECKING:
36
+ time_types = cast(models.manager.RelatedManager["ExaminationTimeType"], time_types)
37
+
27
38
  def __str__(self) -> str:
28
39
  """
29
40
  String representation of the examination time.
@@ -43,7 +54,6 @@ class ExaminationTime(models.Model):
43
54
  return (self.name,)
44
55
 
45
56
  class Meta:
46
- verbose_name = 'Examination Time'
47
- verbose_name_plural = 'Examination Times'
48
- ordering = ['name']
49
-
57
+ verbose_name = "Examination Time"
58
+ verbose_name_plural = "Examination Times"
59
+ ordering = ["name"]
@@ -1,12 +1,15 @@
1
1
  from django.db import models
2
2
 
3
+
3
4
  class ExaminationTimeTypeManager(models.Manager):
4
5
  """
5
6
  Manager for ExaminationTimeType with custom query methods.
6
7
  """
8
+
7
9
  def get_by_natural_key(self, name: str) -> "ExaminationTimeType":
8
10
  return self.get(name=name)
9
-
11
+
12
+
10
13
  class ExaminationTimeType(models.Model):
11
14
  """
12
15
  Represents a type of examination time.
@@ -15,9 +18,10 @@ class ExaminationTimeType(models.Model):
15
18
  name (str): The unique name of the examination time type.
16
19
  examinations: The examinations associated with this type.
17
20
  """
21
+
18
22
  objects = ExaminationTimeTypeManager()
19
23
  name = models.CharField(max_length=100, unique=True)
20
- examinations = models.ManyToManyField('Examination', blank=True)
24
+ examinations = models.ManyToManyField("Examination", blank=True)
21
25
 
22
26
  def __str__(self) -> str:
23
27
  """
@@ -35,7 +39,6 @@ class ExaminationTimeType(models.Model):
35
39
  return (self.name,)
36
40
 
37
41
  class Meta:
38
- verbose_name = 'Examination Time Type'
39
- verbose_name_plural = 'Examination Time Types'
40
- ordering = ['name']
41
-
42
+ verbose_name = "Examination Time Type"
43
+ verbose_name_plural = "Examination Time Types"
44
+ ordering = ["name"]
@@ -9,10 +9,10 @@ class ExaminationTypeManager(models.Manager):
9
9
  def get_by_natural_key(self, name: str) -> "ExaminationType":
10
10
  """
11
11
  Retrieves an ExaminationType instance using its natural key.
12
-
12
+
13
13
  Args:
14
14
  name: The natural identifier for the ExaminationType, typically the unique name.
15
-
15
+
16
16
  Returns:
17
17
  The ExaminationType instance that matches the given name.
18
18
  """
@@ -34,8 +34,7 @@ class ExaminationType(models.Model):
34
34
  """
35
35
  Return the string representation of the examination type using its name.
36
36
  """
37
- name = self.name_en or self.name
38
- name = str(name)
37
+ name = str(self.name)
39
38
  return name
40
39
 
41
40
  def natural_key(self) -> tuple:
@@ -1,86 +1,85 @@
1
1
  # Class to represent findings of examinations
2
+ from typing import TYPE_CHECKING, Optional, cast
3
+
2
4
  from django.db import models
3
- from typing import List
4
5
 
5
- from typing import TYPE_CHECKING
6
6
 
7
7
  class FindingManager(models.Manager):
8
8
  def get_by_natural_key(self, name):
9
9
  return self.get(name=name)
10
10
 
11
+
11
12
  class Finding(models.Model):
12
13
  name = models.CharField(max_length=100, unique=True)
13
14
  description = models.TextField(blank=True, null=True)
14
- examinations = models.ManyToManyField(
15
- 'Examination',
16
- blank=True,
17
- related_name='findings'
18
- ) # type: ignore
19
- finding_types = models.ManyToManyField(
20
- 'FindingType',
21
- blank=True,
22
- related_name='findings'
23
- ) # type: ignore
24
-
25
- finding_interventions = models.ManyToManyField(
26
- 'FindingIntervention',
27
- blank=True,
28
- related_name='findings'
29
- ) # type: ignore
15
+ examinations = models.ManyToManyField("Examination", blank=True, related_name="findings")
16
+ finding_types = models.ManyToManyField("FindingType", blank=True, related_name="findings")
17
+
18
+ finding_interventions = models.ManyToManyField("FindingIntervention", blank=True, related_name="findings")
30
19
 
31
20
  objects = FindingManager()
32
21
 
33
22
  if TYPE_CHECKING:
34
23
  from endoreg_db.models import (
35
- Examination, FindingType, FindingIntervention, FindingClassificationType,
24
+ Examination,
36
25
  FindingClassification,
37
- PatientFindingClassification
26
+ FindingClassificationType,
27
+ FindingIntervention,
28
+ FindingType,
29
+ PatientFindingClassification,
38
30
  )
39
-
40
- finding_classifications: models.QuerySet['FindingClassification']
41
- examinations: models.QuerySet[Examination]
42
- finding_types: models.QuerySet[FindingType]
43
- finding_interventions: models.QuerySet[FindingIntervention]
44
-
31
+
32
+ finding_types = cast(models.manager.RelatedManager["FindingType"], finding_types)
33
+ examinations = cast(models.manager.RelatedManager["Examination"], examinations)
34
+ finding_interventions = cast(models.manager.RelatedManager["FindingIntervention"], finding_interventions)
35
+
36
+ @property
37
+ def finding_classifications(self) -> "models.manager.RelatedManager[FindingClassification]": ...
38
+
39
+ # finding_classifications: models.QuerySet["FindingClassification"]
40
+ # examinations: models.QuerySet[Examination]
41
+ # finding_types: models.QuerySet[FindingType]
42
+ # finding_interventions: models.QuerySet[FindingIntervention]
43
+
45
44
  def natural_key(self):
46
45
  """
47
46
  Return a tuple containing the unique natural key for this Finding instance.
48
-
47
+
49
48
  Returns:
50
49
  tuple: A single-element tuple with the Finding's name.
51
50
  """
52
51
  return (self.name,)
53
-
52
+
54
53
  def __str__(self):
55
54
  return self.name
56
-
55
+
57
56
  def get_finding_types(self):
58
57
  """
59
58
  Return all finding types associated with this finding.
60
-
59
+
61
60
  Returns:
62
61
  QuerySet: All related FindingType instances.
63
62
  """
64
63
  return self.finding_types.all()
65
-
66
- def get_classifications(self, classification_type: str = None) -> models.QuerySet['FindingClassification']:
64
+
65
+ def get_classifications(self, classification_type: Optional[str] = None) -> models.QuerySet["FindingClassification"]:
67
66
  """
68
67
  Retrieve all classifications associated with this finding, optionally filtered by classification type.
69
-
68
+
70
69
  Parameters:
71
- classification_type (str, optional): If provided, only classifications with a matching type name are returned.
72
-
70
+ classification_type (str, optional): If provided, only classifications with a matching type name are returned.
71
+
73
72
  Returns:
74
- List[FindingClassification]: List of related classification objects, filtered by type if specified.
73
+ List[FindingClassification]: List of related classification objects, filtered by type if specified.
75
74
  """
76
75
  if classification_type:
77
76
  return self.finding_classifications.filter(classification_types__name=classification_type)
78
77
  return self.finding_classifications.all()
79
-
78
+
80
79
  def get_location_classifications(self):
81
80
  """
82
81
  Retrieve all related FindingClassification objects with classification type 'location'.
83
-
82
+
84
83
  Returns:
85
84
  QuerySet: All FindingClassification instances linked to this finding where the classification type name is 'location' (case-insensitive).
86
85
  """
@@ -89,7 +88,7 @@ class Finding(models.Model):
89
88
  def get_morphology_classifications(self):
90
89
  """
91
90
  Retrieve all related FindingClassification objects with classification type 'morphology'.
92
-
91
+
93
92
  Returns:
94
93
  QuerySet: A queryset of FindingClassification instances associated with this finding and classified as 'morphology'.
95
94
  """
@@ -1,30 +1,31 @@
1
+ from typing import TYPE_CHECKING, cast
2
+
1
3
  from django.db import models
2
- from typing import TYPE_CHECKING, List
4
+
3
5
 
4
6
  class FindingClassificationTypeManager(models.Manager):
5
7
  def get_by_natural_key(self, name):
6
8
  return self.get(name=name)
7
-
9
+
10
+
8
11
  class FindingClassificationType(models.Model):
9
12
  name = models.CharField(max_length=255, unique=True)
10
13
  description = models.TextField(blank=True)
11
-
14
+
12
15
  objects = FindingClassificationTypeManager()
13
-
16
+
14
17
  def natural_key(self):
15
18
  return (self.name,)
16
-
19
+
17
20
  def __str__(self):
18
21
  return str(self.name)
19
-
22
+
20
23
  @classmethod
21
24
  def get_required_classifications_for_finding(cls, finding):
22
25
  """
23
26
  Returns all required finding classification types for a given finding.
24
27
  """
25
- required_classification_types = [
26
- _ for _ in finding.required_morphology_classification_types.all()
27
- ]
28
+ required_classification_types = [_ for _ in finding.required_morphology_classification_types.all()]
28
29
  return required_classification_types
29
30
 
30
31
 
@@ -37,31 +38,25 @@ class FindingClassification(models.Model):
37
38
  name = models.CharField(max_length=255, unique=True)
38
39
  description = models.TextField(blank=True)
39
40
  classification_types = models.ManyToManyField(
40
- to=FindingClassificationType,
41
+ to=FindingClassificationType,
41
42
  # on_delete=models.CASCADE
42
43
  )
43
- choices = models.ManyToManyField(
44
- 'FindingClassificationChoice',
45
- related_name='classifications',
46
- blank=True
47
- )
44
+ choices = models.ManyToManyField("FindingClassificationChoice", related_name="classifications", blank=True)
48
45
 
49
- findings = models.ManyToManyField('Finding', blank=True, related_name='finding_classifications')
50
- examinations = models.ManyToManyField('Examination', blank=True, related_name='finding_classifications')
51
- finding_types = models.ManyToManyField('FindingType', blank=True, related_name='finding_classifications')
46
+ findings = models.ManyToManyField("Finding", blank=True, related_name="finding_classifications")
47
+ examinations = models.ManyToManyField("Examination", blank=True, related_name="finding_classifications")
48
+ finding_types = models.ManyToManyField("FindingType", blank=True, related_name="finding_classifications")
52
49
 
53
50
  objects = FindingClassificationManager()
54
51
 
55
52
  if TYPE_CHECKING:
56
- from endoreg_db.models import (
57
- Finding, Examination, FindingType, PatientFindingClassification
58
- )
59
- classification_types: models.ManyToManyField[FindingClassificationType]
60
- findings: models.QuerySet[Finding]
61
- examinations: models.QuerySet[Examination]
62
- finding_types: models.QuerySet[FindingType]
63
- choices: models.QuerySet['FindingClassificationChoice']
64
- patient_finding_classifications: models.QuerySet['PatientFindingClassification']
53
+ from endoreg_db.models import Examination, Finding, FindingType, PatientFindingClassification
54
+
55
+ classification_types = cast(models.manager.RelatedManager["FindingClassificationType"], classification_types)
56
+ choices = cast(models.manager.RelatedManager["FindingClassificationChoice"], choices)
57
+ examinations = cast(models.manager.RelatedManager["Examination"], examinations)
58
+ findings = cast(models.manager.RelatedManager["Finding"], findings)
59
+ finding_types = cast(models.manager.RelatedManager["FindingType"], finding_types)
65
60
 
66
61
  def natural_key(self):
67
62
  return (self.name,)
@@ -72,9 +67,9 @@ class FindingClassification(models.Model):
72
67
  def get_choices(self):
73
68
  """
74
69
  Return all choices associated with this classification.
75
-
70
+
76
71
  Returns:
77
- QuerySet: All related FindingClassificationChoice instances.
72
+ QuerySet: All related FindingClassificationChoice instances.
78
73
  """
79
74
  return self.choices.all()
80
75
 
@@ -97,46 +92,40 @@ class FindingClassificationChoiceManager(models.Manager):
97
92
  def get_by_natural_key(self, name):
98
93
  """
99
94
  Retrieve an instance by its unique name using the natural key.
100
-
95
+
101
96
  Parameters:
102
97
  name (str): The unique name identifying the instance.
103
-
98
+
104
99
  Returns:
105
100
  The model instance with the specified name.
106
101
  """
107
102
  return self.get(name=name)
108
-
103
+
104
+
109
105
  class FindingClassificationChoice(models.Model):
110
106
  name = models.CharField(max_length=255, unique=True)
111
107
  description = models.TextField(blank=True)
112
108
  # classifications = models.ManyToManyField(
113
- # "FindingClassification",
109
+ # "FindingClassification",
114
110
  # related_name='choices'
115
111
  # )
116
-
117
- subcategories = models.JSONField(
118
- default = dict
119
- )
120
112
 
121
- numerical_descriptors = models.JSONField(
122
- default = dict
123
- )
113
+ subcategories = models.JSONField(default=dict)
114
+
115
+ numerical_descriptors = models.JSONField(default=dict)
124
116
 
125
117
  objects = FindingClassificationChoiceManager()
126
118
 
127
119
  if TYPE_CHECKING:
128
- from endoreg_db.models import (
129
- PatientFindingClassification
130
- )
131
- classifications: models.QuerySet['FindingClassification']
132
- patient_finding_classifications: models.QuerySet['PatientFindingClassification']
120
+ from endoreg_db.models import PatientFindingClassification
121
+
122
+ classifications: models.QuerySet["FindingClassification"]
123
+ patient_finding_classifications: models.QuerySet["PatientFindingClassification"]
133
124
 
134
-
135
125
  def natural_key(self):
136
126
  return (self.name,)
137
-
127
+
138
128
  def __str__(self):
139
129
  classifications_names = ", ".join([c.name for c in self.classifications.all()])
140
130
  _str = f"{self.name} ({classifications_names})"
141
131
  return _str
142
-
@@ -1,52 +1,57 @@
1
+ from typing import TYPE_CHECKING, cast
2
+
1
3
  from django.db import models
2
4
 
5
+
3
6
  class FindingInterventionManager(models.Manager):
4
7
  def get_by_natural_key(self, name):
5
8
  return self.get(name=name)
6
-
9
+
10
+
7
11
  class FindingIntervention(models.Model):
8
12
  name = models.CharField(max_length=100, unique=True)
9
13
  description = models.TextField(blank=True, null=True)
10
14
 
11
- intervention_types = models.ManyToManyField(
12
- 'FindingInterventionType',
13
- blank=True,
14
- related_name='interventions'
15
- )
15
+ intervention_types = models.ManyToManyField("FindingInterventionType", blank=True, related_name="interventions")
16
16
 
17
- required_lab_values = models.ManyToManyField(
18
- 'LabValue',
19
- blank=True,
20
- related_name='required_by_finding_interventions'
21
- )
17
+ required_lab_values = models.ManyToManyField("LabValue", blank=True, related_name="required_by_finding_interventions")
22
18
 
23
- contraindications = models.ManyToManyField(
24
- 'Contraindication',
25
- blank=True,
26
- related_name='contraindicating_finding_interventions'
27
- )
19
+ contraindications = models.ManyToManyField("Contraindication", blank=True, related_name="contraindicating_finding_interventions")
28
20
 
29
21
  objects = FindingInterventionManager()
30
-
22
+
23
+ if TYPE_CHECKING:
24
+ from endoreg_db.models import Contraindication, FindingInterventionType, LabValue
25
+
26
+ intervention_types = cast(models.manager.RelatedManager["FindingInterventionType"], intervention_types)
27
+ required_lab_values = cast(models.manager.RelatedManager["LabValue"], required_lab_values)
28
+ contraindications = cast(models.manager.RelatedManager["Contraindication"], contraindications)
29
+
31
30
  def natural_key(self):
32
31
  return (self.name,)
33
-
32
+
34
33
  def __str__(self):
35
34
  return str(self.name)
36
-
35
+
37
36
 
38
37
  class FindingInterventionTypeManager(models.Manager):
39
38
  def get_by_natural_key(self, name):
40
39
  return self.get(name=name)
41
-
40
+
41
+
42
42
  class FindingInterventionType(models.Model):
43
43
  name = models.CharField(max_length=100, unique=True)
44
44
  description = models.TextField(blank=True, null=True)
45
45
 
46
46
  objects = FindingInterventionTypeManager()
47
-
47
+
48
+ if TYPE_CHECKING:
49
+
50
+ @property
51
+ def interventions(self) -> "models.manager.RelatedManager[FindingIntervention]": ...
52
+
48
53
  def natural_key(self):
49
54
  return (self.name,)
50
-
55
+
51
56
  def __str__(self):
52
57
  return str(self.name)