diff --git a/hello_nexus/__init__.py b/hello_nexus/__init__.py new file mode 100644 index 00000000..7919e866 --- /dev/null +++ b/hello_nexus/__init__.py @@ -0,0 +1,3 @@ +from rich.traceback import install + +install(show_locals=True) diff --git a/hello_nexus/caller/app.py b/hello_nexus/caller/app.py new file mode 100644 index 00000000..7097b7e9 --- /dev/null +++ b/hello_nexus/caller/app.py @@ -0,0 +1,72 @@ +import asyncio +import sys +from typing import Any, Type + +from temporalio.client import Client +from temporalio.worker import UnsandboxedWorkflowRunner, Worker + +interrupt_event = asyncio.Event() + + +async def execute_workflow(workflow_cls: Type[Any], input: Any) -> None: + client = await Client.connect( + "localhost:7233", namespace="my-caller-namespace-python" + ) + task_queue = "my-caller-task-queue" + + async with Worker( + client, + task_queue=task_queue, + workflows=[workflow_cls], + workflow_runner=UnsandboxedWorkflowRunner(), + ): + print("🟠 Caller worker started") + result = await client.execute_workflow( + workflow_cls.run, + input, + id="my-caller-workflow-id", + task_queue=task_queue, + ) + print("🟢 workflow result:", result) + + +if __name__ == "__main__": + if len(sys.argv) != 3: + print("Usage: python -m nexus.caller.app [echo|hello] [impl|interface]") + sys.exit(1) + + [wf_name, impl_or_interface] = sys.argv[1:] + + if impl_or_interface == "impl": + from hello_nexus.caller.workflows_via_impl import ( + Echo2CallerWorkflow, + Echo3CallerWorkflow, + EchoCallerWorkflow, + Hello2CallerWorkflow, + HelloCallerWorkflow, + ) + elif impl_or_interface == "interface": + from hello_nexus.caller.workflows_via_interface import ( + Echo2CallerWorkflow, + Echo3CallerWorkflow, + EchoCallerWorkflow, + Hello2CallerWorkflow, + HelloCallerWorkflow, + ) + else: + raise ValueError(f"Invalid impl_or_interface: {impl_or_interface}") + + fn = { + "echo": lambda: execute_workflow(EchoCallerWorkflow, "hello"), + "echo2": lambda: execute_workflow(Echo2CallerWorkflow, "hello"), + "echo3": lambda: execute_workflow(Echo3CallerWorkflow, "hello"), + "hello": lambda: execute_workflow(HelloCallerWorkflow, "world"), + "hello2": lambda: execute_workflow(Hello2CallerWorkflow, "world"), + }[wf_name] + + loop = asyncio.new_event_loop() + try: + loop.run_until_complete(fn()) + except KeyboardInterrupt: + interrupt_event.set() + loop.run_until_complete(loop.shutdown_asyncgens()) diff --git a/hello_nexus/caller/workflows_via_impl.py b/hello_nexus/caller/workflows_via_impl.py new file mode 100644 index 00000000..fa8c6aa2 --- /dev/null +++ b/hello_nexus/caller/workflows_via_impl.py @@ -0,0 +1,93 @@ +from datetime import timedelta + +import xray +from temporalio import workflow +from temporalio.exceptions import FailureError +from temporalio.workflow import NexusClient + +from hello_nexus.handler.nexus_service import ( + EchoInput, + EchoOutput, + HelloInput, + HelloOutput, + MyNexusService, +) + + +class CallerWorkflowBase: + def __init__(self): + self.nexus_client = NexusClient( + MyNexusService, # or string name "my-nexus-service", + "my-nexus-endpoint-name-python", + schedule_to_close_timeout=timedelta(seconds=30), + ) + + +@workflow.defn +class EchoCallerWorkflow(CallerWorkflowBase): + @xray.start_as_current_workflow_method_span() + @workflow.run + async def run(self, message: str) -> EchoOutput: + op_output = await self.nexus_client.execute_operation( + MyNexusService.echo, + EchoInput(message), + ) + return op_output + + +@workflow.defn +class Echo2CallerWorkflow(CallerWorkflowBase): + @xray.start_as_current_workflow_method_span() + @workflow.run + async def run(self, message: str) -> EchoOutput: + op_output = await self.nexus_client.execute_operation( + MyNexusService.echo2, + EchoInput(message), + ) + return op_output + + +@workflow.defn +class Echo3CallerWorkflow(CallerWorkflowBase): + @xray.start_as_current_workflow_method_span() + @workflow.run + async def run(self, message: str) -> EchoOutput: + op_output = await self.nexus_client.execute_operation( + MyNexusService.echo3, + EchoInput(message), + ) + return op_output + + +@workflow.defn +class HelloCallerWorkflow(CallerWorkflowBase): + @xray.start_as_current_workflow_method_span() + @workflow.run + async def run(self, name: str) -> HelloOutput: + handle = await self.nexus_client.start_operation( + MyNexusService.hello, + HelloInput(name), + ) + assert handle.cancel() + try: + await handle + except FailureError: + handle = await self.nexus_client.start_operation( + MyNexusService.hello, + HelloInput(name), + ) + result = await handle + return result + raise AssertionError("Expected Nexus operation to be cancelled") + + +@workflow.defn +class Hello2CallerWorkflow(CallerWorkflowBase): + @xray.start_as_current_workflow_method_span() + @workflow.run + async def run(self, name: str) -> HelloOutput: + handle = await self.nexus_client.start_operation( + MyNexusService.hello2, + HelloInput(name), + ) + return await handle diff --git a/hello_nexus/caller/workflows_via_interface.py b/hello_nexus/caller/workflows_via_interface.py new file mode 100644 index 00000000..79915155 --- /dev/null +++ b/hello_nexus/caller/workflows_via_interface.py @@ -0,0 +1,93 @@ +from datetime import timedelta + +import xray +from temporalio import workflow +from temporalio.exceptions import FailureError +from temporalio.workflow import NexusClient + +from hello_nexus.service.interface import ( + EchoInput, + EchoOutput, + HelloInput, + HelloOutput, + MyNexusService, +) + + +class CallerWorkflowBase: + def __init__(self): + self.nexus_client = NexusClient( + MyNexusService, # or string name "my-nexus-service", + "my-nexus-endpoint-name-python", + schedule_to_close_timeout=timedelta(seconds=30), + ) + + +@workflow.defn +class EchoCallerWorkflow(CallerWorkflowBase): + @xray.start_as_current_workflow_method_span() + @workflow.run + async def run(self, message: str) -> EchoOutput: + op_output = await self.nexus_client.execute_operation( + MyNexusService.echo, + EchoInput(message), + ) + return op_output + + +@workflow.defn +class Echo2CallerWorkflow(CallerWorkflowBase): + @xray.start_as_current_workflow_method_span() + @workflow.run + async def run(self, message: str) -> EchoOutput: + op_output = await self.nexus_client.execute_operation( + MyNexusService.echo2, + EchoInput(message), + ) + return op_output + + +@workflow.defn +class Echo3CallerWorkflow(CallerWorkflowBase): + @xray.start_as_current_workflow_method_span() + @workflow.run + async def run(self, message: str) -> EchoOutput: + op_output = await self.nexus_client.execute_operation( + MyNexusService.echo3, + EchoInput(message), + ) + return op_output + + +@workflow.defn +class HelloCallerWorkflow(CallerWorkflowBase): + @xray.start_as_current_workflow_method_span() + @workflow.run + async def run(self, name: str) -> HelloOutput: + handle = await self.nexus_client.start_operation( + MyNexusService.hello, + HelloInput(name), + ) + assert handle.cancel() + try: + await handle + except FailureError: + handle = await self.nexus_client.start_operation( + MyNexusService.hello, + HelloInput(name), + ) + result = await handle + return result + raise AssertionError("Expected Nexus operation to be cancelled") + + +@workflow.defn +class Hello2CallerWorkflow(CallerWorkflowBase): + @xray.start_as_current_workflow_method_span() + @workflow.run + async def run(self, name: str) -> HelloOutput: + handle = await self.nexus_client.start_operation( + MyNexusService.hello2, + HelloInput(name), + ) + return await handle diff --git a/hello_nexus/clean b/hello_nexus/clean new file mode 100755 index 00000000..0fd588c3 --- /dev/null +++ b/hello_nexus/clean @@ -0,0 +1,14 @@ +temporal-delete-all my-target-namespace-python +temporal-delete-all my-caller-namespace-python + +temporal operator namespace create --namespace my-target-namespace-python +temporal operator namespace create --namespace my-caller-namespace-python + +sleep 1 + +temporal operator nexus endpoint create \ + --name my-nexus-endpoint-name-python \ + --target-namespace my-target-namespace-python \ + --target-task-queue my-target-task-queue-python \ + --description-file ./hello_nexus/service/description.md + \ No newline at end of file diff --git a/hello_nexus/handler/activities.py b/hello_nexus/handler/activities.py new file mode 100644 index 00000000..a43241eb --- /dev/null +++ b/hello_nexus/handler/activities.py @@ -0,0 +1,14 @@ +import asyncio + +from temporalio import activity + +from hello_nexus.service.interface import ( + HelloInput, + HelloOutput, +) + + +@activity.defn +async def hello_activity(input: HelloInput) -> HelloOutput: + await asyncio.sleep(1) + return HelloOutput(message=f"hello {input.name}") diff --git a/hello_nexus/handler/dbclient.py b/hello_nexus/handler/dbclient.py new file mode 100644 index 00000000..22f22316 --- /dev/null +++ b/hello_nexus/handler/dbclient.py @@ -0,0 +1,3 @@ +class MyDBClient: + def execute(self, query: str) -> str: + return "" diff --git a/hello_nexus/handler/nexus_service.py b/hello_nexus/handler/nexus_service.py new file mode 100644 index 00000000..4aed7bf2 --- /dev/null +++ b/hello_nexus/handler/nexus_service.py @@ -0,0 +1,176 @@ +""" +Notes: + +Sync operations: +--------------- +Implementations are free to make arbitrary network calls, or perform CPU-bound +computations such as this one. Total execution duration must not exceed 10s. To +perform Temporal client calls such as signaling/querying/listing workflows, use +self.client. + + +Workflow operations: +--------------------- +The task queue defaults to the task queue being used by the Nexus worker. +""" + +from __future__ import annotations + +import nexusrpc.handler +import temporalio.common +import temporalio.nexus.handler + +from hello_nexus.handler.dbclient import MyDBClient +from hello_nexus.handler.workflows import HelloWorkflow +from hello_nexus.service import interface +from hello_nexus.service.interface import ( + EchoInput, + EchoOutput, + HelloInput, + HelloOutput, +) + + +# Inheriting from the protocol here is optional. Users who do it will get the +# operation definition itself type-checked in situ against the interface (*). +# Call-sites using instances of the operation are always type-checked. +# +# (*) However, in VSCode/Pyright this is done only when type-checking is set to +# 'strict'. +class EchoOperation(nexusrpc.handler.Operation[EchoInput, EchoOutput]): + def __init__(self, service: MyNexusService): + self.service = service + + # TODO support non-async def + async def start( + self, input: EchoInput, options: nexusrpc.handler.StartOperationOptions + ) -> EchoOutput: + return EchoOutput(message=f"Echo {input.message}!") + + async def cancel( + self, token: str, options: nexusrpc.handler.CancelOperationOptions + ) -> None: + raise NotImplementedError + + async def fetch_info( + self, token: str, options: nexusrpc.handler.FetchOperationInfoOptions + ) -> nexusrpc.handler.OperationInfo: + raise NotImplementedError + + async def fetch_result( + self, token: str, options: nexusrpc.handler.FetchOperationResultOptions + ) -> EchoOutput: + raise NotImplementedError + + +# Inheriting from the protocol here is optional. Users who do it will get the +# operation definition itself type-checked in situ against the interface (*). +# Call-sites using instances of the operation are always type-checked. +# +# (*) However, in VSCode/Pyright this is done only when type-checking is set to +# 'strict'. +class HelloOperation: # (nexusrpc.handler.Operation[HelloInput, HelloOutput]): + def __init__(self, service: "MyNexusService"): + self.service = service + + async def start( + self, input: HelloInput, options: nexusrpc.handler.StartOperationOptions + ) -> temporalio.nexus.handler.StartWorkflowOperationResult[HelloOutput]: + self.service.db_client.execute("") + workflow_id = "default-workflow-id" + return await temporalio.nexus.handler.start_workflow( + HelloWorkflow.run, + input, + id=workflow_id, + options=options, + ) + + async def cancel( + self, token: str, options: nexusrpc.handler.CancelOperationOptions + ) -> None: + return await temporalio.nexus.handler.cancel_workflow(token, options) + + async def fetch_info( + self, token: str, options: nexusrpc.handler.FetchOperationInfoOptions + ) -> nexusrpc.handler.OperationInfo: + return await temporalio.nexus.handler.fetch_workflow_info(token, options) + + async def fetch_result( + self, token: str, options: nexusrpc.handler.FetchOperationResultOptions + ) -> HelloOutput: + return await temporalio.nexus.handler.fetch_workflow_result(token, options) + + +class EchoOperation3(nexusrpc.handler.AbstractOperation[EchoInput, EchoOutput]): + async def start( + self, input: EchoInput, options: nexusrpc.handler.StartOperationOptions + ) -> EchoOutput: + return EchoOutput(message=f"Echo {input.message}! [from base class variant]") + + +@nexusrpc.handler.service(interface=interface.MyNexusService) +class MyNexusService: + def __init__(self, db_client: MyDBClient): + # An example of something that might be held by the service instance. + self.db_client = db_client + + # -------------------------------------------------------------------------- + # Operations defined by explicitly implementing the Operation interface. + # + + @nexusrpc.handler.operation + def echo(self) -> nexusrpc.handler.Operation[EchoInput, EchoOutput]: + return EchoOperation(self) + + @nexusrpc.handler.operation + def hello(self) -> nexusrpc.handler.Operation[HelloInput, HelloOutput]: + return HelloOperation(self) + + @nexusrpc.handler.operation + def echo3(self) -> nexusrpc.handler.Operation[EchoInput, EchoOutput]: + return EchoOperation3() + + # -------------------------------------------------------------------------- + # Operations defined by providing the start method only, using the + # "shorthand" decorators. + # + # Note that a start method defined this way has access to the service + # instance, but not to the operation instance (users who need the latter + # should implement the Operation interface directly). + + @nexusrpc.handler.sync_operation + async def echo2( + self, input: EchoInput, _: nexusrpc.handler.StartOperationOptions + ) -> EchoOutput: + return EchoOutput(message=f"Echo {input.message} [via shorthand]!") + + # -------------------------------------------------------------------------- + # Operations defined by providing the start method only, using the + # "shorthand" decorators. + # + # Note that a start method defined this way has access to the service + # instance, but not to the operation instance (users who need the latter + # should implement the Operation interface directly). + + @temporalio.nexus.handler.workflow_run_operation + async def hello2( + self, input: HelloInput, options: nexusrpc.handler.StartOperationOptions + ) -> temporalio.nexus.handler.StartWorkflowOperationResult[HelloOutput]: + self.db_client.execute("") + workflow_id = "default-workflow-id" + input.name += " [via shorthand]" + return await temporalio.nexus.handler.start_workflow( + HelloWorkflow.run, + input, + id=workflow_id, + options=options, + ) + + +if __name__ == "__main__": + # Check run-time type annotations resulting from the decorators. + service = MyNexusService(MyDBClient()) + print("echo:", temporalio.common._type_hints_from_func(service.echo2().start)) + print( + "hello:", temporalio.common._type_hints_from_func(service.hello2().fetch_result) + ) diff --git a/hello_nexus/handler/worker.py b/hello_nexus/handler/worker.py new file mode 100644 index 00000000..e3a8f4ef --- /dev/null +++ b/hello_nexus/handler/worker.py @@ -0,0 +1,36 @@ +import asyncio + +from temporalio.client import Client +from temporalio.worker import UnsandboxedWorkflowRunner, Worker + +from hello_nexus.handler.dbclient import MyDBClient +from hello_nexus.handler.nexus_service import MyNexusService +from hello_nexus.handler.workflows import HelloWorkflow + +interrupt_event = asyncio.Event() + + +async def main(): + client = await Client.connect( + "localhost:7233", namespace="my-target-namespace-python" + ) + task_queue = "my-target-task-queue-python" + + async with Worker( + client, + task_queue=task_queue, + workflows=[HelloWorkflow], + nexus_services=[MyNexusService(db_client=MyDBClient())], + workflow_runner=UnsandboxedWorkflowRunner(), + ): + print("Handler worker started") + await asyncio.Future() + + +if __name__ == "__main__": + loop = asyncio.new_event_loop() + try: + loop.run_until_complete(main()) + except KeyboardInterrupt: + interrupt_event.set() + loop.run_until_complete(loop.shutdown_asyncgens()) diff --git a/hello_nexus/handler/workflows.py b/hello_nexus/handler/workflows.py new file mode 100644 index 00000000..bb22b742 --- /dev/null +++ b/hello_nexus/handler/workflows.py @@ -0,0 +1,27 @@ +import asyncio + +import xray +from temporalio import workflow + +from hello_nexus.service.interface import ( + HelloInput, + HelloOutput, +) + + +@workflow.defn +class HelloWorkflow: + """ + Workflow that backs the `hello` operation. + """ + + @xray.start_as_current_workflow_method_span() + @workflow.run + async def run(self, input: HelloInput) -> HelloOutput: + await asyncio.sleep(1) # so that it can be cancelled + return HelloOutput(message=f"Hello {input.name}! [from workflow]") + + @workflow.update + async def my_update(self, input: HelloInput) -> HelloOutput: + await asyncio.sleep(1) + return HelloOutput(message=f"Hello {input.name}! [from update]") diff --git a/hello_nexus/service/description.md b/hello_nexus/service/description.md new file mode 100644 index 00000000..c761f32f --- /dev/null +++ b/hello_nexus/service/description.md @@ -0,0 +1,8 @@ +Service Name: + MyNexusService +Operation Names: + echo + hello + +Input / Output arguments are in the following repository: +https://github.com/temporalio/samples-python/blob/main/nexus/service/interface.py diff --git a/hello_nexus/service/interface.py b/hello_nexus/service/interface.py new file mode 100644 index 00000000..9d4e958d --- /dev/null +++ b/hello_nexus/service/interface.py @@ -0,0 +1,34 @@ +from dataclasses import dataclass + +import nexusrpc + + +@dataclass +class HelloInput: + name: str + + +@dataclass +class HelloOutput: + message: str + + +@dataclass +class EchoInput: + message: str + + +@dataclass +class EchoOutput: + message: str + + +# TODO(dan): for now, making interface explicit in imports to distinguish from handler +# implementation. Final import scheme and names TBD. +@nexusrpc.interface.service +class MyNexusService: + echo: nexusrpc.interface.Operation[EchoInput, EchoOutput] + hello: nexusrpc.interface.Operation[HelloInput, HelloOutput] + echo2: nexusrpc.interface.Operation[EchoInput, EchoOutput] + hello2: nexusrpc.interface.Operation[HelloInput, HelloOutput] + echo3: nexusrpc.interface.Operation[EchoInput, EchoOutput] diff --git a/hello_nexus/simple.py b/hello_nexus/simple.py new file mode 100644 index 00000000..d0aa83e9 --- /dev/null +++ b/hello_nexus/simple.py @@ -0,0 +1,24 @@ +from datetime import timedelta + +import nexusrpc +from temporalio import workflow +from temporalio.workflow import NexusClient + + +@nexusrpc.handler.service +class MyNexusService: + @nexusrpc.handler.sync_operation + async def my_op(self, input: str, _: nexusrpc.handler.StartOperationOptions) -> str: + return f"{input}-result" + + +@workflow.defn +class Workflow: + @workflow.run + async def run(self, message: str) -> str: + nexus_client = NexusClient( + MyNexusService, + "my-endpoint", + schedule_to_close_timeout=timedelta(seconds=30), + ) + return await nexus_client.execute_operation(MyNexusService.my_op, message) diff --git a/pyproject.toml b/pyproject.toml index a7e0921d..60325d96 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -6,7 +6,11 @@ authors = [{ name = "Temporal Technologies Inc", email = "sdk@temporal.io" }] requires-python = "~=3.9" readme = "README.md" license = "MIT" -dependencies = ["temporalio>=1.11.0,<2"] +dependencies = [ + "ipython>=8.18.1", + "rich>=13.9.4", + "temporalio", +] [project.urls] Homepage = "https://github.com/temporalio/samples-python" @@ -22,6 +26,8 @@ dev = [ "pytest>=7.1.2,<8", "pytest-asyncio>=0.18.3,<0.19", "frozenlist>=1.4.0,<2", + "pdbpp>=0.10.3", + "pyright>=1.1.394", "types-pyyaml>=6.0.12.20241230,<7", ] bedrock = ["boto3>=1.34.92,<2"] @@ -43,9 +49,12 @@ langchain = [ "tqdm>=4.62.0,<5", "uvicorn[standard]>=0.24.0.post1,<0.25", ] +nexus = [ + "nexus-rpc", +] open-telemetry = [ "temporalio[opentelemetry]", - "opentelemetry-exporter-otlp-proto-grpc==1.18.0", + "opentelemetry-exporter-otlp-proto-grpc", ] pydantic-converter = ["pydantic>=2.10.6,<3"] sentry = ["sentry-sdk>=1.11.0,<2"] @@ -68,12 +77,17 @@ default-groups = [ "encryption", "gevent", "langchain", + "nexus", "open-telemetry", "pydantic-converter", "sentry", "trio-async", ] +[tool.uv.sources] +nexus-rpc = { path = "../nexus-sdk-python", editable = true } +temporalio = { path = "../sdk-python", editable = true } + [tool.hatch.build.targets.sdist] include = ["./**/*.py"] @@ -91,6 +105,7 @@ packages = [ "encryption", "gevent_async", "hello", + "hello_nexus", "langchain", "message_passing", "open_telemetry", diff --git a/uv.lock b/uv.lock index 3221e5e8..156d0fae 100644 --- a/uv.lock +++ b/uv.lock @@ -151,6 +151,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/19/24/44299477fe7dcc9cb58d0a57d5a7588d6af2ff403fdd2d47a246c91a3246/anyio-3.7.1-py3-none-any.whl", hash = "sha256:91dee416e570e92c64041bd18b900d1d6fa78dff7048769ce5ac5ddad004fbb5", size = 80896 }, ] +[[package]] +name = "asttokens" +version = "3.0.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/4a/e7/82da0a03e7ba5141f05cce0d302e6eed121ae055e0456ca228bf693984bc/asttokens-3.0.0.tar.gz", hash = "sha256:0dcd8baa8d62b0c1d118b399b2ddba3c4aff271d0d7a9e0d4c1681c79035bbc7", size = 61978 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/25/8a/c46dcc25341b5bce5472c718902eb3d38600a903b14fa6aeecef3f21a46f/asttokens-3.0.0-py3-none-any.whl", hash = "sha256:e3078351a059199dd5138cb1c706e6430c05eff2ff136af5eb4790f9d28932e2", size = 26918 }, +] + [[package]] name = "async-timeout" version = "4.0.3" @@ -453,6 +462,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/c3/be/d0d44e092656fe7a06b55e6103cbce807cdbdee17884a5367c68c9860853/dataclasses_json-0.6.7-py3-none-any.whl", hash = "sha256:0dbf33f26c8d5305befd61b39d2b3414e8a407bedc2834dea9b8d642666fb40a", size = 28686 }, ] +[[package]] +name = "decorator" +version = "5.2.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/43/fa/6d96a0978d19e17b68d634497769987b16c8f4cd0a7a05048bec693caa6b/decorator-5.2.1.tar.gz", hash = "sha256:65f266143752f734b0a7cc83c46f4618af75b8c5911b00ccb61d0ac9b6da0360", size = 56711 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/4e/8c/f3147f5c4b73e7550fe5f9352eaa956ae838d5c51eb58e7a25b9f3e2643b/decorator-5.2.1-py3-none-any.whl", hash = "sha256:d316bb415a2d9e2d2b3abcc4084c6502fc09240e292cd76a76afc106a1c8e04a", size = 9190 }, +] + [[package]] name = "deprecated" version = "1.2.18" @@ -483,6 +501,28 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/02/cc/b7e31358aac6ed1ef2bb790a9746ac2c69bcb3c8588b41616914eb106eaf/exceptiongroup-1.2.2-py3-none-any.whl", hash = "sha256:3111b9d131c238bec2f8f516e123e14ba243563fb135d3fe885990585aa7795b", size = 16453 }, ] +[[package]] +name = "executing" +version = "2.2.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/91/50/a9d80c47ff289c611ff12e63f7c5d13942c65d68125160cefd768c73e6e4/executing-2.2.0.tar.gz", hash = "sha256:5d108c028108fe2551d1a7b2e8b713341e2cb4fc0aa7dcf966fa4327a5226755", size = 978693 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7b/8f/c4d9bafc34ad7ad5d8dc16dd1347ee0e507a52c3adb6bfa8887e1c6a26ba/executing-2.2.0-py2.py3-none-any.whl", hash = "sha256:11387150cad388d62750327a53d3339fad4888b39a6fe233c3afbb54ecffd3aa", size = 26702 }, +] + +[[package]] +name = "fancycompleter" +version = "0.11.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pyreadline3", marker = "sys_platform == 'win32'" }, + { name = "pyrepl", marker = "python_full_version < '3.13'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/f3/03/eb007f5e90c13016debb6ecd717f0595ce758bf30906f2cb273673e8427d/fancycompleter-0.11.0.tar.gz", hash = "sha256:632b265b29dd0315b96d33d13d83132a541d6312262214f50211b3981bb4fa00", size = 341517 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/07/52/d3e234bf32ee97e71b45886a52871dc681345d64b449a930bab38c73cbcb/fancycompleter-0.11.0-py3-none-any.whl", hash = "sha256:a4712fdda8d7f3df08511ab2755ea0f1e669e2c65701a28c0c0aa2ff528521ed", size = 11166 }, +] + [[package]] name = "fastapi" version = "0.105.0" @@ -840,6 +880,11 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/2a/39/e50c7c3a983047577ee07d2a9e53faf5a69493943ec3f6a384bdc792deb2/httpx-0.28.1-py3-none-any.whl", hash = "sha256:d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad", size = 73517 }, ] +[[package]] +name = "hyperlinked" +version = "0.1.0" +source = { editable = "../../hyperlinked/python" } + [[package]] name = "idna" version = "3.10" @@ -870,6 +915,95 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/2c/e1/e6716421ea10d38022b952c159d5161ca1193197fb744506875fbb87ea7b/iniconfig-2.1.0-py3-none-any.whl", hash = "sha256:9deba5723312380e77435581c6bf4935c94cbfab9b1ed33ef8d238ea168eb760", size = 6050 }, ] +[[package]] +name = "ipython" +version = "8.18.1" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version < '3.10'", +] +dependencies = [ + { name = "colorama", marker = "python_full_version < '3.10' and sys_platform == 'win32'" }, + { name = "decorator", marker = "python_full_version < '3.10'" }, + { name = "exceptiongroup", marker = "python_full_version < '3.10'" }, + { name = "jedi", marker = "python_full_version < '3.10'" }, + { name = "matplotlib-inline", marker = "python_full_version < '3.10'" }, + { name = "pexpect", marker = "python_full_version < '3.10' and sys_platform != 'win32'" }, + { name = "prompt-toolkit", marker = "python_full_version < '3.10'" }, + { name = "pygments", marker = "python_full_version < '3.10'" }, + { name = "stack-data", marker = "python_full_version < '3.10'" }, + { name = "traitlets", marker = "python_full_version < '3.10'" }, + { name = "typing-extensions", marker = "python_full_version < '3.10'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/b1/b9/3ba6c45a6df813c09a48bac313c22ff83efa26cbb55011218d925a46e2ad/ipython-8.18.1.tar.gz", hash = "sha256:ca6f079bb33457c66e233e4580ebfc4128855b4cf6370dddd73842a9563e8a27", size = 5486330 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/47/6b/d9fdcdef2eb6a23f391251fde8781c38d42acd82abe84d054cb74f7863b0/ipython-8.18.1-py3-none-any.whl", hash = "sha256:e8267419d72d81955ec1177f8a29aaa90ac80ad647499201119e2f05e99aa397", size = 808161 }, +] + +[[package]] +name = "ipython" +version = "8.35.0" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version == '3.10.*'", +] +dependencies = [ + { name = "colorama", marker = "python_full_version == '3.10.*' and sys_platform == 'win32'" }, + { name = "decorator", marker = "python_full_version == '3.10.*'" }, + { name = "exceptiongroup", marker = "python_full_version == '3.10.*'" }, + { name = "jedi", marker = "python_full_version == '3.10.*'" }, + { name = "matplotlib-inline", marker = "python_full_version == '3.10.*'" }, + { name = "pexpect", marker = "python_full_version == '3.10.*' and sys_platform != 'emscripten' and sys_platform != 'win32'" }, + { name = "prompt-toolkit", marker = "python_full_version == '3.10.*'" }, + { name = "pygments", marker = "python_full_version == '3.10.*'" }, + { name = "stack-data", marker = "python_full_version == '3.10.*'" }, + { name = "traitlets", marker = "python_full_version == '3.10.*'" }, + { name = "typing-extensions", marker = "python_full_version == '3.10.*'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/0c/77/7d1501e8b539b179936e0d5969b578ed23887be0ab8c63e0120b825bda3e/ipython-8.35.0.tar.gz", hash = "sha256:d200b7d93c3f5883fc36ab9ce28a18249c7706e51347681f80a0aef9895f2520", size = 5605027 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/91/bf/17ffca8c8b011d0bac90adb5d4e720cb3ae1fe5ccfdfc14ca31f827ee320/ipython-8.35.0-py3-none-any.whl", hash = "sha256:e6b7470468ba6f1f0a7b116bb688a3ece2f13e2f94138e508201fad677a788ba", size = 830880 }, +] + +[[package]] +name = "ipython" +version = "9.1.0" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.12.4'", + "python_full_version >= '3.12' and python_full_version < '3.12.4'", + "python_full_version == '3.11.*'", +] +dependencies = [ + { name = "colorama", marker = "python_full_version >= '3.11' and sys_platform == 'win32'" }, + { name = "decorator", marker = "python_full_version >= '3.11'" }, + { name = "ipython-pygments-lexers", marker = "python_full_version >= '3.11'" }, + { name = "jedi", marker = "python_full_version >= '3.11'" }, + { name = "matplotlib-inline", marker = "python_full_version >= '3.11'" }, + { name = "pexpect", marker = "python_full_version >= '3.11' and sys_platform != 'emscripten' and sys_platform != 'win32'" }, + { name = "prompt-toolkit", marker = "python_full_version >= '3.11'" }, + { name = "pygments", marker = "python_full_version >= '3.11'" }, + { name = "stack-data", marker = "python_full_version >= '3.11'" }, + { name = "traitlets", marker = "python_full_version >= '3.11'" }, + { name = "typing-extensions", marker = "python_full_version == '3.11.*'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/70/9a/6b8984bedc990f3a4aa40ba8436dea27e23d26a64527de7c2e5e12e76841/ipython-9.1.0.tar.gz", hash = "sha256:a47e13a5e05e02f3b8e1e7a0f9db372199fe8c3763532fe7a1e0379e4e135f16", size = 4373688 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b2/9d/4ff2adf55d1b6e3777b0303fdbe5b723f76e46cba4a53a32fe82260d2077/ipython-9.1.0-py3-none-any.whl", hash = "sha256:2df07257ec2f84a6b346b8d83100bcf8fa501c6e01ab75cd3799b0bb253b3d2a", size = 604053 }, +] + +[[package]] +name = "ipython-pygments-lexers" +version = "1.1.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pygments", marker = "python_full_version >= '3.11'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/ef/4c/5dd1d8af08107f88c7f741ead7a40854b8ac24ddf9ae850afbcf698aa552/ipython_pygments_lexers-1.1.1.tar.gz", hash = "sha256:09c0138009e56b6854f9535736f4171d855c8c08a563a0dcd8022f78355c7e81", size = 8393 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d9/33/1f075bf72b0b747cb3288d011319aaf64083cf2efef8354174e3ed4540e2/ipython_pygments_lexers-1.1.1-py3-none-any.whl", hash = "sha256:a9462224a505ade19a605f71f8fa63c2048833ce50abc86768a0d81d876dc81c", size = 8074 }, +] + [[package]] name = "isort" version = "5.13.2" @@ -879,6 +1013,18 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/d1/b3/8def84f539e7d2289a02f0524b944b15d7c75dab7628bedf1c4f0992029c/isort-5.13.2-py3-none-any.whl", hash = "sha256:8ca5e72a8d85860d5a3fa69b8745237f2939afe12dbf656afbcb47fe72d947a6", size = 92310 }, ] +[[package]] +name = "jedi" +version = "0.19.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "parso" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/72/3a/79a912fbd4d8dd6fbb02bf69afd3bb72cf0c729bb3063c6f4498603db17a/jedi-0.19.2.tar.gz", hash = "sha256:4770dc3de41bde3966b02eb84fbcf557fb33cce26ad23da12c742fb50ecb11f0", size = 1231287 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c0/5a/9cac0c82afec3d09ccd97c8b6502d48f165f9124db81b4bcb90b4af974ee/jedi-0.19.2-py2.py3-none-any.whl", hash = "sha256:a8ef22bde8490f57fe5c7681a3c83cb58874daf72b4784de3cce5b6ef6edb5b9", size = 1572278 }, +] + [[package]] name = "jiter" version = "0.9.0" @@ -1084,6 +1230,18 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/de/f0/63b06b99b730b9954f8709f6f7d9b8d076fa0a973e472efe278089bde42b/langsmith-0.1.147-py3-none-any.whl", hash = "sha256:7166fc23b965ccf839d64945a78e9f1157757add228b086141eb03a60d699a15", size = 311812 }, ] +[[package]] +name = "markdown-it-py" +version = "3.0.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "mdurl" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/38/71/3b932df36c1a044d397a1f92d1cf91ee0a503d91e470cbd670aa66b07ed0/markdown-it-py-3.0.0.tar.gz", hash = "sha256:e3f60a94fa066dc52ec76661e37c851cb232d92f9886b15cb560aaada2df8feb", size = 74596 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/42/d7/1ec15b46af6af88f19b8e5ffea08fa375d433c998b8a7639e76935c14f1f/markdown_it_py-3.0.0-py3-none-any.whl", hash = "sha256:355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1", size = 87528 }, +] + [[package]] name = "marshmallow" version = "3.26.1" @@ -1096,6 +1254,27 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/34/75/51952c7b2d3873b44a0028b1bd26a25078c18f92f256608e8d1dc61b39fd/marshmallow-3.26.1-py3-none-any.whl", hash = "sha256:3350409f20a70a7e4e11a27661187b77cdcaeb20abca41c1454fe33636bea09c", size = 50878 }, ] +[[package]] +name = "matplotlib-inline" +version = "0.1.7" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "traitlets" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/99/5b/a36a337438a14116b16480db471ad061c36c3694df7c2084a0da7ba538b7/matplotlib_inline-0.1.7.tar.gz", hash = "sha256:8423b23ec666be3d16e16b60bdd8ac4e86e840ebd1dd11a30b9f117f2fa0ab90", size = 8159 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/8f/8e/9ad090d3553c280a8060fbf6e24dc1c0c29704ee7d1c372f0c174aa59285/matplotlib_inline-0.1.7-py3-none-any.whl", hash = "sha256:df192d39a4ff8f21b1895d72e6a13f5fcc5099f00fa84384e0ea28c2cc0653ca", size = 9899 }, +] + +[[package]] +name = "mdurl" +version = "0.1.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d6/54/cfe61301667036ec958cb99bd3efefba235e65cdeb9c84d24a8293ba1d90/mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba", size = 8729 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", size = 9979 }, +] + [[package]] name = "multidict" version = "6.2.0" @@ -1251,6 +1430,34 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/2a/e2/5d3f6ada4297caebe1a2add3b126fe800c96f56dbe5d1988a2cbe0b267aa/mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d", size = 4695 }, ] +[[package]] +name = "nexus-rpc" +version = "0.1.0" +source = { editable = "../nexus-sdk-python" } +dependencies = [ + { name = "typing-extensions" }, +] + +[package.metadata] +requires-dist = [{ name = "typing-extensions", specifier = ">=4.12.2" }] + +[package.metadata.requires-dev] +dev = [ + { name = "mypy", specifier = ">=1.15.0" }, + { name = "pyright", specifier = ">=1.1.400" }, + { name = "pytest", specifier = ">=8.3.5" }, + { name = "ruff", specifier = ">=0.11.7" }, +] + +[[package]] +name = "nodeenv" +version = "1.9.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/43/16/fc88b08840de0e0a72a2f9d8c6bae36be573e475a6326ae854bcc549fc45/nodeenv-1.9.1.tar.gz", hash = "sha256:6ec12890a2dab7946721edbfbcd91f3319c6ccc9aec47be7c7e6b7011ee6645f", size = 47437 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d2/1d/1b658dbd2b9fa9c4c9f32accbfc0205d532c8c6194dc0f2a4c0428e7128a/nodeenv-1.9.1-py2.py3-none-any.whl", hash = "sha256:ba11c9782d29c27c70ffbdda2d7415098754709be8a7056d79a737cd901155c9", size = 22314 }, +] + [[package]] name = "numpy" version = "1.26.4" @@ -1545,6 +1752,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/2f/49/5c30646e96c684570925b772eac4eb0a8cb0ca590fa978f56c5d3ae73ea1/pandas-2.2.3-cp39-cp39-win_amd64.whl", hash = "sha256:4850ba03528b6dd51d6c5d273c46f183f39a9baf3f0143e566b89450965b105e", size = 11618011 }, ] +[[package]] +name = "parso" +version = "0.8.4" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/66/94/68e2e17afaa9169cf6412ab0f28623903be73d1b32e208d9e8e541bb086d/parso-0.8.4.tar.gz", hash = "sha256:eb3a7b58240fb99099a345571deecc0f9540ea5f4dd2fe14c2a99d6b281ab92d", size = 400609 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c6/ac/dac4a63f978e4dcb3c6d3a78c4d8e0192a113d288502a1216950c41b1027/parso-0.8.4-py2.py3-none-any.whl", hash = "sha256:a418670a20291dacd2dddc80c377c5c3791378ee1e8d12bffc35420643d43f18", size = 103650 }, +] + [[package]] name = "pathspec" version = "0.12.1" @@ -1554,6 +1770,31 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/cc/20/ff623b09d963f88bfde16306a54e12ee5ea43e9b597108672ff3a408aad6/pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08", size = 31191 }, ] +[[package]] +name = "pdbpp" +version = "0.11.6" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "fancycompleter" }, + { name = "pygments" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/27/ef/e6ae1a1e1d2cbe0fbf04f22b21d7d58e8e13d24dfcc3b6a4dea18a3ed1e0/pdbpp-0.11.6.tar.gz", hash = "sha256:36a73c5bcf0c3c35034be4cf99e6106e3ee0c8f5e0faafc2cf9be5f1481eb4b7", size = 78178 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c5/e1/77fa5c45fcd95a80b0d793b604c19b71c9fa8d5b27d403eced79f3842828/pdbpp-0.11.6-py3-none-any.whl", hash = "sha256:8e024d36bd2f35a3b19d8732524c696b8b4aef633250d28547198e746cd81ccb", size = 33334 }, +] + +[[package]] +name = "pexpect" +version = "4.9.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "ptyprocess" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/42/92/cc564bf6381ff43ce1f4d06852fc19a2f11d180f23dc32d9588bee2f149d/pexpect-4.9.0.tar.gz", hash = "sha256:ee7d41123f3c9911050ea2c2dac107568dc43b2d3b0c7557a33212c398ead30f", size = 166450 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9e/c3/059298687310d527a58bb01f3b1965787ee3b40dce76752eda8b44e9a2c5/pexpect-4.9.0-py2.py3-none-any.whl", hash = "sha256:7236d1e080e4936be2dc3e326cec0af72acf9212a7e1d060210e70a47e253523", size = 63772 }, +] + [[package]] name = "platformdirs" version = "4.3.7" @@ -1572,6 +1813,18 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/88/5f/e351af9a41f866ac3f1fac4ca0613908d9a41741cfcf2228f4ad853b697d/pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669", size = 20556 }, ] +[[package]] +name = "prompt-toolkit" +version = "3.0.51" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "wcwidth" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/bb/6e/9d084c929dfe9e3bfe0c6a47e31f78a25c54627d64a66e884a8bf5474f1c/prompt_toolkit-3.0.51.tar.gz", hash = "sha256:931a162e3b27fc90c86f1b48bb1fb2c528c2761475e57c9c06de13311c7b54ed", size = 428940 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ce/4f/5249960887b1fbe561d9ff265496d170b55a735b76724f10ef19f9e40716/prompt_toolkit-3.0.51-py3-none-any.whl", hash = "sha256:52742911fde84e2d423e2f9a4cf1de7d7ac4e51958f648d9540e0fb8db077b07", size = 387810 }, +] + [[package]] name = "propcache" version = "0.3.1" @@ -1693,6 +1946,24 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/71/eb/be11a1244d0e58ee04c17a1f939b100199063e26ecca8262c04827fe0bf5/protobuf-4.25.6-py3-none-any.whl", hash = "sha256:07972021c8e30b870cfc0863409d033af940213e0e7f64e27fe017b929d2c9f7", size = 156466 }, ] +[[package]] +name = "ptyprocess" +version = "0.7.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/20/e5/16ff212c1e452235a90aeb09066144d0c5a6a8c0834397e03f5224495c4e/ptyprocess-0.7.0.tar.gz", hash = "sha256:5c5d0a3b48ceee0b48485e0c26037c0acd7d29765ca3fbb5cb3831d347423220", size = 70762 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/22/a6/858897256d0deac81a172289110f31629fc4cee19b6f01283303e18c8db3/ptyprocess-0.7.0-py2.py3-none-any.whl", hash = "sha256:4b41f3967fce3af57cc7e94b888626c18bf37a083e3651ca8feeb66d492fef35", size = 13993 }, +] + +[[package]] +name = "pure-eval" +version = "0.2.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/cd/05/0a34433a064256a578f1783a10da6df098ceaa4a57bbeaa96a6c0352786b/pure_eval-0.2.3.tar.gz", hash = "sha256:5f4e983f40564c576c7c8635ae88db5956bb2229d7e9237d03b3c0b0190eaf42", size = 19752 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/8e/37/efad0257dc6e593a18957422533ff0f87ede7c9c6ea010a2177d738fb82f/pure_eval-0.2.3-py3-none-any.whl", hash = "sha256:1db8e35b67b3d218d818ae653e27f06c3aa420901fa7b081ca98cbedc874e0d0", size = 11842 }, +] + [[package]] name = "pyarrow" version = "19.0.1" @@ -1875,6 +2146,46 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/da/a2/2670964d7046025b96f8c6d35c38e5310ec6aa1681e4158ef31ab21a4727/pydantic_core-2.33.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:68504959253303d3ae9406b634997a2123a0b0c1da86459abbd0ffc921695eac", size = 2082790 }, ] +[[package]] +name = "pygments" +version = "2.19.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/7c/2d/c3338d48ea6cc0feb8446d8e6937e1408088a72a39937982cc6111d17f84/pygments-2.19.1.tar.gz", hash = "sha256:61c16d2a8576dc0649d9f39e089b5f02bcd27fba10d8fb4dcc28173f7a45151f", size = 4968581 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/8a/0b/9fcc47d19c48b59121088dd6da2488a49d5f72dacf8262e2790a1d2c7d15/pygments-2.19.1-py3-none-any.whl", hash = "sha256:9ea1544ad55cecf4b8242fab6dd35a93bbce657034b0611ee383099054ab6d8c", size = 1225293 }, +] + +[[package]] +name = "pyreadline3" +version = "3.5.4" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/0f/49/4cea918a08f02817aabae639e3d0ac046fef9f9180518a3ad394e22da148/pyreadline3-3.5.4.tar.gz", hash = "sha256:8d57d53039a1c75adba8e50dd3d992b28143480816187ea5efbd5c78e6c885b7", size = 99839 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5a/dc/491b7661614ab97483abf2056be1deee4dc2490ecbf7bff9ab5cdbac86e1/pyreadline3-3.5.4-py3-none-any.whl", hash = "sha256:eaf8e6cc3c49bcccf145fc6067ba8643d1df34d604a1ec0eccbf7a18e6d3fae6", size = 83178 }, +] + +[[package]] +name = "pyrepl" +version = "0.11.3.post1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/92/78/65b9a4a4b15f7f5aae84c3edb9d3adc1acb2acc38eb9d5404cd5cf980927/pyrepl-0.11.3.post1.tar.gz", hash = "sha256:0ca7568c8be919b69f99644d29d31738a5b1a87750d06dd36564bcfad278d402", size = 50954 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2d/45/02a5e2da58a32ff407b14d38690c1d2f8705bd6909320817b444070dcbb0/pyrepl-0.11.3.post1-py3-none-any.whl", hash = "sha256:59fcd67588892731dc6e7aff106c380d303d54324ff028827804a2b056223d92", size = 55613 }, +] + +[[package]] +name = "pyright" +version = "1.1.394" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "nodeenv" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/b1/e4/79f4d8a342eed6790fdebdb500e95062f319ee3d7d75ae27304ff995ae8c/pyright-1.1.394.tar.gz", hash = "sha256:56f2a3ab88c5214a451eb71d8f2792b7700434f841ea219119ade7f42ca93608", size = 3809348 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d6/4c/50c74e3d589517a9712a61a26143b587dba6285434a17aebf2ce6b82d2c3/pyright-1.1.394-py3-none-any.whl", hash = "sha256:5f74cce0a795a295fb768759bbeeec62561215dea657edcaab48a932b031ddbb", size = 5679540 }, +] + [[package]] name = "pytest" version = "7.4.4" @@ -2101,6 +2412,20 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/3f/51/d4db610ef29373b879047326cbf6fa98b6c1969d6f6dc423279de2b1be2c/requests_toolbelt-1.0.0-py2.py3-none-any.whl", hash = "sha256:cccfdd665f0a24fcf4726e690f65639d272bb0637b9b92dfd91a5568ccf6bd06", size = 54481 }, ] +[[package]] +name = "rich" +version = "14.0.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "markdown-it-py" }, + { name = "pygments" }, + { name = "typing-extensions", marker = "python_full_version < '3.11'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/a1/53/830aa4c3066a8ab0ae9a9955976fb770fe9c6102117c8ec4ab3ea62d89e8/rich-14.0.0.tar.gz", hash = "sha256:82f1bc23a6a21ebca4ae0c45af9bdbc492ed20231dcb63f297d6d1021a9d5725", size = 224078 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0d/9b/63f4c7ebc259242c89b3acafdb37b41d1185c07ff0011164674e9076b491/rich-14.0.0-py3-none-any.whl", hash = "sha256:1c9491e1951aac09caffd42f448ee3d04e58923ffe14993f6e83068dc395d7e0", size = 243229 }, +] + [[package]] name = "s3transfer" version = "0.11.4" @@ -2216,6 +2541,20 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/d1/7c/5fc8e802e7506fe8b55a03a2e1dab156eae205c91bee46305755e086d2e2/sqlalchemy-2.0.40-py3-none-any.whl", hash = "sha256:32587e2e1e359276957e6fe5dad089758bc042a971a8a09ae8ecf7a8fe23d07a", size = 1903894 }, ] +[[package]] +name = "stack-data" +version = "0.6.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "asttokens" }, + { name = "executing" }, + { name = "pure-eval" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/28/e3/55dcc2cfbc3ca9c29519eb6884dd1415ecb53b0e934862d3559ddcb7e20b/stack_data-0.6.3.tar.gz", hash = "sha256:836a778de4fec4dcd1dcd89ed8abff8a221f58308462e1c4aa2a3cf30148f0b9", size = 44707 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f1/7b/ce1eafaf1a76852e2ec9b22edecf1daa58175c090266e9f6c64afcd81d91/stack_data-0.6.3-py3-none-any.whl", hash = "sha256:d5558e0c25a4cb0853cddad3d77da9891a08cb85dd9f9f91b9f8cd66e511e695", size = 24521 }, +] + [[package]] name = "starlette" version = "0.27.0" @@ -2232,21 +2571,17 @@ wheels = [ [[package]] name = "temporalio" version = "1.11.0" -source = { registry = "https://pypi.org/simple" } +source = { editable = "../sdk-python" } dependencies = [ + { name = "hyperlinked" }, + { name = "nexus-rpc" }, + { name = "pdbpp" }, { name = "protobuf" }, { name = "python-dateutil", marker = "python_full_version < '3.11'" }, + { name = "temporalio-xray" }, { name = "types-protobuf" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/2c/c0/e3824f1982198ec477b4dc0496b8f3fe02b85fc2afedcb6ed6a28a7b54f8/temporalio-1.11.0.tar.gz", hash = "sha256:13dd4f7c877db7c3db32932aa669e533e4f9da1c04800de9298a6cb874056ae4", size = 1507385 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/d8/a7/8b53d51d1cfe66dda845218ed41436fdeb0adee946381fcc157e45bafad3/temporalio-1.11.0-cp39-abi3-macosx_10_12_x86_64.whl", hash = "sha256:f9aed3d9c7088d9576f435a83723c61f9ccf3adf749ea3dc42ad16558542d355", size = 11792050 }, - { url = "https://files.pythonhosted.org/packages/4d/d0/ddaa9fb71bc3b192d2592f59abc81230602baac7c6fd97d0f165e5687a1b/temporalio-1.11.0-cp39-abi3-macosx_11_0_arm64.whl", hash = "sha256:d21a28c6e39de1e8408b6637957bdc76e590a1364d2419e57208608eba067074", size = 11483188 }, - { url = "https://files.pythonhosted.org/packages/09/37/bd91ad08c6a9942fd0265add2aa9976122b8f9a7aa0bef8d8de18a494a1f/temporalio-1.11.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8e4f85caf6cde04a2d5bbb586d761302bdd5e2531a0e554cdff73a1194a6c495", size = 11864957 }, - { url = "https://files.pythonhosted.org/packages/c2/61/3d76f06e16127e288eeabc9cdd099ef12492c0ac75ee73dece2645577b29/temporalio-1.11.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4ae69089b371a8f05f8c1a4519d3d0c6cdda39ca4cdbe2cb322607514ca0122c", size = 12040920 }, - { url = "https://files.pythonhosted.org/packages/b0/d8/020a21063eeefdeaeb39ab2c8c9fd87f4709da33e0ab1b14fad81b734bcd/temporalio-1.11.0-cp39-abi3-win_amd64.whl", hash = "sha256:97ce571d08ba23b0bd088c71eca723ae155721ea5bfa9a733a9a3ad2cf52c14c", size = 12124609 }, -] [package.optional-dependencies] opentelemetry = [ @@ -2254,11 +2589,51 @@ opentelemetry = [ { name = "opentelemetry-sdk" }, ] +[package.metadata] +requires-dist = [ + { name = "grpcio", marker = "extra == 'grpc'", specifier = ">=1.48.2,<2" }, + { name = "hyperlinked", editable = "../../hyperlinked/python" }, + { name = "nexus-rpc", editable = "../nexus-sdk-python" }, + { name = "opentelemetry-api", marker = "extra == 'opentelemetry'", specifier = ">=1.11.1,<2" }, + { name = "opentelemetry-sdk", marker = "extra == 'opentelemetry'", specifier = ">=1.11.1,<2" }, + { name = "pdbpp", specifier = ">=0.11.6" }, + { name = "protobuf", specifier = ">=3.20" }, + { name = "pydantic", marker = "extra == 'pydantic'", specifier = ">=2.0.0,<3" }, + { name = "python-dateutil", marker = "python_full_version < '3.11'", specifier = ">=2.8.2,<3" }, + { name = "temporalio-xray", editable = "../xray/sdks/python" }, + { name = "types-protobuf", specifier = ">=3.20" }, + { name = "typing-extensions", specifier = ">=4.2.0,<5" }, +] +provides-extras = ["grpc", "opentelemetry", "pydantic"] + +[package.metadata.requires-dev] +dev = [ + { name = "cibuildwheel", specifier = ">=2.22.0,<3" }, + { name = "grpcio-tools", specifier = ">=1.48.2,<2" }, + { name = "maturin", specifier = ">=1.8.2" }, + { name = "mypy", specifier = "==1.4.1" }, + { name = "mypy-protobuf", specifier = ">=3.3.0,<4" }, + { name = "psutil", specifier = ">=5.9.3,<6" }, + { name = "pydocstyle", specifier = ">=6.3.0,<7" }, + { name = "pydoctor", specifier = ">=24.11.1,<25" }, + { name = "pyright", specifier = "==1.1.400" }, + { name = "pytest", specifier = "~=7.4" }, + { name = "pytest-asyncio", specifier = ">=0.21,<0.22" }, + { name = "pytest-timeout", specifier = "~=2.2" }, + { name = "ruff", specifier = ">=0.5.0,<0.6" }, + { name = "toml", specifier = ">=0.10.2,<0.11" }, + { name = "twine", specifier = ">=4.0.1,<5" }, +] + [[package]] name = "temporalio-samples" version = "0.1a1" source = { editable = "." } dependencies = [ + { name = "ipython", version = "8.18.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, + { name = "ipython", version = "8.35.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.10.*'" }, + { name = "ipython", version = "9.1.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, + { name = "rich" }, { name = "temporalio" }, ] @@ -2277,6 +2652,8 @@ dev = [ { name = "frozenlist" }, { name = "isort" }, { name = "mypy" }, + { name = "pdbpp" }, + { name = "pyright" }, { name = "pytest" }, { name = "pytest-asyncio" }, { name = "types-pyyaml" }, @@ -2301,6 +2678,9 @@ langchain = [ { name = "tqdm" }, { name = "uvicorn", extra = ["standard"] }, ] +nexus = [ + { name = "nexus-rpc" }, +] open-telemetry = [ { name = "opentelemetry-exporter-otlp-proto-grpc" }, { name = "temporalio", extra = ["opentelemetry"] }, @@ -2317,7 +2697,11 @@ trio-async = [ ] [package.metadata] -requires-dist = [{ name = "temporalio", specifier = ">=1.11.0,<2" }] +requires-dist = [ + { name = "ipython", specifier = ">=8.18.1" }, + { name = "rich", specifier = ">=13.9.4" }, + { name = "temporalio", editable = "../sdk-python" }, +] [package.metadata.requires-dev] bedrock = [{ name = "boto3", specifier = ">=1.34.92,<2" }] @@ -2332,6 +2716,8 @@ dev = [ { name = "frozenlist", specifier = ">=1.4.0,<2" }, { name = "isort", specifier = ">=5.10.1,<6" }, { name = "mypy", specifier = ">=1.4.1,<2" }, + { name = "pdbpp", specifier = ">=0.10.3" }, + { name = "pyright", specifier = ">=1.1.394" }, { name = "pytest", specifier = ">=7.1.2,<8" }, { name = "pytest-asyncio", specifier = ">=0.18.3,<0.19" }, { name = "types-pyyaml", specifier = ">=6.0.12.20241230,<7" }, @@ -2354,9 +2740,10 @@ langchain = [ { name = "tqdm", specifier = ">=4.62.0,<5" }, { name = "uvicorn", extras = ["standard"], specifier = ">=0.24.0.post1,<0.25" }, ] +nexus = [{ name = "nexus-rpc", editable = "../nexus-sdk-python" }] open-telemetry = [ - { name = "opentelemetry-exporter-otlp-proto-grpc", specifier = "==1.18.0" }, - { name = "temporalio", extras = ["opentelemetry"] }, + { name = "opentelemetry-exporter-otlp-proto-grpc" }, + { name = "temporalio", extras = ["opentelemetry"], editable = "../sdk-python" }, ] pydantic-converter = [{ name = "pydantic", specifier = ">=2.10.6,<3" }] sentry = [{ name = "sentry-sdk", specifier = ">=1.11.0,<2" }] @@ -2365,6 +2752,25 @@ trio-async = [ { name = "trio-asyncio", specifier = ">=0.15.0,<0.16" }, ] +[[package]] +name = "temporalio-xray" +version = "0.1.0" +source = { editable = "../xray/sdks/python" } +dependencies = [ + { name = "opentelemetry-exporter-otlp-proto-grpc" }, + { name = "opentelemetry-sdk" }, + { name = "protobuf" }, + { name = "temporalio" }, +] + +[package.metadata] +requires-dist = [ + { name = "opentelemetry-exporter-otlp-proto-grpc", specifier = ">=1.18" }, + { name = "opentelemetry-sdk", specifier = ">=1.11.1,<2" }, + { name = "protobuf", specifier = ">=3.20" }, + { name = "temporalio", specifier = ">=1.10.0" }, +] + [[package]] name = "tenacity" version = "8.5.0" @@ -2467,6 +2873,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/d0/30/dc54f88dd4a2b5dc8a0279bdd7270e735851848b762aeb1c1184ed1f6b14/tqdm-4.67.1-py3-none-any.whl", hash = "sha256:26445eca388f82e72884e0d580d5464cd801a3ea01e63e5601bdff9ba6a48de2", size = 78540 }, ] +[[package]] +name = "traitlets" +version = "5.14.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/eb/79/72064e6a701c2183016abbbfedaba506d81e30e232a68c9f0d6f6fcd1574/traitlets-5.14.3.tar.gz", hash = "sha256:9ed0579d3502c94b4b3732ac120375cda96f923114522847de4b3bb98b96b6b7", size = 161621 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/00/c0/8f5d070730d7836adc9c9b6408dec68c6ced86b304a9b26a14df072a6e8c/traitlets-5.14.3-py3-none-any.whl", hash = "sha256:b74e89e397b1ed28cc831db7aea759ba6640cb3de13090ca145426688ff1ac4f", size = 85359 }, +] + [[package]] name = "trio" version = "0.28.0" @@ -2733,6 +3148,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/7a/e9/3cbcf4d70cd0b6d3f30631deae1bf37cc0be39887ca327a44462fe546bf5/watchfiles-1.0.4-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5e0227b8ed9074c6172cf55d85b5670199c99ab11fd27d2c473aa30aec67ee42", size = 452488 }, ] +[[package]] +name = "wcwidth" +version = "0.2.13" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/6c/63/53559446a878410fc5a5974feb13d31d78d752eb18aeba59c7fef1af7598/wcwidth-0.2.13.tar.gz", hash = "sha256:72ea0c06399eb286d978fdedb6923a9eb47e1c486ce63e9b4e64fc18303972b5", size = 101301 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/fd/84/fd2ba7aafacbad3c4201d395674fc6348826569da3c0937e75505ead3528/wcwidth-0.2.13-py2.py3-none-any.whl", hash = "sha256:3da69048e4540d84af32131829ff948f1e022c1c6bdb8d6102117aac784f6859", size = 34166 }, +] + [[package]] name = "websockets" version = "15.0.1"