endoreg-db 0.8.3.3__py3-none-any.whl → 0.8.6.5__py3-none-any.whl

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

Potentially problematic release.


This version of endoreg-db might be problematic. Click here for more details.

Files changed (41) hide show
  1. endoreg_db/data/ai_model_meta/default_multilabel_classification.yaml +23 -1
  2. endoreg_db/data/setup_config.yaml +38 -0
  3. endoreg_db/management/commands/create_model_meta_from_huggingface.py +1 -2
  4. endoreg_db/management/commands/load_ai_model_data.py +18 -15
  5. endoreg_db/management/commands/setup_endoreg_db.py +218 -33
  6. endoreg_db/models/media/pdf/raw_pdf.py +241 -97
  7. endoreg_db/models/media/video/pipe_1.py +30 -33
  8. endoreg_db/models/media/video/video_file.py +300 -187
  9. endoreg_db/models/medical/hardware/endoscopy_processor.py +10 -1
  10. endoreg_db/models/metadata/model_meta_logic.py +34 -45
  11. endoreg_db/models/metadata/sensitive_meta_logic.py +555 -150
  12. endoreg_db/serializers/__init__.py +26 -55
  13. endoreg_db/serializers/misc/__init__.py +1 -1
  14. endoreg_db/serializers/misc/file_overview.py +65 -35
  15. endoreg_db/serializers/misc/{vop_patient_data.py → sensitive_patient_data.py} +1 -1
  16. endoreg_db/serializers/video_examination.py +198 -0
  17. endoreg_db/services/lookup_service.py +228 -58
  18. endoreg_db/services/lookup_store.py +174 -30
  19. endoreg_db/services/pdf_import.py +585 -282
  20. endoreg_db/services/video_import.py +493 -240
  21. endoreg_db/urls/__init__.py +36 -23
  22. endoreg_db/urls/label_video_segments.py +2 -0
  23. endoreg_db/urls/media.py +103 -66
  24. endoreg_db/utils/setup_config.py +177 -0
  25. endoreg_db/views/__init__.py +5 -3
  26. endoreg_db/views/media/pdf_media.py +3 -1
  27. endoreg_db/views/media/video_media.py +1 -1
  28. endoreg_db/views/media/video_segments.py +187 -259
  29. endoreg_db/views/pdf/__init__.py +5 -8
  30. endoreg_db/views/pdf/pdf_stream.py +186 -0
  31. endoreg_db/views/pdf/reimport.py +110 -94
  32. endoreg_db/views/requirement/lookup.py +171 -287
  33. endoreg_db/views/video/__init__.py +0 -2
  34. endoreg_db/views/video/video_examination_viewset.py +202 -289
  35. {endoreg_db-0.8.3.3.dist-info → endoreg_db-0.8.6.5.dist-info}/METADATA +1 -2
  36. {endoreg_db-0.8.3.3.dist-info → endoreg_db-0.8.6.5.dist-info}/RECORD +38 -37
  37. endoreg_db/views/pdf/pdf_media.py +0 -239
  38. endoreg_db/views/pdf/pdf_stream_views.py +0 -127
  39. endoreg_db/views/video/video_media.py +0 -158
  40. {endoreg_db-0.8.3.3.dist-info → endoreg_db-0.8.6.5.dist-info}/WHEEL +0 -0
  41. {endoreg_db-0.8.3.3.dist-info → endoreg_db-0.8.6.5.dist-info}/licenses/LICENSE +0 -0
@@ -18,13 +18,14 @@ endoreg_db/config/env.py,sha256=S244AQRkDP0PpP0MPaShgqeBJgI1BQknfER1_vUFMD4,2673
18
18
  endoreg_db/data/__init__.py,sha256=Wqu24f5-FVKE5pis0wGDYsMHOTkieN40b10S5zU5240,5932
19
19
  endoreg_db/data/db_summary.csv,sha256=K4PcufVHQ64H1i2MbCShMxReEa96I8cL6IfwCVpqF2M,1225
20
20
  endoreg_db/data/db_summary.xlsx,sha256=pwsc_IcxNETNrYjDXjpSW83b8f-WsSunRDiJLZXENZ0,5829
21
+ endoreg_db/data/setup_config.yaml,sha256=ZlL_DwHNqdulPzfZzNDlsMEHC9hSrZZ3Ri9OUDJKXn8,1301
21
22
  endoreg_db/data/ai_model/data.yaml,sha256=9XIRMS_meioGu-vYY6zUvz4RUXhRLdalaHhCTdaq4nA,306
22
23
  endoreg_db/data/ai_model_label/label/data.yaml,sha256=qkt0FfrLvPrcW_N0GUzu3q9TpiXrvZU047xAIOk_33A,1737
23
24
  endoreg_db/data/ai_model_label/label/polyp_classification.yaml,sha256=lHx2VwwVgKzOM_3PcuHuSIStgvMK6rHVi3WP67Qjv70,936
24
25
  endoreg_db/data/ai_model_label/label-set/data.yaml,sha256=ocaxnkqiZgwi4sY561TbP_DEQWkPG1hBZ3olwPOqiXQ,789
25
26
  endoreg_db/data/ai_model_label/label-set/polyp_classifications.yaml,sha256=GVmctJCgnr2lPUMttgPThNXoLcUl4XpliiuSjvE6h_Q,443
26
27
  endoreg_db/data/ai_model_label/label-type/data.yaml,sha256=vffKYpTae_gu63_wza6LONs5ys4pna1EbrUUO6CafQs,136
27
- endoreg_db/data/ai_model_meta/default_multilabel_classification.yaml,sha256=JhrFP6WXSFRa4kKujKAtgNVmnFYMiz8-J_oN-JQsSi0,182
28
+ endoreg_db/data/ai_model_meta/default_multilabel_classification.yaml,sha256=VelCJXavWT4HYbPko1S8O1gv7wBZBsvz6r5FvjXTm2o,1196
28
29
  endoreg_db/data/ai_model_type/data.yaml,sha256=vCMMo8wiI5uL2zrQROmgsHq1GrC8IdagGIgNdQunUeQ,149
29
30
  endoreg_db/data/ai_model_video_segmentation_label/base_segmentation.yaml,sha256=EZ83vq02Cf2KfflWQ4HEe1NHmuzSCsmKtWW5Bv8jet0,4060
30
31
  endoreg_db/data/ai_model_video_segmentation_labelset/data.yaml,sha256=07uB1ousJVNpp8B9enJ_YIdZf3y4sBPlME4bZwDv6ho,404
@@ -248,7 +249,7 @@ endoreg_db/management/__init__.py,sha256=3dsK9Mizq1veuWTcvSOyWMFT9VI8wtyk-P2K9Ri
248
249
  endoreg_db/management/commands/__init__.py,sha256=Ch0jwQfNpOSr4O5KKMfYJ93dsesk1Afb-JtbRVyFXZs,21
249
250
  endoreg_db/management/commands/anonymize_video.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
250
251
  endoreg_db/management/commands/check_auth.py,sha256=TPiYeCZ5QcqIvR33xhbqXunO2nrcNAmHb_izoMTqgpg,5390
251
- endoreg_db/management/commands/create_model_meta_from_huggingface.py,sha256=RUuoBjTzdchuMY6qcwBENN7FTyTygPTZQBZYWwhugDc,3925
252
+ endoreg_db/management/commands/create_model_meta_from_huggingface.py,sha256=NeTAl35RLI4Fad5V1W3ohyzuOl0LEzevlVRyLLeXrJM,3881
252
253
  endoreg_db/management/commands/create_multilabel_model_meta.py,sha256=qeoyqcF2CWcnhniVRrlYbmJmwNwyZb-VQ0pjkr6arJU,7566
253
254
  endoreg_db/management/commands/fix_missing_patient_data.py,sha256=5TPUTOQwI2fVh3Zd88o4ne0R8N_V98k0GZsI1gW0kGM,7766
254
255
  endoreg_db/management/commands/fix_video_paths.py,sha256=7LLwc38oX3B_tYWbLJA43Li_KBO3m5Lyw0CF6YqN5rU,7145
@@ -257,7 +258,7 @@ endoreg_db/management/commands/import_report.py,sha256=vFst-NeQdL-w62yoH4kDamq-2
257
258
  endoreg_db/management/commands/import_video.py,sha256=AMvgi1eN0F_hjhgnNNYIFkJtHfjalBfh2lfDxw6VTzE,17980
258
259
  endoreg_db/management/commands/import_video_with_classification.py,sha256=ulZH5jvAWu_pJ1kI9B3hbIO1-p_BReY0zbIQDS_d9OI,14726
259
260
  endoreg_db/management/commands/init_default_ai_model.py,sha256=98yBigGZ5gkA-b1LPcvzS5x2jAms3pX58fU-TEAcjKw,4669
260
- endoreg_db/management/commands/load_ai_model_data.py,sha256=QDyWPjIC1ga13Ou67_mnE8HUGTAK0uF2LLQ12sE-95E,2747
261
+ endoreg_db/management/commands/load_ai_model_data.py,sha256=ba2z-0qWtweUC6iYyiusH3xGDkpkYNNlIjei3QK7YAA,2887
261
262
  endoreg_db/management/commands/load_ai_model_label_data.py,sha256=jnm2720TsnRTBKF6guwnjLo7sropW_YoRjgyjo1TUr8,2143
262
263
  endoreg_db/management/commands/load_base_db_data.py,sha256=0Go2cYbqfx6MBSeQaHPAq22yeJxOyX25xpmcBcE9Auw,9374
263
264
  endoreg_db/management/commands/load_center_data.py,sha256=GQpbe7dxgbTgd66oBqrBXax-os3ibnPmCeSEFDVauPU,2570
@@ -290,7 +291,7 @@ endoreg_db/management/commands/load_unit_data.py,sha256=tcux-iL-ByT2ApgmHEkLllZS
290
291
  endoreg_db/management/commands/load_user_groups.py,sha256=D7SK2FvZEHoE4TIXNGCjDw5_12MH9bpGZvoS7eEv0Os,1031
291
292
  endoreg_db/management/commands/register_ai_model.py,sha256=KixTfuQR6TUfRmzB5GOos16BFOz7NL4TzLzBkgtPPgE,2510
292
293
  endoreg_db/management/commands/reset_celery_schedule.py,sha256=U-m_FNRTw6LAwJoT9RUE4qrhmQXm7AyFToPcHYyJpIE,386
293
- endoreg_db/management/commands/setup_endoreg_db.py,sha256=_mJkNB2IZNcgDQkOExUTkmmjp9qMwEiZH2KEJcyCi_Y,8635
294
+ endoreg_db/management/commands/setup_endoreg_db.py,sha256=vwjb5jH1oBNXtLpPrthbnP1WcwXPgBMoO4K2ZMH5dEI,17886
294
295
  endoreg_db/management/commands/start_filewatcher.py,sha256=3jESBqRiYPa9f35--zd70qQaYnyT0tzRO_b_HJuyteQ,4093
295
296
  endoreg_db/management/commands/storage_management.py,sha256=NpToX59ndwTFNmnSoeppmiPdMvpjSHH7mAdIe4SvUoI,22396
296
297
  endoreg_db/management/commands/summarize_db_content.py,sha256=pOIz3qbY4Ktmh0zV_DKFx971VD0pPx027gCD7a47EL0,10766
@@ -379,17 +380,17 @@ endoreg_db/models/media/__init__.py,sha256=WuomOKk-3kNGDLKoLO_ltnXbo028JDVlCCScd
379
380
  endoreg_db/models/media/frame/__init__.py,sha256=25WriZHocR82rbHr_IMIgBt5z-mkV2O0LVWUpJRnQ5E,45
380
381
  endoreg_db/models/media/frame/frame.py,sha256=6BvNKTAGsC_Q0S27nrvZ2cySDy3LSu5HCxrNcZwIEsA,4408
381
382
  endoreg_db/models/media/pdf/__init__.py,sha256=1fimtZK5LUuP_yqETN6pMj0hxKXuQqeLb1DP5wPmtT4,343
382
- endoreg_db/models/media/pdf/raw_pdf.py,sha256=sBm5C1Pr4N4n8oQw_nNMLN5cnl3efQ-WKWby2_xBauk,26185
383
+ endoreg_db/models/media/pdf/raw_pdf.py,sha256=aUOGyqFAMcOdfPE_BDGM1_e9vk_YQvZgNcXoSxOR2sg,29963
383
384
  endoreg_db/models/media/pdf/report_file.py,sha256=6Vt_TJSB3qaF26qXbyjRSn-s_zN5y4e-PPrN8ZbYS9s,4296
384
385
  endoreg_db/models/media/pdf/report_reader/__init__.py,sha256=LiMooVstXRay5qcB-uZW0wxbcdUvPrfAs_xBwWiuuWc,166
385
386
  endoreg_db/models/media/pdf/report_reader/report_reader_config.py,sha256=wYVDmPSmNIuCTpaaWqoLVgVZFYW-dqGpnAyVBqRLqXE,3445
386
387
  endoreg_db/models/media/pdf/report_reader/report_reader_flag.py,sha256=j9tjbLRenxpWfeaseALl8rV2Dqem9YaM_duS1iJkARU,536
387
388
  endoreg_db/models/media/video/__init__.py,sha256=ifW4SXXN2q6wAuFwSP7XlYskpX7UX6uy0py5mpCCOCM,211
388
389
  endoreg_db/models/media/video/create_from_file.py,sha256=3n4bbzFteEOFDUuEikP0x-StCKI5R5IhyKC7o3kLZ6Y,15128
389
- endoreg_db/models/media/video/pipe_1.py,sha256=yUzTi0pkw2ISsOoFpLmNky6S_V-TEWMxXmPLfB7gUpA,9899
390
+ endoreg_db/models/media/video/pipe_1.py,sha256=ljO3vO2mqqTXLZsKjzMTC6-sW4JRWMVRfJcK0n5CjKg,9740
390
391
  endoreg_db/models/media/video/pipe_2.py,sha256=DnMxW0uOqSsf7-0n9Rlvn7u89U4Jpkv7n6hFpQfUjkQ,4964
391
392
  endoreg_db/models/media/video/refactor_plan.md,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
392
- endoreg_db/models/media/video/video_file.py,sha256=txlxR8d1OBgt3UEkWvLcGSyLarh0jXLw-z0SAV5KOok,26789
393
+ endoreg_db/models/media/video/video_file.py,sha256=VFRgP1QRtuxzE9l74tCW7Kz5leHdv5d5i3aqtH3Y1vA,30281
393
394
  endoreg_db/models/media/video/video_file_ai.py,sha256=3ABea52FOF1qlrlxHdYhz_M3Kmqfzqtgq7M0prl-FAo,18819
394
395
  endoreg_db/models/media/video/video_file_anonymize.py,sha256=pet1UfSsbSHJJZxq6gDPifAfBWpGyEpD1jEQuSQi0Gg,16027
395
396
  endoreg_db/models/media/video/video_file_frames.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -435,7 +436,7 @@ endoreg_db/models/medical/finding/finding_intervention.py,sha256=FBwjI15yitMpTXk
435
436
  endoreg_db/models/medical/finding/finding_type.py,sha256=ohDEmLcgEpYjG5q0uhCaq2xQS8jH_rj4qyKQ2DUumqQ,1117
436
437
  endoreg_db/models/medical/hardware/__init__.py,sha256=uX2-UpBzX2chpZEeCyqbv2BSrv3OZNG9PrB8sHEWpHQ,178
437
438
  endoreg_db/models/medical/hardware/endoscope.py,sha256=8T8R2Bo2T29psQ3C_HTrhBogN8hiysuZkJOxUefqGoI,1657
438
- endoreg_db/models/medical/hardware/endoscopy_processor.py,sha256=DLKMXPWValfJCf4rZ1u6PdpeBa2ST0WTjkcuruFlzG0,6201
439
+ endoreg_db/models/medical/hardware/endoscopy_processor.py,sha256=9HMTgODfJo36gDg4N3QtcH3_NOriOanwYMtIPTlULVk,6626
439
440
  endoreg_db/models/medical/laboratory/__init__.py,sha256=595XF1ikkwzQWbUsyasU23v1kDRugrgTp3eUfrMd0UQ,62
440
441
  endoreg_db/models/medical/laboratory/lab_value.py,sha256=uw4mjguVrqvsxQ-NzGO0DoNlSCaydI8KaJgUhuM16wo,20258
441
442
  endoreg_db/models/medical/medication/__init__.py,sha256=BHh6ARvm2uVNswN12EQAEMFPnoGBiVwl7RCjKrW6C2I,761
@@ -464,10 +465,10 @@ endoreg_db/models/medical/risk/risk_type.py,sha256=kEugcaWSTEWH_Vxq4dcF80Iv1L4_K
464
465
  endoreg_db/models/metadata/__init__.py,sha256=8I6oLj3YTmeaPGJpL0AWG5gLwp38QzrEggxSkTisv7c,474
465
466
  endoreg_db/models/metadata/frame_ocr_result.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
466
467
  endoreg_db/models/metadata/model_meta.py,sha256=F_r-PTLeNi4J-4EaGCQkGIguhdl7Bwba7_i56ZAjc-4,7589
467
- endoreg_db/models/metadata/model_meta_logic.py,sha256=6w1YX8hVq40UXbVN1fvDO9OljwekBZaDVHEjVZecoV8,12252
468
+ endoreg_db/models/metadata/model_meta_logic.py,sha256=vAbNDaoZygH8xOCulWlXoHoR1T0BSvr9kIloxjzhfjo,12533
468
469
  endoreg_db/models/metadata/pdf_meta.py,sha256=BTmpSgqxmPKi0apcNjyrZAS4AFKCPXVdBd6VBeyyv6E,3174
469
470
  endoreg_db/models/metadata/sensitive_meta.py,sha256=ekLHrW-b5uYcjfkRd0EW5ncx5ef8Bu-K6msDkpWCAbk,13034
470
- endoreg_db/models/metadata/sensitive_meta_logic.py,sha256=Oh7ssZQEPfKGfRMF5nXKJpOIxXx-Xibd3rpOu-bQilk,29988
471
+ endoreg_db/models/metadata/sensitive_meta_logic.py,sha256=FRkBX_EgR2cfXO2_7TzllyceJJgU2lfGPkGsPGiLF2E,43119
471
472
  endoreg_db/models/metadata/video_meta.py,sha256=c6xWdLW3uNqJ5VPJXHCxXA3mbXw-b0uR54-TOS3qL2Q,14966
472
473
  endoreg_db/models/metadata/video_prediction_logic.py,sha256=j5N82mHtiomeeIaf1HA65kT5d0htQfJmbI2bJb8mpxQ,7677
473
474
  endoreg_db/models/metadata/video_prediction_meta.py,sha256=EyfctAAAVcW9L0gf76ZBc9-G8MLMcD-tc2kkjaaLH4w,10592
@@ -516,10 +517,11 @@ endoreg_db/queries/sanity/__init_.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZ
516
517
  endoreg_db/schemas/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
517
518
  endoreg_db/schemas/examination_evaluation.py,sha256=G6uBSQf9ZclwnGvMI-xVPd4IzD6GORUHYYRRCr5Qp6k,844
518
519
  endoreg_db/serializers/Frames_NICE_and_PARIS_classifications.py,sha256=q06UKC0Nt4sOJphwN9lEaY28ZAvtcMAlOwT5Zq_sblI,31384
519
- endoreg_db/serializers/__init__.py,sha256=DFcJPYKdCKHgfB8emktMyAWa9nArjzEqRsy0IXLagS8,3386
520
+ endoreg_db/serializers/__init__.py,sha256=LryzaMvorz_qacOnaT8Uu10L8KHHQRtLVaWU-nlQ43g,3589
520
521
  endoreg_db/serializers/anonymization.py,sha256=R5hlk6KiHpQ2JshKlFq5gY6Ed4TrarA74hlvll9w-4s,2576
521
522
  endoreg_db/serializers/examination_serializer.py,sha256=JPI9diMup9e-nSCH6UwU9KulnSKreg6pOwjKCLHWJfs,281
522
523
  endoreg_db/serializers/sensitive_meta_serializer.py,sha256=zF_0HOrdhi9714DExVD1DTsQqDbRIJevkjLU4vZEgYE,10748
524
+ endoreg_db/serializers/video_examination.py,sha256=jotR5PNTA_xEMpqsqdP3PFaie8TO7SGv2Vp18sj8TlY,6937
523
525
  endoreg_db/serializers/_old/raw_pdf_meta_validation.py,sha256=hZaPTY4AA4wO7uAA0-DKLueHwtqnNsJqFR8Apdv6wTk,7608
524
526
  endoreg_db/serializers/_old/raw_video_meta_validation.py,sha256=Owku2MmHjEZR_FpgKUdaG9In9IRwur53NmhJdser9Bs,7542
525
527
  endoreg_db/serializers/_old/video.py,sha256=O7PIt7uJNP5Xy9R9tbWuptCcsrm1dV0382_ymyVgl5w,2634
@@ -556,12 +558,12 @@ endoreg_db/serializers/meta/sensitive_meta_detail.py,sha256=1i-9Osl9vBH7_KObdm8B
556
558
  endoreg_db/serializers/meta/sensitive_meta_update.py,sha256=qy7cM2MhQUJST9YcEXuyYmL8oX4kkKCIcyiz2nXHo-g,5591
557
559
  endoreg_db/serializers/meta/sensitive_meta_verification.py,sha256=gXH2RfJtVPSgnA3Z58FU6kxTZs6vBI14EEZT7lx2NFE,2289
558
560
  endoreg_db/serializers/meta/video_meta.py,sha256=g96J4va5_oIg7rbbVqcyBsy8imgmbiHjysuEEtas0cA,1284
559
- endoreg_db/serializers/misc/__init__.py,sha256=iO8DlpYe5GUIcd4rpHUUzfMt604V8BcoKc4d3YX_WvQ,483
560
- endoreg_db/serializers/misc/file_overview.py,sha256=DsKFBCgGUIrDo5b4879pGBnw1GL8bilr3Pe7xh2lH9I,7210
561
+ endoreg_db/serializers/misc/__init__.py,sha256=MfG55Bb9sNBajmt-QkTOg1qFNSOEFQ6RWHIA_DVtneE,489
562
+ endoreg_db/serializers/misc/file_overview.py,sha256=ImOTX4a_zjboVyQs2IHBFNqhEfZWDvgcrx1bf2XpL2w,7395
563
+ endoreg_db/serializers/misc/sensitive_patient_data.py,sha256=cewApBYKsk0s9T7CGY_FJmuXAYs3hJV3Ra7oYazKndk,5831
561
564
  endoreg_db/serializers/misc/stats.py,sha256=iL8iZseOLeLaoaCDF3MtTQBH3b0yX5ZFkrZbq5MiMGM,1255
562
565
  endoreg_db/serializers/misc/translatable_field_mix_in.py,sha256=ZH8ZUE1-No0DLCcIGk445c00jQcX7M6Yldxik-FaGfg,1724
563
566
  endoreg_db/serializers/misc/upload_job.py,sha256=e8rXbgs7lkh-NAswLBV2pkEngWdfqHmJcIqS1fM0bJY,2306
564
- endoreg_db/serializers/misc/vop_patient_data.py,sha256=DHsp8Uc4ZqvxQMlWG3gVtLjxoA-U8eLu51g-yQLA5AY,5823
565
567
  endoreg_db/serializers/patient/__init__.py,sha256=ogQGq3jGnFP3L7gK9FbcJodhrzdR6_6xAM89sO9dZjM,185
566
568
  endoreg_db/serializers/patient/patient.py,sha256=8GlQw9a6zxhrieuzw0qf2Xryiuj64-Pe-jgYFdGlRdk,3072
567
569
  endoreg_db/serializers/patient/patient_dropdown.py,sha256=0hijgjMbgrUo78Em6hNqRMv5XdQJ42pTXmOZClSDtuQ,964
@@ -594,30 +596,30 @@ endoreg_db/services/__init__.py,sha256=CMLgpzemgjXvKN5HGFD_UVtRAg9XeMIfXvoSu-aUa
594
596
  endoreg_db/services/anonymization.py,sha256=iM-xW1aJm99G3PmkfZtMJmvoaj99c8OASP5-abBNcy0,8986
595
597
  endoreg_db/services/examination_evaluation.py,sha256=jx9IL2PIoBzjiITzs00c1XucE7Ab2LAUydNbErRmtTM,5943
596
598
  endoreg_db/services/finding_description_service.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
597
- endoreg_db/services/lookup_service.py,sha256=A2t07-qlQhFEeNvOhez0GU0sxi7mnN0MIlhYzxj4W1U,10581
598
- endoreg_db/services/lookup_store.py,sha256=8sB2HmJQrnzq5Vfqt-UdaJLHYMRZCxnui9BCCXscnJE,4856
599
- endoreg_db/services/pdf_import.py,sha256=_ll_Vng1SpI7mEKxNRYuNttVnehuJFpKjQGDB8OX7no,47133
599
+ endoreg_db/services/lookup_service.py,sha256=425eHruJ1JbLxiSiv0bTeVXKLoS0tqK74t70epDKj9o,16176
600
+ endoreg_db/services/lookup_store.py,sha256=k-dxq_0oocXJLzLPENmsvfxxN2whCJyCFPo_2wwIsD8,8962
601
+ endoreg_db/services/pdf_import.py,sha256=a-JwePNsXGZEYyVKHSm77K_Q9xoz5gThAbk4fVfotHI,54693
600
602
  endoreg_db/services/polling_coordinator.py,sha256=alnPB-kdMyxbYaxQN9fki9dKrwmAsY3s68bUHWDSNeI,10662
601
603
  endoreg_db/services/pseudonym_service.py,sha256=CJhbtRa6K6SPbphgCZgEMi8AFQtB18CUoBDttFnxEoM,3126
602
604
  endoreg_db/services/requirements_object.py,sha256=290zf8AEbVtCoHhW4Jr7_ud-RvrqYmb1Nz9UBHtTnc0,6164
603
605
  endoreg_db/services/segment_sync.py,sha256=YgHvIHkbW4mqCu0ACf3zjRSZnNfxWwt4gh5syUVXuE0,6400
604
606
  endoreg_db/services/storage_aware_video_processor.py,sha256=kKFK64vXLeBSVkp1YJonU3gFDTeXZ8C4qb9QZZB99SE,13420
605
- endoreg_db/services/video_import.py,sha256=gDuVTW5WUYGSc0m5ly67cc10YpnTpBkxO7uOEcRa3Ok,45663
607
+ endoreg_db/services/video_import.py,sha256=mtEQlHq-n5x-PE1w8CpeCNnkmKpLhbjWflqtK43nBlw,52237
606
608
  endoreg_db/tasks/upload_tasks.py,sha256=OJq7DhNwcbWdXzHY8jz5c51BCVkPN5gSWOz-6Fx6W5M,7799
607
609
  endoreg_db/tasks/video_ingest.py,sha256=kxFuYkHijINV0VabQKCFVpJRv6eCAw07tviONurDgg8,5265
608
610
  endoreg_db/tasks/video_processing_tasks.py,sha256=rZ7Kr49bAR4Q-vALO2SURebrhcJ5hSFGwjF4aULrOao,14089
609
611
  endoreg_db/templates/timeline.html,sha256=H9VXKOecCzqcWWkpNIZXFI29ztg-oxV5uvxMglgoClk,6167
610
612
  endoreg_db/templates/admin/patient_finding_intervention.html,sha256=F3JUKm3HhWIf_xoZZ-SET5d5ZDlm2jMM8g909w1dnYc,10164
611
613
  endoreg_db/templates/admin/start_examination.html,sha256=3K4wirul9KNyB5mN9cpfCSCAyAD6ro19GwxFOY5sZ3A,267
612
- endoreg_db/urls/__init__.py,sha256=xR1QnSBY0mdUUJ8Wkf71063in59ZEKIFgoaw3Ak76Ow,2973
614
+ endoreg_db/urls/__init__.py,sha256=YpT06IceApAkWfQvNmqMku8F_vozWD4UDl6j3BamS_I,3303
613
615
  endoreg_db/urls/anonymization.py,sha256=zLoOOpu4XSha002nOi0fiJUAT8Dff7u7RQFtdU4A6aw,1853
614
616
  endoreg_db/urls/auth.py,sha256=t95D8n3fiOhkUiINVGygrW0jiQiJc_XNmfk2S8pcDxk,440
615
617
  endoreg_db/urls/classification.py,sha256=2JdHsCSpLs5bZWiTsDpWvyLE_OJkf7LrCCOob7H8M-k,1802
616
618
  endoreg_db/urls/examination.py,sha256=IWNIR-hsWKD3nfL27EzMMazcZnOa_imjgk8RL0mql2U,2344
617
619
  endoreg_db/urls/files.py,sha256=qfa8mPDNF9SW4z66B26SCtX7WHyoAo1muS1DR2QwST8,192
618
620
  endoreg_db/urls/label_video_segment_validate.py,sha256=bGWacxIG4pHnGRbnHL_L91ShKWfKCn5X-YXsHGs6i-I,1044
619
- endoreg_db/urls/label_video_segments.py,sha256=Hjc__HjohZnNE-oudqBc_uOIHqiSbQ_zpN4aHzGYRuE,1142
620
- endoreg_db/urls/media.py,sha256=ufFP3GL3fpxYUSlFJfIfg1L6pmUcC_Blao46G3PsEPQ,10699
621
+ endoreg_db/urls/label_video_segments.py,sha256=Xj7Gf-JSq5iB3ubit5aCaLMJcgQXgDmqMSCb-n-CIl8,1144
622
+ endoreg_db/urls/media.py,sha256=zAlnosi_KGv8lo--xv-3uhRcy5hXT8geJ7mOsJ3J0z8,11178
621
623
  endoreg_db/urls/patient.py,sha256=VLKFbEiNgpfYLWFisbHidyoUnoQuEzj1U0SgZDpdPDM,588
622
624
  endoreg_db/urls/report.py,sha256=9i3sOSofB7_PHGByr3DMghZFtcbjKf_U5PVSlxu9d4I,1917
623
625
  endoreg_db/urls/requirements.py,sha256=5d-SD_7nsTA9YXlBeWdZuh-mXh26BkgH29fFBaTLjU8,455
@@ -644,6 +646,7 @@ endoreg_db/utils/parse_and_generate_yaml.py,sha256=k7y0fl9Jbb_LNryeJYd6tebklRlu1
644
646
  endoreg_db/utils/paths.py,sha256=ncXtB_l6FBVXXdk59U7v4FhSvLO7Yb0DQ-GQMcOqiTw,3398
645
647
  endoreg_db/utils/permissions.py,sha256=IqxG9IqJBSZuxvT1ItVgGS8fMzkA2OLdDV6y8mKHSuo,5096
646
648
  endoreg_db/utils/requirement_helpers.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
649
+ endoreg_db/utils/setup_config.py,sha256=yeDPStTEJm8Xy6ah5AJTpXMoPUyouxuPIsRUpqdiXf4,6775
647
650
  endoreg_db/utils/translation.py,sha256=77Xel12pAGo0rQ0NxB7nfejvMb0GBjEmhC3I7mcU91I,1256
648
651
  endoreg_db/utils/uuid.py,sha256=T4HXqYtKwXFqE5kPyvlgWHyllBBF6LL6N48nl9TpwBk,53
649
652
  endoreg_db/utils/validate_endo_roi.py,sha256=Ct2H0JJW9gxYZc7099NYee4kxdKL90a3LGYahqibwms,925
@@ -680,7 +683,7 @@ endoreg_db/utils/video/names.py,sha256=m268j2Ynt94OYH6dYxeL8gzU5ODtFJD4OmzS7l0nB
680
683
  endoreg_db/utils/video/streaming_processor.py,sha256=C-39DtxhSnL7B2cObFE5k829VLXl_Fl0KQFrFP368JA,13747
681
684
  endoreg_db/utils/video/video_splitter.py,sha256=EZEnhNjaUva_9VxjcjScgRSrxsEuifhBjlwIMLX1qaA,3698
682
685
  endoreg_db/views/Frames_NICE_and_PARIS_classifications_views.py,sha256=Lu1JuUD44B6yUAR9pcYLlQ-3g66VTktmzStuO0uGIj4,8752
683
- endoreg_db/views/__init__.py,sha256=L1xXouAYYqIK7zXDvA6qhcEv7gs5b7wc3g8HeFCVFWU,6553
686
+ endoreg_db/views/__init__.py,sha256=HAQ9leXNixe7AAB8LG6k9TqPp1OxI_XJc0javkCSDNI,6589
684
687
  endoreg_db/views/anonymization/__init__.py,sha256=s1_r9j0jPJsKHy1-isjFAlRF3Cw0o8EXxyUP7Xv1Kqo,698
685
688
  endoreg_db/views/anonymization/media_management.py,sha256=ObiXjPa-KsSGs3IfmABE-TVzQZ2U6yJioFh64T7TtKY,16799
686
689
  endoreg_db/views/anonymization/overview.py,sha256=fA4a4tZ4tbnWf3BUP6heAtqmHvinixUnDoI3dqPjTE0,8320
@@ -714,11 +717,11 @@ endoreg_db/views/label_video_segment/label_video_segment_detail.py,sha256=gs1llC
714
717
  endoreg_db/views/label_video_segment/update_lvs_from_annotation.py,sha256=an3Bf4Jxap_vZrHW2XZV72fKkQhP3S2fsB3ZjXRjED8,1599
715
718
  endoreg_db/views/label_video_segment/validate.py,sha256=1R7Ml-XgzZmzooYbPEnIkjm-u6rlvH-Yu5XGulhZEpI,8951
716
719
  endoreg_db/views/media/__init__.py,sha256=JRRICKlyxrVQqN3ORM8WoJzVo2iRq6Mr72d-1REsM0k,1282
717
- endoreg_db/views/media/pdf_media.py,sha256=VqW4jI_PzQklf07SOM7kRhin_6SfZFhCzELDS-4naYY,14463
720
+ endoreg_db/views/media/pdf_media.py,sha256=0xUszgT7wbMQ5iW4ak4p_Xg78l1CMntsKqtnCLYp-EE,14573
718
721
  endoreg_db/views/media/segments.py,sha256=d995_pLD2W6zdrB3bL9bdHrwS22sZXeG19-SLNU38gU,2613
719
722
  endoreg_db/views/media/sensitive_metadata.py,sha256=CuIHLVGkjnBtWJHHERQvRApLzjkFbuRu-HBJEPqnhhQ,10456
720
- endoreg_db/views/media/video_media.py,sha256=wj848cz0qbWhTj8h4LRau_isYgwbn8TMV6yD3uL_0Ow,9640
721
- endoreg_db/views/media/video_segments.py,sha256=tYocxt3ZhQJ8GabTb34-4SFnyKVC71HdSahOfrBTj58,21795
723
+ endoreg_db/views/media/video_media.py,sha256=rt3DmuxHSH52yWW_r1t5ilq4DJ3w571IpUvyz5ilxz8,9632
724
+ endoreg_db/views/media/video_segments.py,sha256=N1gHYRI4Mdn74Amiv_gcuPessPDtXo65RdLTT70ZOOs,20027
722
725
  endoreg_db/views/meta/__init__.py,sha256=cMwPBx55ad5zRX9DILqFm-a_ATc5SRVSMEGyHTC5cOo,470
723
726
  endoreg_db/views/meta/available_files_list.py,sha256=CBaYVkj2YKB5n_J0gop0vXHkpgTE9Aamqt4tdCjTN2I,6181
724
727
  endoreg_db/views/meta/report_meta.py,sha256=oLFTQ5YCVoCKlcYfbiN89--_9drBhMLeW9Ck_tmq08E,1733
@@ -754,23 +757,22 @@ endoreg_db/views/patient_finding_location/__init__.py,sha256=RiUqJl22PkM2Iv6UcV8
754
757
  endoreg_db/views/patient_finding_location/pfl_create.py,sha256=eZEtj4ST_Ue3YURna_x04MUKAeAo3mv_wfcGGlVO07g,2971
755
758
  endoreg_db/views/patient_finding_morphology/__init__.py,sha256=Gw4REKbb14tlKGGf__XlS2Pi2ygA0iCh85LYIHndUy0,113
756
759
  endoreg_db/views/patient_finding_morphology/pfm_create.py,sha256=-OYTH7iHPuSrYxbUrF7fQ6aAC0ES6UhiQ_Qo7tZi7II,2998
757
- endoreg_db/views/pdf/__init__.py,sha256=N3fR1qX7xpt4LMFU0BmJxnHRGoG-nKezj9ifStWVt7M,188
758
- endoreg_db/views/pdf/pdf_media.py,sha256=Ox981PIOVPqhRwZUZ_nkuLZ3L91owZpOzYZRS06C94k,11055
759
- endoreg_db/views/pdf/pdf_stream_views.py,sha256=oLfV60lNAqn2eZgbkRxuoVftDphTYHiSoZaqfX2pcl4,5495
760
- endoreg_db/views/pdf/reimport.py,sha256=GNUUFJS56qaegbhCdD4t3ytdp-EGPb5mRvq6BSe5QQ4,6902
760
+ endoreg_db/views/pdf/__init__.py,sha256=bmDbvDLRmhOYTuPHMMaJMJU67js9t_K6Df987wRs4wU,135
761
+ endoreg_db/views/pdf/pdf_stream.py,sha256=rI0f5P4c91A01hp8SK3rxgjgdX5Zgr73LUk9mQg5TrQ,7403
762
+ endoreg_db/views/pdf/reimport.py,sha256=9tMIsxZ5R83rC-GBcJt78QBLqmYaEBypFd6ToEeTsfk,6939
761
763
  endoreg_db/views/report/__init__.py,sha256=mw1WncSWijE73mSzkZPWsQ66ii9icZMLmEEEx9iV4BA,241
762
764
  endoreg_db/views/report/report_list.py,sha256=Ziav43FKYux2dsETaX7zUYs-g7__4laHwXEMZSq1Ahs,3940
763
765
  endoreg_db/views/report/report_with_secure_url.py,sha256=vMGgngPGvNkPYxhNjSJG6rZKN0yuSoJNl1vZPiAoh6I,1042
764
766
  endoreg_db/views/report/start_examination.py,sha256=iYC_40S4aJEGsel1Y4boZFAR5UQTPKp9TIWW3oJwgTc,224
765
767
  endoreg_db/views/requirement/__init__.py,sha256=dJzmbtO5-fLyzY3hfV3XHi6BbwElv_cF6R0TpsIaRJw,159
766
768
  endoreg_db/views/requirement/evaluate.py,sha256=_P5b6DoJBOnsGtIzL3usR2tTG1GXBRgsvG0LzQ9f9_A,10666
767
- endoreg_db/views/requirement/lookup.py,sha256=rxZ4zH122QLj32q8pzCe1dsp8YRpwcamqgmvGI3NdeM,8816
769
+ endoreg_db/views/requirement/lookup.py,sha256=BNR7Ai6QdPvdfSYZWMRTzwO8dLvVDuxoqD4YHi3LbaM,12544
768
770
  endoreg_db/views/requirement/lookup_store.py,sha256=LyohEAfHtPy40zDuJUDyN4S02BB_AOAbPM_CZIcHHRQ,4922
769
771
  endoreg_db/views/requirement_lookup/lookup.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
770
772
  endoreg_db/views/requirement_lookup/lookup_store.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
771
773
  endoreg_db/views/stats/__init__.py,sha256=VHxrW0-RAWYki_89jWWJ0TrD7Nb0D3m-VjYV6bvP2k4,259
772
774
  endoreg_db/views/stats/stats_views.py,sha256=v9ue1BKXdcApOgyolgNiT3hazx1xSVVvo26r91IozWY,8656
773
- endoreg_db/views/video/__init__.py,sha256=wRYF-M3amwlmTRlJ7nAYQZiwS0QgLLPxH3pPtHSQy-A,1288
775
+ endoreg_db/views/video/__init__.py,sha256=KXne9Hcg_rhWogmnmf_ZpbrpnNfJlhwbF0cqBXhYCEY,1196
774
776
  endoreg_db/views/video/correction.py,sha256=VEzpnDPCAhsYatXVRZhGZA5FpFS_t9mENs89zFJsoYo,19750
775
777
  endoreg_db/views/video/reimport.py,sha256=gSDBQ_Bam2xpJIj1SIMoLKnoBDBRgQ9V_TZdK9OICrI,8959
776
778
  endoreg_db/views/video/segmentation.py,sha256=jzsLB95rYnHALSX2E_QNpAM9BpE1pbteOBxcAr_EjZo,11758
@@ -780,13 +782,12 @@ endoreg_db/views/video/video_analyze.py,sha256=vxQHnXRFH5Y6IaWEmEnE4Svkz6Vjw1O9N
780
782
  endoreg_db/views/video/video_apply_mask.py,sha256=spGK4oXMAKhVotJuwZGndbKKws6klveKe35mbX7Rv6k,1630
781
783
  endoreg_db/views/video/video_correction.py,sha256=9mFICVvRSxp0WhGv7ib4d4M1hJs1iIhYmTl2OUIXQAg,767
782
784
  endoreg_db/views/video/video_download_processed.py,sha256=tp5llYJKyQD0WSr4Fvqi-YrgBw2EPPe23E8F8SZbR4w,2000
783
- endoreg_db/views/video/video_examination_viewset.py,sha256=77ujdUh8fzTC5Oe2fo4ESLBkwJ10rGhJLlQBpP1eMbQ,13663
784
- endoreg_db/views/video/video_media.py,sha256=fvMQmSM1a-3rxpx_wK0wee9sRXV3EZz2bF8jLRAeaIQ,7022
785
+ endoreg_db/views/video/video_examination_viewset.py,sha256=ej6CUK1JGFN7JmZOj25g1heaIIAwh6cf1HaYFmcR9EE,8331
785
786
  endoreg_db/views/video/video_meta.py,sha256=C1wBMTtQb_yzEUrhFGAy2UHEWMk_CbU75WXX_5z00sE,1021
786
787
  endoreg_db/views/video/video_processing_history.py,sha256=mhFuS8RG5GV8E-lTtuD0qrq-bIpnUFp8vy9aERfC-J8,770
787
788
  endoreg_db/views/video/video_remove_frames.py,sha256=2FmvNrSPM0fUXiBxINN6vBUUDCqDlBkNcGR3WsLDgKo,1696
788
789
  endoreg_db/views/video/video_stream.py,sha256=kLyuf0ORTmsLeYUQkTQ6iRYqlIQozWhMMR3Lhfe_trk,12148
789
- endoreg_db-0.8.3.3.dist-info/METADATA,sha256=anKqQ1fidx7S7ca0cWHU1UHEDNI67ujUV-RO4IGgr1g,14758
790
- endoreg_db-0.8.3.3.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
791
- endoreg_db-0.8.3.3.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
792
- endoreg_db-0.8.3.3.dist-info/RECORD,,
790
+ endoreg_db-0.8.6.5.dist-info/METADATA,sha256=P5cPs3gb-7jMn1oNYxxZNZ_8FUBQzVIJauyDx9JrXy4,14719
791
+ endoreg_db-0.8.6.5.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
792
+ endoreg_db-0.8.6.5.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
793
+ endoreg_db-0.8.6.5.dist-info/RECORD,,
@@ -1,239 +0,0 @@
1
- from django.http import FileResponse, Http404, StreamingHttpResponse
2
- import mimetypes
3
- import os
4
- import logging
5
- import re
6
- from ...models import RawPdfFile
7
- from ...serializers._old.raw_pdf_meta_validation import PDFFileForMetaSerializer, SensitiveMetaUpdateSerializer
8
- from rest_framework.views import APIView
9
- from rest_framework.response import Response
10
- from rest_framework import status
11
- from ...models import SensitiveMeta
12
- from django.views.decorators.clickjacking import xframe_options_sameorigin
13
- from django.utils.decorators import method_decorator
14
- from django.db import transaction
15
- from django.urls import reverse
16
- from django.utils.encoding import iri_to_uri
17
- from endoreg_db.utils.paths import PDF_DIR, STORAGE_DIR
18
- from .pdf_stream_views import ClosingFileWrapper
19
-
20
- logger = logging.getLogger(__name__)
21
- _RANGE_RE = re.compile(r"bytes=(\d+)-(\d*)")
22
-
23
- class PDFMediaView(APIView):
24
- """
25
- Unified API for PDFs to support frontend flows:
26
- - Without `id`: returns next PDF metadata (including anonymized_text) and stream URLs
27
- - With `id`: streams the PDF (original by default; `?variant=anonymized` for anonymized)
28
- - Integrates with Media Management expectations (clean deletion after validation is handled elsewhere)
29
- """
30
-
31
- def get(self, request):
32
- """
33
- Handles both:
34
- - Fetching PDF metadata (if `id` is NOT provided)
35
- - Streaming the actual PDF file (if `id` is provided)
36
- """
37
- pdf_id = request.GET.get("id")
38
- last_id = request.GET.get("last_id")
39
-
40
- if pdf_id:
41
- return self.serve_pdf_file(pdf_id)
42
- else:
43
- return self.fetch_pdf_metadata(last_id)
44
-
45
- def fetch_pdf_metadata(self, last_id):
46
- """
47
- Fetches the first or next available PDF metadata and provides stream URLs.
48
- """
49
- pdf_entry = PDFFileForMetaSerializer.get_next_pdf(last_id)
50
- if pdf_entry is None:
51
- return Response({"error": "No more PDFs available."}, status=status.HTTP_404_NOT_FOUND)
52
-
53
- serialized_pdf = PDFFileForMetaSerializer(pdf_entry, context={'request': self.request})
54
-
55
- # Build stream URLs pointing to this unified endpoint
56
- try:
57
- media_url = reverse('pdf_media')
58
- except Exception:
59
- media_url = "/api/pdf/media/"
60
- stream_url = f"{media_url}?id={pdf_entry.id}"
61
- anon_stream_url = f"{media_url}?id={pdf_entry.id}&variant=anonymized"
62
-
63
- data = dict(serialized_pdf.data)
64
- data.update({
65
- 'stream_url': iri_to_uri(self.request.build_absolute_uri(stream_url)),
66
- 'anonymized_stream_url': iri_to_uri(self.request.build_absolute_uri(anon_stream_url)),
67
- 'pdf_id': pdf_entry.id,
68
- 'has_anonymized': bool(getattr(pdf_entry, 'anonymized_file', None) and getattr(pdf_entry.anonymized_file, 'name', None)),
69
- })
70
- return Response(data, status=status.HTTP_200_OK)
71
-
72
- @method_decorator(xframe_options_sameorigin)
73
- def serve_pdf_file(self, pdf_id):
74
- """
75
- Streams the actual PDF file (original or anonymized) with Range support.
76
- Query param `variant=anonymized` selects anonymized file; default is original.
77
- """
78
- variant = (self.request.GET.get('variant') or 'original').lower()
79
- range_header = self.request.headers.get("Range")
80
-
81
- try:
82
- pdf_entry = RawPdfFile.objects.get(id=pdf_id)
83
- except RawPdfFile.DoesNotExist:
84
- return Response({"error": "Invalid PDF ID."}, status=status.HTTP_400_BAD_REQUEST)
85
-
86
- # Choose file according to variant
87
- file_field = None
88
- if variant == 'anonymized' and getattr(pdf_entry, 'anonymized_file', None):
89
- file_field = pdf_entry.anonymized_file
90
- else:
91
- file_field = pdf_entry.file
92
-
93
- if not file_field:
94
- return Response({"error": "PDF file not found."}, status=status.HTTP_404_NOT_FOUND)
95
-
96
- # Resolve path and attempt self-heal for originals
97
- try:
98
- file_path = file_field.path
99
- except Exception:
100
- file_path = None
101
-
102
- if not file_path or not os.path.exists(file_path):
103
- if variant != 'anonymized':
104
- # Try to self-heal original reference to sensitive storage
105
- sensitive_path = os.path.join(str(PDF_DIR), "sensitive", f"{pdf_entry.pdf_hash}.pdf")
106
- if os.path.exists(sensitive_path):
107
- try:
108
- relative_name = os.path.relpath(sensitive_path, str(STORAGE_DIR))
109
- if getattr(pdf_entry.file, 'name', None) != relative_name:
110
- pdf_entry.file.name = relative_name
111
- pdf_entry.save(update_fields=['file'])
112
- logger.info("Self-healed PDF file reference for ID %s -> %s", pdf_entry.id, pdf_entry.file.path)
113
- file_path = sensitive_path
114
- except Exception as e:
115
- logger.error("Failed to self-heal file path for PDF %s: %s", pdf_entry.id, e)
116
- file_path = sensitive_path
117
- # If still missing (or anonymized missing), fail
118
- if not file_path or not os.path.exists(file_path):
119
- raise Http404("PDF file not found on server.")
120
-
121
- # Prepare headers
122
- safe_filename = os.path.basename(getattr(file_field, 'name', None) or f"document_{pdf_id}.pdf")
123
- if not safe_filename.endswith('.pdf'):
124
- safe_filename += '.pdf'
125
-
126
- file_size = os.path.getsize(file_path)
127
-
128
- # Range support
129
- if range_header:
130
- match = _RANGE_RE.match(range_header)
131
- if match:
132
- start = int(match.group(1))
133
- end = int(match.group(2) or file_size - 1)
134
-
135
- if start < 0 or start >= file_size:
136
- raise Http404("Invalid range")
137
- if end >= file_size:
138
- end = file_size - 1
139
-
140
- chunk_size = end - start + 1
141
- try:
142
- fh = open(file_path, 'rb')
143
- fh.seek(start)
144
- resp = StreamingHttpResponse(
145
- ClosingFileWrapper(fh, blksize=8192),
146
- status=206,
147
- content_type="application/pdf",
148
- )
149
- resp["Content-Length"] = str(chunk_size)
150
- resp["Content-Range"] = f"bytes {start}-{end}/{file_size}"
151
- resp["Accept-Ranges"] = "bytes"
152
- resp["Content-Disposition"] = f'inline; filename="{safe_filename}"'
153
- return resp
154
- except (OSError, IOError) as e:
155
- logger.error(f"Error opening PDF file for range request: {e}")
156
- raise Http404("Error accessing PDF file")
157
-
158
- # Fallback: serve full file
159
- mime_type, _ = mimetypes.guess_type(file_path)
160
- try:
161
- fh = open(file_path, 'rb')
162
- response = FileResponse(fh, content_type=mime_type or "application/pdf")
163
- response["Content-Length"] = str(file_size)
164
- response["Accept-Ranges"] = "bytes"
165
- response["Content-Disposition"] = f'inline; filename="{safe_filename}"'
166
- return response
167
- except (OSError, IOError) as e:
168
- logger.error(f"Error opening PDF file: {e}")
169
- raise Http404("Error accessing PDF file")
170
-
171
- class UpdateSensitiveMetaView(APIView):
172
- """
173
- API endpoint to update patient details in the SensitiveMeta table.
174
- Handles partial updates (only edited fields) and raw file deletion after validation acceptance.
175
- """
176
-
177
- @transaction.atomic
178
- def patch(self, request, *args, **kwargs):
179
- """
180
- Updates the provided fields for a specific patient record.
181
- Only updates fields that are sent in the request.
182
- Automatically deletes raw PDF files when validation is accepted.
183
- """
184
- sensitive_meta_id = request.data.get("sensitive_meta_id")
185
-
186
- if not sensitive_meta_id:
187
- return Response({"error": "sensitive_meta_id is required."}, status=status.HTTP_400_BAD_REQUEST)
188
-
189
- try:
190
- sensitive_meta = SensitiveMeta.objects.get(id=sensitive_meta_id)
191
- except SensitiveMeta.DoesNotExist:
192
- return Response({"error": "Patient record not found."}, status=status.HTTP_404_NOT_FOUND)
193
-
194
- is_accepting_validation = request.data.get("is_verified", False)
195
- delete_raw_files = request.data.get("delete_raw_files", False)
196
- if is_accepting_validation:
197
- delete_raw_files = True
198
- logger.info(f"Validation accepted for PDF SensitiveMeta {sensitive_meta_id}, marking raw files for deletion")
199
-
200
- serializer = SensitiveMetaUpdateSerializer(sensitive_meta, data=request.data, partial=True)
201
-
202
- if serializer.is_valid():
203
- updated_sm = serializer.save()
204
- if delete_raw_files and updated_sm.is_verified:
205
- try:
206
- pdf_file = RawPdfFile.objects.filter(sensitive_meta=updated_sm).first()
207
- if pdf_file:
208
- self._schedule_raw_file_deletion(pdf_file)
209
- logger.info(f"Scheduled raw file deletion for PDF {pdf_file.id}")
210
- else:
211
- logger.warning(f"No PDF file found for SensitiveMeta {sensitive_meta_id}")
212
- except Exception as e:
213
- logger.error(f"Error scheduling raw file deletion for PDF SensitiveMeta {sensitive_meta_id}: {e}")
214
- return Response({"message": "Patient information updated successfully.", "updated_data": serializer.data}, status=status.HTTP_200_OK)
215
-
216
- return Response({"error": "Invalid data.", "details": serializer.errors}, status=status.HTTP_400_BAD_REQUEST)
217
-
218
- def _schedule_raw_file_deletion(self, pdf_file):
219
- """
220
- Schedule deletion of raw PDF file after validation acceptance.
221
- Deletes the original (sensitive) file but keeps anonymized_file for frontend.
222
- """
223
- try:
224
- def cleanup_raw_files():
225
- try:
226
- if pdf_file.file and getattr(pdf_file.file, 'path', None) and os.path.exists(pdf_file.file.path):
227
- logger.info(f"Deleting original (sensitive) PDF file: {pdf_file.file.path}")
228
- os.remove(pdf_file.file.path)
229
- pdf_file.file = None
230
- pdf_file.save(update_fields=['file'])
231
- logger.info(f"Successfully deleted original file for PDF {pdf_file.id}")
232
- else:
233
- logger.info(f"Original file already deleted or not found for PDF {pdf_file.id}")
234
- except Exception as e:
235
- logger.error(f"Error during raw file cleanup for PDF {pdf_file.id}: {e}")
236
- transaction.on_commit(cleanup_raw_files)
237
- except Exception as e:
238
- logger.error(f"Error scheduling raw file deletion for PDF {pdf_file.id}: {e}")
239
- raise
@@ -1,127 +0,0 @@
1
- import re
2
- import logging
3
- from django.http import FileResponse, StreamingHttpResponse, Http404
4
- from rest_framework.views import APIView
5
- from ...utils.permissions import EnvironmentAwarePermission
6
- from endoreg_db.models import RawPdfFile
7
- import os
8
- from django.views.decorators.clickjacking import xframe_options_sameorigin
9
-
10
- logger = logging.getLogger(__name__)
11
- _RANGE_RE = re.compile(r"bytes=(\d+)-(\d*)")
12
-
13
- class ClosingFileWrapper:
14
- """Custom file wrapper that ensures file is closed after streaming"""
15
- def __init__(self, file_handle, blksize=8192):
16
- self.file_handle = file_handle
17
- self.blksize = blksize
18
-
19
- def __iter__(self):
20
- return self
21
-
22
- def __next__(self):
23
- data = self.file_handle.read(self.blksize)
24
- if not data:
25
- self.file_handle.close()
26
- raise StopIteration
27
- return data
28
-
29
- def close(self):
30
- if hasattr(self.file_handle, 'close'):
31
- self.file_handle.close()
32
-
33
- class PDFStreamView(APIView):
34
- """
35
- Streams a PDF file with correct HTTP range support and proper file handle management.
36
- """
37
- permission_classes = [EnvironmentAwarePermission]
38
-
39
- @xframe_options_sameorigin
40
- def get(self, request, pdf_id: int, *args, **kwargs):
41
- try:
42
- pdf_obj = RawPdfFile.objects.filter(pk=pdf_id).first()
43
- if not pdf_obj or not pdf_obj.file:
44
- logger.warning(f"PDF not found: ID {pdf_id}")
45
- raise Http404("PDF not found")
46
-
47
- # Check if file exists on filesystem
48
- try:
49
- file_path = pdf_obj.file.path
50
- if not os.path.exists(file_path):
51
- logger.error(f"PDF file does not exist on filesystem: {file_path}")
52
- raise Http404("PDF file not found on filesystem")
53
-
54
- file_size = os.path.getsize(file_path)
55
- except (OSError, IOError, AttributeError) as e:
56
- logger.error(f"Error accessing PDF file {pdf_id}: {e}")
57
- raise Http404("PDF file not accessible")
58
-
59
- # Generate safe filename
60
- safe_filename = os.path.basename(pdf_obj.file.name) if pdf_obj.file.name else f"document_{pdf_id}.pdf"
61
- if not safe_filename.endswith('.pdf'):
62
- safe_filename += '.pdf'
63
-
64
- # Handle Range requests
65
- range_header = request.headers.get("Range")
66
- if range_header:
67
- logger.debug(f"Range request for PDF {pdf_id}: {range_header}")
68
- match = _RANGE_RE.match(range_header)
69
- if match:
70
- start = int(match.group(1))
71
- end = int(match.group(2) or file_size - 1)
72
-
73
- # Validate range
74
- if start >= file_size or start < 0:
75
- logger.warning(f"Invalid range start {start} for file size {file_size}")
76
- raise Http404("Invalid range")
77
-
78
- if end >= file_size:
79
- end = file_size - 1
80
-
81
- chunk_size = end - start + 1
82
-
83
- try:
84
- file_handle = open(file_path, "rb")
85
- file_handle.seek(start)
86
-
87
- logger.debug(f"Serving PDF {pdf_id} range {start}-{end}/{file_size}")
88
-
89
- response = StreamingHttpResponse(
90
- ClosingFileWrapper(file_handle, blksize=8192),
91
- status=206,
92
- content_type="application/pdf",
93
- )
94
- response["Content-Length"] = str(chunk_size)
95
- response["Content-Range"] = f"bytes {start}-{end}/{file_size}"
96
- response["Accept-Ranges"] = "bytes"
97
- response["Content-Disposition"] = f'inline; filename="{safe_filename}"'
98
-
99
- return response
100
- except (OSError, IOError) as e:
101
- logger.error(f"Error opening PDF file for range request: {e}")
102
- raise Http404("Error accessing PDF file")
103
- else:
104
- logger.warning(f"Invalid Range header format: {range_header}")
105
-
106
- # Serve entire file using FileResponse (automatically handles file closing)
107
- logger.debug(f"Serving full PDF {pdf_id} ({file_size} bytes)")
108
-
109
- try:
110
- file_handle = open(file_path, "rb")
111
- response = FileResponse(
112
- file_handle,
113
- content_type="application/pdf"
114
- )
115
- response["Content-Length"] = str(file_size)
116
- response["Accept-Ranges"] = "bytes"
117
- response["Content-Disposition"] = f'inline; filename="{safe_filename}"'
118
-
119
- # FileResponse will take ownership of file_handle and close it after response
120
- return response
121
- except (OSError, IOError) as e:
122
- logger.error(f"Error opening PDF file: {e}")
123
- raise Http404("Error accessing PDF file")
124
-
125
- except Exception as e:
126
- logger.error(f"Unexpected error streaming PDF {pdf_id}: {e}", exc_info=True)
127
- raise Http404("Error streaming PDF")