streamlit-octostar-utils 0.5.4.dev5__tar.gz → 0.5.5.dev1__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.dev5 → streamlit_octostar_utils-0.5.5.dev1}/PKG-INFO +2 -1
  2. {streamlit_octostar_utils-0.5.4.dev5 → streamlit_octostar_utils-0.5.5.dev1}/pyproject.toml +2 -1
  3. {streamlit_octostar_utils-0.5.4.dev5 → streamlit_octostar_utils-0.5.5.dev1}/streamlit_octostar_utils/api_crafter/nifi.py +168 -0
  4. {streamlit_octostar_utils-0.5.4.dev5 → streamlit_octostar_utils-0.5.5.dev1}/LICENSE +0 -0
  5. {streamlit_octostar_utils-0.5.4.dev5 → streamlit_octostar_utils-0.5.5.dev1}/README.md +0 -0
  6. {streamlit_octostar_utils-0.5.4.dev5 → streamlit_octostar_utils-0.5.5.dev1}/streamlit_octostar_utils/__init__.py +0 -0
  7. {streamlit_octostar_utils-0.5.4.dev5 → streamlit_octostar_utils-0.5.5.dev1}/streamlit_octostar_utils/api_crafter/__init__.py +0 -0
  8. {streamlit_octostar_utils-0.5.4.dev5 → streamlit_octostar_utils-0.5.5.dev1}/streamlit_octostar_utils/api_crafter/celery.py +0 -0
  9. {streamlit_octostar_utils-0.5.4.dev5 → streamlit_octostar_utils-0.5.5.dev1}/streamlit_octostar_utils/api_crafter/contents.py +0 -0
  10. {streamlit_octostar_utils-0.5.4.dev5 → streamlit_octostar_utils-0.5.5.dev1}/streamlit_octostar_utils/api_crafter/fastapi.py +0 -0
  11. {streamlit_octostar_utils-0.5.4.dev5 → streamlit_octostar_utils-0.5.5.dev1}/streamlit_octostar_utils/api_crafter/parallelism.py +0 -0
  12. {streamlit_octostar_utils-0.5.4.dev5 → streamlit_octostar_utils-0.5.5.dev1}/streamlit_octostar_utils/api_crafter/parser/__init__.py +0 -0
  13. {streamlit_octostar_utils-0.5.4.dev5 → streamlit_octostar_utils-0.5.5.dev1}/streamlit_octostar_utils/api_crafter/parser/combine_fields.py +0 -0
  14. {streamlit_octostar_utils-0.5.4.dev5 → streamlit_octostar_utils-0.5.5.dev1}/streamlit_octostar_utils/api_crafter/parser/entities_parser.py +0 -0
  15. {streamlit_octostar_utils-0.5.4.dev5 → streamlit_octostar_utils-0.5.5.dev1}/streamlit_octostar_utils/api_crafter/parser/generics.py +0 -0
  16. {streamlit_octostar_utils-0.5.4.dev5 → streamlit_octostar_utils-0.5.5.dev1}/streamlit_octostar_utils/api_crafter/parser/info.py +0 -0
  17. {streamlit_octostar_utils-0.5.4.dev5 → streamlit_octostar_utils-0.5.5.dev1}/streamlit_octostar_utils/api_crafter/parser/linkchart_functions.py +0 -0
  18. {streamlit_octostar_utils-0.5.4.dev5 → streamlit_octostar_utils-0.5.5.dev1}/streamlit_octostar_utils/api_crafter/parser/matches.py +0 -0
  19. {streamlit_octostar_utils-0.5.4.dev5 → streamlit_octostar_utils-0.5.5.dev1}/streamlit_octostar_utils/api_crafter/parser/parameters.py +0 -0
  20. {streamlit_octostar_utils-0.5.4.dev5 → streamlit_octostar_utils-0.5.5.dev1}/streamlit_octostar_utils/api_crafter/parser/rules.py +0 -0
  21. {streamlit_octostar_utils-0.5.4.dev5 → streamlit_octostar_utils-0.5.5.dev1}/streamlit_octostar_utils/api_crafter/parser/signals.py +0 -0
  22. {streamlit_octostar_utils-0.5.4.dev5 → streamlit_octostar_utils-0.5.5.dev1}/streamlit_octostar_utils/core/__init__.py +0 -0
  23. {streamlit_octostar_utils-0.5.4.dev5 → streamlit_octostar_utils-0.5.5.dev1}/streamlit_octostar_utils/core/dict.py +0 -0
  24. {streamlit_octostar_utils-0.5.4.dev5 → streamlit_octostar_utils-0.5.5.dev1}/streamlit_octostar_utils/core/filetypes.py +0 -0
  25. {streamlit_octostar_utils-0.5.4.dev5 → streamlit_octostar_utils-0.5.5.dev1}/streamlit_octostar_utils/core/threading/__init__.py +0 -0
  26. {streamlit_octostar_utils-0.5.4.dev5 → streamlit_octostar_utils-0.5.5.dev1}/streamlit_octostar_utils/core/threading/key_queue.py +0 -0
  27. {streamlit_octostar_utils-0.5.4.dev5 → streamlit_octostar_utils-0.5.5.dev1}/streamlit_octostar_utils/core/timestamp.py +0 -0
  28. {streamlit_octostar_utils-0.5.4.dev5 → streamlit_octostar_utils-0.5.5.dev1}/streamlit_octostar_utils/nlp/__init__.py +0 -0
  29. {streamlit_octostar_utils-0.5.4.dev5 → streamlit_octostar_utils-0.5.5.dev1}/streamlit_octostar_utils/nlp/custom_recognizers.py +0 -0
  30. {streamlit_octostar_utils-0.5.4.dev5 → streamlit_octostar_utils-0.5.5.dev1}/streamlit_octostar_utils/nlp/language.py +0 -0
  31. {streamlit_octostar_utils-0.5.4.dev5 → streamlit_octostar_utils-0.5.5.dev1}/streamlit_octostar_utils/nlp/ner.py +0 -0
  32. {streamlit_octostar_utils-0.5.4.dev5 → streamlit_octostar_utils-0.5.5.dev1}/streamlit_octostar_utils/octostar/__init__.py +0 -0
  33. {streamlit_octostar_utils-0.5.4.dev5 → streamlit_octostar_utils-0.5.5.dev1}/streamlit_octostar_utils/octostar/client.py +0 -0
  34. {streamlit_octostar_utils-0.5.4.dev5 → streamlit_octostar_utils-0.5.5.dev1}/streamlit_octostar_utils/octostar/context.py +0 -0
  35. {streamlit_octostar_utils-0.5.4.dev5 → streamlit_octostar_utils-0.5.5.dev1}/streamlit_octostar_utils/octostar/permissions.py +0 -0
  36. {streamlit_octostar_utils-0.5.4.dev5 → streamlit_octostar_utils-0.5.5.dev1}/streamlit_octostar_utils/ontology/__init__.py +0 -0
  37. {streamlit_octostar_utils-0.5.4.dev5 → streamlit_octostar_utils-0.5.5.dev1}/streamlit_octostar_utils/ontology/inheritance.py +0 -0
  38. {streamlit_octostar_utils-0.5.4.dev5 → streamlit_octostar_utils-0.5.5.dev1}/streamlit_octostar_utils/ontology/relationships.py +0 -0
  39. {streamlit_octostar_utils-0.5.4.dev5 → streamlit_octostar_utils-0.5.5.dev1}/streamlit_octostar_utils/ontology/validation.py +0 -0
  40. {streamlit_octostar_utils-0.5.4.dev5 → streamlit_octostar_utils-0.5.5.dev1}/streamlit_octostar_utils/style/__init__.py +0 -0
  41. {streamlit_octostar_utils-0.5.4.dev5 → streamlit_octostar_utils-0.5.5.dev1}/streamlit_octostar_utils/style/common.py +0 -0
  42. {streamlit_octostar_utils-0.5.4.dev5 → streamlit_octostar_utils-0.5.5.dev1}/streamlit_octostar_utils/threading/__init__.py +0 -0
  43. {streamlit_octostar_utils-0.5.4.dev5 → streamlit_octostar_utils-0.5.5.dev1}/streamlit_octostar_utils/threading/async_task_manager.py +0 -0
  44. {streamlit_octostar_utils-0.5.4.dev5 → streamlit_octostar_utils-0.5.5.dev1}/streamlit_octostar_utils/threading/session_callback_manager.py +0 -0
  45. {streamlit_octostar_utils-0.5.4.dev5 → streamlit_octostar_utils-0.5.5.dev1}/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.dev5
3
+ Version: 0.5.5.dev1
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.5"
8
+ version = "0.5.5-dev.1"
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"
@@ -54,6 +54,144 @@ OS_RESERVED_FIELDS = [
54
54
  MAX_IN_MEMORY_SIZE_BYTES = 5_242_880
55
55
 
56
56
 
57
+ class NifiPriority:
58
+ COMPONENT_WIDTHS = (10, 10, 1, 20)
59
+ SEPARATOR = "."
60
+ MAX_FRAGMENT_DEPTH = 9
61
+ BASE62_CHARS = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
62
+ BASE = len(BASE62_CHARS)
63
+ _BASE62_SET = frozenset(BASE62_CHARS)
64
+
65
+ @staticmethod
66
+ def _normalize_component(value, width):
67
+ if value is None:
68
+ return "z" * width
69
+ s = str(value)
70
+ invalid = set(s) - NifiPriority._BASE62_SET
71
+ if invalid:
72
+ raise ValueError(f"Invalid base62 character(s): {sorted(invalid)!r}")
73
+ if len(s) > width:
74
+ return "z" * width
75
+ return s.rjust(width, "0")
76
+
77
+ def __init__(self, op_reserved=None, user_prio=None, fragment_prio=0, entity_timestamp=0):
78
+ w = self.COMPONENT_WIDTHS
79
+ self.op_reserved = self._normalize_component(op_reserved, w[0])
80
+ self.user_prio = self._normalize_component(user_prio, w[1])
81
+ self.fragment_prio = int(fragment_prio)
82
+ self.entity_timestamp = int(entity_timestamp)
83
+
84
+ @staticmethod
85
+ def _encode_base62(value, width):
86
+ chars = NifiPriority.BASE62_CHARS
87
+ base = NifiPriority.BASE
88
+ if value < 0:
89
+ value = 0
90
+ if value == 0:
91
+ return "0" * width
92
+ result = []
93
+ v = value
94
+ while v > 0:
95
+ result.append(chars[v % base])
96
+ v //= base
97
+ result.reverse()
98
+ s = "".join(result)
99
+ if len(s) > width:
100
+ return chars[-1] * width
101
+ return s.rjust(width, "0")
102
+
103
+ @staticmethod
104
+ def _decode_base62(s):
105
+ chars = NifiPriority.BASE62_CHARS
106
+ result = 0
107
+ for c in s:
108
+ idx = chars.find(c)
109
+ if idx < 0:
110
+ raise ValueError(f"Invalid base62 character: {c!r}")
111
+ result = result * NifiPriority.BASE + idx
112
+ return result
113
+
114
+ @classmethod
115
+ def from_string(cls, s):
116
+ if not s or cls.SEPARATOR not in s:
117
+ return cls()
118
+ parts = s.split(cls.SEPARATOR)
119
+ if len(parts) != 4:
120
+ return cls()
121
+ try:
122
+ for part in parts:
123
+ if set(part) - cls._BASE62_SET:
124
+ return cls()
125
+ return cls(
126
+ op_reserved=parts[0],
127
+ user_prio=parts[1],
128
+ fragment_prio=cls._decode_base62(parts[2]),
129
+ entity_timestamp=cls._decode_base62(parts[3]),
130
+ )
131
+ except (ValueError, TypeError):
132
+ return cls()
133
+
134
+ @classmethod
135
+ def from_dict(cls, d):
136
+ if not d:
137
+ return cls()
138
+ return cls(
139
+ op_reserved=d.get("op_reserved"),
140
+ user_prio=d.get("user_prio"),
141
+ fragment_prio=d.get("fragment_prio", 0),
142
+ entity_timestamp=d.get("entity_timestamp", 0),
143
+ )
144
+
145
+ @classmethod
146
+ def from_entity(cls, entity):
147
+ existing = entity.request.get("priority", {})
148
+ prio = cls.from_dict(existing)
149
+ prio.fragment_prio = cls.compute_fragment_depth(entity)
150
+ ts_str = entity.request.get("entity_timestamp")
151
+ if ts_str:
152
+ try:
153
+ dt = string_to_datetime(ts_str)
154
+ prio.entity_timestamp = int(dt.timestamp() * 1000)
155
+ except Exception:
156
+ prio.entity_timestamp = 0
157
+ else:
158
+ prio.entity_timestamp = 0
159
+ return prio
160
+
161
+ @staticmethod
162
+ def compute_fragment_depth(entity):
163
+ stack = entity.request.get("config", {}).get("fragment", {}).get("fragments_stack", [])
164
+ depth = 0
165
+ for key in stack:
166
+ try:
167
+ info = NifiFragmenter.get_fragment_info(entity, key)
168
+ if info.get("index", 0) != 0:
169
+ depth += 1
170
+ else:
171
+ break
172
+ except (KeyError, RuntimeError):
173
+ break
174
+ return min(depth, 9)
175
+
176
+ def to_string(self):
177
+ w = self.COMPONENT_WIDTHS
178
+ return self.SEPARATOR.join([
179
+ self.op_reserved,
180
+ self.user_prio,
181
+ self._encode_base62(self.fragment_prio, w[2]),
182
+ self._encode_base62(self.entity_timestamp, w[3]),
183
+ ])
184
+
185
+ def to_dict(self):
186
+ return {
187
+ "op_reserved": self.op_reserved,
188
+ "user_prio": self.user_prio,
189
+ }
190
+
191
+ def apply_to_entity(self, entity):
192
+ entity.request["priority"] = self.to_dict()
193
+
194
+
57
195
  class NifiProxyEntityModel(BaseModel):
58
196
  entity_id: str
59
197
  entity_type: str
@@ -86,6 +224,7 @@ class NifiEntityModel(BaseModel):
86
224
  exception: dict = Field(default_factory=dict)
87
225
  last_processor_name: Optional[str] = None
88
226
  fallback_os_workspace: Optional[str] = None
227
+ priority: dict = Field(default_factory=dict)
89
228
 
90
229
  class RecordModel(BaseModel):
91
230
  model_config = ConfigDict(extra="allow")
@@ -528,6 +667,8 @@ class NifiContextManager(object):
528
667
  key=lambda x: string_to_datetime(x.request.get("entity_timestamp")),
529
668
  )
530
669
  entities = list({e.record["entity_id"]: e for e in entities}.values())
670
+ for entity in entities:
671
+ NifiPriority.from_entity(entity).apply_to_entity(entity)
531
672
  entities = [
532
673
  (
533
674
  jsondict_hash(NifiContextManager._config_get(entity, processor_name)),
@@ -602,6 +743,9 @@ class NifiContextManager(object):
602
743
  )
603
744
  self.out_entities = list({e.record["entity_id"]: e for e in all_entities}.values())
604
745
  self.sync_entities()
746
+ for entity in self.out_entities:
747
+ prio = NifiPriority.from_entity(entity)
748
+ entity.request["nifi_attributes"]["priority"] = prio.to_string()
605
749
  return [entity for entity in self.jsonify(self.out_entities)["content"]]
606
750
 
607
751
  def raise_exception(self, entity, exc):
@@ -1020,6 +1164,29 @@ class NifiEntity(object):
1020
1164
  options={"verify_signature": False},
1021
1165
  )
1022
1166
 
1167
+ @property
1168
+ def priority(self):
1169
+ return NifiPriority.from_entity(self)
1170
+
1171
+ @priority.setter
1172
+ def priority(self, value):
1173
+ if isinstance(value, NifiPriority):
1174
+ self.request["priority"] = value.to_dict()
1175
+ elif isinstance(value, dict):
1176
+ self.request["priority"] = value
1177
+ else:
1178
+ raise TypeError("priority must be a NifiPriority or dict")
1179
+
1180
+ def set_user_priority(self, value):
1181
+ prio = self.priority
1182
+ prio.user_prio = NifiPriority._normalize_component(value, NifiPriority.COMPONENT_WIDTHS[1])
1183
+ self.priority = prio
1184
+
1185
+ def set_op_priority(self, value):
1186
+ prio = self.priority
1187
+ prio.op_reserved = NifiPriority._normalize_component(value, NifiPriority.COMPONENT_WIDTHS[0])
1188
+ self.priority = prio
1189
+
1023
1190
  def update_last_timestamp(self):
1024
1191
  self.record["os_last_updated_at"] = now()
1025
1192
 
@@ -1211,6 +1378,7 @@ class NifiEntity(object):
1211
1378
  "exception": {},
1212
1379
  "last_processor_name": None,
1213
1380
  "fallback_os_workspace": self.request["fallback_os_workspace"],
1381
+ "priority": deepcopy(self.request.get("priority", {})),
1214
1382
  }
1215
1383
  child_entity = NifiEntity(
1216
1384
  self.context,