streamlit-octostar-utils 0.4.2.dev16__tar.gz → 0.4.2.dev18__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.4.2.dev16 → streamlit_octostar_utils-0.4.2.dev18}/PKG-INFO +1 -1
  2. {streamlit_octostar_utils-0.4.2.dev16 → streamlit_octostar_utils-0.4.2.dev18}/pyproject.toml +1 -1
  3. {streamlit_octostar_utils-0.4.2.dev16 → streamlit_octostar_utils-0.4.2.dev18}/streamlit_octostar_utils/api_crafter/celery.py +7 -2
  4. {streamlit_octostar_utils-0.4.2.dev16 → streamlit_octostar_utils-0.4.2.dev18}/streamlit_octostar_utils/api_crafter/contents.py +100 -0
  5. {streamlit_octostar_utils-0.4.2.dev16 → streamlit_octostar_utils-0.4.2.dev18}/streamlit_octostar_utils/api_crafter/fastapi.py +10 -1
  6. {streamlit_octostar_utils-0.4.2.dev16 → streamlit_octostar_utils-0.4.2.dev18}/streamlit_octostar_utils/api_crafter/nifi.py +1 -1
  7. {streamlit_octostar_utils-0.4.2.dev16 → streamlit_octostar_utils-0.4.2.dev18}/LICENSE +0 -0
  8. {streamlit_octostar_utils-0.4.2.dev16 → streamlit_octostar_utils-0.4.2.dev18}/README.md +0 -0
  9. {streamlit_octostar_utils-0.4.2.dev16 → streamlit_octostar_utils-0.4.2.dev18}/streamlit_octostar_utils/__init__.py +0 -0
  10. {streamlit_octostar_utils-0.4.2.dev16 → streamlit_octostar_utils-0.4.2.dev18}/streamlit_octostar_utils/api_crafter/__init__.py +0 -0
  11. {streamlit_octostar_utils-0.4.2.dev16 → streamlit_octostar_utils-0.4.2.dev18}/streamlit_octostar_utils/api_crafter/parallelism.py +0 -0
  12. {streamlit_octostar_utils-0.4.2.dev16 → streamlit_octostar_utils-0.4.2.dev18}/streamlit_octostar_utils/api_crafter/parser/__init__.py +0 -0
  13. {streamlit_octostar_utils-0.4.2.dev16 → streamlit_octostar_utils-0.4.2.dev18}/streamlit_octostar_utils/api_crafter/parser/combine_fields.py +0 -0
  14. {streamlit_octostar_utils-0.4.2.dev16 → streamlit_octostar_utils-0.4.2.dev18}/streamlit_octostar_utils/api_crafter/parser/entities_parser.py +0 -0
  15. {streamlit_octostar_utils-0.4.2.dev16 → streamlit_octostar_utils-0.4.2.dev18}/streamlit_octostar_utils/api_crafter/parser/generics.py +0 -0
  16. {streamlit_octostar_utils-0.4.2.dev16 → streamlit_octostar_utils-0.4.2.dev18}/streamlit_octostar_utils/api_crafter/parser/info.py +0 -0
  17. {streamlit_octostar_utils-0.4.2.dev16 → streamlit_octostar_utils-0.4.2.dev18}/streamlit_octostar_utils/api_crafter/parser/linkchart_functions.py +0 -0
  18. {streamlit_octostar_utils-0.4.2.dev16 → streamlit_octostar_utils-0.4.2.dev18}/streamlit_octostar_utils/api_crafter/parser/matches.py +0 -0
  19. {streamlit_octostar_utils-0.4.2.dev16 → streamlit_octostar_utils-0.4.2.dev18}/streamlit_octostar_utils/api_crafter/parser/parameters.py +0 -0
  20. {streamlit_octostar_utils-0.4.2.dev16 → streamlit_octostar_utils-0.4.2.dev18}/streamlit_octostar_utils/api_crafter/parser/rules.py +0 -0
  21. {streamlit_octostar_utils-0.4.2.dev16 → streamlit_octostar_utils-0.4.2.dev18}/streamlit_octostar_utils/api_crafter/parser/signals.py +0 -0
  22. {streamlit_octostar_utils-0.4.2.dev16 → streamlit_octostar_utils-0.4.2.dev18}/streamlit_octostar_utils/core/__init__.py +0 -0
  23. {streamlit_octostar_utils-0.4.2.dev16 → streamlit_octostar_utils-0.4.2.dev18}/streamlit_octostar_utils/core/dict.py +0 -0
  24. {streamlit_octostar_utils-0.4.2.dev16 → streamlit_octostar_utils-0.4.2.dev18}/streamlit_octostar_utils/core/filetypes.py +0 -0
  25. {streamlit_octostar_utils-0.4.2.dev16 → streamlit_octostar_utils-0.4.2.dev18}/streamlit_octostar_utils/core/threading/__init__.py +0 -0
  26. {streamlit_octostar_utils-0.4.2.dev16 → streamlit_octostar_utils-0.4.2.dev18}/streamlit_octostar_utils/core/threading/key_queue.py +0 -0
  27. {streamlit_octostar_utils-0.4.2.dev16 → streamlit_octostar_utils-0.4.2.dev18}/streamlit_octostar_utils/core/timestamp.py +0 -0
  28. {streamlit_octostar_utils-0.4.2.dev16 → streamlit_octostar_utils-0.4.2.dev18}/streamlit_octostar_utils/nlp/__init__.py +0 -0
  29. {streamlit_octostar_utils-0.4.2.dev16 → streamlit_octostar_utils-0.4.2.dev18}/streamlit_octostar_utils/nlp/custom_recognizers.py +0 -0
  30. {streamlit_octostar_utils-0.4.2.dev16 → streamlit_octostar_utils-0.4.2.dev18}/streamlit_octostar_utils/nlp/language.py +0 -0
  31. {streamlit_octostar_utils-0.4.2.dev16 → streamlit_octostar_utils-0.4.2.dev18}/streamlit_octostar_utils/nlp/ner.py +0 -0
  32. {streamlit_octostar_utils-0.4.2.dev16 → streamlit_octostar_utils-0.4.2.dev18}/streamlit_octostar_utils/octostar/__init__.py +0 -0
  33. {streamlit_octostar_utils-0.4.2.dev16 → streamlit_octostar_utils-0.4.2.dev18}/streamlit_octostar_utils/octostar/client.py +0 -0
  34. {streamlit_octostar_utils-0.4.2.dev16 → streamlit_octostar_utils-0.4.2.dev18}/streamlit_octostar_utils/octostar/context.py +0 -0
  35. {streamlit_octostar_utils-0.4.2.dev16 → streamlit_octostar_utils-0.4.2.dev18}/streamlit_octostar_utils/octostar/permissions.py +0 -0
  36. {streamlit_octostar_utils-0.4.2.dev16 → streamlit_octostar_utils-0.4.2.dev18}/streamlit_octostar_utils/ontology/__init__.py +0 -0
  37. {streamlit_octostar_utils-0.4.2.dev16 → streamlit_octostar_utils-0.4.2.dev18}/streamlit_octostar_utils/ontology/inheritance.py +0 -0
  38. {streamlit_octostar_utils-0.4.2.dev16 → streamlit_octostar_utils-0.4.2.dev18}/streamlit_octostar_utils/ontology/relationships.py +0 -0
  39. {streamlit_octostar_utils-0.4.2.dev16 → streamlit_octostar_utils-0.4.2.dev18}/streamlit_octostar_utils/ontology/validation.py +0 -0
  40. {streamlit_octostar_utils-0.4.2.dev16 → streamlit_octostar_utils-0.4.2.dev18}/streamlit_octostar_utils/style/__init__.py +0 -0
  41. {streamlit_octostar_utils-0.4.2.dev16 → streamlit_octostar_utils-0.4.2.dev18}/streamlit_octostar_utils/style/common.py +0 -0
  42. {streamlit_octostar_utils-0.4.2.dev16 → streamlit_octostar_utils-0.4.2.dev18}/streamlit_octostar_utils/threading/__init__.py +0 -0
  43. {streamlit_octostar_utils-0.4.2.dev16 → streamlit_octostar_utils-0.4.2.dev18}/streamlit_octostar_utils/threading/async_task_manager.py +0 -0
  44. {streamlit_octostar_utils-0.4.2.dev16 → streamlit_octostar_utils-0.4.2.dev18}/streamlit_octostar_utils/threading/session_callback_manager.py +0 -0
  45. {streamlit_octostar_utils-0.4.2.dev16 → streamlit_octostar_utils-0.4.2.dev18}/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.4.2.dev16
3
+ Version: 0.4.2.dev18
4
4
  Summary:
5
5
  License: MIT
6
6
  License-File: LICENSE
@@ -5,7 +5,7 @@ include = '\.pyi?$'
5
5
 
6
6
  [tool.poetry]
7
7
  name = "streamlit-octostar-utils"
8
- version = "0.4.2-dev.16"
8
+ version = "0.4.2-dev.18"
9
9
  description = ""
10
10
  license = "MIT"
11
11
  authors = ["Octostar"]
@@ -28,7 +28,7 @@ logging.getLogger("pottery").setLevel(logging.WARNING)
28
28
  from celery.app.defaults import DEFAULTS as CELERY_DEFAULTS
29
29
  import urllib
30
30
 
31
- from .fastapi import Route, CommonModels, DefaultErrorRoute
31
+ from .fastapi import Route, CommonModels, DefaultErrorRoute, RemoteTraceback
32
32
 
33
33
 
34
34
  class RedisFileLock:
@@ -700,7 +700,12 @@ class CeleryExecutor(object):
700
700
 
701
701
  async def get_task_result(self, task_id, remove=False):
702
702
  def _try_get_task_data(celery_app, task_id):
703
- celery_app.AsyncResult(task_id).get() # will raise if the task raised an exception
703
+ async_result = celery_app.AsyncResult(task_id)
704
+ if async_result.state in ("FAILURE", "RETRY", "REVOKED"):
705
+ exc = async_result.result
706
+ if not isinstance(exc, BaseException):
707
+ exc = RuntimeError(str(exc))
708
+ raise exc from RemoteTraceback(async_result.traceback)
704
709
 
705
710
  def _read_task_data(out_folder, task_id):
706
711
  serialized_data = CelerySerialized(folder=out_folder, redis_client=self.redis_client)
@@ -29,6 +29,7 @@ class ContentsLocation(Enum):
29
29
  MEMORY = "memory"
30
30
  WORKSPACE_ATTACHMENT = "workspace_attachment"
31
31
  TEMPORARY_ATTACHMENT = "temporary_attachment"
32
+ REFERENCE = "reference"
32
33
 
33
34
 
34
35
  class Contents(ABC):
@@ -283,6 +284,8 @@ class Contents(ABC):
283
284
  return WorkspaceAttachmentContents._from_locator(locator, client)
284
285
  case ContentsLocation.TEMPORARY_ATTACHMENT.value:
285
286
  return TemporaryAttachmentContents._from_locator(locator, client)
287
+ case ContentsLocation.REFERENCE.value:
288
+ return ReferenceContents._from_locator(locator, client)
286
289
  case _:
287
290
  raise ValueError(f"Unknown contents location type: {location}")
288
291
 
@@ -954,3 +957,100 @@ class TemporaryAttachmentContents(Contents):
954
957
  filename=locator["filename"],
955
958
  client=client
956
959
  )
960
+
961
+
962
+ class ReferenceContents(Contents):
963
+ """
964
+ Contents that delegates reads to one source and writes to another.
965
+
966
+ Useful for fragments that share their parent's attachment but need their
967
+ own write target for content syncing. When the sync system calls
968
+ ``read()``, the data is read from ``read_source``. On ``write()``, the data is written to ``write_target``.
969
+
970
+ ``read_source`` is **not owned** by this instance — it will not be closed
971
+ or deleted, since it may be shared across multiple fragments.
972
+ """
973
+
974
+ def __init__(
975
+ self,
976
+ entity_type: Optional[str] = None,
977
+ filetype: Optional[str] = None,
978
+ *,
979
+ read_source: Optional[Contents] = None,
980
+ write_target: Optional[Contents] = None,
981
+ **kwargs
982
+ ):
983
+ super().__init__(entity_type, filetype, **kwargs)
984
+ self._read_source = read_source
985
+ self._write_target = write_target
986
+
987
+ # ==================== FileIO Interface ====================
988
+
989
+ def read(self, size: int = -1) -> bytes:
990
+ if self._read_source:
991
+ return self._read_source.read(size)
992
+ return b""
993
+
994
+ def write(self, b: bytes) -> int:
995
+ if self._write_target:
996
+ return self._write_target.write(b)
997
+ raise IOError("ReferenceContents has no write_target configured")
998
+
999
+ def seek(self, offset: int, whence: int = SEEK_SET) -> int:
1000
+ if self._read_source:
1001
+ return self._read_source.seek(offset, whence)
1002
+ return 0
1003
+
1004
+ def tell(self) -> int:
1005
+ if self._read_source:
1006
+ return self._read_source.tell()
1007
+ return 0
1008
+
1009
+ def flush(self):
1010
+ if self._write_target:
1011
+ self._write_target.flush()
1012
+
1013
+ def close(self):
1014
+ if not self._closed:
1015
+ if self._write_target:
1016
+ self._write_target.close()
1017
+ super().close()
1018
+
1019
+ def delete(self):
1020
+ if self._write_target:
1021
+ self._write_target.delete()
1022
+
1023
+ def truncate(self, size: Optional[int] = None) -> int:
1024
+ if self._write_target:
1025
+ return self._write_target.truncate(size)
1026
+ return 0
1027
+
1028
+ def getvalue(self) -> bytes:
1029
+ if self._read_source:
1030
+ return self._read_source.getvalue()
1031
+ return b""
1032
+
1033
+ # ==================== Locator Interface ====================
1034
+
1035
+ def to_locator(self) -> Dict[str, Any]:
1036
+ locator: Dict[str, Any] = {
1037
+ "location": ContentsLocation.REFERENCE.value,
1038
+ "read_source": self._read_source.to_locator() if self._read_source else None,
1039
+ "write_target": self._write_target.to_locator() if self._write_target else None,
1040
+ }
1041
+ if self._entity_type:
1042
+ locator["entity_type"] = self._entity_type
1043
+ if self._filetype:
1044
+ locator["filetype"] = self._filetype
1045
+ return locator
1046
+
1047
+ @staticmethod
1048
+ def _from_locator(locator: Dict[str, Any], client=None) -> 'ReferenceContents':
1049
+ read_source = Contents.from_locator(locator.get("read_source"), client)
1050
+ write_target = Contents.from_locator(locator.get("write_target"), client)
1051
+ return ReferenceContents(
1052
+ entity_type=locator.get("entity_type"),
1053
+ filetype=locator.get("filetype"),
1054
+ read_source=read_source,
1055
+ write_target=write_target,
1056
+ )
@@ -267,6 +267,11 @@ class ErrorLogFilter(logging.Filter):
267
267
  return True
268
268
 
269
269
 
270
+ class RemoteTraceback(Exception):
271
+ """Holds a formatted traceback string from a remote worker process."""
272
+ pass
273
+
274
+
270
275
  class DefaultErrorRoute:
271
276
  DEFAULT_STATUS_CODE_MAPPINGS = {
272
277
  StarletteHTTPException: lambda exc: exc.status_code,
@@ -329,7 +334,11 @@ class DefaultErrorRoute:
329
334
  if len(message) > MAX_ERROR_MESSAGE_BYTES:
330
335
  message = message[-MAX_ERROR_MESSAGE_BYTES:]
331
336
  try:
332
- tcbk = "\n".join(traceback.format_exception(exc))
337
+ remote_cause = getattr(exc, "__cause__", None)
338
+ if isinstance(remote_cause, RemoteTraceback):
339
+ tcbk = str(remote_cause)
340
+ else:
341
+ tcbk = "\n".join(traceback.format_exception(exc))
333
342
  if len(tcbk) > MAX_ERROR_TRACEBACK_BYTES:
334
343
  tcbk = tcbk[-MAX_ERROR_TRACEBACK_BYTES:]
335
344
  except:
@@ -489,7 +489,7 @@ class NifiContextManager(object):
489
489
  old_contents.delete()
490
490
  except Exception:
491
491
  pass
492
- new_entity = target.last_flush_result or {}
492
+ new_entity = target.last_flush_result
493
493
  if new_entity:
494
494
  file.record = {**record, **new_entity}
495
495
  file.record["entity_id"] = file.record["os_entity_uid"]