Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ dev = [
"mypy-protobuf>=3.3.0,<4",
"psutil>=5.9.3,<6",
"pydocstyle>=6.3.0,<7",
"pydoctor>=24.11.1,<25",
"pydoctor>=25.10.1,<26",
"pyright==1.1.403",
"pytest~=7.4",
"pytest-asyncio>=0.21,<0.22",
Expand Down Expand Up @@ -158,6 +158,7 @@ intersphinx = [
"https://docs.python.org/3/objects.inv",
"https://googleapis.dev/python/protobuf/latest/objects.inv",
"https://opentelemetry-python.readthedocs.io/en/latest/objects.inv",
"https://nexus-rpc.github.io/sdk-python/objects.inv",
]
privacy = [
"PRIVATE:temporalio.bridge",
Expand All @@ -177,6 +178,7 @@ privacy = [
]
project-name = "Temporal Python"
sidebar-expand-depth = 2
warnings-as-errors = true

[tool.pyright]
enableTypeIgnoreComments = true
Expand Down
2 changes: 1 addition & 1 deletion temporalio/activity.py
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,7 @@ def wait_sync(self, timeout: Optional[float] = None) -> None:
def client() -> Client:
"""Return a Temporal Client for use in the current activity.

The client is only available in `async def` activities.
The client is only available in ``async def`` activities.

In tests it is not available automatically, but you can pass a client when creating a
:py:class:`temporalio.testing.ActivityEnvironment`.
Expand Down
2 changes: 1 addition & 1 deletion temporalio/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -1088,7 +1088,7 @@ def to_canonical_string(self) -> str:
@staticmethod
def from_canonical_string(canonical: str) -> WorkerDeploymentVersion:
"""Parse a version from a canonical string, which must be in the format
`<deployment_name>.<build_id>`. Deployment name must not have a `.` in it.
`<deployment_name>.<build_id>`. Deployment name must not have a ``.`` in it.
"""
parts = canonical.split(".", maxsplit=1)
if len(parts) != 2:
Expand Down
6 changes: 4 additions & 2 deletions temporalio/contrib/openai_agents/workflow.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,11 +60,13 @@ def activity_as_tool(
of inputs and outputs between the agent and the activity. Note that if you take a context,
mutation will not be persisted, as the activity may not be running in the same location.

For undocumented arguments, refer to :py:mod:`workflow` and :py:meth:`start_activity`

Args:
fn: A Temporal activity function to convert to a tool.
strict_json_schema: Whether the tool should follow a strict schema.
See https://openai.github.io/openai-agents-python/ref/tool/#agents.tool.FunctionTool.strict_json_schema
For other arguments, refer to :py:mod:`workflow` :py:meth:`start_activity`


Returns:
An OpenAI agent tool that wraps the provided activity.
Expand Down Expand Up @@ -178,7 +180,7 @@ def nexus_operation_as_tool(
of inputs and outputs between the agent and the operation.

Args:
fn: A Nexus operation to convert into a tool.
operation: A Nexus operation to convert into a tool.
service: The Nexus service class that contains the operation.
endpoint: The Nexus endpoint to use for the operation.
strict_json_schema: Whether the tool should follow a strict schema
Expand Down
6 changes: 3 additions & 3 deletions temporalio/envconfig.py
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ class ClientConfigProfile:
"""Represents a client configuration profile.

This class holds the configuration as loaded from a file or environment.
See `to_connect_config` to transform the profile to `ClientConnectConfig`,
See `to_client_connect_config` to transform the profile to `ClientConnectConfig`,
which can be used to create a client.

.. warning::
Expand Down Expand Up @@ -304,8 +304,8 @@ class ClientConfig:
"""Client configuration loaded from TOML and environment variables.

This contains a mapping of profile names to client profiles. Use
`ClientConfigProfile.to_connect_config` to create a `ClientConnectConfig`
from a profile. See `load_profile` to load an individual profile.
`ClientConfigProfile.to_client_connect_config` to create a `ClientConnectConfig`
from a profile. See `ClientConfigProfile.load` to load an individual profile.

.. warning::
Experimental API.
Expand Down
33 changes: 23 additions & 10 deletions temporalio/nexus/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,28 @@
See https://github.com/temporalio/sdk-python/tree/main#nexus
"""

from ._decorators import workflow_run_operation as workflow_run_operation
from ._operation_context import Info as Info
from ._operation_context import LoggerAdapter as LoggerAdapter
from ._operation_context import NexusCallback as NexusCallback
from ._decorators import workflow_run_operation
from ._operation_context import (
WorkflowRunOperationContext as WorkflowRunOperationContext,
Info,
LoggerAdapter,
NexusCallback,
WorkflowRunOperationContext,
client,
in_operation,
info,
logger,
)
from ._token import WorkflowHandle

__all__ = (
"workflow_run_operation",
"Info",
"LoggerAdapter",
"NexusCallback",
"WorkflowRunOperationContext",
"client",
"in_operation",
"info",
"logger",
"WorkflowHandle",
)
from ._operation_context import client as client
from ._operation_context import in_operation as in_operation
from ._operation_context import info as info
from ._operation_context import logger as logger
from ._token import WorkflowHandle as WorkflowHandle
16 changes: 10 additions & 6 deletions temporalio/nexus/_operation_context.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,6 @@
import temporalio.api.common.v1
import temporalio.api.workflowservice.v1
import temporalio.common
from temporalio.nexus import _link_conversion
from temporalio.nexus._token import WorkflowHandle
from temporalio.types import (
MethodAsyncNoParam,
MethodAsyncSingleParam,
Expand All @@ -34,6 +32,13 @@
SelfType,
)

from ._link_conversion import (
nexus_link_to_workflow_event,
workflow_event_to_nexus_link,
workflow_execution_started_event_link_from_workflow_handle,
)
from ._token import WorkflowHandle

if TYPE_CHECKING:
import temporalio.client

Expand Down Expand Up @@ -162,7 +167,7 @@ def _get_workflow_event_links(
) -> list[temporalio.api.common.v1.Link.WorkflowEvent]:
event_links = []
for inbound_link in self.nexus_context.inbound_links:
if link := _link_conversion.nexus_link_to_workflow_event(inbound_link):
if link := nexus_link_to_workflow_event(inbound_link):
event_links.append(link)
return event_links

Expand All @@ -182,14 +187,13 @@ def _add_outbound_links(
wf_event_links.append(link.workflow_event)
if not wf_event_links:
wf_event_links = [
_link_conversion.workflow_execution_started_event_link_from_workflow_handle(
workflow_execution_started_event_link_from_workflow_handle(
workflow_handle,
self.nexus_context.request_id,
)
]
self.nexus_context.outbound_links.extend(
_link_conversion.workflow_event_to_nexus_link(link)
for link in wf_event_links
workflow_event_to_nexus_link(link) for link in wf_event_links
)
except Exception as e:
logger.warning(
Expand Down
2 changes: 1 addition & 1 deletion temporalio/nexus/_operation_handlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ async def _cancel_workflow(

Args:
token: The token of the workflow to cancel. kwargs: Additional keyword arguments
to pass to the workflow cancel method.
to pass to the workflow cancel method.
"""
try:
nexus_workflow_handle = WorkflowHandle[Any].from_token(token)
Expand Down
8 changes: 4 additions & 4 deletions temporalio/nexus/_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ def get_workflow_run_start_method_input_and_output_type_annotations(
]:
"""Return operation input and output types.

`start` must be a type-annotated start method that returns a
``start`` must be a type-annotated start method that returns a
:py:class:`temporalio.nexus.WorkflowHandle`.
"""
input_type, output_type = _get_start_method_input_and_output_type_annotations(start)
Expand Down Expand Up @@ -125,7 +125,7 @@ def get_operation_factory(
Optional[Callable[[Any], Any]],
Optional[nexusrpc.Operation[Any, Any]],
]:
"""Return the :py:class:`Operation` for the object along with the factory function.
"""Return the :py:class:`nexusrpc.Operation` for the object along with the factory function.

``obj`` should be a decorated operation start method.
"""
Expand All @@ -145,7 +145,7 @@ def set_operation_factory(
obj: Any,
operation_factory: Callable[[Any], Any],
) -> None:
"""Set the :py:class:`OperationHandler` factory for this object.
"""Set the :py:class:`nexusrpc.handler.OperationHandler` factory for this object.

``obj`` should be an operation start method.
"""
Expand All @@ -158,7 +158,7 @@ def set_operation_factory(
#
# This file is licensed under the MIT License.
def is_async_callable(obj: Any) -> bool:
"""Return True if `obj` is an async callable.
"""Return True if ``obj`` is an async callable.

Supports partials of async callable class instances.
"""
Expand Down
2 changes: 1 addition & 1 deletion temporalio/runtime.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ class Runtime:
thread pool is created.

Runtimes do not work across forks. Advanced users should consider using
:py:meth:`prevent_default` and `:py:meth`set_default` to ensure each
:py:meth:`prevent_default` and :py:meth:`set_default` to ensure each
fork creates it's own runtime.

"""
Expand Down
7 changes: 2 additions & 5 deletions temporalio/service.py
Original file line number Diff line number Diff line change
Expand Up @@ -230,11 +230,8 @@ async def check_health(
metadata: Mapping[str, Union[str, bytes]] = {},
timeout: Optional[timedelta] = None,
) -> bool:
"""Check whether the WorkflowService is up.

In addition to accepting which service to check health on, this accepts
some of the same parameters as other RPC calls. See
:py:meth:`ServiceCall.__call__`.
"""Check whether the provided service is up. If no service is specified,
the WorkflowService is used.

Returns:
True when available, false if the server is running but the service
Expand Down
2 changes: 1 addition & 1 deletion temporalio/worker/_interceptor.py
Original file line number Diff line number Diff line change
Expand Up @@ -469,5 +469,5 @@ def start_local_activity(
async def start_nexus_operation(
self, input: StartNexusOperationInput[InputT, OutputT]
) -> temporalio.workflow.NexusOperationHandle[OutputT]:
"""Called for every :py:func:`temporalio.workflow.start_nexus_operation` call."""
"""Called for every :py:func:`temporalio.workflow.NexusClient.start_operation` call."""
return await self.next.start_nexus_operation(input)
4 changes: 2 additions & 2 deletions temporalio/worker/_tuning.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ class FixedSizeSlotSupplier:

@dataclass(frozen=True)
class ResourceBasedTunerConfig:
"""Options for a :py:class:`ResourceBasedTuner` or a :py:class:`ResourceBasedSlotSupplier`."""
"""Options for a :py:class:`ResourceBasedSlotSupplier`."""

target_memory_usage: float
"""A value between 0 and 1 that represents the target (system) memory usage. It's not recommended
Expand Down Expand Up @@ -62,7 +62,7 @@ class ResourceBasedSlotSupplier:
slot_config: ResourceBasedSlotConfig
tuner_config: ResourceBasedTunerConfig
"""Options for the tuner that will be used to adjust the number of slots. When used with a
:py:class:`CompositeTuner`, all resource-based slot suppliers must use the same tuner options."""
:py:class:`_CompositeTuner`, all resource-based slot suppliers must use the same tuner options."""


class SlotPermit:
Expand Down
14 changes: 7 additions & 7 deletions temporalio/worker/_worker.py
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ def __init__(
:py:func:`@activity.defn<temporalio.activity.defn>`. Activities
may be async functions or non-async functions.
nexus_service_handlers: Instances of Nexus service handler classes
decorated with :py:func:`@nexusrpc.handler.service_handler`.
decorated with :py:func:`@nexusrpc.handler.service_handler<nexusrpc.handler.service_handler>`.

.. warning::
This parameter is experimental and unstable.
Expand All @@ -187,7 +187,7 @@ def __init__(
the worker is shut down.
nexus_task_executor: Executor to use for non-async
Nexus operations. This is required if any operation start methods
are non-`async def`. :py:class:`concurrent.futures.ThreadPoolExecutor`
are non-``async def``. :py:class:`concurrent.futures.ThreadPoolExecutor`
is recommended.

.. warning::
Expand Down Expand Up @@ -298,23 +298,23 @@ def __init__(
on_fatal_error: An async function that can handle a failure before
the worker shutdown commences. This cannot stop the shutdown and
any exception raised is logged and ignored.
use_worker_versioning: If true, the `build_id` argument must be
use_worker_versioning: If true, the ``build_id`` argument must be
specified, and this worker opts into the worker versioning
feature. This ensures it only receives workflow tasks for
workflows which it claims to be compatible with. For more
information, see
https://docs.temporal.io/workers#worker-versioning.
Exclusive with `deployment_config`.
WARNING: Deprecated. Use `deployment_config` instead.
Exclusive with ``deployment_config``.
WARNING: Deprecated. Use ``deployment_config`` instead.
disable_safe_workflow_eviction: If true, instead of letting the
workflow collect its tasks properly, the worker will simply let
the Python garbage collector collect the tasks. WARNING: Users
should not set this value to true. The garbage collector will
throw ``GeneratorExit`` in coroutines causing them to wake up
in different threads and run ``finally`` and other code in the
wrong workflow environment.
deployment_config: Deployment config for the worker. Exclusive with `build_id` and
`use_worker_versioning`.
deployment_config: Deployment config for the worker. Exclusive with ``build_id`` and
``use_worker_versioning``.
WARNING: This is an experimental feature and may change in the future.
workflow_task_poller_behavior: Specify the behavior of workflow task polling.
Defaults to a 5-poller maximum.
Expand Down
2 changes: 1 addition & 1 deletion temporalio/worker/_workflow.py
Original file line number Diff line number Diff line change
Expand Up @@ -626,7 +626,7 @@ class _DeadlockError(Exception):
"""Exception class for deadlocks. Contains functionality to swap the default traceback for another."""

def __init__(self, message: str, replacement_tb: Optional[TracebackType] = None):
"""Create a new DeadlockError, with message `message` and optionally a traceback `replacement_tb` to be swapped in later.
"""Create a new DeadlockError, with message ``message`` and optionally a traceback ``replacement_tb`` to be swapped in later.

Args:
message: Message to be presented through exception.
Expand Down
1 change: 0 additions & 1 deletion temporalio/worker/workflow_sandbox/_importer.py
Original file line number Diff line number Diff line change
Expand Up @@ -339,7 +339,6 @@ def _maybe_passthrough_module(self, name: str) -> Optional[types.ModuleType]:
def _maybe_restrict_module(
self, mod: types.ModuleType
) -> Optional[types.ModuleType]:
"""Implements :py:meth:`_Environment.maybe_restrict_module`."""
matcher = self.restrictions.invalid_module_members.child_matcher(
*mod.__name__.split(".")
)
Expand Down
4 changes: 2 additions & 2 deletions temporalio/worker/workflow_sandbox/_restrictions.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ def default_message(qualified_name: str) -> str:

class UnintentionalPassthroughError(temporalio.exceptions.TemporalError):
"""Error that occurs when a workflow unintentionally passes an import to the sandbox when
the import notification policy includes :py:attr:`temporalio.workflow.SandboxImportNotificationPolicy.RAISE_ON_NON_PASSTHROUGH`.
the import notification policy includes :py:attr:`temporalio.workflow.SandboxImportNotificationPolicy.RAISE_ON_UNINTENTIONAL_PASSTHROUGH`.

Attributes:
qualified_name: Fully qualified name of what was passed through to the sandbox.
Expand Down Expand Up @@ -196,7 +196,7 @@ def with_passthrough_all_modules(self) -> SandboxRestrictions:
def with_import_notification_policy(
self, policy: temporalio.workflow.SandboxImportNotificationPolicy
) -> SandboxRestrictions:
"""Create a new restriction set with the given import notification policy as the :py:attr:`import_policy`."""
"""Create a new restriction set with the given import notification policy as the :py:attr:`import_notification_policy`."""
return dataclasses.replace(self, import_notification_policy=policy)


Expand Down
4 changes: 2 additions & 2 deletions temporalio/workflow.py
Original file line number Diff line number Diff line change
Expand Up @@ -4355,7 +4355,7 @@ async def start_child_workflow(
static_details: General fixed details for this child workflow execution that may appear in
UI/CLI. This can be in Temporal markdown format and can span multiple lines. This is
a fixed value on the workflow that cannot be updated. For details that can be
updated, use :py:meth:`Workflow.get_current_details` within the workflow.
updated, use :py:meth:`get_current_details` within the workflow.
priority: Priority to use for this workflow.

Returns:
Expand Down Expand Up @@ -5300,7 +5300,7 @@ class NexusOperationCancellationType(IntEnum):
Pass one of these values to :py:meth:`NexusClient.start_operation` to define cancellation
behavior.

To initiate cancellation, use :py:meth:`NexusOperationHandle.cancel` and then `await` the
To initiate cancellation, use :py:meth:`NexusOperationHandle.cancel` and then ``await`` the
operation handle. This will result in a :py:class:`exceptions.NexusOperationError`. The values
of this enum define what is guaranteed to have happened by that point.
"""
Expand Down
Loading