streamlit-octostar-utils 0.1.7a8__py3-none-any.whl → 0.1.7a10__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.
- streamlit_octostar_utils/api_crafter/celery.py +25 -28
- streamlit_octostar_utils/api_crafter/fastapi.py +32 -21
- streamlit_octostar_utils/api_crafter/parser/entities_parser.py +63 -26
- {streamlit_octostar_utils-0.1.7a8.dist-info → streamlit_octostar_utils-0.1.7a10.dist-info}/METADATA +1 -1
- {streamlit_octostar_utils-0.1.7a8.dist-info → streamlit_octostar_utils-0.1.7a10.dist-info}/RECORD +7 -7
- {streamlit_octostar_utils-0.1.7a8.dist-info → streamlit_octostar_utils-0.1.7a10.dist-info}/LICENSE +0 -0
- {streamlit_octostar_utils-0.1.7a8.dist-info → streamlit_octostar_utils-0.1.7a10.dist-info}/WHEEL +0 -0
@@ -493,18 +493,9 @@ class CeleryExecutor(object):
|
|
493
493
|
task_id,
|
494
494
|
)
|
495
495
|
|
496
|
-
|
497
|
-
|
498
|
-
|
499
|
-
)
|
500
|
-
|
501
|
-
except CeleryExecutor.QueueFullException as e:
|
502
|
-
if os.path.isfile(os.path.join(self.in_folder, task_id)):
|
503
|
-
with RedisFileLock(self.redis_client, os.path.join(self.in_folder, task_id)):
|
504
|
-
os.remove(os.path.join(self.in_folder, task_id))
|
505
|
-
|
506
|
-
logger.warning(f"Queue full exception: {str(e)}")
|
507
|
-
return None
|
496
|
+
await asyncio.get_running_loop().run_in_executor(
|
497
|
+
self.set_thread_pool, _send_task, task_fn, task_id, options
|
498
|
+
)
|
508
499
|
|
509
500
|
except asyncio.CancelledError:
|
510
501
|
logger.info(f"Cancelling task {task_id} due to disconnect!")
|
@@ -694,20 +685,26 @@ class CeleryErrorRoute(DefaultErrorRoute):
|
|
694
685
|
DEFAULT_SILENCED_EXCEPTIONS = {CeleryExecutor.QueueFullException: lambda exc: True}
|
695
686
|
|
696
687
|
def add_default_exceptions_handler(
|
697
|
-
|
698
|
-
|
699
|
-
|
700
|
-
|
701
|
-
log_filter=None,
|
688
|
+
fs_app,
|
689
|
+
debug=False,
|
690
|
+
excs_to_status_codes=None,
|
691
|
+
silenced_excs=None,
|
702
692
|
):
|
703
|
-
|
704
|
-
|
705
|
-
|
706
|
-
|
707
|
-
|
708
|
-
|
709
|
-
|
710
|
-
|
711
|
-
|
712
|
-
|
713
|
-
|
693
|
+
extra_status = {CeleryExecutor.QueueFullException: lambda exc: 429}
|
694
|
+
extra_silence = {CeleryExecutor.QueueFullException: lambda exc: True}
|
695
|
+
|
696
|
+
status_codes = {
|
697
|
+
**DefaultErrorRoute.DEFAULT_STATUS_CODE_MAPPINGS,
|
698
|
+
**(excs_to_status_codes or {}),
|
699
|
+
**extra_status,
|
700
|
+
}
|
701
|
+
|
702
|
+
silenced = {
|
703
|
+
**DefaultErrorRoute.DEFAULT_SILENCED_EXCEPTIONS,
|
704
|
+
**(silenced_excs or {}),
|
705
|
+
**extra_silence,
|
706
|
+
}
|
707
|
+
|
708
|
+
super(CeleryErrorRoute, CeleryErrorRoute).add_default_exceptions_handler(
|
709
|
+
fs_app, debug, status_codes, silenced
|
710
|
+
)
|
@@ -241,20 +241,30 @@ class CommonModels(object):
|
|
241
241
|
headers["Content-Disposition"] += f' filename="{filename}"'
|
242
242
|
return StreamingResponse(zip_buffer, media_type="application/zip", headers=headers)
|
243
243
|
|
244
|
+
|
244
245
|
class ErrorLogFilter(logging.Filter):
|
245
|
-
def __init__(self, silenced_excs: dict):
|
246
|
+
def __init__(self, silenced_excs: dict[type, callable]):
|
246
247
|
super().__init__()
|
247
248
|
self.silenced_excs = silenced_excs
|
248
|
-
|
249
|
-
def
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
249
|
+
|
250
|
+
def _silenced(self, exc_value) -> bool:
|
251
|
+
for etype, cond in self.silenced_excs.items():
|
252
|
+
if isinstance(exc_value, etype) and cond(exc_value):
|
253
|
+
return True
|
254
|
+
return False
|
255
|
+
|
256
|
+
def filter(self, record: logging.LogRecord) -> bool:
|
257
|
+
if record.exc_info:
|
258
|
+
exc_type, exc_value, _ = record.exc_info
|
259
|
+
if self._silenced(exc_value):
|
260
|
+
return False
|
261
|
+
|
262
|
+
msg = record.getMessage()
|
263
|
+
for etype in self.silenced_excs:
|
264
|
+
if etype.__name__ in msg:
|
265
|
+
if self.silenced_excs[etype](None):
|
266
|
+
return False
|
267
|
+
|
258
268
|
return True
|
259
269
|
|
260
270
|
|
@@ -304,7 +314,7 @@ class DefaultErrorRoute:
|
|
304
314
|
},
|
305
315
|
}
|
306
316
|
|
307
|
-
def format_error(exc, body=
|
317
|
+
def format_error(exc, body=b"", debug=False, excs_to_status_codes=DEFAULT_STATUS_CODE_MAPPINGS):
|
308
318
|
"""Generic Error Handler"""
|
309
319
|
status_code = 500
|
310
320
|
for exc_type, handler in excs_to_status_codes.items():
|
@@ -334,10 +344,10 @@ class DefaultErrorRoute:
|
|
334
344
|
return DefaultErrorRoute.format_error(exc, body, debug, excs_to_status_codes)
|
335
345
|
|
336
346
|
def add_default_exceptions_handler(
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
347
|
+
fs_app,
|
348
|
+
debug=False,
|
349
|
+
excs_to_status_codes=None,
|
350
|
+
silenced_excs=None,
|
341
351
|
):
|
342
352
|
if excs_to_status_codes is None:
|
343
353
|
excs_to_status_codes = DefaultErrorRoute.DEFAULT_STATUS_CODE_MAPPINGS
|
@@ -345,17 +355,18 @@ class DefaultErrorRoute:
|
|
345
355
|
silenced_excs = DefaultErrorRoute.DEFAULT_SILENCED_EXCEPTIONS
|
346
356
|
|
347
357
|
async def _async_handle_error(request: Request, exc: Exception):
|
348
|
-
return await DefaultErrorRoute.handle_error(
|
358
|
+
return await DefaultErrorRoute.handle_error(b"", exc, debug, excs_to_status_codes)
|
349
359
|
|
350
360
|
# Added all three since FastAPI seems to intercept some exceptions before Exception
|
351
361
|
fs_app.add_exception_handler(RequestValidationError, _async_handle_error)
|
352
362
|
fs_app.add_exception_handler(StarletteHTTPException, _async_handle_error)
|
353
363
|
fs_app.add_exception_handler(Exception, _async_handle_error)
|
354
|
-
|
364
|
+
|
355
365
|
log_filter = ErrorLogFilter(silenced_excs)
|
356
|
-
|
357
|
-
|
358
|
-
|
366
|
+
for name in ("uvicorn.error", "uvicorn.access", "fastapi", "uvicorn"):
|
367
|
+
logging.getLogger(name).addFilter(log_filter)
|
368
|
+
|
369
|
+
logging.getLogger().addFilter(log_filter)
|
359
370
|
|
360
371
|
class RequestCancelledMiddleware:
|
361
372
|
def __init__(self, app):
|
@@ -60,6 +60,10 @@ class EntitiesInvalidReason(Enum):
|
|
60
60
|
INVALID_REL_TYPE = 20
|
61
61
|
UNKNOWN_UUID = 21
|
62
62
|
WRONG_SOURCE_OR_TARGET_TYPE = 22
|
63
|
+
|
64
|
+
|
65
|
+
EntityDict = dict
|
66
|
+
InvalidErrorDict = dict
|
63
67
|
|
64
68
|
|
65
69
|
class EntitiesParser(object):
|
@@ -547,29 +551,42 @@ class EntitiesParser(object):
|
|
547
551
|
self._get_ontology()
|
548
552
|
if not self.ontology:
|
549
553
|
raise RuntimeError("Ontology could not be fetched for validation!")
|
554
|
+
ontology = self.ontology
|
550
555
|
from streamlit_octostar_utils.ontology.validation import (
|
551
556
|
validate_and_format_timbr_type,
|
552
557
|
)
|
553
558
|
from streamlit_octostar_utils.ontology.inheritance import is_child_concept
|
554
559
|
|
555
560
|
processed_entities = []
|
556
|
-
|
561
|
+
processed_relationships = []
|
557
562
|
for entity in entities:
|
558
|
-
if entity.concept_name not in
|
559
|
-
processed_entities.append(
|
560
|
-
|
563
|
+
if entity.concept_name not in ontology["concepts"]:
|
564
|
+
processed_entities.append(
|
565
|
+
(
|
566
|
+
EntitiesInvalidReason.INVALID_TYPE,
|
567
|
+
entity,
|
568
|
+
{"error_message": f"{entity} has invalid concept name"},
|
569
|
+
)
|
570
|
+
)
|
561
571
|
entity_properties = [
|
562
|
-
k
|
572
|
+
k
|
573
|
+
for k in entity.fields.keys()
|
574
|
+
if not k.startswith("#") and k != "extra_fields"
|
563
575
|
]
|
564
576
|
ontology_properties = {
|
565
577
|
e["property_name"]: e
|
566
|
-
for e in
|
578
|
+
for e in ontology["concepts"][entity.concept_name]["allProperties"]
|
567
579
|
}
|
568
580
|
if any(prop not in ontology_properties for prop in entity_properties):
|
569
581
|
processed_entities.append(
|
570
|
-
(
|
582
|
+
(
|
583
|
+
EntitiesInvalidReason.INVALID_PROPERTIES,
|
584
|
+
entity,
|
585
|
+
{
|
586
|
+
"error_message": f"{entity} has invalid entity properties: {str(set(entity_properties) - set(ontology_properties))}"
|
587
|
+
},
|
588
|
+
)
|
571
589
|
)
|
572
|
-
continue
|
573
590
|
for prop in entity_properties:
|
574
591
|
try:
|
575
592
|
entity.fields[prop] = validate_and_format_timbr_type(
|
@@ -577,46 +594,66 @@ class EntitiesParser(object):
|
|
577
594
|
)
|
578
595
|
except:
|
579
596
|
processed_entities.append(
|
580
|
-
(
|
597
|
+
(
|
598
|
+
EntitiesInvalidReason.INVALID_PROPERTIES,
|
599
|
+
entity,
|
600
|
+
{
|
601
|
+
"error_message": f"{entity} has an invalid property type for property {prop}"
|
602
|
+
},
|
603
|
+
)
|
581
604
|
)
|
582
|
-
|
583
|
-
processed_entities.append((EntitiesInvalidReason.VALID, entity))
|
605
|
+
processed_entities.append((EntitiesInvalidReason.VALID, entity, {}))
|
584
606
|
ontology_relationships = {
|
585
|
-
r["relationship_name"]: r for r in
|
607
|
+
r["relationship_name"]: r for r in ontology["relationships"]
|
586
608
|
}
|
587
609
|
for rel in relationships:
|
588
610
|
if rel.name not in ontology_relationships.keys():
|
589
|
-
|
590
|
-
(
|
611
|
+
processed_relationships.append(
|
612
|
+
(
|
613
|
+
EntitiesInvalidReason.INVALID_REL_TYPE,
|
614
|
+
rel,
|
615
|
+
{"error_message": f"{rel} relationship name is invalid"},
|
616
|
+
)
|
591
617
|
)
|
592
|
-
|
593
|
-
entities_by_id = {e.unique_id: e for e in entities}
|
618
|
+
entities_by_id = {e[1].unique_id: e[1] for e in processed_entities}
|
594
619
|
if (
|
595
620
|
rel.concept_from not in entities_by_id.keys()
|
596
621
|
or rel.concept_to not in entities_by_id.keys()
|
597
622
|
):
|
598
|
-
|
599
|
-
(
|
623
|
+
processed_relationships.append(
|
624
|
+
(
|
625
|
+
EntitiesInvalidReason.UNKNOWN_UUID,
|
626
|
+
rel,
|
627
|
+
{
|
628
|
+
"error_message": f"for {rel}, source concept or target concept are invalid"
|
629
|
+
},
|
630
|
+
)
|
600
631
|
)
|
601
|
-
continue
|
602
632
|
ontology_relationship = ontology_relationships[rel.name]
|
603
633
|
rel_concept_types = (
|
604
634
|
entities_by_id[rel.concept_from].concept_name,
|
605
635
|
entities_by_id[rel.concept_to].concept_name,
|
606
636
|
)
|
607
637
|
if not is_child_concept(
|
608
|
-
rel_concept_types[0],
|
638
|
+
rel_concept_types[0],
|
639
|
+
ontology_relationship["concept"],
|
640
|
+
ontology,
|
609
641
|
) or not is_child_concept(
|
610
642
|
rel_concept_types[1],
|
611
643
|
ontology_relationship["target_concept"],
|
612
|
-
|
644
|
+
ontology,
|
613
645
|
):
|
614
|
-
|
615
|
-
(
|
646
|
+
processed_relationships.append(
|
647
|
+
(
|
648
|
+
EntitiesInvalidReason.WRONG_SOURCE_OR_TARGET_TYPE,
|
649
|
+
rel,
|
650
|
+
{
|
651
|
+
"error_message": f"for {rel}, type for source concept or for target concept is invalid"
|
652
|
+
},
|
653
|
+
)
|
616
654
|
)
|
617
|
-
|
618
|
-
|
619
|
-
return processed_entities, processsed_relationships
|
655
|
+
processed_relationships.append((EntitiesInvalidReason.VALID, rel, {}))
|
656
|
+
return processed_entities, processed_relationships
|
620
657
|
|
621
658
|
def replace_unique_id(self, id_from, id_to, entities, relationships):
|
622
659
|
for entity in entities:
|
{streamlit_octostar_utils-0.1.7a8.dist-info → streamlit_octostar_utils-0.1.7a10.dist-info}/RECORD
RENAMED
@@ -1,11 +1,11 @@
|
|
1
1
|
streamlit_octostar_utils/__init__.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
|
2
2
|
streamlit_octostar_utils/api_crafter/__init__.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
|
3
|
-
streamlit_octostar_utils/api_crafter/celery.py,sha256=
|
4
|
-
streamlit_octostar_utils/api_crafter/fastapi.py,sha256=
|
3
|
+
streamlit_octostar_utils/api_crafter/celery.py,sha256=bQq8P95j0XDWqx6Hdnm96PJL8kcp9ZcSKjveZUCQTVk,29874
|
4
|
+
streamlit_octostar_utils/api_crafter/fastapi.py,sha256=2bktT5Mwjs9XixWcOqUKMoLM_cgKl-cqZDUa2Imf4xA,14357
|
5
5
|
streamlit_octostar_utils/api_crafter/nifi.py,sha256=fQ5k9eZl2oSQZ2BexZYwKUiO05-FryUi7wnCd_56P9Y,44375
|
6
6
|
streamlit_octostar_utils/api_crafter/parser/__init__.py,sha256=YeYWF6sdQiCFV_RKNW2t9Vs6KJExE2pbXxWTe_DOayY,107
|
7
7
|
streamlit_octostar_utils/api_crafter/parser/combine_fields.py,sha256=ddc44xkajw8MU0peAX_263DL7rPXbTKbHUjpOhRgvyU,8790
|
8
|
-
streamlit_octostar_utils/api_crafter/parser/entities_parser.py,sha256=
|
8
|
+
streamlit_octostar_utils/api_crafter/parser/entities_parser.py,sha256=Z740IViQ8WX3xBzgWzsO6JHUps6GyNLJE8nlpt3KTzc,31418
|
9
9
|
streamlit_octostar_utils/api_crafter/parser/generics.py,sha256=GefvTUWkqsICS_TdXA2p73_Uzh6041g88mWql3Fr9cY,1861
|
10
10
|
streamlit_octostar_utils/api_crafter/parser/info.py,sha256=L2cdtsmfIdFSkAnIXhGhQZG6YMZRtY1GgLXn-847avA,649
|
11
11
|
streamlit_octostar_utils/api_crafter/parser/linkchart_functions.py,sha256=WfHl-EfH4SWjpk8civS7HL11eIl4SAV5Dtwe8mTidrc,7163
|
@@ -37,7 +37,7 @@ streamlit_octostar_utils/threading/__init__.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzp
|
|
37
37
|
streamlit_octostar_utils/threading/async_task_manager.py,sha256=q7N6YZwUvIYMzkSHmsJNheNVCv93c03H6Hyg9uH8pvk,4747
|
38
38
|
streamlit_octostar_utils/threading/session_callback_manager.py,sha256=LvZVP4g6tvKtYmI13f2j1sX_7hm61Groqp5xJine9_k,3973
|
39
39
|
streamlit_octostar_utils/threading/session_state_hot_swapper.py,sha256=6eeCQI6A42hp4DmW2NQw2rbeR-k9N8DhfBKQdN_fbLU,811
|
40
|
-
streamlit_octostar_utils-0.1.
|
41
|
-
streamlit_octostar_utils-0.1.
|
42
|
-
streamlit_octostar_utils-0.1.
|
43
|
-
streamlit_octostar_utils-0.1.
|
40
|
+
streamlit_octostar_utils-0.1.7a10.dist-info/LICENSE,sha256=dkwVPyV03fPHHtERnF6RnvRXcll__tud9gWca1RcgnQ,1073
|
41
|
+
streamlit_octostar_utils-0.1.7a10.dist-info/METADATA,sha256=s86wH6OAhUfZBkiM2dIFUcw1x7g3COOUjBkWSYnmJGc,2268
|
42
|
+
streamlit_octostar_utils-0.1.7a10.dist-info/WHEEL,sha256=fGIA9gx4Qxk2KDKeNJCbOEwSrmLtjWCwzBz351GyrPQ,88
|
43
|
+
streamlit_octostar_utils-0.1.7a10.dist-info/RECORD,,
|
{streamlit_octostar_utils-0.1.7a8.dist-info → streamlit_octostar_utils-0.1.7a10.dist-info}/LICENSE
RENAMED
File without changes
|
{streamlit_octostar_utils-0.1.7a8.dist-info → streamlit_octostar_utils-0.1.7a10.dist-info}/WHEEL
RENAMED
File without changes
|