orca-python 0.4.0__tar.gz → 0.5.0__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: orca-python
3
- Version: 0.4.0
3
+ Version: 0.5.0
4
4
  Summary: Python SDK for the Predixus Orca product
5
5
  Author: Frederick Mannings
6
6
  Author-email: contact@predixus.com
@@ -0,0 +1,3 @@
1
+ from orca_python.main import Window, Processor, EmitWindow, WindowType, ExecutionParams
2
+
3
+ __all__ = ["Processor", "EmitWindow", "Window", "WindowType", "ExecutionParams"]
@@ -26,8 +26,9 @@ from typing import (
26
26
  TypeVar,
27
27
  Callable,
28
28
  Iterable,
29
+ Optional,
30
+ Protocol,
29
31
  Generator,
30
- TypeAlias,
31
32
  AsyncGenerator,
32
33
  )
33
34
  from concurrent import futures
@@ -48,7 +49,16 @@ ALGORITHM_NAME = r"^[A-Z][a-zA-Z0-9]*$"
48
49
  SEMVER_PATTERN = r"^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)$"
49
50
  WINDOW_NAME = r"^[A-Z][a-zA-Z0-9]*$"
50
51
 
51
- AlgorithmFn: TypeAlias = Callable[..., Any]
52
+
53
+ @dataclass
54
+ class ExecutionParams:
55
+ window: pb.Window
56
+ dependencies: Optional[Iterable[pb.AlgorithmResult]] = None
57
+
58
+
59
+ class AlgorithmFn(Protocol):
60
+ def __call__(self, params: ExecutionParams, *args: Any, **kwargs: Any) -> Any: ...
61
+
52
62
 
53
63
  T = TypeVar("T", bound=AlgorithmFn)
54
64
 
@@ -200,12 +210,11 @@ class Algorithms:
200
210
  break
201
211
 
202
212
  if not dependencyAlgo:
213
+ dep_name = getattr(dependency, "__name__", "<unknown>")
203
214
  LOGGER.error(
204
- f"Failed to find registered algorithm for dependency: {dependency.__name__}"
205
- )
206
- raise ValueError(
207
- f"Dependency {dependency.__name__} not found in registered algorithms"
215
+ f"Failed to find registered algorithm for dependency: {dep_name}"
208
216
  )
217
+ raise ValueError(f"Dependency {dep_name} not found in reg=ms")
209
218
 
210
219
  if algorithm not in self._dependencyFns:
211
220
  self._dependencyFns[algorithm] = [dependency]
@@ -265,7 +274,7 @@ class Processor(OrcaProcessorServicer): # type: ignore
265
274
  self,
266
275
  exec_id: str,
267
276
  algorithm: pb.Algorithm,
268
- dependencyResults: Iterable[pb.AlgorithmResult],
277
+ params: ExecutionParams,
269
278
  ) -> pb.ExecutionResult:
270
279
  """
271
280
  Executes a single algorithm with resolved dependencies.
@@ -273,7 +282,7 @@ class Processor(OrcaProcessorServicer): # type: ignore
273
282
  Args:
274
283
  exec_id (str): Unique execution ID.
275
284
  algorithm (pb.Algorithm): The algorithm to execute.
276
- dependencyResults (Iterable[pb.AlgorithmResult]): Results from dependency algorithms.
285
+ params (ExecutionParams): The execution params object, which contains the triggering window and dependency results.
277
286
 
278
287
  Returns:
279
288
  pb.ExecutionResult: The result of the execution.
@@ -288,27 +297,28 @@ class Processor(OrcaProcessorServicer): # type: ignore
288
297
 
289
298
  # convert dependency results into a dict of name -> value
290
299
  dependency_values = {}
291
- for dep_result in dependencyResults:
292
- # extract value based on which oneof field is set
293
- dep_value = None
294
- if dep_result.result.HasField("single_value"):
295
- dep_value = dep_result.result.single_value
296
- elif dep_result.result.HasField("float_values"):
297
- dep_value = list(dep_result.result.float_values.values)
298
- elif dep_result.result.HasField("struct_value"):
299
- dep_value = json_format.MessageToDict(
300
- dep_result.result.struct_value
300
+ if params.dependencies:
301
+ for dep_result in params.dependencies:
302
+ # extract value based on which oneof field is set
303
+ dep_value = None
304
+ if dep_result.result.HasField("single_value"):
305
+ dep_value = dep_result.result.single_value
306
+ elif dep_result.result.HasField("float_values"):
307
+ dep_value = list(dep_result.result.float_values.values)
308
+ elif dep_result.result.HasField("struct_value"):
309
+ dep_value = json_format.MessageToDict(
310
+ dep_result.result.struct_value
311
+ )
312
+
313
+ dep_name = (
314
+ f"{dep_result.algorithm.name}_{dep_result.algorithm.version}"
301
315
  )
302
-
303
- dep_name = f"{dep_result.algorithm.name}_{dep_result.algorithm.version}"
304
- dependency_values[dep_name] = dep_value
316
+ dependency_values[dep_name] = dep_value
305
317
 
306
318
  # execute in thread pool since algo.exec_fn is synchronous
307
319
  loop = asyncio.get_event_loop()
308
320
 
309
- algoResult = await loop.run_in_executor(
310
- None, algo.exec_fn, dependency_values
311
- )
321
+ algoResult = await loop.run_in_executor(None, algo.exec_fn, params)
312
322
 
313
323
  # create result based on the return type
314
324
  current_time = int(time.time()) # Current timestamp in seconds
@@ -410,13 +420,13 @@ class Processor(OrcaProcessorServicer): # type: ignore
410
420
  return pb.ExecutionResult(exec_id=exec_id, algorithm_result=algo_result)
411
421
 
412
422
  def ExecuteDagPart(
413
- self, ExecutionRequest: pb.ExecutionRequest, context: grpc.ServicerContext
423
+ self, executionRequest: pb.ExecutionRequest, context: grpc.ServicerContext
414
424
  ) -> Generator[pb.ExecutionResult, None, None]:
415
425
  """
416
426
  Executes part of a DAG (Directed Acyclic Graph) of algorithms.
417
427
 
418
428
  Args:
419
- ExecutionRequest (pb.ExecutionRequest): The DAG execution request.
429
+ executionRequest (pb.ExecutionRequest): The DAG execution request.
420
430
  context (grpc.ServicerContext): gRPC context for the request.
421
431
 
422
432
  Yields:
@@ -428,8 +438,8 @@ class Processor(OrcaProcessorServicer): # type: ignore
428
438
 
429
439
  LOGGER.info(
430
440
  (
431
- f"Received DAG execution request with {len(ExecutionRequest.algorithms)} "
432
- f"algorithms and ExecId: {ExecutionRequest.exec_id}"
441
+ f"Received DAG execution request with {len(executionRequest.algorithms)} "
442
+ f"algorithms and ExecId: {executionRequest.exec_id}"
433
443
  )
434
444
  )
435
445
 
@@ -444,11 +454,14 @@ class Processor(OrcaProcessorServicer): # type: ignore
444
454
  # create tasks for all algorithms
445
455
  tasks = [
446
456
  self.execute_algorithm(
447
- ExecutionRequest.exec_id,
457
+ executionRequest.exec_id,
448
458
  algorithm,
449
- ExecutionRequest.algorithm_results,
459
+ ExecutionParams(
460
+ window=executionRequest.window,
461
+ dependencies=executionRequest.algorithm_results,
462
+ ),
450
463
  )
451
- for algorithm in ExecutionRequest.algorithms
464
+ for algorithm in executionRequest.algorithms
452
465
  ]
453
466
 
454
467
  # execute all tasks concurrently and yield results as they complete
@@ -637,18 +650,16 @@ class Processor(OrcaProcessorServicer): # type: ignore
637
650
 
638
651
  def inner(algo: T) -> T:
639
652
  def wrapper(
640
- dependency_values: Dict[str, Any] | None = None,
653
+ params: ExecutionParams,
641
654
  *args: Any,
642
655
  **kwargs: Any,
643
656
  ) -> Any:
644
657
  LOGGER.debug(f"Executing algorithm {name}_{version}")
645
658
  try:
646
659
  # setup ready for the algo
647
- # add dependency values to kwargs if provided
648
- if dependency_values:
649
- kwargs["dependencies"] = dependency_values
660
+ # pack the params into the kwargs - user can decide if they want it
661
+ kwargs["params"] = params
650
662
  LOGGER.debug(f"Algorithm {name}_{version} setup complete")
651
- # TODO
652
663
 
653
664
  # run the algo
654
665
  LOGGER.info(f"Running algorithm {name}_{version}")
@@ -695,6 +706,6 @@ class Processor(OrcaProcessorServicer): # type: ignore
695
706
  # needs to be defined before a dependency can be created, and you can only register depencenies
696
707
  # once. But when dependencies are grabbed from a server, circular dependencies will be possible
697
708
 
698
- return wrapper # type: ignore
709
+ return wrapper # type: ignore[return-value]
699
710
 
700
711
  return inner
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "orca-python"
3
- version = "0.4.0"
3
+ version = "0.5.0"
4
4
  description = "Python SDK for the Predixus Orca product"
5
5
  authors = [
6
6
  "Frederick Mannings <contact@predixus.com>"
@@ -1,3 +0,0 @@
1
- from orca_python.main import Window, Processor, EmitWindow, WindowType
2
-
3
- __all__ = ["Processor", "EmitWindow", "Window", "WindowType"]
File without changes
File without changes