streamlit-octostar-utils 0.5.4.dev4__tar.gz → 0.5.5__tar.gz

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.
Files changed (45) hide show
  1. {streamlit_octostar_utils-0.5.4.dev4 → streamlit_octostar_utils-0.5.5}/PKG-INFO +2 -1
  2. {streamlit_octostar_utils-0.5.4.dev4 → streamlit_octostar_utils-0.5.5}/pyproject.toml +2 -1
  3. {streamlit_octostar_utils-0.5.4.dev4 → streamlit_octostar_utils-0.5.5}/streamlit_octostar_utils/api_crafter/celery.py +25 -14
  4. {streamlit_octostar_utils-0.5.4.dev4 → streamlit_octostar_utils-0.5.5}/streamlit_octostar_utils/api_crafter/nifi.py +16 -50
  5. {streamlit_octostar_utils-0.5.4.dev4 → streamlit_octostar_utils-0.5.5}/LICENSE +0 -0
  6. {streamlit_octostar_utils-0.5.4.dev4 → streamlit_octostar_utils-0.5.5}/README.md +0 -0
  7. {streamlit_octostar_utils-0.5.4.dev4 → streamlit_octostar_utils-0.5.5}/streamlit_octostar_utils/__init__.py +0 -0
  8. {streamlit_octostar_utils-0.5.4.dev4 → streamlit_octostar_utils-0.5.5}/streamlit_octostar_utils/api_crafter/__init__.py +0 -0
  9. {streamlit_octostar_utils-0.5.4.dev4 → streamlit_octostar_utils-0.5.5}/streamlit_octostar_utils/api_crafter/contents.py +0 -0
  10. {streamlit_octostar_utils-0.5.4.dev4 → streamlit_octostar_utils-0.5.5}/streamlit_octostar_utils/api_crafter/fastapi.py +0 -0
  11. {streamlit_octostar_utils-0.5.4.dev4 → streamlit_octostar_utils-0.5.5}/streamlit_octostar_utils/api_crafter/parallelism.py +0 -0
  12. {streamlit_octostar_utils-0.5.4.dev4 → streamlit_octostar_utils-0.5.5}/streamlit_octostar_utils/api_crafter/parser/__init__.py +0 -0
  13. {streamlit_octostar_utils-0.5.4.dev4 → streamlit_octostar_utils-0.5.5}/streamlit_octostar_utils/api_crafter/parser/combine_fields.py +0 -0
  14. {streamlit_octostar_utils-0.5.4.dev4 → streamlit_octostar_utils-0.5.5}/streamlit_octostar_utils/api_crafter/parser/entities_parser.py +0 -0
  15. {streamlit_octostar_utils-0.5.4.dev4 → streamlit_octostar_utils-0.5.5}/streamlit_octostar_utils/api_crafter/parser/generics.py +0 -0
  16. {streamlit_octostar_utils-0.5.4.dev4 → streamlit_octostar_utils-0.5.5}/streamlit_octostar_utils/api_crafter/parser/info.py +0 -0
  17. {streamlit_octostar_utils-0.5.4.dev4 → streamlit_octostar_utils-0.5.5}/streamlit_octostar_utils/api_crafter/parser/linkchart_functions.py +0 -0
  18. {streamlit_octostar_utils-0.5.4.dev4 → streamlit_octostar_utils-0.5.5}/streamlit_octostar_utils/api_crafter/parser/matches.py +0 -0
  19. {streamlit_octostar_utils-0.5.4.dev4 → streamlit_octostar_utils-0.5.5}/streamlit_octostar_utils/api_crafter/parser/parameters.py +0 -0
  20. {streamlit_octostar_utils-0.5.4.dev4 → streamlit_octostar_utils-0.5.5}/streamlit_octostar_utils/api_crafter/parser/rules.py +0 -0
  21. {streamlit_octostar_utils-0.5.4.dev4 → streamlit_octostar_utils-0.5.5}/streamlit_octostar_utils/api_crafter/parser/signals.py +0 -0
  22. {streamlit_octostar_utils-0.5.4.dev4 → streamlit_octostar_utils-0.5.5}/streamlit_octostar_utils/core/__init__.py +0 -0
  23. {streamlit_octostar_utils-0.5.4.dev4 → streamlit_octostar_utils-0.5.5}/streamlit_octostar_utils/core/dict.py +0 -0
  24. {streamlit_octostar_utils-0.5.4.dev4 → streamlit_octostar_utils-0.5.5}/streamlit_octostar_utils/core/filetypes.py +0 -0
  25. {streamlit_octostar_utils-0.5.4.dev4 → streamlit_octostar_utils-0.5.5}/streamlit_octostar_utils/core/threading/__init__.py +0 -0
  26. {streamlit_octostar_utils-0.5.4.dev4 → streamlit_octostar_utils-0.5.5}/streamlit_octostar_utils/core/threading/key_queue.py +0 -0
  27. {streamlit_octostar_utils-0.5.4.dev4 → streamlit_octostar_utils-0.5.5}/streamlit_octostar_utils/core/timestamp.py +0 -0
  28. {streamlit_octostar_utils-0.5.4.dev4 → streamlit_octostar_utils-0.5.5}/streamlit_octostar_utils/nlp/__init__.py +0 -0
  29. {streamlit_octostar_utils-0.5.4.dev4 → streamlit_octostar_utils-0.5.5}/streamlit_octostar_utils/nlp/custom_recognizers.py +0 -0
  30. {streamlit_octostar_utils-0.5.4.dev4 → streamlit_octostar_utils-0.5.5}/streamlit_octostar_utils/nlp/language.py +0 -0
  31. {streamlit_octostar_utils-0.5.4.dev4 → streamlit_octostar_utils-0.5.5}/streamlit_octostar_utils/nlp/ner.py +0 -0
  32. {streamlit_octostar_utils-0.5.4.dev4 → streamlit_octostar_utils-0.5.5}/streamlit_octostar_utils/octostar/__init__.py +0 -0
  33. {streamlit_octostar_utils-0.5.4.dev4 → streamlit_octostar_utils-0.5.5}/streamlit_octostar_utils/octostar/client.py +0 -0
  34. {streamlit_octostar_utils-0.5.4.dev4 → streamlit_octostar_utils-0.5.5}/streamlit_octostar_utils/octostar/context.py +0 -0
  35. {streamlit_octostar_utils-0.5.4.dev4 → streamlit_octostar_utils-0.5.5}/streamlit_octostar_utils/octostar/permissions.py +0 -0
  36. {streamlit_octostar_utils-0.5.4.dev4 → streamlit_octostar_utils-0.5.5}/streamlit_octostar_utils/ontology/__init__.py +0 -0
  37. {streamlit_octostar_utils-0.5.4.dev4 → streamlit_octostar_utils-0.5.5}/streamlit_octostar_utils/ontology/inheritance.py +0 -0
  38. {streamlit_octostar_utils-0.5.4.dev4 → streamlit_octostar_utils-0.5.5}/streamlit_octostar_utils/ontology/relationships.py +0 -0
  39. {streamlit_octostar_utils-0.5.4.dev4 → streamlit_octostar_utils-0.5.5}/streamlit_octostar_utils/ontology/validation.py +0 -0
  40. {streamlit_octostar_utils-0.5.4.dev4 → streamlit_octostar_utils-0.5.5}/streamlit_octostar_utils/style/__init__.py +0 -0
  41. {streamlit_octostar_utils-0.5.4.dev4 → streamlit_octostar_utils-0.5.5}/streamlit_octostar_utils/style/common.py +0 -0
  42. {streamlit_octostar_utils-0.5.4.dev4 → streamlit_octostar_utils-0.5.5}/streamlit_octostar_utils/threading/__init__.py +0 -0
  43. {streamlit_octostar_utils-0.5.4.dev4 → streamlit_octostar_utils-0.5.5}/streamlit_octostar_utils/threading/async_task_manager.py +0 -0
  44. {streamlit_octostar_utils-0.5.4.dev4 → streamlit_octostar_utils-0.5.5}/streamlit_octostar_utils/threading/session_callback_manager.py +0 -0
  45. {streamlit_octostar_utils-0.5.4.dev4 → streamlit_octostar_utils-0.5.5}/streamlit_octostar_utils/threading/session_state_hot_swapper.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: streamlit-octostar-utils
3
- Version: 0.5.4.dev4
3
+ Version: 0.5.5
4
4
  Summary:
5
5
  License: MIT
6
6
  License-File: LICENSE
@@ -26,6 +26,7 @@ Requires-Dist: numpy (>=1.20.0)
26
26
  Requires-Dist: octostar-streamlit (>=0.1.25,<0.2.0)
27
27
  Requires-Dist: pottery (>=3.0.0,<4.0.0)
28
28
  Requires-Dist: presidio-analyzer (>=2.2.0,<3.0.0) ; extra == "nlp"
29
+ Requires-Dist: psutil (>=5.9.0)
29
30
  Requires-Dist: py3langid (>=0.2.0,<0.3.0) ; extra == "nlp"
30
31
  Requires-Dist: pydantic (>=2.6.4,<3.0.0)
31
32
  Requires-Dist: python-multipart (>=0.0.9,<0.0.10)
@@ -5,7 +5,7 @@ include = '\.pyi?$'
5
5
 
6
6
  [tool.poetry]
7
7
  name = "streamlit-octostar-utils"
8
- version = "0.5.4-dev.4"
8
+ version = "0.5.5"
9
9
  description = ""
10
10
  license = "MIT"
11
11
  authors = ["Octostar"]
@@ -37,6 +37,7 @@ numpy = ">=1.20.0"
37
37
  scipy = "^1.10.0"
38
38
  rapidfuzz = "^3.5.0"
39
39
  celery = "^5.3.0"
40
+ psutil = ">=5.9.0"
40
41
  redis = ">=4.0.0,<5.0.0"
41
42
  pottery = "^3.0.0"
42
43
  slowapi = "^0.1.9"
@@ -122,7 +122,7 @@ class MemoryMonitor:
122
122
 
123
123
  _DEFAULTS = {
124
124
  "sample_interval": 30,
125
- "warning_threshold_mb": None,
125
+ "warn_memory_per_child": None,
126
126
  "gc_collect_on_end": True,
127
127
  "malloc_trim_on_end": True,
128
128
  }
@@ -138,7 +138,7 @@ class MemoryMonitor:
138
138
  if config and isinstance(config, dict):
139
139
  cfg.update({k: v for k, v in config.items() if v is not None})
140
140
  self._sample_interval = cfg["sample_interval"]
141
- self._warning_threshold_mb = cfg["warning_threshold_mb"]
141
+ self._warn_memory_per_child = cfg["warn_memory_per_child"]
142
142
  self._gc_collect_on_end = cfg["gc_collect_on_end"]
143
143
  self._malloc_trim_on_end = cfg["malloc_trim_on_end"]
144
144
 
@@ -173,15 +173,18 @@ class MemoryMonitor:
173
173
  return "?"
174
174
 
175
175
  def _resolve_threshold(self, queue):
176
- """Resolve ``warning_threshold_mb`` for *queue*.
176
+ """Resolve ``warn_memory_per_child`` (KiB) for *queue*.
177
177
 
178
- ``warning_threshold_mb`` is a dict mapping queue names to
179
- per-queue thresholds. Returns ``None`` when unconfigured.
178
+ Returns the threshold in MiB (converted from KiB config) for
179
+ comparison with RSS readings, or ``None`` when unconfigured.
180
180
  """
181
- threshold = self._warning_threshold_mb
182
- if not isinstance(threshold, dict):
181
+ thresholds = self._warn_memory_per_child
182
+ if not isinstance(thresholds, dict):
183
183
  return None
184
- return threshold.get(queue)
184
+ kib = thresholds.get(queue)
185
+ if kib is None:
186
+ return None
187
+ return kib / 1024
185
188
 
186
189
  def _try_malloc_trim(self):
187
190
  """Ask glibc to return free pages to the OS. No-op on non-Linux."""
@@ -201,8 +204,8 @@ class MemoryMonitor:
201
204
 
202
205
  logger.info(
203
206
  "[MEM] Memory monitor enabled: sample_interval=%s, "
204
- "warning_threshold_mb=%s, gc_collect=%s, malloc_trim=%s",
205
- self._sample_interval, self._warning_threshold_mb,
207
+ "gc_collect=%s, malloc_trim=%s",
208
+ self._sample_interval,
206
209
  self._gc_collect_on_end, self._malloc_trim_on_end,
207
210
  )
208
211
 
@@ -348,12 +351,14 @@ class CeleryQueueConfig:
348
351
  max_tasks_in_queue=None,
349
352
  max_tasks_per_child=None,
350
353
  max_memory_per_child=None,
354
+ warn_memory_per_child=None,
351
355
  **options,
352
356
  ):
353
357
  self.n_workers = n_workers
354
358
  self.max_tasks_in_queue = max_tasks_in_queue
355
359
  self.max_tasks_per_child = max_tasks_per_child
356
- self.max_memory_per_child = max_memory_per_child # KiB
360
+ self.max_memory_per_child = max_memory_per_child # KiB — hard limit, worker restarted
361
+ self.warn_memory_per_child = warn_memory_per_child # KiB — soft limit, logs WARNING
357
362
  self.options = options
358
363
 
359
364
 
@@ -555,9 +560,15 @@ class CeleryExecutor(object):
555
560
 
556
561
  self._memory_monitor = None
557
562
  if memory_monitor:
558
- self._memory_monitor = MemoryMonitor(
559
- memory_monitor if isinstance(memory_monitor, dict) else {}
560
- )
563
+ mm_cfg = dict(memory_monitor) if isinstance(memory_monitor, dict) else {}
564
+ thresholds = {
565
+ q: qc.warn_memory_per_child
566
+ for q, qc in self.queue_config.items()
567
+ if qc.warn_memory_per_child is not None
568
+ }
569
+ if thresholds:
570
+ mm_cfg["warn_memory_per_child"] = thresholds
571
+ self._memory_monitor = MemoryMonitor(mm_cfg)
561
572
 
562
573
  self._is_owner = False
563
574
  self.set_cleanup_task()
@@ -17,7 +17,6 @@ from starlette.exceptions import HTTPException as StarletteHTTPException
17
17
 
18
18
  from octostar.utils.workspace import upsert_entities
19
19
  from octostar.utils.ontology import fetch_ontology_data
20
- from octostar.utils.workspace.permissions import get_permissions, PermissionLevel
21
20
  from octostar.utils.pipeline import update_processing_status
22
21
 
23
22
  from octostar.client import make_client
@@ -85,7 +84,6 @@ class NifiEntityModel(BaseModel):
85
84
  is_temporary: bool = False
86
85
  exception: dict = Field(default_factory=dict)
87
86
  last_processor_name: Optional[str] = None
88
- fallback_os_workspace: Optional[str] = None
89
87
 
90
88
  class RecordModel(BaseModel):
91
89
  model_config = ConfigDict(extra="allow")
@@ -475,7 +473,6 @@ class NifiContextManager(object):
475
473
  def __init__(self, json_data, lazy_sync=True):
476
474
  if not json_data:
477
475
  raise ValueError("Nifi context manager received list of 0 entities")
478
- self.permissions = {}
479
476
  self.in_batches = None
480
477
  self.out_entities = None
481
478
  self.nonlazy_sync_ids = set()
@@ -552,16 +549,6 @@ class NifiContextManager(object):
552
549
  def __enter__(self):
553
550
  return self
554
551
 
555
- def get_workspaces_permissions(self, workspace_ids):
556
- permissions_to_fetch = list(set(workspace_ids).difference(set(list(self.permissions.keys()))))
557
- if permissions_to_fetch:
558
- permissions = get_permissions.sync(permissions_to_fetch, client=self.client)
559
- self.permissions.update(permissions)
560
- permissions = {}
561
- for k in workspace_ids:
562
- permissions[k] = self.permissions.get(k, PermissionLevel.NONE)
563
- return permissions
564
-
565
552
  def request_entity_sync(
566
553
  self,
567
554
  entity,
@@ -628,16 +615,18 @@ class NifiContextManager(object):
628
615
  import logging
629
616
  _lock_logger = logging.getLogger(__name__)
630
617
 
631
- records = []
632
- for e in entities:
633
- if isinstance(e, dict):
634
- records.append(
635
- (e, e.get("entity_timestamp"))
636
- )
637
- else:
638
- records.append(
639
- (e.record, e.request.get("entity_timestamp") if e.request else None)
640
- )
618
+ def _read_entries():
619
+ entries = []
620
+ for e in entities:
621
+ if isinstance(e, dict):
622
+ entries.append((e, e.get("entity_timestamp")))
623
+ else:
624
+ entries.append(
625
+ (e.record, e.request.get("entity_timestamp") if e.request else None)
626
+ )
627
+ return entries
628
+
629
+ records = _read_entries()
641
630
 
642
631
  long_expiry = (datetime.now(timezone.utc) + timedelta(seconds=timeout)).strftime("%Y-%m-%dT%H:%M:%SZ")
643
632
  statuses = [
@@ -671,6 +660,7 @@ class NifiContextManager(object):
671
660
  try:
672
661
  yield True
673
662
  finally:
663
+ records = _read_entries()
674
664
  short_expiry = datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ")
675
665
  statuses = [
676
666
  {
@@ -705,10 +695,8 @@ class NifiContextManager(object):
705
695
  self._sync_upsert_entities(entities_to_upsert)
706
696
  self._sync_fetch_relationships(entities, fetch_rel_entities, fetch_concept_rels)
707
697
 
708
- now_ts = datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ")
709
698
  for entity in all_entities_to_modify:
710
699
  entity.request["is_temporary"] = False
711
- entity.request["entity_timestamp"] = now_ts
712
700
 
713
701
  for entity in entities:
714
702
  entity.sync_params = {}
@@ -970,29 +958,7 @@ class NifiEntity(object):
970
958
 
971
959
  @property
972
960
  def write_os_workspace(self):
973
- permissions = self.context.get_workspaces_permissions(
974
- [
975
- e
976
- for e in [
977
- self.record.get("os_workspace"),
978
- self.request.get("fallback_os_workspace"),
979
- ]
980
- if e
981
- ]
982
- )
983
- if (
984
- self.record.get("os_workspace")
985
- and (permissions.get(self.record.get("os_workspace")) or PermissionLevel.NONE) >= PermissionLevel.WRITE
986
- ):
987
- return self.record["os_workspace"]
988
- elif (
989
- self.request.get("fallback_os_workspace")
990
- and (permissions.get(self.request.get("fallback_os_workspace")) or PermissionLevel.NONE)
991
- >= PermissionLevel.WRITE
992
- ):
993
- return self.request["fallback_os_workspace"]
994
- else:
995
- return None
961
+ return self.record.get("os_workspace")
996
962
 
997
963
  @property
998
964
  def label(self):
@@ -1210,7 +1176,6 @@ class NifiEntity(object):
1210
1176
  "is_temporary": True,
1211
1177
  "exception": {},
1212
1178
  "last_processor_name": None,
1213
- "fallback_os_workspace": self.request["fallback_os_workspace"],
1214
1179
  }
1215
1180
  child_entity = NifiEntity(
1216
1181
  self.context,
@@ -1436,6 +1401,7 @@ class NifiEntity(object):
1436
1401
  os_entity_uid=None,
1437
1402
  os_relationship_uid=None,
1438
1403
  os_entity_type=FRAGMENT_ENTITY_NAME,
1404
+ os_parent_uid=None,
1439
1405
  previous_fragment_uid=None,
1440
1406
  previous_fragment_relationship_uid=None,
1441
1407
  previous_fragment_relationship=PREVIOUS_FRAGMENT_RELATIONSHIP,
@@ -1448,7 +1414,7 @@ class NifiEntity(object):
1448
1414
  fields = {
1449
1415
  **{k: v for k, v in self.record.items() if k.startswith("fragment") and v is not None},
1450
1416
  **fields,
1451
- "os_parent_uid": self.record["os_entity_uid"],
1417
+ "os_parent_uid": os_parent_uid or self.record["os_entity_uid"],
1452
1418
  "source_entity_uid": source_entity_uid,
1453
1419
  "previous_entity_uid": previous_fragment_uid,
1454
1420
  "next_entity_uid": next_fragment_uid,