endoreg-db 0.8.4.8__py3-none-any.whl → 0.8.5.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.

@@ -4,6 +4,7 @@ import logging
4
4
  from pathlib import Path
5
5
  import uuid
6
6
  from typing import TYPE_CHECKING, Optional, Union, cast
7
+ import os
7
8
 
8
9
  from django.db import models
9
10
  from django.core.files import File
@@ -208,46 +209,25 @@ class VideoFile(models.Model):
208
209
  return ffmpeg_meta
209
210
 
210
211
 
212
+ # Exception message constants
213
+ NO_ACTIVE_FILE = "Has no raw file"
214
+ NO_FILE_ASSOCIATED = "Active file has no associated file."
215
+
211
216
  @property
212
- def active_file_url(self) -> str:
213
- """
214
- Return the URL of the active processed file.
215
-
216
- Returns:
217
- str: The URL of the active video file.
218
-
219
- Raises:
220
- Value Error if no active VideoFile is available.
221
- """
222
- active = self.active_file
223
- if not isinstance(active, FieldFile):
224
- raise ValueError("Active file is not a stored FieldFile instance.")
225
- if not active.name:
226
- raise ValueError("Active file has no associated name.")
227
- return active.url
228
-
229
- @property
230
- def active_raw_file(self) -> FieldFile:
231
- raw = self.raw_file
232
- if isinstance(raw, FieldFile) and raw.name:
233
- return raw
234
- raise ValueError("No raw file available for this video")
235
-
236
- @property
237
- def active_raw_file_url(self)-> str:
238
- """
239
- Return the path of the URL of the active raw file for name reading.
217
+ def active_raw_file(self) -> File:
218
+ """Return the raw file if available, otherwise raise ValueError."""
219
+ if self.has_raw:
220
+ return self.raw_file
221
+ raise ValueError(self.NO_ACTIVE_FILE)
240
222
 
241
- Raises:
242
- ValueError("Active file has no associated file")
243
-
244
- Returns:
245
- """
246
- raw = self.active_raw_file
247
- if not raw.name:
248
- raise ValueError("Active raw file has no associated name.")
249
- return raw.url
250
-
223
+ @property
224
+ def active_raw_file_url(self) -> str:
225
+ """Return the URL of the active raw file, or raise ValueError if unavailable."""
226
+ _file = self.active_raw_file
227
+ assert _file is not None, self.NO_ACTIVE_FILE
228
+ if not _file or not _file.name:
229
+ raise ValueError(self.NO_FILE_ASSOCIATED)
230
+ return _file.url
251
231
 
252
232
  # Pipeline Functions
253
233
  pipe_1 = _pipe_1
@@ -414,6 +394,12 @@ class VideoFile(models.Model):
414
394
  if isinstance(file_path, str):
415
395
  file_path = Path(file_path)
416
396
  # Pass center_name and other kwargs to the helper function
397
+ if not center_name:
398
+ try:
399
+ center_name = os.environ["CENTER_NAME"]
400
+ except KeyError:
401
+ logger.error("Center name must be provided to create VideoFile from file. You can set CENTER_NAME in environment variables.")
402
+ return None
417
403
  return _create_from_file(cls, file_path, center_name=center_name, **kwargs)
418
404
 
419
405
  @classmethod
@@ -160,6 +160,9 @@ def calculate_patient_hash(instance: "SensitiveMeta", salt: str = SECRET_SALT) -
160
160
  if not center:
161
161
  raise ValueError("Center is required to calculate patient hash.")
162
162
 
163
+ assert first_name is not None, "First name is required to calculate patient hash."
164
+ assert last_name is not None, "Last name is required to calculate patient hash."
165
+
163
166
  hash_str = get_patient_hash(
164
167
  first_name=first_name,
165
168
  last_name=last_name,
@@ -11,23 +11,26 @@ Changelog:
11
11
 
12
12
  from datetime import date
13
13
  import logging
14
- import sys
15
14
  import os
15
+ import random
16
16
  import shutil
17
+ import sys
17
18
  import time
18
19
  from contextlib import contextmanager
20
+ from datetime import date
19
21
  from pathlib import Path
20
- from typing import Union, Dict, Any, Optional, List, Tuple
22
+ from typing import Any, Dict, List, Optional, Tuple, Union
23
+
21
24
  from django.db import transaction
25
+ from django.db.models.fields.files import FieldFile
22
26
  from lx_anonymizer import FrameCleaner
23
27
  from moviepy import video
24
- from endoreg_db.models import VideoFile, SensitiveMeta
25
- from endoreg_db.utils.paths import STORAGE_DIR, VIDEO_DIR, ANONYM_VIDEO_DIR
26
- import random
28
+
29
+ from endoreg_db.models import EndoscopyProcessor, SensitiveMeta, VideoFile
30
+ from endoreg_db.models.media.video.video_file_anonymize import \
31
+ _cleanup_raw_assets
27
32
  from endoreg_db.utils.hashs import get_video_hash
28
- from endoreg_db.models.media.video.video_file_anonymize import _cleanup_raw_assets
29
- from django.db.models.fields.files import FieldFile
30
- from endoreg_db.models import EndoscopyProcessor
33
+ from endoreg_db.utils.paths import ANONYM_VIDEO_DIR, STORAGE_DIR, VIDEO_DIR
31
34
 
32
35
  # File lock configuration (matches PDF import)
33
36
  STALE_LOCK_SECONDS = 6000 # 100 minutes - reclaim locks older than this
@@ -895,20 +898,46 @@ class VideoImportService:
895
898
 
896
899
  sm = sensitive_meta
897
900
  updated_fields = []
898
-
901
+
902
+ # Ensure center is set from video.center if not in extracted_metadata
903
+ metadata_to_update = extracted_metadata.copy()
904
+
905
+ # FIX: Set center object instead of center_name string
906
+ if not hasattr(sm, 'center') or not sm.center:
907
+ if video.center:
908
+ metadata_to_update['center'] = video.center
909
+ self.logger.debug("Added center object '%s' to metadata for SensitiveMeta update", video.center.name)
910
+ else:
911
+ center_name = metadata_to_update.get('center_name')
912
+ if center_name:
913
+ try:
914
+ from ..models.administration import Center
915
+ center_obj = Center.objects.get(name=center_name)
916
+ metadata_to_update['center'] = center_obj
917
+ self.logger.debug("Loaded center object '%s' from center_name", center_name)
918
+ metadata_to_update.pop('center_name', None)
919
+ except Center.DoesNotExist:
920
+ self.logger.error("Center '%s' not found in database", center_name)
921
+ return
922
+
899
923
  try:
900
- sm.update_from_dict(extracted_metadata)
901
- updated_fields = list(extracted_metadata.keys())
924
+ sm.update_from_dict(metadata_to_update)
925
+ updated_fields = list(extracted_metadata.keys()) # Only log originally extracted fields
902
926
  except KeyError as e:
903
927
  self.logger.warning(f"Failed to update SensitiveMeta field {e}")
928
+ return
904
929
 
905
930
  if updated_fields:
906
- sm.save(update_fields=updated_fields)
907
- self.logger.info("Updated SensitiveMeta fields for video %s: %s", video.uuid, updated_fields)
931
+ try:
932
+ sm.save() # Remove update_fields to allow all necessary fields to be saved
933
+ self.logger.info("Updated SensitiveMeta fields for video %s: %s", video.uuid, updated_fields)
908
934
 
909
- state = video.get_or_create_state()
910
- state.mark_sensitive_meta_processed(save=True)
911
- self.logger.info("Marked sensitive metadata as processed for video %s", video.uuid)
935
+ state = video.get_or_create_state()
936
+ state.mark_sensitive_meta_processed(save=True)
937
+ self.logger.info("Marked sensitive metadata as processed for video %s", video.uuid)
938
+ except Exception as e:
939
+ self.logger.error(f"Failed to save SensitiveMeta: {e}")
940
+ raise # Re-raise to trigger fallback in calling method
912
941
  else:
913
942
  self.logger.info("No SensitiveMeta fields updated for video %s - all existing values preserved", video.uuid)
914
943
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: endoreg-db
3
- Version: 0.8.4.8
3
+ Version: 0.8.5.0
4
4
  Summary: EndoReg Db Django App
5
5
  Project-URL: Homepage, https://info.coloreg.de
6
6
  Project-URL: Repository, https://github.com/wg-lux/endoreg-db
@@ -390,7 +390,7 @@ endoreg_db/models/media/video/create_from_file.py,sha256=3n4bbzFteEOFDUuEikP0x-S
390
390
  endoreg_db/models/media/video/pipe_1.py,sha256=ljO3vO2mqqTXLZsKjzMTC6-sW4JRWMVRfJcK0n5CjKg,9740
391
391
  endoreg_db/models/media/video/pipe_2.py,sha256=DnMxW0uOqSsf7-0n9Rlvn7u89U4Jpkv7n6hFpQfUjkQ,4964
392
392
  endoreg_db/models/media/video/refactor_plan.md,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
393
- endoreg_db/models/media/video/video_file.py,sha256=txlxR8d1OBgt3UEkWvLcGSyLarh0jXLw-z0SAV5KOok,26789
393
+ endoreg_db/models/media/video/video_file.py,sha256=XYF0uhA4VjfGu3w7CsFWt0pdkbMzbGkjzBE2s--ZrPY,26604
394
394
  endoreg_db/models/media/video/video_file_ai.py,sha256=3ABea52FOF1qlrlxHdYhz_M3Kmqfzqtgq7M0prl-FAo,18819
395
395
  endoreg_db/models/media/video/video_file_anonymize.py,sha256=pet1UfSsbSHJJZxq6gDPifAfBWpGyEpD1jEQuSQi0Gg,16027
396
396
  endoreg_db/models/media/video/video_file_frames.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -468,7 +468,7 @@ endoreg_db/models/metadata/model_meta.py,sha256=F_r-PTLeNi4J-4EaGCQkGIguhdl7Bwba
468
468
  endoreg_db/models/metadata/model_meta_logic.py,sha256=vAbNDaoZygH8xOCulWlXoHoR1T0BSvr9kIloxjzhfjo,12533
469
469
  endoreg_db/models/metadata/pdf_meta.py,sha256=BTmpSgqxmPKi0apcNjyrZAS4AFKCPXVdBd6VBeyyv6E,3174
470
470
  endoreg_db/models/metadata/sensitive_meta.py,sha256=ekLHrW-b5uYcjfkRd0EW5ncx5ef8Bu-K6msDkpWCAbk,13034
471
- endoreg_db/models/metadata/sensitive_meta_logic.py,sha256=XN3x3p0cqLlzPSZl7e35JBUXr_QKYSq48vwF1N60N4U,32134
471
+ endoreg_db/models/metadata/sensitive_meta_logic.py,sha256=BnxWSSGHRlWLvqGgChzZ13qCXMB7onLE6MOBdE5CBhg,32311
472
472
  endoreg_db/models/metadata/video_meta.py,sha256=c6xWdLW3uNqJ5VPJXHCxXA3mbXw-b0uR54-TOS3qL2Q,14966
473
473
  endoreg_db/models/metadata/video_prediction_logic.py,sha256=j5N82mHtiomeeIaf1HA65kT5d0htQfJmbI2bJb8mpxQ,7677
474
474
  endoreg_db/models/metadata/video_prediction_meta.py,sha256=EyfctAAAVcW9L0gf76ZBc9-G8MLMcD-tc2kkjaaLH4w,10592
@@ -603,7 +603,7 @@ endoreg_db/services/pseudonym_service.py,sha256=CJhbtRa6K6SPbphgCZgEMi8AFQtB18CU
603
603
  endoreg_db/services/requirements_object.py,sha256=290zf8AEbVtCoHhW4Jr7_ud-RvrqYmb1Nz9UBHtTnc0,6164
604
604
  endoreg_db/services/segment_sync.py,sha256=YgHvIHkbW4mqCu0ACf3zjRSZnNfxWwt4gh5syUVXuE0,6400
605
605
  endoreg_db/services/storage_aware_video_processor.py,sha256=kKFK64vXLeBSVkp1YJonU3gFDTeXZ8C4qb9QZZB99SE,13420
606
- endoreg_db/services/video_import.py,sha256=quQ1z_hqJFcrq5pOeq74pqqmnS2I9ybJIh5D0v8qtOk,46514
606
+ endoreg_db/services/video_import.py,sha256=bnmdtE2-XMXoNOHRfL_NBO03RIIznzHi0DzVxGkLc5I,48006
607
607
  endoreg_db/tasks/upload_tasks.py,sha256=OJq7DhNwcbWdXzHY8jz5c51BCVkPN5gSWOz-6Fx6W5M,7799
608
608
  endoreg_db/tasks/video_ingest.py,sha256=kxFuYkHijINV0VabQKCFVpJRv6eCAw07tviONurDgg8,5265
609
609
  endoreg_db/tasks/video_processing_tasks.py,sha256=rZ7Kr49bAR4Q-vALO2SURebrhcJ5hSFGwjF4aULrOao,14089
@@ -788,7 +788,7 @@ endoreg_db/views/video/video_meta.py,sha256=C1wBMTtQb_yzEUrhFGAy2UHEWMk_CbU75WXX
788
788
  endoreg_db/views/video/video_processing_history.py,sha256=mhFuS8RG5GV8E-lTtuD0qrq-bIpnUFp8vy9aERfC-J8,770
789
789
  endoreg_db/views/video/video_remove_frames.py,sha256=2FmvNrSPM0fUXiBxINN6vBUUDCqDlBkNcGR3WsLDgKo,1696
790
790
  endoreg_db/views/video/video_stream.py,sha256=kLyuf0ORTmsLeYUQkTQ6iRYqlIQozWhMMR3Lhfe_trk,12148
791
- endoreg_db-0.8.4.8.dist-info/METADATA,sha256=TbemUzPCUJkNOQV3TdNGw0EdQCfefEMuWoChAjYjik8,14719
792
- endoreg_db-0.8.4.8.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
793
- endoreg_db-0.8.4.8.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
794
- endoreg_db-0.8.4.8.dist-info/RECORD,,
791
+ endoreg_db-0.8.5.0.dist-info/METADATA,sha256=sbgw_9rLtOsgqYAvPKG0MwFZOyVJ01QGnh5sMBIEPVk,14719
792
+ endoreg_db-0.8.5.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
793
+ endoreg_db-0.8.5.0.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
794
+ endoreg_db-0.8.5.0.dist-info/RECORD,,