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.
- endoreg_db/data/ai_model_meta/default_multilabel_classification.yaml +23 -1
- endoreg_db/data/setup_config.yaml +38 -0
- endoreg_db/management/commands/create_model_meta_from_huggingface.py +1 -2
- endoreg_db/management/commands/load_ai_model_data.py +18 -15
- endoreg_db/management/commands/setup_endoreg_db.py +218 -33
- endoreg_db/models/media/pdf/raw_pdf.py +241 -97
- endoreg_db/models/media/video/pipe_1.py +30 -33
- endoreg_db/models/media/video/video_file.py +300 -187
- endoreg_db/models/medical/hardware/endoscopy_processor.py +10 -1
- endoreg_db/models/metadata/model_meta_logic.py +34 -45
- endoreg_db/models/metadata/sensitive_meta_logic.py +555 -150
- endoreg_db/serializers/__init__.py +26 -55
- endoreg_db/serializers/misc/__init__.py +1 -1
- endoreg_db/serializers/misc/file_overview.py +65 -35
- endoreg_db/serializers/misc/{vop_patient_data.py → sensitive_patient_data.py} +1 -1
- endoreg_db/serializers/video_examination.py +198 -0
- endoreg_db/services/lookup_service.py +228 -58
- endoreg_db/services/lookup_store.py +174 -30
- endoreg_db/services/pdf_import.py +585 -282
- endoreg_db/services/video_import.py +493 -240
- endoreg_db/urls/__init__.py +36 -23
- endoreg_db/urls/label_video_segments.py +2 -0
- endoreg_db/urls/media.py +103 -66
- endoreg_db/utils/setup_config.py +177 -0
- endoreg_db/views/__init__.py +5 -3
- endoreg_db/views/media/pdf_media.py +3 -1
- endoreg_db/views/media/video_media.py +1 -1
- endoreg_db/views/media/video_segments.py +187 -259
- endoreg_db/views/pdf/__init__.py +5 -8
- endoreg_db/views/pdf/pdf_stream.py +186 -0
- endoreg_db/views/pdf/reimport.py +110 -94
- endoreg_db/views/requirement/lookup.py +171 -287
- endoreg_db/views/video/__init__.py +0 -2
- endoreg_db/views/video/video_examination_viewset.py +202 -289
- {endoreg_db-0.8.3.3.dist-info → endoreg_db-0.8.6.5.dist-info}/METADATA +1 -2
- {endoreg_db-0.8.3.3.dist-info → endoreg_db-0.8.6.5.dist-info}/RECORD +38 -37
- endoreg_db/views/pdf/pdf_media.py +0 -239
- endoreg_db/views/pdf/pdf_stream_views.py +0 -127
- endoreg_db/views/video/video_media.py +0 -158
- {endoreg_db-0.8.3.3.dist-info → endoreg_db-0.8.6.5.dist-info}/WHEEL +0 -0
- {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=
|
|
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=
|
|
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=
|
|
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=
|
|
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=
|
|
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=
|
|
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=
|
|
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=
|
|
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=
|
|
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=
|
|
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=
|
|
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=
|
|
560
|
-
endoreg_db/serializers/misc/file_overview.py,sha256=
|
|
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=
|
|
598
|
-
endoreg_db/services/lookup_store.py,sha256=
|
|
599
|
-
endoreg_db/services/pdf_import.py,sha256=
|
|
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=
|
|
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=
|
|
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=
|
|
620
|
-
endoreg_db/urls/media.py,sha256=
|
|
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=
|
|
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=
|
|
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=
|
|
721
|
-
endoreg_db/views/media/video_segments.py,sha256=
|
|
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=
|
|
758
|
-
endoreg_db/views/pdf/
|
|
759
|
-
endoreg_db/views/pdf/
|
|
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=
|
|
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=
|
|
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=
|
|
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.
|
|
790
|
-
endoreg_db-0.8.
|
|
791
|
-
endoreg_db-0.8.
|
|
792
|
-
endoreg_db-0.8.
|
|
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")
|