From fdf1aabffec054247cec9ef919d02c70ed08fcbf Mon Sep 17 00:00:00 2001 From: Frederick Mannings Date: Tue, 13 Jan 2026 14:32:21 +0000 Subject: [PATCH 1/4] Simple implementation of the lookback function --- .../simpletrigger/simpletrigger/processor.py | 12 ++++++++++ orca_python/__init__.py | 2 ++ orca_python/main.py | 23 +++++++++++++++++++ 3 files changed, 37 insertions(+) diff --git a/examples/simpletrigger/simpletrigger/processor.py b/examples/simpletrigger/simpletrigger/processor.py index a7860f1..f2bcb10 100644 --- a/examples/simpletrigger/simpletrigger/processor.py +++ b/examples/simpletrigger/simpletrigger/processor.py @@ -1,8 +1,11 @@ import time +import datetime as dt from orca_python import ( + Lookback, Processor, WindowType, + ValueResult, StructResult, MetadataField, ExecutionParams, @@ -34,6 +37,15 @@ def my_algorithm(params: ExecutionParams) -> StructResult: return StructResult({"result": 42}) +@proc.algorithm( + "SecondAlgo", + "2.0.0", + Every30Second, + depends_on=[Lookback(my_algorithm, td=dt.timedelta(days=10), n=10)], +) +def second_algorithm(params: ExecutionParams) -> ValueResult: ... + + if __name__ == "__main__": proc.Register() proc.Start() diff --git a/orca_python/__init__.py b/orca_python/__init__.py index 78fb3a5..98c8e50 100644 --- a/orca_python/__init__.py +++ b/orca_python/__init__.py @@ -1,5 +1,6 @@ from orca_python.main import ( Window, + Lookback, Processor, EmitWindow, NoneResult, @@ -22,4 +23,5 @@ "ArrayResult", "NoneResult", "ExecutionParams", + "Lookback", ] diff --git a/orca_python/main.py b/orca_python/main.py index c429af2..21a64bb 100644 --- a/orca_python/main.py +++ b/orca_python/main.py @@ -213,6 +213,29 @@ class RemoteAlgorithm: Version: str +@dataclass +class Lookback(AlgorithmFn): + """Defines a lookback period in an algorithm dependency""" + + _lookback_td: dt.timedelta + _lookback_n: int + _algorithm: AlgorithmFn = field(repr=False) + + def __init__(self, algorithm: AlgorithmFn, td: dt.timedelta, n: int) -> None: + self.__dict__.update(algorithm.__dict__) + + self._algorithm = algorithm + + self._lookback_td = td + self._lookback_n = n + + def __call__( + self, params: ExecutionParams, *args: Any, **kwargs: Any + ) -> returnResult: + """Delegate the call to the wrapped algorithm""" + return self._algorithm(params, *args, **kwargs) + + T = TypeVar("T", bound=AlgorithmFn) From aa9ad6240dcd98dbeded289f289d32af86649967 Mon Sep 17 00:00:00 2001 From: Frederick Mannings Date: Tue, 13 Jan 2026 14:47:09 +0000 Subject: [PATCH 2/4] Updated implementation to send the lookback parameters off to the registration message --- orca | 2 +- orca_python/main.py | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/orca b/orca index 09af32c..03fac0a 160000 --- a/orca +++ b/orca @@ -1 +1 @@ -Subproject commit 09af32c578020fdbb55fdc85b003f41039027da8 +Subproject commit 03fac0aef26d49e664c36709e693700e2623ea1b diff --git a/orca_python/main.py b/orca_python/main.py index 21a64bb..055249e 100644 --- a/orca_python/main.py +++ b/orca_python/main.py @@ -217,8 +217,6 @@ class RemoteAlgorithm: class Lookback(AlgorithmFn): """Defines a lookback period in an algorithm dependency""" - _lookback_td: dt.timedelta - _lookback_n: int _algorithm: AlgorithmFn = field(repr=False) def __init__(self, algorithm: AlgorithmFn, td: dt.timedelta, n: int) -> None: @@ -232,7 +230,6 @@ def __init__(self, algorithm: AlgorithmFn, td: dt.timedelta, n: int) -> None: def __call__( self, params: ExecutionParams, *args: Any, **kwargs: Any ) -> returnResult: - """Delegate the call to the wrapped algorithm""" return self._algorithm(params, *args, **kwargs) @@ -744,6 +741,8 @@ def Register(self) -> None: dep_msg.version = dep.version dep_msg.processor_name = dep.processor dep_msg.processor_runtime = dep.runtime + dep_msg.lookback_num = getattr(dep, "_lookback_num", 0) + dep_msg.lookback_num = getattr(dep, "_lookback_td", 0) # Add remote dependencies if they exist if algorithm.full_name in self._algorithmsSingleton._remoteDependencies: @@ -755,6 +754,8 @@ def Register(self) -> None: dep_msg.version = remote_dep.Version dep_msg.processor_name = remote_dep.ProcessorName dep_msg.processor_runtime = remote_dep.ProcessorRuntime + dep_msg.lookback_num = getattr(dep, "_lookback_num", 0) + dep_msg.lookback_num = getattr(dep, "_lookback_td", 0) try: if envs.is_production: # secure channel with TLS From 380db2911220c2e49d36f1c97b3e1bd9231327a5 Mon Sep 17 00:00:00 2001 From: Frederick Mannings Date: Wed, 21 Jan 2026 14:01:51 +0000 Subject: [PATCH 3/4] final touches --- .../simpletrigger/simpletrigger/processor.py | 28 +- .../simpletrigger/simpletrigger/window.py | 6 +- orca | 2 +- orca_python/__init__.py | 4 +- orca_python/main.py | 252 ++++++++++++++---- poetry.lock | 121 +++++---- 6 files changed, 295 insertions(+), 118 deletions(-) diff --git a/examples/simpletrigger/simpletrigger/processor.py b/examples/simpletrigger/simpletrigger/processor.py index f2bcb10..8f4f5ea 100644 --- a/examples/simpletrigger/simpletrigger/processor.py +++ b/examples/simpletrigger/simpletrigger/processor.py @@ -2,13 +2,13 @@ import datetime as dt from orca_python import ( - Lookback, Processor, WindowType, ValueResult, StructResult, MetadataField, ExecutionParams, + lookback, ) proc = Processor("ml") @@ -26,7 +26,7 @@ ) -@proc.algorithm("MyAlgo", "1.0.0", Every30Second) +@proc.algorithm("MyAlgo", "1.0.0", Every30Second, description="Does nothing") def my_algorithm(params: ExecutionParams) -> StructResult: """A simple algorithms that does nothing interesting""" route_id = params.window.metadata.get("route_id", None) @@ -38,12 +38,30 @@ def my_algorithm(params: ExecutionParams) -> StructResult: @proc.algorithm( - "SecondAlgo", + "NewSuperDuperAlgo", "2.0.0", Every30Second, - depends_on=[Lookback(my_algorithm, td=dt.timedelta(days=10), n=10)], + description="Depends on other", + depends_on=[lookback(my_algorithm, td=dt.timedelta(days=10))], ) -def second_algorithm(params: ExecutionParams) -> ValueResult: ... +def second_algorithm(params: ExecutionParams) -> ValueResult: + if params.dependencies is None: + raise Exception("could not get dependencies") + dependencyResults = params.dependencies.get_result(my_algorithm) + + if dependencyResults is None: + return ValueResult(10) + + value = 0 + for res in dependencyResults.results: + if not isinstance(res.result, dict): + raise Exception("Bad result received") + _res = res.result.get("result", None) + if _res is None: + continue + value += _res + + return ValueResult(value) if __name__ == "__main__": diff --git a/examples/simpletrigger/simpletrigger/window.py b/examples/simpletrigger/simpletrigger/window.py index 3541434..3ec0795 100644 --- a/examples/simpletrigger/simpletrigger/window.py +++ b/examples/simpletrigger/simpletrigger/window.py @@ -24,6 +24,6 @@ def emitWindow() -> None: if __name__ == "__main__": emitWindow() - while True: - schedule.run_pending() - time.sleep(1) + # while True: + # schedule.run_pending() + # time.sleep(1) diff --git a/orca b/orca index 03fac0a..55056a2 160000 --- a/orca +++ b/orca @@ -1 +1 @@ -Subproject commit 03fac0aef26d49e664c36709e693700e2623ea1b +Subproject commit 55056a2e30e5774147fbeae874158e38b2ef10e8 diff --git a/orca_python/__init__.py b/orca_python/__init__.py index 98c8e50..59527ec 100644 --- a/orca_python/__init__.py +++ b/orca_python/__init__.py @@ -1,6 +1,5 @@ from orca_python.main import ( Window, - Lookback, Processor, EmitWindow, NoneResult, @@ -10,6 +9,7 @@ StructResult, MetadataField, ExecutionParams, + lookback, ) __all__ = [ @@ -23,5 +23,5 @@ "ArrayResult", "NoneResult", "ExecutionParams", - "Lookback", + "lookback", ] diff --git a/orca_python/main.py b/orca_python/main.py index 055249e..b3eddd2 100644 --- a/orca_python/main.py +++ b/orca_python/main.py @@ -9,6 +9,7 @@ import re import sys import asyncio +import hashlib import logging import datetime as dt import traceback @@ -28,6 +29,7 @@ Any, Dict, List, + Tuple, Union, TypeVar, Callable, @@ -36,6 +38,7 @@ Protocol, Generator, AsyncGenerator, + cast, ) from inspect import signature from concurrent import futures @@ -175,15 +178,57 @@ class Window: metadata: Dict[str, Any] = field(default_factory=dict) +@dataclass +class DependencyResultRow: + window: Window + result: float | List[float] | Dict[str, Any] | None + + +@dataclass +class DependencyAlgorithm: + name: str + version: str + description: str + + @property + def full_name(self): + return f"{self.name}_{self.version}" + + @property + def id(self): + return f"{self.name}_{self.version}" + + +@dataclass +class DependencyResult: + algorithm: DependencyAlgorithm + results: List[DependencyResultRow] + + +@dataclass +class Dependencies: + _dependencies: Optional[Dict[str, DependencyResult]] = None + + def get_result(self, algorithmFn: "AlgorithmFn") -> DependencyResult | None: + if self._dependencies is None: + return None + algo_name = getattr(algorithmFn, "_name", None) + algo_version = getattr(algorithmFn, "_version", None) + if algo_name is None or algo_version is None: + return None + full_qual_name = f"{algo_name}_{algo_version}" + return self._dependencies.get(full_qual_name, None) + + @dataclass class ExecutionParams: window: Window - dependencies: Optional[Iterable[pb.AlgorithmResult]] = None + dependencies: Optional[Dependencies] = None def __init__( self, window: Window | pb.Window, - dependencies: Optional[Iterable[pb.AlgorithmResult]] = None, + dependencies: Optional[Dependencies] = None, ): if isinstance(window, Window): self.window = window @@ -199,12 +244,6 @@ def __init__( self.dependencies = dependencies -class AlgorithmFn(Protocol): - def __call__( - self, params: ExecutionParams, *args: Any, **kwargs: Any - ) -> returnResult: ... - - @dataclass class RemoteAlgorithm: ProcessorName: str @@ -212,25 +251,45 @@ class RemoteAlgorithm: Name: str Version: str + @property + def full_name(self) -> str: + """Returns the full name as `name_version`.""" + return f"{self.Name}_{self.Version}" -@dataclass -class Lookback(AlgorithmFn): - """Defines a lookback period in an algorithm dependency""" - _algorithm: AlgorithmFn = field(repr=False) +class AlgorithmFn(Protocol): + __slots__ = ("_lookback_n", "_lookback_td", "_name", "_version") - def __init__(self, algorithm: AlgorithmFn, td: dt.timedelta, n: int) -> None: - self.__dict__.update(algorithm.__dict__) + def __call__( + self, params: ExecutionParams, *args: Any, **kwargs: Any + ) -> returnResult: ... - self._algorithm = algorithm - self._lookback_td = td - self._lookback_n = n +def get_id(algorithm: AlgorithmFn) -> str: + """Get the fully qualified ID of the algorithm""" + algo_name = getattr(algorithm, "_name", None) + algo_version = getattr(algorithm, "_version", None) + if algo_name is None or algo_version is None: + raise Exception( + "Unexpected issue - algorithm name, version and runtime cannot be determined from algorithm function " + ) + full_qual_name = f"{algo_name}_{algo_version}" + return full_qual_name - def __call__( - self, params: ExecutionParams, *args: Any, **kwargs: Any - ) -> returnResult: - return self._algorithm(params, *args, **kwargs) + +def lookback( + algorithm: AlgorithmFn, + td: dt.timedelta | None = None, + n: int | None = None, +) -> AlgorithmFn: + """Annotate a function with lookback metadata""" + if td is None and n is None: + raise ValueError("One of `td` and `n` should be provided") + + algorithm._lookback_td = 0 if td is None else int(td.total_seconds() * 1e9) # need to be in nano seconds + algorithm._lookback_n = 0 if n is None else n + + return algorithm T = TypeVar("T", bound=AlgorithmFn) @@ -308,6 +367,12 @@ def full_name(self) -> str: """Returns the full name as `name_version`.""" return f"{self.name}_{self.version}" + @property + def id(self) -> str: + """The globally unique identifier of this algorithm""" + hash = hashlib.md5(self.runtime.encode()) + return f"{self.name}_{self.version}_{hash.hexdigest()}" + @property def full_window_name(self) -> str: """Returns the full window name as `window_name_window_version`.""" @@ -330,6 +395,8 @@ def _flush(self) -> None: self._dependencyFns: Dict[str, List[AlgorithmFn]] = {} self._remoteDependencies: Dict[str, List[RemoteAlgorithm]] = {} self._window_triggers: Dict[str, List[Algorithm]] = {} + # maps the algorithm to the dependency, resulting in the lookback params + self._lookbacks: Dict[str, Dict[str, Tuple[int, int]]] = {} def _add_algorithm(self, name: str, algorithm: Algorithm) -> None: """ @@ -383,6 +450,14 @@ def _add_dependency( else: self._remoteDependencies[algorithm].append(remoteAlgo) + # add the lookback + self._add_lookback( + algorithm, + remoteAlgo.full_name, + getattr(dependency, "_lookback_n", 0), + getattr(dependency, "_lookback_td", 0), + ) + return dependencyAlgo = None @@ -403,6 +478,14 @@ def _add_dependency( self._dependencyFns[algorithm].append(dependency) self._dependencies[algorithm].append(dependencyAlgo) + # add the lookback + self._add_lookback( + algorithm, + dependencyAlgo.full_name, + getattr(dependency, "_lookback_n", 0), + getattr(dependency, "_lookback_td", 0), + ) + def _add_window_trigger(self, window: str, algorithm: Algorithm) -> None: """Associates an algorithm with a triggering window.""" if window not in self._window_triggers: @@ -425,6 +508,27 @@ def _has_algorithm_fn(self, algorithm_fn: AlgorithmFn) -> bool: return True return False + def _add_lookback( + self, algoFrom: str, algoTo: str, n: int = 0, td: int = 0 + ) -> None: + """ + Adds a lookback for a given algorithm (from) and + it's dependency (to) + """ + self._lookbacks.update({algoFrom: {algoTo: (n, td)}}) + + def _get_lookback(self, algoFrom: str, algoTo: str) -> Tuple[int, int]: + """ + Gets the lookback for a given algorithm (from) and + its dependency (to) + """ + toDict = self._lookbacks.get(algoFrom, None) + + if toDict is None: + return (0, 0) + + return toDict.get(algoTo, (0, 0)) + # the orca processor class Processor(OrcaProcessorServicer): # type: ignore @@ -452,7 +556,8 @@ async def execute_algorithm( self, exec_id: str, algorithm: pb.Algorithm, - params: ExecutionParams, + window: pb.Window, + dependencies: Iterable[pb.AlgorithmDependencyResult], ) -> pb.ExecutionResult: """ Executes a single algorithm with resolved dependencies. @@ -474,28 +579,64 @@ async def execute_algorithm( algo = self._algorithmsSingleton._algorithms[algoName] # convert dependency results into a dict of name -> value - dependency_values = {} - if params.dependencies: - for dep_result in params.dependencies: - # extract value based on which oneof field is set - dep_value = None - if dep_result.result.HasField("single_value"): - dep_value = dep_result.result.single_value - elif dep_result.result.HasField("float_values"): - dep_value = list(dep_result.result.float_values.values) - elif dep_result.result.HasField("struct_value"): - dep_value = json_format.MessageToDict( - dep_result.result.struct_value + dependency_results = {} + if dependencies: + for dep_result in dependencies: + # initialise the sub array + dependency = DependencyAlgorithm( + name=dep_result.algorithm.name, + version=dep_result.algorithm.version, + description=dep_result.algorithm.description, + ) + dependency_values = [] + + for res in dep_result.result: + # FIXME: Turn into a generator to better handle large results + # extract value based on which oneof field is set + dep_value = None + if res.result.HasField("single_value"): + dep_value = res.result.single_value + elif res.result.HasField("float_values"): + dep_value = list(res.result.float_values.values) + elif res.result.HasField("struct_value"): + dep_value = json_format.MessageToDict( + res.result.struct_value + ) + + dependency_values.append( + DependencyResultRow( + result=dep_value, + window=Window( + time_from=res.window.time_from.ToDatetime(dt.UTC), + time_to=res.window.time_to.ToDatetime(dt.UTC), + name=res.window.window_type_name, + version=res.window.window_type_version, + origin=res.window.origin, + ), + ), ) - dep_name = ( - f"{dep_result.algorithm.name}_{dep_result.algorithm.version}" + dependency_result = DependencyResult( + algorithm=dependency, results=dependency_values ) - dependency_values[dep_name] = dep_value + dependency_results[dependency_result.algorithm.id] = ( + dependency_result + ) + + params = ExecutionParams( + window=Window( + time_from=window.time_from.ToDatetime(dt.UTC), + time_to=window.time_to.ToDatetime(dt.UTC), + name=window.window_type_name, + version=window.window_type_version, + origin=window.origin, + metadata=cast(dict, window.metadata.fields), + ), + dependencies=Dependencies(_dependencies=dependency_results), + ) # execute in thread pool since algo.exec_fn is synchronous loop = asyncio.get_event_loop() - algoResult = await loop.run_in_executor(None, algo.exec_fn, params) # depending on algo result type, map to whatever instance @@ -603,7 +744,7 @@ def ExecuteDagPart( LOGGER.info( ( - f"Received DAG execution request with {len(executionRequest.algorithms)} " + f"Received DAG execution request with {len(executionRequest.algorithm_executions)} " f"algorithms and ExecId: {executionRequest.exec_id}" ) ) @@ -620,13 +761,11 @@ def ExecuteDagPart( tasks = [ self.execute_algorithm( executionRequest.exec_id, - algorithm, - ExecutionParams( - window=executionRequest.window, - dependencies=executionRequest.algorithm_results, - ), + algorithm.algorithm, + executionRequest.window, + algorithm.dependencies, ) - for algorithm in executionRequest.algorithms + for algorithm in executionRequest.algorithm_executions ] # execute all tasks concurrently and yield results as they complete @@ -736,26 +875,37 @@ def Register(self) -> None: # Add dependencies if they exist if algorithm.full_name in self._algorithmsSingleton._dependencies: for dep in self._algorithmsSingleton._dependencies[algorithm.full_name]: + lookback_num, lookback_td = self._algorithmsSingleton._get_lookback( + algorithm.full_name, dep.full_name + ) dep_msg = algo_msg.dependencies.add() dep_msg.name = dep.name dep_msg.version = dep.version dep_msg.processor_name = dep.processor dep_msg.processor_runtime = dep.runtime - dep_msg.lookback_num = getattr(dep, "_lookback_num", 0) - dep_msg.lookback_num = getattr(dep, "_lookback_td", 0) + if lookback_num > 0: + dep_msg.lookback_num = lookback_num + elif lookback_td > 0: + dep_msg.lookback_time_delta = lookback_td # Add remote dependencies if they exist if algorithm.full_name in self._algorithmsSingleton._remoteDependencies: for remote_dep in self._algorithmsSingleton._remoteDependencies[ algorithm.full_name ]: + lookback_num, lookback_td = self._algorithmsSingleton._get_lookback( + algorithm.full_name, remote_dep.full_name + ) dep_msg = algo_msg.dependencies.add() dep_msg.name = remote_dep.Name dep_msg.version = remote_dep.Version dep_msg.processor_name = remote_dep.ProcessorName dep_msg.processor_runtime = remote_dep.ProcessorRuntime - dep_msg.lookback_num = getattr(dep, "_lookback_num", 0) - dep_msg.lookback_num = getattr(dep, "_lookback_td", 0) + if lookback_num > 0: + dep_msg.lookback_num = lookback_num + elif lookback_td > 0: + dep_msg.lookback_time_delta = lookback_td + try: if envs.is_production: # secure channel with TLS @@ -950,6 +1100,10 @@ def wrapper( # needs to be defined before a dependency can be created, and you can only register depencenies # once. But when dependencies are grabbed from a server, circular dependencies will be possible + # store details of the algorithm in the wrapper itself for utility purposes. + wrapper._name = name + wrapper._version = version + return wrapper # type: ignore[return-value] return inner diff --git a/poetry.lock b/poetry.lock index 26badb5..8157616 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 2.1.3 and should not be changed by hand. +# This file is automatically @generated by Poetry 2.2.1 and should not be changed by hand. [[package]] name = "colorama" @@ -352,22 +352,22 @@ poetry-plugin = ["poetry (>=1.2.0,<3.0.0) ; python_version < \"4.0\""] [[package]] name = "protobuf" -version = "6.33.2" +version = "6.33.4" description = "" optional = false python-versions = ">=3.9" groups = ["main"] files = [ - {file = "protobuf-6.33.2-cp310-abi3-win32.whl", hash = "sha256:87eb388bd2d0f78febd8f4c8779c79247b26a5befad525008e49a6955787ff3d"}, - {file = "protobuf-6.33.2-cp310-abi3-win_amd64.whl", hash = "sha256:fc2a0e8b05b180e5fc0dd1559fe8ebdae21a27e81ac77728fb6c42b12c7419b4"}, - {file = "protobuf-6.33.2-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:d9b19771ca75935b3a4422957bc518b0cecb978b31d1dd12037b088f6bcc0e43"}, - {file = "protobuf-6.33.2-cp39-abi3-manylinux2014_aarch64.whl", hash = "sha256:b5d3b5625192214066d99b2b605f5783483575656784de223f00a8d00754fc0e"}, - {file = "protobuf-6.33.2-cp39-abi3-manylinux2014_s390x.whl", hash = "sha256:8cd7640aee0b7828b6d03ae518b5b4806fdfc1afe8de82f79c3454f8aef29872"}, - {file = "protobuf-6.33.2-cp39-abi3-manylinux2014_x86_64.whl", hash = "sha256:1f8017c48c07ec5859106533b682260ba3d7c5567b1ca1f24297ce03384d1b4f"}, - {file = "protobuf-6.33.2-cp39-cp39-win32.whl", hash = "sha256:7109dcc38a680d033ffb8bf896727423528db9163be1b6a02d6a49606dcadbfe"}, - {file = "protobuf-6.33.2-cp39-cp39-win_amd64.whl", hash = "sha256:2981c58f582f44b6b13173e12bb8656711189c2a70250845f264b877f00b1913"}, - {file = "protobuf-6.33.2-py3-none-any.whl", hash = "sha256:7636aad9bb01768870266de5dc009de2d1b936771b38a793f73cbbf279c91c5c"}, - {file = "protobuf-6.33.2.tar.gz", hash = "sha256:56dc370c91fbb8ac85bc13582c9e373569668a290aa2e66a590c2a0d35ddb9e4"}, + {file = "protobuf-6.33.4-cp310-abi3-win32.whl", hash = "sha256:918966612c8232fc6c24c78e1cd89784307f5814ad7506c308ee3cf86662850d"}, + {file = "protobuf-6.33.4-cp310-abi3-win_amd64.whl", hash = "sha256:8f11ffae31ec67fc2554c2ef891dcb561dae9a2a3ed941f9e134c2db06657dbc"}, + {file = "protobuf-6.33.4-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:2fe67f6c014c84f655ee06f6f66213f9254b3a8b6bda6cda0ccd4232c73c06f0"}, + {file = "protobuf-6.33.4-cp39-abi3-manylinux2014_aarch64.whl", hash = "sha256:757c978f82e74d75cba88eddec479df9b99a42b31193313b75e492c06a51764e"}, + {file = "protobuf-6.33.4-cp39-abi3-manylinux2014_s390x.whl", hash = "sha256:c7c64f259c618f0bef7bee042075e390debbf9682334be2b67408ec7c1c09ee6"}, + {file = "protobuf-6.33.4-cp39-abi3-manylinux2014_x86_64.whl", hash = "sha256:3df850c2f8db9934de4cf8f9152f8dc2558f49f298f37f90c517e8e5c84c30e9"}, + {file = "protobuf-6.33.4-cp39-cp39-win32.whl", hash = "sha256:955478a89559fa4568f5a81dce77260eabc5c686f9e8366219ebd30debf06aa6"}, + {file = "protobuf-6.33.4-cp39-cp39-win_amd64.whl", hash = "sha256:0f12ddbf96912690c3582f9dffb55530ef32015ad8e678cd494312bd78314c4f"}, + {file = "protobuf-6.33.4-py3-none-any.whl", hash = "sha256:1fe3730068fcf2e595816a6c34fe66eeedd37d51d0400b72fabc848811fdc1bc"}, + {file = "protobuf-6.33.4.tar.gz", hash = "sha256:dc2e61bca3b10470c1912d166fe0af67bfc20eb55971dcef8dfa48ce14f0ed91"}, ] [[package]] @@ -387,14 +387,14 @@ windows-terminal = ["colorama (>=0.4.6)"] [[package]] name = "pyright" -version = "1.1.407" +version = "1.1.408" description = "Command line wrapper for pyright" optional = false python-versions = ">=3.7" groups = ["dev"] files = [ - {file = "pyright-1.1.407-py3-none-any.whl", hash = "sha256:6dd419f54fcc13f03b52285796d65e639786373f433e243f8b94cf93a7444d21"}, - {file = "pyright-1.1.407.tar.gz", hash = "sha256:099674dba5c10489832d4a4b2d302636152a9a42d317986c38474c76fe562262"}, + {file = "pyright-1.1.408-py3-none-any.whl", hash = "sha256:090b32865f4fdb1e0e6cd82bf5618480d48eecd2eb2e70f960982a3d9a4c17c1"}, + {file = "pyright-1.1.408.tar.gz", hash = "sha256:f28f2321f96852fa50b5829ea492f6adb0e6954568d1caa3f3af3a5f555eb684"}, ] [package.dependencies] @@ -579,55 +579,60 @@ type = ["importlib_metadata (>=7.0.2) ; python_version < \"3.10\"", "jaraco.deve [[package]] name = "tomli" -version = "2.3.0" +version = "2.4.0" description = "A lil' TOML parser" optional = false python-versions = ">=3.8" groups = ["dev"] markers = "python_version == \"3.10\"" files = [ - {file = "tomli-2.3.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:88bd15eb972f3664f5ed4b57c1634a97153b4bac4479dcb6a495f41921eb7f45"}, - {file = "tomli-2.3.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:883b1c0d6398a6a9d29b508c331fa56adbcdff647f6ace4dfca0f50e90dfd0ba"}, - {file = "tomli-2.3.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d1381caf13ab9f300e30dd8feadb3de072aeb86f1d34a8569453ff32a7dea4bf"}, - {file = "tomli-2.3.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a0e285d2649b78c0d9027570d4da3425bdb49830a6156121360b3f8511ea3441"}, - {file = "tomli-2.3.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:0a154a9ae14bfcf5d8917a59b51ffd5a3ac1fd149b71b47a3a104ca4edcfa845"}, - {file = "tomli-2.3.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:74bf8464ff93e413514fefd2be591c3b0b23231a77f901db1eb30d6f712fc42c"}, - {file = "tomli-2.3.0-cp311-cp311-win32.whl", hash = "sha256:00b5f5d95bbfc7d12f91ad8c593a1659b6387b43f054104cda404be6bda62456"}, - {file = "tomli-2.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:4dc4ce8483a5d429ab602f111a93a6ab1ed425eae3122032db7e9acf449451be"}, - {file = "tomli-2.3.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:d7d86942e56ded512a594786a5ba0a5e521d02529b3826e7761a05138341a2ac"}, - {file = "tomli-2.3.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:73ee0b47d4dad1c5e996e3cd33b8a76a50167ae5f96a2607cbe8cc773506ab22"}, - {file = "tomli-2.3.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:792262b94d5d0a466afb5bc63c7daa9d75520110971ee269152083270998316f"}, - {file = "tomli-2.3.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4f195fe57ecceac95a66a75ac24d9d5fbc98ef0962e09b2eddec5d39375aae52"}, - {file = "tomli-2.3.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:e31d432427dcbf4d86958c184b9bfd1e96b5b71f8eb17e6d02531f434fd335b8"}, - {file = "tomli-2.3.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:7b0882799624980785240ab732537fcfc372601015c00f7fc367c55308c186f6"}, - {file = "tomli-2.3.0-cp312-cp312-win32.whl", hash = "sha256:ff72b71b5d10d22ecb084d345fc26f42b5143c5533db5e2eaba7d2d335358876"}, - {file = "tomli-2.3.0-cp312-cp312-win_amd64.whl", hash = "sha256:1cb4ed918939151a03f33d4242ccd0aa5f11b3547d0cf30f7c74a408a5b99878"}, - {file = "tomli-2.3.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:5192f562738228945d7b13d4930baffda67b69425a7f0da96d360b0a3888136b"}, - {file = "tomli-2.3.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:be71c93a63d738597996be9528f4abe628d1adf5e6eb11607bc8fe1a510b5dae"}, - {file = "tomli-2.3.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c4665508bcbac83a31ff8ab08f424b665200c0e1e645d2bd9ab3d3e557b6185b"}, - {file = "tomli-2.3.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4021923f97266babc6ccab9f5068642a0095faa0a51a246a6a02fccbb3514eaf"}, - {file = "tomli-2.3.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a4ea38c40145a357d513bffad0ed869f13c1773716cf71ccaa83b0fa0cc4e42f"}, - {file = "tomli-2.3.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:ad805ea85eda330dbad64c7ea7a4556259665bdf9d2672f5dccc740eb9d3ca05"}, - {file = "tomli-2.3.0-cp313-cp313-win32.whl", hash = "sha256:97d5eec30149fd3294270e889b4234023f2c69747e555a27bd708828353ab606"}, - {file = "tomli-2.3.0-cp313-cp313-win_amd64.whl", hash = "sha256:0c95ca56fbe89e065c6ead5b593ee64b84a26fca063b5d71a1122bf26e533999"}, - {file = "tomli-2.3.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:cebc6fe843e0733ee827a282aca4999b596241195f43b4cc371d64fc6639da9e"}, - {file = "tomli-2.3.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:4c2ef0244c75aba9355561272009d934953817c49f47d768070c3c94355c2aa3"}, - {file = "tomli-2.3.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c22a8bf253bacc0cf11f35ad9808b6cb75ada2631c2d97c971122583b129afbc"}, - {file = "tomli-2.3.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0eea8cc5c5e9f89c9b90c4896a8deefc74f518db5927d0e0e8d4a80953d774d0"}, - {file = "tomli-2.3.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:b74a0e59ec5d15127acdabd75ea17726ac4c5178ae51b85bfe39c4f8a278e879"}, - {file = "tomli-2.3.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:b5870b50c9db823c595983571d1296a6ff3e1b88f734a4c8f6fc6188397de005"}, - {file = "tomli-2.3.0-cp314-cp314-win32.whl", hash = "sha256:feb0dacc61170ed7ab602d3d972a58f14ee3ee60494292d384649a3dc38ef463"}, - {file = "tomli-2.3.0-cp314-cp314-win_amd64.whl", hash = "sha256:b273fcbd7fc64dc3600c098e39136522650c49bca95df2d11cf3b626422392c8"}, - {file = "tomli-2.3.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:940d56ee0410fa17ee1f12b817b37a4d4e4dc4d27340863cc67236c74f582e77"}, - {file = "tomli-2.3.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:f85209946d1fe94416debbb88d00eb92ce9cd5266775424ff81bc959e001acaf"}, - {file = "tomli-2.3.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a56212bdcce682e56b0aaf79e869ba5d15a6163f88d5451cbde388d48b13f530"}, - {file = "tomli-2.3.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c5f3ffd1e098dfc032d4d3af5c0ac64f6d286d98bc148698356847b80fa4de1b"}, - {file = "tomli-2.3.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:5e01decd096b1530d97d5d85cb4dff4af2d8347bd35686654a004f8dea20fc67"}, - {file = "tomli-2.3.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:8a35dd0e643bb2610f156cca8db95d213a90015c11fee76c946aa62b7ae7e02f"}, - {file = "tomli-2.3.0-cp314-cp314t-win32.whl", hash = "sha256:a1f7f282fe248311650081faafa5f4732bdbfef5d45fe3f2e702fbc6f2d496e0"}, - {file = "tomli-2.3.0-cp314-cp314t-win_amd64.whl", hash = "sha256:70a251f8d4ba2d9ac2542eecf008b3c8a9fc5c3f9f02c56a9d7952612be2fdba"}, - {file = "tomli-2.3.0-py3-none-any.whl", hash = "sha256:e95b1af3c5b07d9e643909b5abbec77cd9f1217e6d0bca72b0234736b9fb1f1b"}, - {file = "tomli-2.3.0.tar.gz", hash = "sha256:64be704a875d2a59753d80ee8a533c3fe183e3f06807ff7dc2232938ccb01549"}, + {file = "tomli-2.4.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b5ef256a3fd497d4973c11bf142e9ed78b150d36f5773f1ca6088c230ffc5867"}, + {file = "tomli-2.4.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5572e41282d5268eb09a697c89a7bee84fae66511f87533a6f88bd2f7b652da9"}, + {file = "tomli-2.4.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:551e321c6ba03b55676970b47cb1b73f14a0a4dce6a3e1a9458fd6d921d72e95"}, + {file = "tomli-2.4.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5e3f639a7a8f10069d0e15408c0b96a2a828cfdec6fca05296ebcdcc28ca7c76"}, + {file = "tomli-2.4.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1b168f2731796b045128c45982d3a4874057626da0e2ef1fdd722848b741361d"}, + {file = "tomli-2.4.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:133e93646ec4300d651839d382d63edff11d8978be23da4cc106f5a18b7d0576"}, + {file = "tomli-2.4.0-cp311-cp311-win32.whl", hash = "sha256:b6c78bdf37764092d369722d9946cb65b8767bfa4110f902a1b2542d8d173c8a"}, + {file = "tomli-2.4.0-cp311-cp311-win_amd64.whl", hash = "sha256:d3d1654e11d724760cdb37a3d7691f0be9db5fbdaef59c9f532aabf87006dbaa"}, + {file = "tomli-2.4.0-cp311-cp311-win_arm64.whl", hash = "sha256:cae9c19ed12d4e8f3ebf46d1a75090e4c0dc16271c5bce1c833ac168f08fb614"}, + {file = "tomli-2.4.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:920b1de295e72887bafa3ad9f7a792f811847d57ea6b1215154030cf131f16b1"}, + {file = "tomli-2.4.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:7d6d9a4aee98fac3eab4952ad1d73aee87359452d1c086b5ceb43ed02ddb16b8"}, + {file = "tomli-2.4.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:36b9d05b51e65b254ea6c2585b59d2c4cb91c8a3d91d0ed0f17591a29aaea54a"}, + {file = "tomli-2.4.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1c8a885b370751837c029ef9bc014f27d80840e48bac415f3412e6593bbc18c1"}, + {file = "tomli-2.4.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:8768715ffc41f0008abe25d808c20c3d990f42b6e2e58305d5da280ae7d1fa3b"}, + {file = "tomli-2.4.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:7b438885858efd5be02a9a133caf5812b8776ee0c969fea02c45e8e3f296ba51"}, + {file = "tomli-2.4.0-cp312-cp312-win32.whl", hash = "sha256:0408e3de5ec77cc7f81960c362543cbbd91ef883e3138e81b729fc3eea5b9729"}, + {file = "tomli-2.4.0-cp312-cp312-win_amd64.whl", hash = "sha256:685306e2cc7da35be4ee914fd34ab801a6acacb061b6a7abca922aaf9ad368da"}, + {file = "tomli-2.4.0-cp312-cp312-win_arm64.whl", hash = "sha256:5aa48d7c2356055feef06a43611fc401a07337d5b006be13a30f6c58f869e3c3"}, + {file = "tomli-2.4.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:84d081fbc252d1b6a982e1870660e7330fb8f90f676f6e78b052ad4e64714bf0"}, + {file = "tomli-2.4.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:9a08144fa4cba33db5255f9b74f0b89888622109bd2776148f2597447f92a94e"}, + {file = "tomli-2.4.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c73add4bb52a206fd0c0723432db123c0c75c280cbd67174dd9d2db228ebb1b4"}, + {file = "tomli-2.4.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1fb2945cbe303b1419e2706e711b7113da57b7db31ee378d08712d678a34e51e"}, + {file = "tomli-2.4.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:bbb1b10aa643d973366dc2cb1ad94f99c1726a02343d43cbc011edbfac579e7c"}, + {file = "tomli-2.4.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4cbcb367d44a1f0c2be408758b43e1ffb5308abe0ea222897d6bfc8e8281ef2f"}, + {file = "tomli-2.4.0-cp313-cp313-win32.whl", hash = "sha256:7d49c66a7d5e56ac959cb6fc583aff0651094ec071ba9ad43df785abc2320d86"}, + {file = "tomli-2.4.0-cp313-cp313-win_amd64.whl", hash = "sha256:3cf226acb51d8f1c394c1b310e0e0e61fecdd7adcb78d01e294ac297dd2e7f87"}, + {file = "tomli-2.4.0-cp313-cp313-win_arm64.whl", hash = "sha256:d20b797a5c1ad80c516e41bc1fb0443ddb5006e9aaa7bda2d71978346aeb9132"}, + {file = "tomli-2.4.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:26ab906a1eb794cd4e103691daa23d95c6919cc2fa9160000ac02370cc9dd3f6"}, + {file = "tomli-2.4.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:20cedb4ee43278bc4f2fee6cb50daec836959aadaf948db5172e776dd3d993fc"}, + {file = "tomli-2.4.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:39b0b5d1b6dd03684b3fb276407ebed7090bbec989fa55838c98560c01113b66"}, + {file = "tomli-2.4.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a26d7ff68dfdb9f87a016ecfd1e1c2bacbe3108f4e0f8bcd2228ef9a766c787d"}, + {file = "tomli-2.4.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:20ffd184fb1df76a66e34bd1b36b4a4641bd2b82954befa32fe8163e79f1a702"}, + {file = "tomli-2.4.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:75c2f8bbddf170e8effc98f5e9084a8751f8174ea6ccf4fca5398436e0320bc8"}, + {file = "tomli-2.4.0-cp314-cp314-win32.whl", hash = "sha256:31d556d079d72db7c584c0627ff3a24c5d3fb4f730221d3444f3efb1b2514776"}, + {file = "tomli-2.4.0-cp314-cp314-win_amd64.whl", hash = "sha256:43e685b9b2341681907759cf3a04e14d7104b3580f808cfde1dfdb60ada85475"}, + {file = "tomli-2.4.0-cp314-cp314-win_arm64.whl", hash = "sha256:3d895d56bd3f82ddd6faaff993c275efc2ff38e52322ea264122d72729dca2b2"}, + {file = "tomli-2.4.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:5b5807f3999fb66776dbce568cc9a828544244a8eb84b84b9bafc080c99597b9"}, + {file = "tomli-2.4.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:c084ad935abe686bd9c898e62a02a19abfc9760b5a79bc29644463eaf2840cb0"}, + {file = "tomli-2.4.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0f2e3955efea4d1cfbcb87bc321e00dc08d2bcb737fd1d5e398af111d86db5df"}, + {file = "tomli-2.4.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0e0fe8a0b8312acf3a88077a0802565cb09ee34107813bba1c7cd591fa6cfc8d"}, + {file = "tomli-2.4.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:413540dce94673591859c4c6f794dfeaa845e98bf35d72ed59636f869ef9f86f"}, + {file = "tomli-2.4.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:0dc56fef0e2c1c470aeac5b6ca8cc7b640bb93e92d9803ddaf9ea03e198f5b0b"}, + {file = "tomli-2.4.0-cp314-cp314t-win32.whl", hash = "sha256:d878f2a6707cc9d53a1be1414bbb419e629c3d6e67f69230217bb663e76b5087"}, + {file = "tomli-2.4.0-cp314-cp314t-win_amd64.whl", hash = "sha256:2add28aacc7425117ff6364fe9e06a183bb0251b03f986df0e78e974047571fd"}, + {file = "tomli-2.4.0-cp314-cp314t-win_arm64.whl", hash = "sha256:2b1e3b80e1d5e52e40e9b924ec43d81570f0e7d09d11081b797bc4692765a3d4"}, + {file = "tomli-2.4.0-py3-none-any.whl", hash = "sha256:1f776e7d669ebceb01dee46484485f43a4048746235e683bcdffacdf1fb4785a"}, + {file = "tomli-2.4.0.tar.gz", hash = "sha256:aa89c3f6c277dd275d8e243ad24f3b5e701491a860d5121f2cdd399fbb31fc9c"}, ] [[package]] From c6ff5c2567dba12617a1cf8bf41507b06765d43a Mon Sep 17 00:00:00 2001 From: Frederick Mannings Date: Thu, 22 Jan 2026 21:32:58 +0000 Subject: [PATCH 4/4] Autoformat --- examples/simpletrigger/simpletrigger/window.py | 1 - orca_python/main.py | 4 +++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/examples/simpletrigger/simpletrigger/window.py b/examples/simpletrigger/simpletrigger/window.py index 3ec0795..b79ff08 100644 --- a/examples/simpletrigger/simpletrigger/window.py +++ b/examples/simpletrigger/simpletrigger/window.py @@ -1,4 +1,3 @@ -import time import datetime as dt import schedule diff --git a/orca_python/main.py b/orca_python/main.py index b3eddd2..8e89da1 100644 --- a/orca_python/main.py +++ b/orca_python/main.py @@ -286,7 +286,9 @@ def lookback( if td is None and n is None: raise ValueError("One of `td` and `n` should be provided") - algorithm._lookback_td = 0 if td is None else int(td.total_seconds() * 1e9) # need to be in nano seconds + algorithm._lookback_td = ( + 0 if td is None else int(td.total_seconds() * 1e9) + ) # need to be in nano seconds algorithm._lookback_n = 0 if n is None else n return algorithm