streamlit-octostar-utils 0.4.2.dev11__tar.gz → 0.4.2.dev13__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.
- {streamlit_octostar_utils-0.4.2.dev11 → streamlit_octostar_utils-0.4.2.dev13}/PKG-INFO +1 -1
- {streamlit_octostar_utils-0.4.2.dev11 → streamlit_octostar_utils-0.4.2.dev13}/pyproject.toml +1 -1
- {streamlit_octostar_utils-0.4.2.dev11 → streamlit_octostar_utils-0.4.2.dev13}/streamlit_octostar_utils/api_crafter/contents.py +52 -139
- {streamlit_octostar_utils-0.4.2.dev11 → streamlit_octostar_utils-0.4.2.dev13}/streamlit_octostar_utils/api_crafter/nifi.py +4 -2
- {streamlit_octostar_utils-0.4.2.dev11 → streamlit_octostar_utils-0.4.2.dev13}/LICENSE +0 -0
- {streamlit_octostar_utils-0.4.2.dev11 → streamlit_octostar_utils-0.4.2.dev13}/README.md +0 -0
- {streamlit_octostar_utils-0.4.2.dev11 → streamlit_octostar_utils-0.4.2.dev13}/streamlit_octostar_utils/__init__.py +0 -0
- {streamlit_octostar_utils-0.4.2.dev11 → streamlit_octostar_utils-0.4.2.dev13}/streamlit_octostar_utils/api_crafter/__init__.py +0 -0
- {streamlit_octostar_utils-0.4.2.dev11 → streamlit_octostar_utils-0.4.2.dev13}/streamlit_octostar_utils/api_crafter/celery.py +0 -0
- {streamlit_octostar_utils-0.4.2.dev11 → streamlit_octostar_utils-0.4.2.dev13}/streamlit_octostar_utils/api_crafter/fastapi.py +0 -0
- {streamlit_octostar_utils-0.4.2.dev11 → streamlit_octostar_utils-0.4.2.dev13}/streamlit_octostar_utils/api_crafter/parallelism.py +0 -0
- {streamlit_octostar_utils-0.4.2.dev11 → streamlit_octostar_utils-0.4.2.dev13}/streamlit_octostar_utils/api_crafter/parser/__init__.py +0 -0
- {streamlit_octostar_utils-0.4.2.dev11 → streamlit_octostar_utils-0.4.2.dev13}/streamlit_octostar_utils/api_crafter/parser/combine_fields.py +0 -0
- {streamlit_octostar_utils-0.4.2.dev11 → streamlit_octostar_utils-0.4.2.dev13}/streamlit_octostar_utils/api_crafter/parser/entities_parser.py +0 -0
- {streamlit_octostar_utils-0.4.2.dev11 → streamlit_octostar_utils-0.4.2.dev13}/streamlit_octostar_utils/api_crafter/parser/generics.py +0 -0
- {streamlit_octostar_utils-0.4.2.dev11 → streamlit_octostar_utils-0.4.2.dev13}/streamlit_octostar_utils/api_crafter/parser/info.py +0 -0
- {streamlit_octostar_utils-0.4.2.dev11 → streamlit_octostar_utils-0.4.2.dev13}/streamlit_octostar_utils/api_crafter/parser/linkchart_functions.py +0 -0
- {streamlit_octostar_utils-0.4.2.dev11 → streamlit_octostar_utils-0.4.2.dev13}/streamlit_octostar_utils/api_crafter/parser/matches.py +0 -0
- {streamlit_octostar_utils-0.4.2.dev11 → streamlit_octostar_utils-0.4.2.dev13}/streamlit_octostar_utils/api_crafter/parser/parameters.py +0 -0
- {streamlit_octostar_utils-0.4.2.dev11 → streamlit_octostar_utils-0.4.2.dev13}/streamlit_octostar_utils/api_crafter/parser/rules.py +0 -0
- {streamlit_octostar_utils-0.4.2.dev11 → streamlit_octostar_utils-0.4.2.dev13}/streamlit_octostar_utils/api_crafter/parser/signals.py +0 -0
- {streamlit_octostar_utils-0.4.2.dev11 → streamlit_octostar_utils-0.4.2.dev13}/streamlit_octostar_utils/core/__init__.py +0 -0
- {streamlit_octostar_utils-0.4.2.dev11 → streamlit_octostar_utils-0.4.2.dev13}/streamlit_octostar_utils/core/dict.py +0 -0
- {streamlit_octostar_utils-0.4.2.dev11 → streamlit_octostar_utils-0.4.2.dev13}/streamlit_octostar_utils/core/filetypes.py +0 -0
- {streamlit_octostar_utils-0.4.2.dev11 → streamlit_octostar_utils-0.4.2.dev13}/streamlit_octostar_utils/core/threading/__init__.py +0 -0
- {streamlit_octostar_utils-0.4.2.dev11 → streamlit_octostar_utils-0.4.2.dev13}/streamlit_octostar_utils/core/threading/key_queue.py +0 -0
- {streamlit_octostar_utils-0.4.2.dev11 → streamlit_octostar_utils-0.4.2.dev13}/streamlit_octostar_utils/core/timestamp.py +0 -0
- {streamlit_octostar_utils-0.4.2.dev11 → streamlit_octostar_utils-0.4.2.dev13}/streamlit_octostar_utils/nlp/__init__.py +0 -0
- {streamlit_octostar_utils-0.4.2.dev11 → streamlit_octostar_utils-0.4.2.dev13}/streamlit_octostar_utils/nlp/custom_recognizers.py +0 -0
- {streamlit_octostar_utils-0.4.2.dev11 → streamlit_octostar_utils-0.4.2.dev13}/streamlit_octostar_utils/nlp/language.py +0 -0
- {streamlit_octostar_utils-0.4.2.dev11 → streamlit_octostar_utils-0.4.2.dev13}/streamlit_octostar_utils/nlp/ner.py +0 -0
- {streamlit_octostar_utils-0.4.2.dev11 → streamlit_octostar_utils-0.4.2.dev13}/streamlit_octostar_utils/octostar/__init__.py +0 -0
- {streamlit_octostar_utils-0.4.2.dev11 → streamlit_octostar_utils-0.4.2.dev13}/streamlit_octostar_utils/octostar/client.py +0 -0
- {streamlit_octostar_utils-0.4.2.dev11 → streamlit_octostar_utils-0.4.2.dev13}/streamlit_octostar_utils/octostar/context.py +0 -0
- {streamlit_octostar_utils-0.4.2.dev11 → streamlit_octostar_utils-0.4.2.dev13}/streamlit_octostar_utils/octostar/permissions.py +0 -0
- {streamlit_octostar_utils-0.4.2.dev11 → streamlit_octostar_utils-0.4.2.dev13}/streamlit_octostar_utils/ontology/__init__.py +0 -0
- {streamlit_octostar_utils-0.4.2.dev11 → streamlit_octostar_utils-0.4.2.dev13}/streamlit_octostar_utils/ontology/inheritance.py +0 -0
- {streamlit_octostar_utils-0.4.2.dev11 → streamlit_octostar_utils-0.4.2.dev13}/streamlit_octostar_utils/ontology/relationships.py +0 -0
- {streamlit_octostar_utils-0.4.2.dev11 → streamlit_octostar_utils-0.4.2.dev13}/streamlit_octostar_utils/ontology/validation.py +0 -0
- {streamlit_octostar_utils-0.4.2.dev11 → streamlit_octostar_utils-0.4.2.dev13}/streamlit_octostar_utils/style/__init__.py +0 -0
- {streamlit_octostar_utils-0.4.2.dev11 → streamlit_octostar_utils-0.4.2.dev13}/streamlit_octostar_utils/style/common.py +0 -0
- {streamlit_octostar_utils-0.4.2.dev11 → streamlit_octostar_utils-0.4.2.dev13}/streamlit_octostar_utils/threading/__init__.py +0 -0
- {streamlit_octostar_utils-0.4.2.dev11 → streamlit_octostar_utils-0.4.2.dev13}/streamlit_octostar_utils/threading/async_task_manager.py +0 -0
- {streamlit_octostar_utils-0.4.2.dev11 → streamlit_octostar_utils-0.4.2.dev13}/streamlit_octostar_utils/threading/session_callback_manager.py +0 -0
- {streamlit_octostar_utils-0.4.2.dev11 → streamlit_octostar_utils-0.4.2.dev13}/streamlit_octostar_utils/threading/session_state_hot_swapper.py +0 -0
|
@@ -18,7 +18,6 @@ from abc import ABC, abstractmethod
|
|
|
18
18
|
from typing import Optional, Dict, Any, List
|
|
19
19
|
from enum import Enum
|
|
20
20
|
import base64
|
|
21
|
-
import httpx
|
|
22
21
|
import logging
|
|
23
22
|
from io import BytesIO, SEEK_SET, SEEK_CUR, SEEK_END
|
|
24
23
|
|
|
@@ -710,20 +709,18 @@ class TemporaryAttachmentContents(Contents):
|
|
|
710
709
|
"""
|
|
711
710
|
Contents implementation for Octostar temporary blob storage.
|
|
712
711
|
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
712
|
+
Uses the SDK's ``read_temporary_blob`` / ``write_temporary_blob`` /
|
|
713
|
+
``delete_temporary_blob`` functions which handle presigned URLs internally.
|
|
714
|
+
|
|
715
|
+
- Reads use ``read_temporary_blob.sync()`` with ``byte_range`` for efficient
|
|
716
|
+
partial reads and ``headers_only=True`` for HEAD metadata.
|
|
717
|
+
- Writes are buffered locally and uploaded on ``flush()`` via
|
|
718
|
+
``write_temporary_blob.sync()``.
|
|
716
719
|
|
|
717
720
|
Temporary blobs are keyed by filename (not workspace/entity), and are not
|
|
718
721
|
associated with any workspace entity. Use WorkspaceAttachmentContents for that.
|
|
719
|
-
|
|
720
|
-
Presigned URL Handling:
|
|
721
|
-
- Download URLs are cached and refreshed automatically on 403 (expired).
|
|
722
722
|
"""
|
|
723
723
|
|
|
724
|
-
DEFAULT_URL_TIMEOUT = 120
|
|
725
|
-
MAX_RETRIES = 3
|
|
726
|
-
|
|
727
724
|
def __init__(
|
|
728
725
|
self,
|
|
729
726
|
entity_type: Optional[str] = None,
|
|
@@ -741,150 +738,70 @@ class TemporaryAttachmentContents(Contents):
|
|
|
741
738
|
self._modified = False
|
|
742
739
|
self._position = 0
|
|
743
740
|
self._size: Optional[int] = None
|
|
744
|
-
self._download_url: Optional[str] = None
|
|
745
|
-
self._http_client: Optional[httpx.Client] = None
|
|
746
|
-
|
|
747
|
-
# ==================== Presigned URL management ====================
|
|
748
|
-
|
|
749
|
-
def _ensure_http_client(self):
|
|
750
|
-
"""Ensure the shared httpx.Client is initialized."""
|
|
751
|
-
if not self._http_client:
|
|
752
|
-
self._http_client = httpx.Client(timeout=self.DEFAULT_URL_TIMEOUT)
|
|
753
|
-
|
|
754
|
-
def _ensure_download_url(self):
|
|
755
|
-
"""Ensure a download URL is cached, fetching one if needed."""
|
|
756
|
-
if not self._download_url:
|
|
757
|
-
self._download_url = self._refresh_download_url()
|
|
758
741
|
|
|
759
|
-
|
|
760
|
-
from octostar.utils.workspace import get_temporary_blob_url
|
|
761
|
-
|
|
762
|
-
return get_temporary_blob_url.sync(
|
|
763
|
-
filename=self._filename,
|
|
764
|
-
client=self._client
|
|
765
|
-
)
|
|
766
|
-
|
|
767
|
-
def _get_upload_info(self) -> Dict[str, Any]:
|
|
768
|
-
from octostar.utils.workspace import request_temporary_blob_url
|
|
769
|
-
|
|
770
|
-
return request_temporary_blob_url.sync(
|
|
771
|
-
filename=self._filename,
|
|
772
|
-
client=self._client
|
|
773
|
-
)
|
|
774
|
-
|
|
775
|
-
# ==================== Remote operations ====================
|
|
742
|
+
# ==================== Remote operations via SDK ====================
|
|
776
743
|
|
|
777
744
|
def _fetch_size(self) -> int:
|
|
778
|
-
"""Fetch remote content size via HEAD request
|
|
745
|
+
"""Fetch the remote content size via a HEAD request."""
|
|
779
746
|
if self._size is not None:
|
|
780
747
|
return self._size
|
|
781
748
|
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
_logger.debug(
|
|
795
|
-
"Presigned URL expired while fetching size, refreshing... (attempt %d/%d)",
|
|
796
|
-
attempt + 1, self.MAX_RETRIES,
|
|
797
|
-
)
|
|
798
|
-
self._download_url = self._refresh_download_url()
|
|
799
|
-
continue
|
|
800
|
-
else:
|
|
801
|
-
response.raise_for_status()
|
|
802
|
-
|
|
803
|
-
raise ConnectionError(
|
|
804
|
-
f"Failed to fetch file size after {self.MAX_RETRIES} attempts (URL kept expiring)"
|
|
805
|
-
)
|
|
749
|
+
try:
|
|
750
|
+
from octostar.utils.workspace import read_temporary_blob
|
|
751
|
+
|
|
752
|
+
headers = read_temporary_blob.sync(
|
|
753
|
+
filename=self._filename,
|
|
754
|
+
headers_only=True,
|
|
755
|
+
client=self._client,
|
|
756
|
+
)
|
|
757
|
+
self._size = int(headers.get('content-length', 0))
|
|
758
|
+
except Exception:
|
|
759
|
+
self._size = 0
|
|
760
|
+
return self._size
|
|
806
761
|
|
|
807
762
|
def _read_range(self, start: int, end: int) -> bytes:
|
|
808
|
-
"""Read a specific byte range
|
|
809
|
-
|
|
810
|
-
self._ensure_http_client()
|
|
811
|
-
assert self._http_client is not None
|
|
812
|
-
assert self._download_url is not None
|
|
813
|
-
|
|
814
|
-
headers = {"Range": f"bytes={start}-{end}"}
|
|
763
|
+
"""Read a specific byte range from the remote blob."""
|
|
764
|
+
from octostar.utils.workspace import read_temporary_blob
|
|
815
765
|
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
elif response.status_code == 416:
|
|
822
|
-
return b""
|
|
823
|
-
elif response.status_code == 403:
|
|
824
|
-
_logger.debug(
|
|
825
|
-
"Presigned URL expired at byte %d, refreshing... (attempt %d/%d)",
|
|
826
|
-
start, attempt + 1, self.MAX_RETRIES,
|
|
827
|
-
)
|
|
828
|
-
self._download_url = self._refresh_download_url()
|
|
829
|
-
continue
|
|
830
|
-
else:
|
|
831
|
-
response.raise_for_status()
|
|
832
|
-
return response.content
|
|
833
|
-
|
|
834
|
-
raise ConnectionError(
|
|
835
|
-
f"Failed to read range {start}-{end} after {self.MAX_RETRIES} attempts (URL kept expiring)"
|
|
766
|
+
data = read_temporary_blob.sync(
|
|
767
|
+
filename=self._filename,
|
|
768
|
+
decode=False,
|
|
769
|
+
byte_range=(start, end),
|
|
770
|
+
client=self._client,
|
|
836
771
|
)
|
|
772
|
+
return data if isinstance(data, bytes) else data.encode()
|
|
837
773
|
|
|
838
774
|
def _load_full(self):
|
|
839
|
-
"""Load the entire remote
|
|
775
|
+
"""Load the entire remote blob into the in-memory buffer."""
|
|
840
776
|
if self._fully_loaded:
|
|
841
777
|
return
|
|
842
778
|
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
self._size = len(data)
|
|
855
|
-
self._buffer.seek(self._position, SEEK_SET)
|
|
856
|
-
return
|
|
857
|
-
elif response.status_code == 403:
|
|
858
|
-
_logger.debug(
|
|
859
|
-
"Presigned URL expired during full load, refreshing... (attempt %d/%d)",
|
|
860
|
-
attempt + 1, self.MAX_RETRIES,
|
|
861
|
-
)
|
|
862
|
-
self._download_url = self._refresh_download_url()
|
|
863
|
-
continue
|
|
864
|
-
else:
|
|
865
|
-
response.raise_for_status()
|
|
779
|
+
try:
|
|
780
|
+
from octostar.utils.workspace import read_temporary_blob
|
|
781
|
+
|
|
782
|
+
data = read_temporary_blob.sync(
|
|
783
|
+
filename=self._filename,
|
|
784
|
+
decode=False,
|
|
785
|
+
client=self._client,
|
|
786
|
+
)
|
|
787
|
+
except Exception:
|
|
788
|
+
# Blob may not exist yet — start with empty buffer
|
|
789
|
+
data = b""
|
|
866
790
|
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
)
|
|
791
|
+
self._buffer = BytesIO(data)
|
|
792
|
+
self._fully_loaded = True
|
|
793
|
+
self._size = len(data)
|
|
794
|
+
self._buffer.seek(self._position, SEEK_SET)
|
|
870
795
|
|
|
871
796
|
def _upload_data(self, data: bytes):
|
|
872
|
-
"""Upload data
|
|
873
|
-
|
|
874
|
-
upload_url = upload_info["url"]
|
|
875
|
-
upload_fields = upload_info.get("fields", {})
|
|
876
|
-
|
|
877
|
-
self._ensure_http_client()
|
|
878
|
-
assert self._http_client is not None
|
|
879
|
-
file_obj = BytesIO(data)
|
|
797
|
+
"""Upload data via the SDK write_temporary_blob."""
|
|
798
|
+
from octostar.utils.workspace import write_temporary_blob
|
|
880
799
|
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
data
|
|
884
|
-
|
|
800
|
+
write_temporary_blob.sync(
|
|
801
|
+
filename=self._filename,
|
|
802
|
+
file=data,
|
|
803
|
+
client=self._client,
|
|
885
804
|
)
|
|
886
|
-
if response.status_code not in (200, 204):
|
|
887
|
-
response.raise_for_status()
|
|
888
805
|
|
|
889
806
|
# ==================== FileIO Interface ====================
|
|
890
807
|
|
|
@@ -952,7 +869,7 @@ class TemporaryAttachmentContents(Contents):
|
|
|
952
869
|
return self._position
|
|
953
870
|
|
|
954
871
|
def flush(self):
|
|
955
|
-
"""Upload buffer to temporary storage
|
|
872
|
+
"""Upload buffer to temporary storage, then invalidate cache."""
|
|
956
873
|
if self._buffer:
|
|
957
874
|
self._buffer.flush()
|
|
958
875
|
|
|
@@ -972,7 +889,6 @@ class TemporaryAttachmentContents(Contents):
|
|
|
972
889
|
self._fully_loaded = False
|
|
973
890
|
self._position = 0
|
|
974
891
|
self._size = None
|
|
975
|
-
self._download_url = None
|
|
976
892
|
|
|
977
893
|
def close(self):
|
|
978
894
|
if not self._closed:
|
|
@@ -980,9 +896,6 @@ class TemporaryAttachmentContents(Contents):
|
|
|
980
896
|
self.flush()
|
|
981
897
|
if self._buffer:
|
|
982
898
|
self._buffer.close()
|
|
983
|
-
if self._http_client:
|
|
984
|
-
self._http_client.close()
|
|
985
|
-
self._http_client = None
|
|
986
899
|
super().close()
|
|
987
900
|
|
|
988
901
|
def truncate(self, size: Optional[int] = None) -> int:
|
|
@@ -524,9 +524,11 @@ class NifiContextManager(object):
|
|
|
524
524
|
fetch_relationships_entities = {}
|
|
525
525
|
fetch_concept_relationships = {}
|
|
526
526
|
for entity in entities:
|
|
527
|
-
|
|
527
|
+
rels_to_fetch = (
|
|
528
|
+
entity.sync_params.get(NifiContextManager.SyncFlag.FETCH_RELATIONSHIPS) or {}
|
|
529
|
+
).get("relationships") or []
|
|
530
|
+
if rels_to_fetch:
|
|
528
531
|
concept_name = entity.record["entity_type"]
|
|
529
|
-
rels_to_fetch = entity.sync_params.get(NifiContextManager.SyncFlag.FETCH_RELATIONSHIPS, [])
|
|
530
532
|
for rel in rels_to_fetch:
|
|
531
533
|
if rel not in fetch_relationships_entities:
|
|
532
534
|
fetch_relationships_entities[rel] = []
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|