nebu 0.1.51__py3-none-any.whl → 0.1.53__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.
- nebu/processors/consumer.py +7 -5
- nebu/processors/decorate.py +202 -72
- {nebu-0.1.51.dist-info → nebu-0.1.53.dist-info}/METADATA +1 -1
- {nebu-0.1.51.dist-info → nebu-0.1.53.dist-info}/RECORD +7 -7
- {nebu-0.1.51.dist-info → nebu-0.1.53.dist-info}/WHEEL +0 -0
- {nebu-0.1.51.dist-info → nebu-0.1.53.dist-info}/licenses/LICENSE +0 -0
- {nebu-0.1.51.dist-info → nebu-0.1.53.dist-info}/top_level.txt +0 -0
nebu/processors/consumer.py
CHANGED
@@ -6,7 +6,7 @@ import socket
|
|
6
6
|
import sys
|
7
7
|
import time
|
8
8
|
import traceback
|
9
|
-
import types
|
9
|
+
import types
|
10
10
|
from datetime import datetime, timezone
|
11
11
|
from typing import Any, Callable, Dict, List, Optional, Tuple, TypeVar, cast
|
12
12
|
|
@@ -350,7 +350,9 @@ def process_message(message_id: str, message_data: Dict[str, str]) -> None:
|
|
350
350
|
user_id = None
|
351
351
|
try:
|
352
352
|
payload_str = message_data.get("data")
|
353
|
-
if
|
353
|
+
if (
|
354
|
+
not payload_str
|
355
|
+
): # Covers None and empty string, isinstance check is redundant
|
354
356
|
raise ValueError(
|
355
357
|
f"Missing or invalid 'data' field (expected non-empty string): {message_data}"
|
356
358
|
)
|
@@ -724,13 +726,13 @@ try:
|
|
724
726
|
assert isinstance(REDIS_STREAM, str)
|
725
727
|
assert isinstance(REDIS_CONSUMER_GROUP, str)
|
726
728
|
|
727
|
-
|
729
|
+
streams_arg: Dict[str, str] = {REDIS_STREAM: ">"}
|
730
|
+
|
728
731
|
# With decode_responses=True, redis-py expects str types here
|
729
|
-
streams_arg = {REDIS_STREAM: ">"}
|
730
732
|
messages = r.xreadgroup(
|
731
733
|
REDIS_CONSUMER_GROUP,
|
732
734
|
consumer_name,
|
733
|
-
streams_arg,
|
735
|
+
streams_arg, # type: ignore[arg-type]
|
734
736
|
count=1,
|
735
737
|
block=5000, # Use milliseconds for block
|
736
738
|
)
|
nebu/processors/decorate.py
CHANGED
@@ -1,11 +1,8 @@
|
|
1
1
|
import ast # For parsing notebook code
|
2
2
|
import inspect
|
3
|
-
import
|
4
|
-
import
|
5
|
-
import re # Import re for fallback check
|
6
|
-
import tempfile # Add tempfile import
|
3
|
+
import os
|
4
|
+
import re # Added import
|
7
5
|
import textwrap
|
8
|
-
import uuid # Add uuid import
|
9
6
|
from typing import (
|
10
7
|
Any,
|
11
8
|
Callable,
|
@@ -17,15 +14,15 @@ from typing import (
|
|
17
14
|
get_origin,
|
18
15
|
get_type_hints,
|
19
16
|
)
|
20
|
-
from urllib.parse import urlparse
|
17
|
+
from urllib.parse import urlparse
|
21
18
|
|
22
|
-
import dill
|
23
|
-
import requests
|
24
|
-
from botocore.exceptions import ClientError
|
19
|
+
import dill
|
20
|
+
import requests
|
21
|
+
from botocore.exceptions import ClientError
|
25
22
|
from pydantic import BaseModel
|
26
23
|
|
27
|
-
from nebu.auth import get_user_profile
|
28
|
-
from nebu.config import GlobalConfig
|
24
|
+
from nebu.auth import get_user_profile
|
25
|
+
from nebu.config import GlobalConfig
|
29
26
|
from nebu.containers.models import (
|
30
27
|
V1AuthzConfig,
|
31
28
|
V1ContainerHealthCheck,
|
@@ -38,7 +35,7 @@ from nebu.containers.models import (
|
|
38
35
|
V1VolumeDriver,
|
39
36
|
V1VolumePath,
|
40
37
|
)
|
41
|
-
from nebu.data import Bucket
|
38
|
+
from nebu.data import Bucket
|
42
39
|
from nebu.meta import V1ResourceMetaRequest
|
43
40
|
from nebu.processors.models import (
|
44
41
|
Message,
|
@@ -79,10 +76,11 @@ def is_jupyter_notebook():
|
|
79
76
|
|
80
77
|
if importlib.util.find_spec("IPython") is None:
|
81
78
|
return False
|
82
|
-
|
79
|
+
# Fix: Import get_ipython directly
|
80
|
+
from IPython.core.getipython import get_ipython # Now safe to import
|
83
81
|
|
84
|
-
ip =
|
85
|
-
if ip is None:
|
82
|
+
ip = get_ipython() # Use the imported function
|
83
|
+
if ip is None: # type: ignore
|
86
84
|
# print("[DEBUG Helper] is_jupyter_notebook: No IPython instance found.")
|
87
85
|
return False
|
88
86
|
class_name = str(ip.__class__)
|
@@ -93,7 +91,9 @@ def is_jupyter_notebook():
|
|
93
91
|
# print("[DEBUG Helper] is_jupyter_notebook: Not Jupyter (IPython instance found, but not ZMQInteractiveShell).")
|
94
92
|
return False
|
95
93
|
except Exception as e:
|
96
|
-
|
94
|
+
print(
|
95
|
+
f"[DEBUG Helper] is_jupyter_notebook: Exception occurred: {e}"
|
96
|
+
) # Reduce verbosity
|
97
97
|
return False
|
98
98
|
|
99
99
|
|
@@ -104,9 +104,10 @@ def get_notebook_executed_code():
|
|
104
104
|
"""
|
105
105
|
print("[DEBUG Helper] Attempting to get notebook execution history...")
|
106
106
|
try:
|
107
|
-
|
107
|
+
# Fix: Import get_ipython directly
|
108
|
+
from IPython.core.getipython import get_ipython
|
108
109
|
|
109
|
-
ip =
|
110
|
+
ip = get_ipython() # Use the imported function
|
110
111
|
if ip is None or not hasattr(ip, "history_manager"):
|
111
112
|
print(
|
112
113
|
"[DEBUG Helper] get_notebook_executed_code: No IPython instance or history_manager."
|
@@ -164,9 +165,10 @@ def extract_definition_source_from_string(
|
|
164
165
|
found_in_cell = False
|
165
166
|
for node in ast.walk(tree):
|
166
167
|
if (
|
167
|
-
isinstance(
|
168
|
-
|
169
|
-
|
168
|
+
isinstance(
|
169
|
+
node, def_type
|
170
|
+
) # Check if it's the right type (FuncDef or ClassDef)
|
171
|
+
and getattr(node, "name", None) == def_name # Safely check name
|
170
172
|
):
|
171
173
|
print(
|
172
174
|
f"[DEBUG Helper] extract: Found node for '{def_name}' in cell #{cell_num}."
|
@@ -188,10 +190,14 @@ def extract_definition_source_from_string(
|
|
188
190
|
start_lineno = getattr(node, "lineno", 1) - 1
|
189
191
|
end_lineno = getattr(node, "end_lineno", start_lineno + 1)
|
190
192
|
|
191
|
-
if hasattr(node, "decorator_list") and node.decorator_list:
|
193
|
+
if hasattr(node, "decorator_list") and node.decorator_list: # type: ignore
|
194
|
+
# Ensure it's a node type that *can* have decorators
|
195
|
+
# FunctionDef and ClassDef have decorator_list
|
192
196
|
first_decorator_start_line = (
|
193
197
|
getattr(
|
194
|
-
node.decorator_list[0],
|
198
|
+
node.decorator_list[0], # type: ignore
|
199
|
+
"lineno",
|
200
|
+
start_lineno + 1,
|
195
201
|
)
|
196
202
|
- 1
|
197
203
|
) # type: ignore
|
@@ -598,28 +604,45 @@ def processor(
|
|
598
604
|
included_sources[obj] = obj_source
|
599
605
|
# Decide how to pass included source - keep using Env Vars for now
|
600
606
|
env_key_base = f"INCLUDED_OBJECT_{i}"
|
601
|
-
if isinstance(obj_source, str):
|
607
|
+
if isinstance(obj_source, str): # type: ignore[arg-type]
|
602
608
|
all_env.append(
|
603
609
|
V1EnvVar(key=f"{env_key_base}_SOURCE", value=obj_source)
|
604
610
|
)
|
605
611
|
# print(f"[DEBUG Decorator] Added string source to env for included obj: {obj_name_str}")
|
606
612
|
elif isinstance(obj_source, tuple):
|
607
613
|
# Handle tuple source (origin, args) - assumes get_model_source/get_type_source logic
|
608
|
-
|
609
|
-
if
|
610
|
-
|
611
|
-
|
612
|
-
|
613
|
-
|
614
|
-
if isinstance(arg_src, str):
|
614
|
+
# Ensure obj_source is indeed a tuple before unpacking
|
615
|
+
if len(obj_source) == 2:
|
616
|
+
# Now safe to unpack
|
617
|
+
origin_src, arg_srcs = obj_source # type: ignore[misc] # Suppress persistent tuple unpacking error
|
618
|
+
# type: ignore[misc] # Suppress persistent tuple unpacking error
|
619
|
+
if origin_src and isinstance(origin_src, str):
|
615
620
|
all_env.append(
|
616
621
|
V1EnvVar(
|
617
|
-
key=f"{env_key_base}
|
618
|
-
value=arg_src,
|
622
|
+
key=f"{env_key_base}_SOURCE", value=origin_src
|
619
623
|
)
|
620
624
|
)
|
621
|
-
# Handle
|
622
|
-
|
625
|
+
# Handle arg_srcs (this part seems okay)
|
626
|
+
if isinstance(arg_srcs, list):
|
627
|
+
for j, arg_src in enumerate(arg_srcs):
|
628
|
+
if isinstance(arg_src, str):
|
629
|
+
all_env.append(
|
630
|
+
V1EnvVar(
|
631
|
+
key=f"{env_key_base}_ARG_{j}_SOURCE",
|
632
|
+
value=arg_src,
|
633
|
+
)
|
634
|
+
)
|
635
|
+
else:
|
636
|
+
print(
|
637
|
+
f"[DEBUG Decorator] Warning: Expected arg_srcs to be a list, got {type(arg_srcs)}"
|
638
|
+
)
|
639
|
+
else:
|
640
|
+
# Handle unexpected type or structure for obj_source if necessary
|
641
|
+
# For now, assume it fits the expected tuple structure if isinstance passes
|
642
|
+
# origin_src, arg_srcs = None, [] # Default/error state (already covered by outer check)
|
643
|
+
print(
|
644
|
+
f"[DEBUG Decorator] Warning: Unexpected obj_source structure: {obj_source}"
|
645
|
+
)
|
623
646
|
else:
|
624
647
|
print(
|
625
648
|
f"Warning: Unknown source type for included object {obj_name_str}: {type(obj_source)}"
|
@@ -690,6 +713,7 @@ def processor(
|
|
690
713
|
print(f"[DEBUG Decorator] get_origin result: {origin}, get_args result: {args}")
|
691
714
|
is_stream_message = False
|
692
715
|
content_type = None
|
716
|
+
content_type_name_from_regex = None # Store regex result here
|
693
717
|
|
694
718
|
# Use Message class directly for comparison
|
695
719
|
message_cls = Message # Get the class object
|
@@ -709,18 +733,63 @@ def processor(
|
|
709
733
|
)
|
710
734
|
else:
|
711
735
|
print(
|
712
|
-
"[DEBUG Decorator] Message detected, but no generic arguments found via get_args."
|
736
|
+
"[DEBUG Decorator] Message detected, but no generic arguments found via get_args. Attempting regex fallback on string repr."
|
737
|
+
)
|
738
|
+
# --- Regex Fallback Start ---
|
739
|
+
match = re.search(r"Message\[([\w\.]+)\]", param_type_str_repr)
|
740
|
+
if match:
|
741
|
+
content_type_name_from_regex = match.group(1)
|
742
|
+
print(
|
743
|
+
f"[DEBUG Decorator] Extracted content type name via regex: {content_type_name_from_regex}"
|
744
|
+
)
|
745
|
+
else:
|
746
|
+
print(
|
747
|
+
"[DEBUG Decorator] Regex fallback failed to extract content type name."
|
748
|
+
)
|
749
|
+
# --- Regex Fallback End ---
|
750
|
+
# Check 2a: Regex fallback if get_origin failed but string matches pattern
|
751
|
+
elif origin is None and param_type is not None:
|
752
|
+
print(
|
753
|
+
"[DEBUG Decorator] get_origin failed. Attempting regex fallback on string representation."
|
754
|
+
)
|
755
|
+
match = re.search(r"Message\[([\w\.]+)\]", param_type_str_repr)
|
756
|
+
if match:
|
757
|
+
print(
|
758
|
+
"[DEBUG Decorator] Regex fallback successful after get_origin failed."
|
759
|
+
)
|
760
|
+
is_stream_message = True
|
761
|
+
content_type_name_from_regex = match.group(1)
|
762
|
+
# We don't have the actual content_type object here, only the name
|
763
|
+
content_type = None
|
764
|
+
print(
|
765
|
+
f"[DEBUG Decorator] Extracted content type name via regex: {content_type_name_from_regex}"
|
766
|
+
)
|
767
|
+
else:
|
768
|
+
print(
|
769
|
+
"[DEBUG Decorator] Regex fallback also failed. Treating as non-Message type."
|
713
770
|
)
|
771
|
+
is_stream_message = False
|
772
|
+
content_type = None
|
714
773
|
# Check 2: Direct type check (Handles cases where get_origin might fail but type is correct)
|
715
774
|
elif isinstance(param_type, type) and param_type is message_cls:
|
716
|
-
|
775
|
+
# This case likely won't have generic args accessible easily if get_origin failed
|
776
|
+
print(
|
777
|
+
"[DEBUG Decorator] Input type identified as direct Message type. Attempting regex fallback."
|
778
|
+
)
|
717
779
|
is_stream_message = True
|
718
|
-
|
719
|
-
|
720
|
-
|
721
|
-
|
722
|
-
|
723
|
-
|
780
|
+
# --- Regex Fallback Start ---
|
781
|
+
match = re.search(r"Message\[([\w\.]+)\]", param_type_str_repr)
|
782
|
+
if match:
|
783
|
+
content_type_name_from_regex = match.group(1)
|
784
|
+
print(
|
785
|
+
f"[DEBUG Decorator] Extracted content type name via regex: {content_type_name_from_regex}"
|
786
|
+
)
|
787
|
+
else:
|
788
|
+
print(
|
789
|
+
"[DEBUG Decorator] Regex fallback failed to extract content type name."
|
790
|
+
)
|
791
|
+
# --- Regex Fallback End ---
|
792
|
+
# Check 3: Removed old placeholder elif branch
|
724
793
|
|
725
794
|
else: # Handle cases where param_type might be None or origin is something else
|
726
795
|
print(
|
@@ -826,19 +895,44 @@ def processor(
|
|
826
895
|
# Add: Included object sources (if any)
|
827
896
|
# Add: INIT_FUNC_NAME (if provided)
|
828
897
|
|
829
|
-
#
|
830
|
-
|
898
|
+
# Calculate module_path based on relative file path
|
899
|
+
calculated_module_path = None
|
831
900
|
if rel_func_path:
|
832
901
|
# Convert OS-specific path to module path (e.g., subdir/file.py -> subdir.file)
|
833
|
-
|
834
|
-
if
|
835
|
-
|
836
|
-
|
837
|
-
|
838
|
-
|
839
|
-
|
840
|
-
|
902
|
+
base, ext = os.path.splitext(rel_func_path)
|
903
|
+
if ext == ".py":
|
904
|
+
module_path_parts = base.split(os.sep)
|
905
|
+
if module_path_parts[-1] == "__init__":
|
906
|
+
module_path_parts.pop() # Remove __init__
|
907
|
+
# Filter out potential empty strings if path started with / or had //
|
908
|
+
module_path_parts = [part for part in module_path_parts if part]
|
909
|
+
calculated_module_path = ".".join(module_path_parts)
|
910
|
+
else:
|
911
|
+
# Not a python file? Should not happen based on inspect.getfile
|
912
|
+
print(
|
913
|
+
f"[DEBUG Decorator] Warning: Function source file is not a .py file: {rel_func_path}"
|
914
|
+
)
|
915
|
+
# Set calculated_module_path to None explicitly to trigger fallback later
|
916
|
+
calculated_module_path = None
|
917
|
+
else:
|
918
|
+
# Should have errored earlier if rel_func_path is None
|
919
|
+
print(
|
920
|
+
"[DEBUG Decorator] Warning: Could not determine relative function path. Falling back to func.__module__."
|
921
|
+
)
|
922
|
+
# Set calculated_module_path to None explicitly to trigger fallback later
|
923
|
+
calculated_module_path = None
|
924
|
+
|
925
|
+
# Assign final module_path using fallback if calculation failed or wasn't applicable
|
926
|
+
if calculated_module_path is not None:
|
927
|
+
module_path = calculated_module_path
|
928
|
+
print(f"[DEBUG Decorator] Using calculated module path: {module_path}")
|
929
|
+
else:
|
930
|
+
module_path = func.__module__ # Fallback
|
931
|
+
print(f"[DEBUG Decorator] Falling back to func.__module__: {module_path}")
|
841
932
|
|
933
|
+
# Basic info needed by consumer to find and run the function
|
934
|
+
all_env.append(V1EnvVar(key="FUNCTION_NAME", value=processor_name))
|
935
|
+
if rel_func_path:
|
842
936
|
# For now, just pass the relative file path, consumer will handle conversion
|
843
937
|
all_env.append(
|
844
938
|
V1EnvVar(key="NEBU_ENTRYPOINT_MODULE_PATH", value=rel_func_path)
|
@@ -846,9 +940,7 @@ def processor(
|
|
846
940
|
print(
|
847
941
|
f"[DEBUG Decorator] Set NEBU_ENTRYPOINT_MODULE_PATH to: {rel_func_path}"
|
848
942
|
)
|
849
|
-
else
|
850
|
-
# Should have errored earlier if rel_func_path is None
|
851
|
-
raise RuntimeError("Internal error: Relative function path not determined.")
|
943
|
+
# No else needed, handled by fallback calculation above
|
852
944
|
|
853
945
|
if init_func:
|
854
946
|
init_func_name = init_func.__name__ # Get name here
|
@@ -862,26 +954,64 @@ def processor(
|
|
862
954
|
print(f"[DEBUG Decorator] Set INIT_FUNC_NAME to: {init_func_name}")
|
863
955
|
|
864
956
|
# Type info (still useful for deserialization/validation in consumer)
|
957
|
+
# Adjust type strings to replace '__main__' with the calculated module path
|
958
|
+
param_type_str_repr = str(param_type)
|
959
|
+
if module_path != "__main__" and "__main__." in param_type_str_repr:
|
960
|
+
# Be careful with replacement - replace only module prefix
|
961
|
+
# Example: "<class '__main__.MyModel'>" -> "<class 'mymodule.MyModel'>"
|
962
|
+
# Example: "typing.Optional[__main__.MyModel]" -> "typing.Optional[mymodule.MyModel]"
|
963
|
+
param_type_str_repr = param_type_str_repr.replace(
|
964
|
+
"__main__.", f"{module_path}."
|
965
|
+
)
|
966
|
+
print(
|
967
|
+
f"[DEBUG Decorator] Adjusted param type string: {param_type_str_repr}"
|
968
|
+
)
|
969
|
+
|
865
970
|
all_env.append(V1EnvVar(key="PARAM_TYPE_STR", value=param_type_str_repr))
|
866
|
-
|
867
|
-
|
868
|
-
|
971
|
+
|
972
|
+
return_type_str_repr = str(return_type)
|
973
|
+
if module_path != "__main__" and "__main__." in return_type_str_repr:
|
974
|
+
return_type_str_repr = return_type_str_repr.replace(
|
975
|
+
"__main__.", f"{module_path}."
|
976
|
+
)
|
977
|
+
print(
|
978
|
+
f"[DEBUG Decorator] Adjusted return type string: {return_type_str_repr}"
|
979
|
+
)
|
980
|
+
|
981
|
+
all_env.append(V1EnvVar(key="RETURN_TYPE_STR", value=return_type_str_repr))
|
869
982
|
all_env.append(V1EnvVar(key="IS_STREAM_MESSAGE", value=str(is_stream_message)))
|
870
|
-
|
871
|
-
|
872
|
-
|
873
|
-
|
874
|
-
|
875
|
-
|
876
|
-
|
877
|
-
|
983
|
+
|
984
|
+
# Determine and set CONTENT_TYPE_NAME using object or regex fallback
|
985
|
+
content_type_name_to_set = None
|
986
|
+
if content_type and isinstance(content_type, type):
|
987
|
+
content_type_name_to_set = content_type.__name__
|
988
|
+
print(
|
989
|
+
f"[DEBUG Decorator] Using content type name from resolved type object: {content_type_name_to_set}"
|
990
|
+
)
|
991
|
+
elif content_type_name_from_regex:
|
992
|
+
content_type_name_to_set = content_type_name_from_regex
|
993
|
+
print(
|
994
|
+
f"[DEBUG Decorator] Using content type name from regex fallback: {content_type_name_to_set}"
|
995
|
+
)
|
996
|
+
else:
|
997
|
+
# Only warn if it was supposed to be a Message type
|
998
|
+
if is_stream_message:
|
878
999
|
print(
|
879
|
-
f"Warning:
|
1000
|
+
f"Warning: Could not determine CONTENT_TYPE_NAME for Message parameter {param_name} ({param_type_str_repr}). Consumer might use raw content."
|
880
1001
|
)
|
881
|
-
|
1002
|
+
|
1003
|
+
if content_type_name_to_set:
|
1004
|
+
all_env.append(
|
1005
|
+
V1EnvVar(key="CONTENT_TYPE_NAME", value=content_type_name_to_set)
|
1006
|
+
)
|
1007
|
+
|
1008
|
+
# Use the calculated module_path for MODULE_NAME
|
882
1009
|
all_env.append(
|
883
|
-
V1EnvVar(
|
884
|
-
|
1010
|
+
V1EnvVar(
|
1011
|
+
key="MODULE_NAME", value=module_path
|
1012
|
+
) # module_path is guaranteed to be a string here (calculated or fallback)
|
1013
|
+
)
|
1014
|
+
print(f"[DEBUG Decorator] Set MODULE_NAME to: {module_path}")
|
885
1015
|
|
886
1016
|
# Add PYTHONPATH
|
887
1017
|
pythonpath_value = CONTAINER_CODE_DIR
|
@@ -1016,7 +1146,7 @@ def processor(
|
|
1016
1146
|
# setattr(processor_instance, 'original_func', func) # Use setattr if not in model
|
1017
1147
|
try:
|
1018
1148
|
# This will fail if Processor hasn't been updated to include this field
|
1019
|
-
processor_instance.original_func = func
|
1149
|
+
processor_instance.original_func = func # type: ignore
|
1020
1150
|
except AttributeError:
|
1021
1151
|
print(
|
1022
1152
|
"Warning: Could not assign original_func to Processor instance. Update Processor model or remove assignment."
|
@@ -10,16 +10,16 @@ nebu/containers/container.py,sha256=yb7KaPTVXnEEAlrpdlUi4HNqF6P7z9bmwAILGlq6iqU,
|
|
10
10
|
nebu/containers/decorator.py,sha256=uFtzlAXRHYZECJ-NPusY7oN9GXvdHrHDd_JNrIGr8aQ,3244
|
11
11
|
nebu/containers/models.py,sha256=0j6NGy4yto-enRDh_4JH_ZTbHrLdSpuMOqNQPnIrwC4,6815
|
12
12
|
nebu/containers/server.py,sha256=yFa2Y9PzBn59E1HftKiv0iapPonli2rbGAiU6r-wwe0,2513
|
13
|
-
nebu/processors/consumer.py,sha256=
|
14
|
-
nebu/processors/decorate.py,sha256=
|
13
|
+
nebu/processors/consumer.py,sha256=q4cFKPEfMf1xIs0Y3CjUDCR35QVjr0F_hSOZUKUYc_U,33667
|
14
|
+
nebu/processors/decorate.py,sha256=XZqCkcLKYev3CO1wJUZXKV0Q8otQUdLTxogBSVUYKcg,53182
|
15
15
|
nebu/processors/default.py,sha256=W4slJenG59rvyTlJ7gRp58eFfXcNOTT2Hfi6zzJAobI,365
|
16
16
|
nebu/processors/models.py,sha256=y40HoW-MEzDWB2dm_tsYlUy3Nf3s6eiLC0iGO9BoNog,3956
|
17
17
|
nebu/processors/processor.py,sha256=cptZEN9ZGcaoFNreaw3BkwV0qKHvjP9b4nNxlQjFT3s,15405
|
18
18
|
nebu/processors/remote.py,sha256=TeAIPGEMqnDIb7H1iett26IEZrBlcbPB_-DSm6jcH1E,1285
|
19
19
|
nebu/redis/models.py,sha256=coPovAcVXnOU1Xh_fpJL4PO3QctgK9nBe5QYoqEcnxg,1230
|
20
20
|
nebu/services/service.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
21
|
-
nebu-0.1.
|
22
|
-
nebu-0.1.
|
23
|
-
nebu-0.1.
|
24
|
-
nebu-0.1.
|
25
|
-
nebu-0.1.
|
21
|
+
nebu-0.1.53.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
22
|
+
nebu-0.1.53.dist-info/METADATA,sha256=GKhvMkM4FEpn8Ln1wUwcuBgtBTTes2D9l0fNmdHiawY,1731
|
23
|
+
nebu-0.1.53.dist-info/WHEEL,sha256=pxyMxgL8-pra_rKaQ4drOZAegBVuX-G_4nRHjjgWbmo,91
|
24
|
+
nebu-0.1.53.dist-info/top_level.txt,sha256=uLIbEKJeGSHWOAJN5S0i5XBGwybALlF9bYoB1UhdEgQ,5
|
25
|
+
nebu-0.1.53.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|