divi 0.0.1.dev15__py3-none-any.whl → 0.0.1.dev23__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.
divi/__init__.py CHANGED
@@ -12,5 +12,5 @@ _core: Optional[Core] = None
12
12
  _auth: Optional[Auth] = None
13
13
  _datapark: Optional[DataPark] = None
14
14
 
15
- __version__ = "0.0.1.dev15"
15
+ __version__ = "0.0.1.dev23"
16
16
  __all__ = ["proto", "obs_openai", "observable"]
@@ -18,7 +18,6 @@ def _get_observable_create(create: Callable) -> Callable:
18
18
  return decorator(create)(*args, stream=stream, **kwargs)
19
19
 
20
20
  # TODO Async Observable Create
21
- print("Is async", is_async(create))
22
21
  return observable_create if not is_async(create) else create
23
22
 
24
23
 
@@ -23,6 +23,7 @@ from divi.proto.trace.v1.trace_pb2 import ScopeSpans
23
23
  from divi.session import SessionExtra
24
24
  from divi.session.setup import setup
25
25
  from divi.signals.trace import Span
26
+ from divi.utils import extract_flattened_inputs
26
27
 
27
28
  R = TypeVar("R", covariant=True)
28
29
  P = ParamSpec("P")
@@ -84,7 +85,12 @@ def observable(
84
85
  # recover parent context
85
86
  _SESSION_EXTRA.reset(token)
86
87
 
87
- # TODO: collect result
88
+ # get the trace to collect data
89
+ trace = session_extra.get("trace")
90
+ if not trace:
91
+ raise ValueError("Trace not found in session_extra")
92
+ # TODO: collect inputs and outputs for SPAN_KIND_FUNCTION
93
+ inputs = extract_flattened_inputs(func, *args, **kwargs)
88
94
  # create the span if it is the root span
89
95
  if divi._datapark and span.trace_id:
90
96
  divi._datapark.create_spans(
@@ -92,42 +98,18 @@ def observable(
92
98
  )
93
99
  # end the trace if it is the root span
94
100
  if divi._datapark and not span.parent_span_id:
95
- trace = session_extra.get("trace")
96
- if trace:
97
- trace.end()
98
- divi._datapark.upsert_traces(
99
- session_id=trace.session_id, traces=[trace.signal]
100
- )
101
+ trace.end()
102
+ # create the chat completion if it is a chat completion
101
103
  if divi._datapark and isinstance(result, ChatCompletion):
102
104
  divi._datapark.create_chat_completion(
103
- span_id=span.span_id, completion=result
105
+ span_id=span.span_id,
106
+ trace_id=trace.trace_id,
107
+ inputs=inputs,
108
+ completion=result,
104
109
  )
105
- return result
106
110
 
107
- @functools.wraps(func)
108
- def generator_wrapper(
109
- *args, session_extra: Optional[SessionExtra] = None, **kwargs
110
- ):
111
- span = Span(
112
- kind=kind, name=name or func.__name__, metadata=metadata
113
- )
114
- session_extra = setup(span, _SESSION_EXTRA.get() or session_extra)
115
- # set current context
116
- token = _SESSION_EXTRA.set(session_extra)
117
- # execute the function
118
- results: List[Any] = []
119
- span.start()
120
- for item in func(*args, **kwargs):
121
- results.append(item)
122
- yield item
123
- span.end()
124
-
125
- # recover parent context
126
- _SESSION_EXTRA.reset(token)
127
- # TODO: collect results
111
+ return result
128
112
 
129
- if inspect.isgeneratorfunction(func):
130
- return generator_wrapper
131
113
  return wrapper
132
114
 
133
115
  # Function Decorator
@@ -5,7 +5,7 @@ import warnings
5
5
 
6
6
  from divi.proto.core.health.v1 import health_service_pb2 as divi_dot_proto_dot_core_dot_health_dot_v1_dot_health__service__pb2
7
7
 
8
- GRPC_GENERATED_VERSION = '1.69.0'
8
+ GRPC_GENERATED_VERSION = '1.71.0'
9
9
  GRPC_VERSION = grpc.__version__
10
10
  _version_not_supported = False
11
11
 
@@ -1,5 +1,3 @@
1
- import requests
2
-
3
1
  from divi.services.auth.tokman import Token
4
2
  from divi.services.service import Service
5
3
 
@@ -12,10 +10,4 @@ class Auth(Service):
12
10
 
13
11
  def auth_with_api_key(self) -> str:
14
12
  """Get the token with the API key."""
15
- r = requests.post(
16
- f"http://{self.target}/api/auth/api_key",
17
- json={"api_key": self.api_key},
18
- )
19
- if r.status_code == 200:
20
- return r.json()["data"]
21
- raise ValueError(r.json()["message"])
13
+ return self.post("/api/auth/api_key", payload={"api_key": self.api_key})
@@ -1,7 +1,10 @@
1
- import requests
1
+ from typing import Any, Dict
2
+
2
3
  from google.protobuf.json_format import MessageToDict
3
- from openai.types.chat.chat_completion import ChatCompletion
4
+ from openai import NotGiven
5
+ from openai.types.chat import ChatCompletion
4
6
  from pydantic import UUID4
7
+ from typing_extensions import Mapping
5
8
 
6
9
  import divi
7
10
  from divi.proto.trace.v1.trace_pb2 import ScopeSpans
@@ -18,46 +21,53 @@ class DataPark(Service):
18
21
  self.token = divi._auth.token
19
22
 
20
23
  @property
21
- def headers(self):
24
+ def headers(self) -> Dict[str, str]:
22
25
  return {"Authorization": f"Bearer {self.token}"}
23
26
 
24
- def create_session(self, session: SessionSignal):
25
- r = requests.post(
26
- f"http://{self.target}/api/session/",
27
- headers=self.headers,
28
- json=session,
29
- )
30
- if r.status_code != 201:
31
- raise ValueError(r.json()["message"])
32
-
33
- def upsert_traces(self, session_id: UUID4, traces: list[TraceSignal]):
34
- r = requests.post(
35
- f"http://{self.target}/api/session/{session_id}/traces",
36
- headers=self.headers,
37
- json=traces,
38
- )
39
- if r.status_code != 201:
40
- raise ValueError(r.json()["message"])
41
-
42
- def create_spans(self, trace_id: UUID4, spans: ScopeSpans):
43
- r = requests.post(
44
- f"http://{self.target}/api/trace/{trace_id}/spans",
45
- headers=self.headers,
46
- json=MessageToDict(spans),
47
- )
48
- if r.status_code != 201:
49
- raise ValueError(r.json()["message"])
27
+ @staticmethod
28
+ def strip_not_given(obj: object | None) -> object:
29
+ """Remove all top-level keys where their values are instances of `NotGiven`"""
30
+ if obj is None:
31
+ return None
32
+
33
+ if not isinstance(obj, Mapping):
34
+ return obj
35
+
36
+ return {
37
+ key: value
38
+ for key, value in obj.items()
39
+ if not isinstance(value, NotGiven)
40
+ }
41
+
42
+ def create_session(self, session: SessionSignal) -> None:
43
+ self.post("/api/session/", payload=session)
44
+
45
+ def upsert_traces(
46
+ self, session_id: UUID4, traces: list[TraceSignal]
47
+ ) -> None:
48
+ self.post(f"/api/session/{session_id}/traces", payload=traces)
49
+
50
+ def create_spans(self, trace_id: UUID4, spans: ScopeSpans) -> None:
51
+ self.post(f"/api/trace/{trace_id}/spans", payload=MessageToDict(spans))
50
52
 
51
53
  def create_chat_completion(
52
- self, span_id: bytes, completion: ChatCompletion
53
- ):
54
- r = requests.post(
55
- f"http://{self.target}/api/v1/chat/completions",
56
- headers=self.headers,
57
- json={
58
- "span_id": span_id.hex(),
59
- "data": completion.model_dump(),
60
- },
54
+ self,
55
+ span_id: bytes,
56
+ trace_id: UUID4,
57
+ inputs: Dict[str, Any],
58
+ completion: ChatCompletion,
59
+ ) -> None:
60
+ hex_span_id = span_id.hex()
61
+ self.post_concurrent(
62
+ {
63
+ "/api/v1/chat/completions/input": {
64
+ "span_id": hex_span_id,
65
+ "data": self.strip_not_given(inputs),
66
+ },
67
+ "/api/v1/chat/completions": {
68
+ "span_id": hex_span_id,
69
+ "trace_id": str(trace_id),
70
+ "data": completion.model_dump(),
71
+ },
72
+ }
61
73
  )
62
- if r.status_code != 201:
63
- raise ValueError(r.json()["message"])
divi/services/service.py CHANGED
@@ -1,3 +1,9 @@
1
+ from concurrent.futures import ThreadPoolExecutor
2
+ from typing import Any, Dict, Mapping, Sequence
3
+
4
+ import requests
5
+
6
+
1
7
  class Service:
2
8
  """Service management class."""
3
9
 
@@ -9,3 +15,40 @@ class Service:
9
15
  def target(self) -> str:
10
16
  """Return the target string: host:port."""
11
17
  return f"{self.host}:{self.port}"
18
+
19
+ @property
20
+ def headers(self) -> Dict[str, str]:
21
+ """Override to provide default headers."""
22
+ return {}
23
+
24
+ def post(
25
+ self,
26
+ path: str,
27
+ payload: Mapping[str, Any] | Sequence[Mapping[str, Any]],
28
+ ) -> Any:
29
+ response = requests.post(
30
+ f"http://{self.target}{path}",
31
+ json=payload,
32
+ headers=self.headers,
33
+ )
34
+ if not 200 <= response.status_code < 300:
35
+ raise ValueError(
36
+ f"{path} failed: {response.json().get('message', 'Unknown error')}"
37
+ )
38
+ return response.json().get("data", response.json())
39
+
40
+ def post_concurrent(
41
+ self,
42
+ calls: Dict[str, Mapping[str, Any] | Sequence[Mapping[str, Any]]],
43
+ ) -> None:
44
+ with ThreadPoolExecutor(max_workers=len(calls)) as executor:
45
+ futures = [
46
+ executor.submit(
47
+ self.post,
48
+ path,
49
+ payload,
50
+ )
51
+ for path, payload in calls.items()
52
+ ]
53
+ for future in futures:
54
+ future.result()
divi/session/session.py CHANGED
@@ -9,13 +9,13 @@ class SessionExtra(TypedDict, total=False):
9
9
 
10
10
  session_name: Optional[str]
11
11
  """Name of the session"""
12
- trace: Optional[Trace]
13
- """Trace ID UUID4"""
12
+ trace: Trace
13
+ """Trace in session"""
14
14
  parent_span_id: Optional[bytes]
15
15
  """Parent Span ID fixed string(8)"""
16
16
 
17
17
 
18
- class SessionSignal(TypedDict, total=False):
18
+ class SessionSignal(TypedDict):
19
19
  """Session request"""
20
20
 
21
21
  id: str
divi/session/setup.py CHANGED
@@ -1,3 +1,4 @@
1
+ from typing_extensions import Optional
1
2
  import divi
2
3
  from divi.services import init as init_services
3
4
  from divi.session import Session, SessionExtra
@@ -5,10 +6,10 @@ from divi.signals.trace import Span
5
6
  from divi.signals.trace.trace import Trace
6
7
 
7
8
 
8
- def init(session_extra: SessionExtra) -> Session:
9
+ def init_session(name: Optional[str]=None) -> Session:
9
10
  """init initializes the services and the Run"""
10
11
  init_services()
11
- session = Session(name=session_extra.get("session_name"))
12
+ session = Session(name=name)
12
13
  if divi._datapark:
13
14
  divi._datapark.create_session(session.signal)
14
15
  return session
@@ -24,39 +25,21 @@ def setup(
24
25
  span (Span): Span instance
25
26
  session_extra (SessionExtra | None): Extra information from user input
26
27
  """
27
- # TOOD: merge run_extra input by user with the one from the context
28
- # temp solution: Priority: run_extra_context.get() > run_extra
29
28
  session_extra = session_extra or SessionExtra()
30
29
 
31
30
  # init the session if not already initialized
32
31
  if not divi._session:
33
- divi._session = init(session_extra=session_extra)
32
+ divi._session = init_session(name=session_extra.get('session_name') or span.name)
34
33
 
35
34
  # setup trace
36
- # init current span
37
- trace = session_extra.get("trace")
35
+ trace = session_extra.get("trace") or Trace(divi._session.id, span.name)
38
36
  parent_span_id = session_extra.get("parent_span_id")
39
- if trace and parent_span_id:
40
- span._add_parent(trace.trace_id, parent_span_id)
41
- else:
42
- trace = Trace(divi._session.id)
43
- trace.start()
44
- span._as_root(trace.trace_id)
45
- # create the trace
46
- if divi._datapark:
47
- divi._datapark.upsert_traces(
48
- session_id=divi._session.id, traces=[trace.signal]
49
- )
50
-
51
- # update the session_extra with the current span
52
- # session_extra["trace_id"] = span.trace_id
53
- # session_extra["parent_span_id"] = span.span_id
54
- session_extra = SessionExtra(
37
+ span._add_node(trace.trace_id, parent_span_id)
38
+
39
+ # update the session_extra with the current trace and span
40
+ return SessionExtra(
55
41
  session_name=divi._session.name,
56
42
  trace=trace,
57
43
  # set the parent_span_id to the current span_id
58
44
  parent_span_id=span.span_id,
59
45
  )
60
-
61
- # offer end hook to collect data at whe end of the span ?
62
- return session_extra
@@ -7,6 +7,7 @@ from uuid import uuid4
7
7
  from pydantic import UUID4
8
8
  from typing_extensions import TypedDict
9
9
 
10
+ import divi
10
11
  from divi.proto.common.v1.common_pb2 import KeyValue
11
12
  from divi.proto.trace.v1.trace_pb2 import Span as SpanProto
12
13
 
@@ -29,15 +30,19 @@ class TraceSignal(TypedDict, total=False):
29
30
  """Start time in iso format"""
30
31
  end_time: NullTime
31
32
  """End time in iso format"""
33
+ name: Optional[str]
32
34
 
33
35
 
34
36
  class Trace:
35
- def __init__(self, session_id: UUID4):
37
+ def __init__(self, session_id: UUID4, name: Optional[str] = None):
36
38
  self.trace_id: UUID4 = uuid4()
37
39
  self.start_time: str | None = None
38
40
  self.end_time: str | None = None
41
+ self.name: Optional[str] = name
39
42
  self.session_id: UUID4 = session_id
40
43
 
44
+ self.start()
45
+
41
46
  @property
42
47
  def signal(self) -> TraceSignal:
43
48
  if self.start_time is None:
@@ -45,6 +50,7 @@ class Trace:
45
50
  signal = TraceSignal(
46
51
  id=str(self.trace_id),
47
52
  start_time=self.start_time,
53
+ name=self.name,
48
54
  )
49
55
  if self.end_time is not None:
50
56
  signal["end_time"] = NullTime(
@@ -60,12 +66,21 @@ class Trace:
60
66
  def start(self):
61
67
  """Start the trace by recording the current time in nanoseconds."""
62
68
  self.start_time = datetime.now(UTC).isoformat()
69
+ self.upsert_trace()
63
70
 
64
71
  def end(self):
65
72
  """End the trace by recording the end time in nanoseconds."""
66
73
  if self.start_time is None:
67
74
  raise ValueError("Span must be started before ending.")
68
75
  self.end_time = datetime.now(UTC).isoformat()
76
+ self.upsert_trace()
77
+
78
+ def upsert_trace(self):
79
+ """Upsert trace with datapark."""
80
+ if divi._datapark:
81
+ divi._datapark.upsert_traces(
82
+ session_id=self.session_id, traces=[self.signal]
83
+ )
69
84
 
70
85
 
71
86
  class Span:
@@ -102,7 +117,6 @@ class Span:
102
117
  trace_id=self.trace_id.bytes if self.trace_id else None,
103
118
  parent_span_id=self.parent_span_id,
104
119
  )
105
- print(self.kind)
106
120
  signal.metadata.extend(
107
121
  KeyValue(key=k, value=v)
108
122
  for k, v in (self.metadata or dict()).items()
@@ -131,21 +145,7 @@ class Span:
131
145
  raise ValueError("Span must be started before ending.")
132
146
  self.end_time_unix_nano = time.time_ns()
133
147
 
134
- def _as_root(self, trace_id: UUID4):
135
- """Set the span as a root span."""
136
- self.trace_id = trace_id
137
- print("as root")
138
- print(f"name: {self.name}")
139
- print(f"trace_id: {self.trace_id}")
140
- print(f"span_id: {self.span_id}")
141
-
142
- def _add_parent(self, trace_id: UUID4, parent_id: bytes):
143
- """Set the parent span ID."""
148
+ def _add_node(self, trace_id: UUID4, parent_id: Optional[bytes] = None):
149
+ """Add node for obs tree."""
144
150
  self.trace_id = trace_id
145
151
  self.parent_span_id = parent_id
146
-
147
- print("add parent")
148
- print(f"name: {self.name}")
149
- print(f"trace_id: {trace_id}")
150
- print(f"span_id: {self.span_id}")
151
- print(f"parent_span_id: {parent_id}")
divi/utils.py CHANGED
@@ -1,6 +1,33 @@
1
1
  import inspect
2
2
  import pathlib
3
- from typing import Callable
3
+ from typing import Any, Callable, Dict
4
+
5
+
6
+ def extract_flattened_inputs(
7
+ func: Callable, *args: Any, **kwargs: Any
8
+ ) -> Dict[str, Any]:
9
+ """
10
+ Extracts a flat dictionary of parameter names and values from a function call.
11
+ Handles default values, removes 'self' and 'cls', and flattens **kwargs.
12
+ """
13
+ signature = inspect.signature(func)
14
+ bound_args = signature.bind_partial(*args, **kwargs)
15
+ bound_args.apply_defaults()
16
+
17
+ arguments = dict(bound_args.arguments)
18
+ arguments.pop("self", None)
19
+ arguments.pop("cls", None)
20
+
21
+ for param_name, param in signature.parameters.items():
22
+ if (
23
+ param.kind == inspect.Parameter.VAR_KEYWORD
24
+ and param_name in arguments
25
+ ):
26
+ kwarg_dict = arguments.pop(param_name)
27
+ if isinstance(kwarg_dict, dict):
28
+ arguments.update(kwarg_dict)
29
+
30
+ return arguments
4
31
 
5
32
 
6
33
  def get_server_path() -> str:
@@ -1,10 +1,11 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: divi
3
- Version: 0.0.1.dev15
3
+ Version: 0.0.1.dev23
4
4
  Summary: The Agent Platform for Observability & Evaluation
5
5
  License-File: LICENSE
6
6
  Requires-Python: >=3.11
7
7
  Requires-Dist: grpcio>=1.71.0
8
+ Requires-Dist: openai>=1.65.2
8
9
  Requires-Dist: protobuf<6.0.dev0,>=5.26.1
9
10
  Requires-Dist: pyjwt>=2.10.1
10
11
  Requires-Dist: requests>=2.32.3
@@ -1,16 +1,16 @@
1
- divi/__init__.py,sha256=RmQ9wc0IZRqR9DN6hACn0YMUrhHC_AJ9gXsKrgvkcWs,396
2
- divi/utils.py,sha256=3iVDogCjqQg0jEjhUKEuQ6vHPFp9w7kXNjSVwXt8KmI,574
1
+ divi/__init__.py,sha256=lcpSVEjIcXy-e9CuJB8V1izwaoEK8YpH8FtkzH0IqJc,396
2
+ divi/utils.py,sha256=fXkjoyo_Lh8AZliKICOP460m0czUcNQjcEcceJbaOVA,1439
3
3
  divi/config/config.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
4
  divi/decorators/__init__.py,sha256=HkyWdC1ctTsVFucCWCkj57JB4NmwONus1d2S2dUbvs4,110
5
- divi/decorators/obs_openai.py,sha256=4LtQPRgJPPyTOw1318Fi04WYqjIwGX8EP0YiWrTW0dk,1003
6
- divi/decorators/observable.py,sha256=N_MCX_HbMGpD7v_dxnK6ewhgONGxH4XBO-i-6ybGpkc,4038
5
+ divi/decorators/obs_openai.py,sha256=GI9c6gFArA6pTfa3EPednMtRqV2zIlofuTDdUYtS_x4,963
6
+ divi/decorators/observable.py,sha256=xKapTyHL50mUyIDhDSYIXR1yZIdHTuw6WtI4H0j1xDE,3464
7
7
  divi/proto/common/v1/common.proto,sha256=Rx8wr0_tOtQ1NseTMnsav4ApD1MDALzQDBA2IvLRTU0,1775
8
8
  divi/proto/common/v1/common_pb2.py,sha256=br61OHQVAi6SI3baFcb5xJv2Xd-AZ04A19xeSjLNMXo,2442
9
9
  divi/proto/common/v1/common_pb2.pyi,sha256=LmTpFFLxHg2a_qPIdNXXwGEMkbiDcTJdarR9eC-6Fq8,2133
10
10
  divi/proto/core/health/v1/health_service.proto,sha256=y39MNiwYiSqxb_JPQI7AmPfNNtP6pbX-WKTseMkjWUM,369
11
11
  divi/proto/core/health/v1/health_service_pb2.py,sha256=PKAxy_z7lU1HrwDNIa7AFHha9i8gICCVrcEhpOM79E0,1999
12
12
  divi/proto/core/health/v1/health_service_pb2.pyi,sha256=VbYHHTcp3epUVg0lTSxo3xpG52ZGhA7KKMRL5LR5e1c,691
13
- divi/proto/core/health/v1/health_service_pb2_grpc.py,sha256=6owvQ41KPqSOQ8WjXDjYsunoDVydJfP93vZ4uVSG59s,3953
13
+ divi/proto/core/health/v1/health_service_pb2_grpc.py,sha256=YmlO94d-G71YBW1XZDSbYkwnHEUe6Z7R3_KAmoDWyA0,3953
14
14
  divi/proto/metric/v1/metric.proto,sha256=YHRMLUW-MtakHuibR3PJ0s2w5KgV12kc4737iHw0DTk,585
15
15
  divi/proto/metric/v1/metric_pb2.py,sha256=uvBhyy8QpaES3Jl82yVfsGazW5654XpRnsdGlpVgIRE,1974
16
16
  divi/proto/metric/v1/metric_pb2.pyi,sha256=S7ipsojkD7QZAYefDE4b3PO99Yzc6mOdtSLxH3-b67A,1304
@@ -20,9 +20,9 @@ divi/proto/trace/v1/trace_pb2.pyi,sha256=rPo2Oa3NWrINE_dyOVU9HUYHo5LY82Bm5TMenj5
20
20
  divi/services/__init__.py,sha256=TcVJ_gKxyPIcwhT9GgttqHeyk0icW44uE285KmUiyh4,185
21
21
  divi/services/finish.py,sha256=XKPKGJ5cWd5H95G_VpIOlOZOLrcf9StoTs7ayRic2jY,173
22
22
  divi/services/init.py,sha256=JVzRQ1m1DTHXFVGUMYnsv-vRvzCO8XFdR6MjIwOL_NY,433
23
- divi/services/service.py,sha256=1c7JQ49BSdBipGLfVIxTHaNxTuyvVAgrvxV7lyYv_68,285
23
+ divi/services/service.py,sha256=539MhcYfMvsVGjDdu0UtYSZnL2cloaPeYeOSMl2eUy8,1532
24
24
  divi/services/auth/__init__.py,sha256=PIQ9rQ0jcRqcy03a3BOY7wbzwluIRG_4kI_H4J4mRFk,74
25
- divi/services/auth/auth.py,sha256=dTpFnNhxbEjzOkBLPQvRblFSO5tedJsdObWTXt84MaE,631
25
+ divi/services/auth/auth.py,sha256=eRcE6Kq8jbBr6YL93HCGDIoga90SoZf3ogOAKeza9WY,445
26
26
  divi/services/auth/init.py,sha256=UXsOweatrWnuFO9ivSjEsJnHrK9YtStKYX2Nup64KEU,477
27
27
  divi/services/auth/tokman.py,sha256=V03wcV6TEy1k9o55teDVB9JZ3Ve2cJdwzWstQhWx4BQ,1070
28
28
  divi/services/core/__init__.py,sha256=FWl4ShX0AEnOyL24NEc9mNIVoQOeYO4q0qYX27L_Yyw,111
@@ -30,16 +30,16 @@ divi/services/core/core.py,sha256=PRwPtLgrgmCrejUfKf7HJNrAhGS0paFNZ7JwDToEUAk,12
30
30
  divi/services/core/finish.py,sha256=dIGQpVXcJY4-tKe7A1_VV3yoSHNCDPfOlUltvzvk6VI,231
31
31
  divi/services/core/init.py,sha256=e7-fgpOPglBXyEoPkgOAnpJk2ApdFbo7LPupxOb8N-w,1966
32
32
  divi/services/datapark/__init__.py,sha256=GbV1mwHE07yutgOlCIYHykSEL5KJ-ApgLutGMzu2eUE,86
33
- divi/services/datapark/datapark.py,sha256=J96C-K9RCaLT7oWXnMQOM1g7btfIlU7BMWReF3ePOlc,2055
33
+ divi/services/datapark/datapark.py,sha256=d2pbrzVJtR3mNW1eQpbm-Wca-SvcfJqT7IuaQy7yHT0,2285
34
34
  divi/services/datapark/init.py,sha256=C32f9t3eLsxcYNqEyheh6nW455G2oR0YhhdqBcbN3ec,92
35
35
  divi/session/__init__.py,sha256=6lYemv21VQCIHx-xIdi7BxXcPNxVdvE60--8ArReUew,82
36
- divi/session/session.py,sha256=ID7bQ4CuRPUcZ9S-DSjndiduslYFJukRLuCtChYm3wk,838
37
- divi/session/setup.py,sha256=jlc3ICR5hRDdrcxoSxi66FYS2TYxqrIJOMgI4i1tEJs,1972
36
+ divi/session/session.py,sha256=LlB2W2qGo0Vf-0L0CTQoXfzg_gCGpf0MTFsXQW7E6i4,817
37
+ divi/session/setup.py,sha256=NeCxCb-uYhkKnOEiw8dBQHz0DEL8j1oxzQY3cBAmHbo,1380
38
38
  divi/session/teardown.py,sha256=YiBz_3yCiljMFEofZ60VmRL5sb8WA5GT7EYF8nFznZ4,133
39
39
  divi/signals/__init__.py,sha256=K1PaTAMwyBDsK6jJUg4QWy0xVJ_5MA6dlWiUyJeiSQA,44
40
40
  divi/signals/trace/__init__.py,sha256=K1PaTAMwyBDsK6jJUg4QWy0xVJ_5MA6dlWiUyJeiSQA,44
41
- divi/signals/trace/trace.py,sha256=y8Xio8Tp_e1tO8l_DAkUuzMrmENNKfIdklF0iWrjGYk,4547
42
- divi-0.0.1.dev15.dist-info/METADATA,sha256=pV_UinVgV7tlDH6lgD1eYH-k_enKQGKe_FTDhenmjWM,467
43
- divi-0.0.1.dev15.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
44
- divi-0.0.1.dev15.dist-info/licenses/LICENSE,sha256=5OJuZ4wMMEV0DgF0tofhAlS_KLkaUsZwwwDS2U_GwQ0,1063
45
- divi-0.0.1.dev15.dist-info/RECORD,,
41
+ divi/signals/trace/trace.py,sha256=OsfrZPHp241_NN8W79U4O69HsHQajez_d3rz6yJRN9s,4508
42
+ divi-0.0.1.dev23.dist-info/METADATA,sha256=KdspT1iEra11ixCEtl94Mz_fCziMVOOER08rDE4yCWU,497
43
+ divi-0.0.1.dev23.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
44
+ divi-0.0.1.dev23.dist-info/licenses/LICENSE,sha256=5OJuZ4wMMEV0DgF0tofhAlS_KLkaUsZwwwDS2U_GwQ0,1063
45
+ divi-0.0.1.dev23.dist-info/RECORD,,