indexify 0.2.30__py3-none-any.whl → 0.2.32__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.
@@ -120,7 +120,7 @@ class Downloader:
120
120
  deserialized_content = serializer.deserialize(response.content)
121
121
 
122
122
  if reducer_url:
123
- init_value = httpx.get(reducer_url)
123
+ init_value = self._client.get(reducer_url)
124
124
  try:
125
125
  init_value.raise_for_status()
126
126
  except httpx.HTTPStatusError as e:
@@ -101,9 +101,9 @@ class Graph:
101
101
  return self
102
102
 
103
103
  if issubclass(indexify_fn, IndexifyFunction) and indexify_fn.accumulate:
104
- self.accumulator_zero_values[
105
- indexify_fn.name
106
- ] = indexify_fn.accumulate().model_dump()
104
+ self.accumulator_zero_values[indexify_fn.name] = (
105
+ indexify_fn.accumulate().model_dump()
106
+ )
107
107
 
108
108
  self.nodes[indexify_fn.name] = indexify_fn
109
109
  return self
@@ -210,6 +210,7 @@ class Graph:
210
210
  )
211
211
 
212
212
  def run(self, block_until_done: bool = False, **kwargs) -> str:
213
+ self.validate_graph()
213
214
  start_node = self.nodes[self._start_node]
214
215
  serializer = get_serializer(start_node.encoder)
215
216
  input = IndexifyData(
@@ -236,6 +237,35 @@ class Graph:
236
237
  self._run(input, outputs)
237
238
  return input.id
238
239
 
240
+ def validate_graph(self) -> None:
241
+ """
242
+ A method to validate that each node in the graph is
243
+ reachable from start node using BFS.
244
+ """
245
+ total_number_of_nodes = len(self.nodes)
246
+ queue = deque([self._start_node])
247
+ visited = {self._start_node}
248
+
249
+ while queue:
250
+ current_node_name = queue.popleft()
251
+ neighbours = (
252
+ self.edges[current_node_name]
253
+ if self.edges[current_node_name]
254
+ else self.routers[current_node_name]
255
+ )
256
+ for neighbour in neighbours:
257
+ if neighbour in visited:
258
+ continue
259
+ else:
260
+ visited.add(neighbour)
261
+ queue.append(neighbour)
262
+
263
+ if total_number_of_nodes != len(visited):
264
+ # all the nodes are not reachable from the start_node.
265
+ raise Exception(
266
+ "Some nodes in the graph are not reachable from start node."
267
+ )
268
+
239
269
  def _run(
240
270
  self,
241
271
  initial_input: IndexifyData,
@@ -244,9 +274,9 @@ class Graph:
244
274
  queue = deque([(self._start_node, initial_input)])
245
275
  while queue:
246
276
  node_name, input = queue.popleft()
247
- function_outputs: Union[
248
- FunctionCallResult, RouterCallResult
249
- ] = self._invoke_fn(node_name, input)
277
+ function_outputs: Union[FunctionCallResult, RouterCallResult] = (
278
+ self._invoke_fn(node_name, input)
279
+ )
250
280
  self._log_local_exec_tracebacks(function_outputs)
251
281
  if isinstance(function_outputs, RouterCallResult):
252
282
  for edge in function_outputs.edges:
@@ -275,7 +305,7 @@ class Graph:
275
305
  self, node_name: str, input: IndexifyData
276
306
  ) -> Optional[Union[RouterCallResult, FunctionCallResult]]:
277
307
  node = self.nodes[node_name]
278
- if node_name in self.routers:
308
+ if node_name in self.routers and len(self.routers[node_name]) > 0:
279
309
  result = IndexifyFunctionWrapper(node, self._local_graph_ctx).invoke_router(
280
310
  node_name, input
281
311
  )
@@ -137,9 +137,11 @@ def indexify_router(
137
137
 
138
138
  attrs = {
139
139
  "name": name if name else fn.__name__,
140
- "description": description
141
- if description
142
- else (fn.__doc__ or "").strip().replace("\n", ""),
140
+ "description": (
141
+ description
142
+ if description
143
+ else (fn.__doc__ or "").strip().replace("\n", "")
144
+ ),
143
145
  "image": image,
144
146
  "placement_constraints": placement_constraints,
145
147
  "encoder": encoder,
@@ -174,9 +176,11 @@ def indexify_function(
174
176
 
175
177
  attrs = {
176
178
  "name": name if name else fn.__name__,
177
- "description": description
178
- if description
179
- else (fn.__doc__ or "").strip().replace("\n", ""),
179
+ "description": (
180
+ description
181
+ if description
182
+ else (fn.__doc__ or "").strip().replace("\n", "")
183
+ ),
180
184
  "image": image,
181
185
  "placement_constraints": placement_constraints,
182
186
  "accumulate": accumulate,
@@ -205,9 +209,9 @@ class IndexifyFunctionWrapper:
205
209
  indexify_function: Union[IndexifyFunction, IndexifyRouter],
206
210
  context: GraphInvocationContext,
207
211
  ):
208
- self.indexify_function: Union[
209
- IndexifyFunction, IndexifyRouter
210
- ] = indexify_function()
212
+ self.indexify_function: Union[IndexifyFunction, IndexifyRouter] = (
213
+ indexify_function()
214
+ )
211
215
  self.indexify_function._ctx = context
212
216
 
213
217
  def get_output_model(self) -> Any:
indexify/remote_graph.py CHANGED
@@ -90,6 +90,7 @@ class RemoteGraph:
90
90
  :param client: The IndexifyClient used to communicate with the server.
91
91
  Prefered over server_url.
92
92
  """
93
+ g.validate_graph()
93
94
  if not client:
94
95
  client = IndexifyClient(service_url=server_url)
95
96
  client.register_compute_graph(g, additional_modules)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: indexify
3
- Version: 0.2.30
3
+ Version: 0.2.32
4
4
  Summary: Python Client for Indexify
5
5
  Home-page: https://github.com/tensorlakeai/indexify
6
6
  License: Apache 2.0
@@ -20,7 +20,7 @@ Requires-Dist: httpx-sse (>=0.4.0,<0.5.0)
20
20
  Requires-Dist: httpx[http2] (>=0,<1)
21
21
  Requires-Dist: jsonpickle (>=4.0.0,<5.0.0)
22
22
  Requires-Dist: nanoid (>=2.0.0,<3.0.0)
23
- Requires-Dist: pydantic (>=2.9.2,<3.0.0)
23
+ Requires-Dist: pydantic (==2.10.2)
24
24
  Requires-Dist: pyyaml (>=6,<7)
25
25
  Requires-Dist: rich (>=13.9.2,<14.0.0)
26
26
  Requires-Dist: typer (>=0.13.0,<0.14.0)
@@ -7,7 +7,7 @@ indexify/data_loaders/url_loader.py,sha256=32SERljcq1Xsi4RdLz2dgyk2TER5pQPTtXl3g
7
7
  indexify/error.py,sha256=qAWr8R6AxPkjsxHSzXTc8zqYnNO_AjOqqYEPsQvF1Zs,238
8
8
  indexify/executor/agent.py,sha256=Zt-KU2yrOuFuHu8CiOg-QmAzkNU1idcv5UZ3YN2YSDU,18649
9
9
  indexify/executor/api_objects.py,sha256=mvmwGbK4paJNQGFvbtNHMPpiH_LpVhrlRnCcrqS6HOQ,859
10
- indexify/executor/downloader.py,sha256=_SQ-6-0Kj3Zg0Dqp_pMwTYxvBP3xvNUOREyDucCJp8M,4944
10
+ indexify/executor/downloader.py,sha256=wwkTdKRrDBHwKQOb_3uUb8pVl1tvg4QzOcYFnGQwNtA,4951
11
11
  indexify/executor/executor_tasks.py,sha256=A0UIEZ5VaB6zSkFQG81UmTW0E57MTYhGlaXuAbRV8lQ,1884
12
12
  indexify/executor/function_worker.py,sha256=wRW2-X9dNI80KhwTD1vD-pcyetsVKVs6vVdg7L7JjcQ,6462
13
13
  indexify/executor/image_dependency_installer.py,sha256=ct8GmzgkaPi6NAblk68IJJWo5MecIUubELotmSrgoRQ,1759
@@ -16,20 +16,20 @@ indexify/executor/runtime_probes.py,sha256=mjw2_mGQ622wRT_39WPGGgPEZQTgtrf3-ICcU
16
16
  indexify/executor/task_reporter.py,sha256=4unHxLUHedKwIoqO3e5YdDJpUe_pJng-vHReoqcPNNU,5141
17
17
  indexify/executor/task_store.py,sha256=JlRlWwAm4YjFRkTNRx-6GsUcmOzcyvzb5Csa5XDpRTI,3982
18
18
  indexify/functions_sdk/data_objects.py,sha256=wXbUa9hjU6rsXmmk19vQ5Kixf3FsI59VBWPNmHasAX0,854
19
- indexify/functions_sdk/graph.py,sha256=TbHtIcAzRcEn3BWewVhNsUGMNfRduI1aSAvK6Vyx-fk,11801
19
+ indexify/functions_sdk/graph.py,sha256=ewm-XUlqIXA0RSl1JxU91yT2XXK3WRqrD9_YSvlK_44,12884
20
20
  indexify/functions_sdk/graph_definition.py,sha256=UeC0PMchgZgo2T0Goog0SW1lIRdFf6ug4iHOS9ItRvI,1622
21
21
  indexify/functions_sdk/graph_validation.py,sha256=mN2Fcp91GIwFZEQP6z_qGqt4LkLM70SnI7AWBi4CmKQ,2509
22
22
  indexify/functions_sdk/image.py,sha256=QK0H6KxLWriB_z4M0kunKzzHdHxYLWL670RPYgYuf_8,1762
23
- indexify/functions_sdk/indexify_functions.py,sha256=EbNC5gZktRc-G9ribQrpMG2X_G-8cujsxTgot734iGQ,10340
23
+ indexify/functions_sdk/indexify_functions.py,sha256=cPUN7Zlgkwl6YUOuhgKogPdoBakQuf-VspQvU3IDmfU,10422
24
24
  indexify/functions_sdk/local_cache.py,sha256=cNWF67zbhbTJe3g86hyLBy3Rqzs6dNvp2SjLazGZWvw,1348
25
25
  indexify/functions_sdk/object_serializer.py,sha256=pOgUOWbRNRix9uZT0aQn0LTCnJCeMNGO1nAE0jAybmg,1546
26
26
  indexify/functions_sdk/pipeline.py,sha256=KmxZE8eBFAQ4bbEcYURXXR26HSyoAT3O6iu9H38-OXE,974
27
27
  indexify/http_client.py,sha256=5d70A6j2vJBn3OfUVjrQvnPml07p7fxOXWBUAUfAkiU,15915
28
- indexify/remote_graph.py,sha256=CWfFxB0jlx8Zgp_xUjvjgrIwv-yNAfEbQwlXt3jfRNM,4976
28
+ indexify/remote_graph.py,sha256=aox9NibZIU8YDiP92syerFSjiZc2jVPkF6g2kfqOvCA,5003
29
29
  indexify/remote_pipeline.py,sha256=oqx57rSPszNS3DToXO_nf-CKqkCZWptm1u_p3orV_gQ,790
30
30
  indexify/settings.py,sha256=Ny59mzYI4gbXoK8hjx66a_men6ndbd1J1zCTcKOoyzg,50
31
- indexify-0.2.30.dist-info/LICENSE.txt,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
32
- indexify-0.2.30.dist-info/METADATA,sha256=iDiwkZ0gmVSy9jio0m6MdcuGCz9x8v92HdRpMDaXBU8,6202
33
- indexify-0.2.30.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
34
- indexify-0.2.30.dist-info/entry_points.txt,sha256=Pih7WV-XMpAzI5dEvROcpLr-ybVhd9Y-AtuzBKUdcDs,49
35
- indexify-0.2.30.dist-info/RECORD,,
31
+ indexify-0.2.32.dist-info/LICENSE.txt,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
32
+ indexify-0.2.32.dist-info/METADATA,sha256=3-sKMgJvXaZByfEAUE6h2fBtymF3pw7MXhXvv9gwhnU,6196
33
+ indexify-0.2.32.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
34
+ indexify-0.2.32.dist-info/entry_points.txt,sha256=Pih7WV-XMpAzI5dEvROcpLr-ybVhd9Y-AtuzBKUdcDs,49
35
+ indexify-0.2.32.dist-info/RECORD,,