Skip to content

Commit 13f9af5

Browse files
committed
More docs and incorporate pydocstyle into CI/lint check
1 parent 0fe8cfd commit 13f9af5

File tree

9 files changed

+143
-74
lines changed

9 files changed

+143
-74
lines changed

pyproject.toml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ build-bridge = "python scripts/build-bridge.py"
3737
format = [{cmd = "black ."}, {cmd = "isort ."}]
3838
gen-docs = "sphinx-build docs docs/_build"
3939
gen-protos = "python scripts/gen-protos.py"
40-
lint = [{cmd = "black --check ."}, {cmd = "isort --check-only ."}, "lint-types"] # TODO(cretz): Add lint-docs
40+
lint = [{cmd = "black --check ."}, {cmd = "isort --check-only ."}, "lint-types", "lint-docs"]
4141
lint-docs = "pydocstyle"
4242
lint-types = "mypy ."
4343
test = "pytest"
@@ -61,6 +61,11 @@ exclude = [
6161
convention = "google"
6262
# https://github.com/PyCQA/pydocstyle/issues/363#issuecomment-625563088
6363
match_dir = "^(?!(docs|scripts|tests|api|proto|\\.)).*"
64+
add_ignore = [
65+
# We like to wrap at a certain number of chars, even long summary sentences.
66+
# https://github.com/PyCQA/pydocstyle/issues/184
67+
"D205", "D415"
68+
]
6469

6570
[build-system]
6671
build-backend = "poetry.core.masonry.api"

temporalio/bridge/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
"""Python interface to SDK Core."""

temporalio/bridge/client.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
"""RPC client using SDK Core."""
2+
13
from __future__ import annotations
24

35
from dataclasses import dataclass
@@ -10,6 +12,8 @@
1012

1113
@dataclass
1214
class ClientTlsConfig:
15+
"""Python representation of the Rust struct for configuring TLS."""
16+
1317
server_root_ca_cert: Optional[bytes]
1418
domain: Optional[str]
1519
client_cert: Optional[bytes]
@@ -18,6 +22,8 @@ class ClientTlsConfig:
1822

1923
@dataclass
2024
class ClientRetryConfig:
25+
"""Python representation of the Rust struct for configuring retry."""
26+
2127
initial_interval_millis: int
2228
randomization_factor: float
2329
multiplier: float
@@ -28,6 +34,8 @@ class ClientRetryConfig:
2834

2935
@dataclass
3036
class ClientOptions:
37+
"""Python representation of the Rust struct for configuring the client."""
38+
3139
target_url: str
3240
static_headers: Mapping[str, str]
3341
identity: str
@@ -43,13 +51,17 @@ class ClientOptions:
4351

4452

4553
class Client:
54+
"""RPC client using SDK Core."""
55+
4656
@staticmethod
4757
async def connect(opts: ClientOptions) -> Client:
58+
"""Establish connection with server."""
4859
return Client(await temporal_sdk_bridge.connect_client(opts))
4960

5061
_ref: temporal_sdk_bridge.ClientRef
5162

5263
def __init__(self, ref: temporal_sdk_bridge.ClientRef):
64+
"""Initialize client with underlying SDK Core reference."""
5365
self._ref = ref
5466

5567
async def rpc_call(
@@ -60,6 +72,7 @@ async def rpc_call(
6072
*,
6173
retry: bool = False,
6274
) -> ProtoMessage:
75+
"""Make RPC call using SDK Core."""
6376
resp = resp_type()
6477
resp.ParseFromString(await self._ref.call(rpc, retry, req.SerializeToString()))
6578
return resp

temporalio/client.py

Lines changed: 40 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ async def connect(
5555
Union[Interceptor, Callable[[OutboundInterceptor], OutboundInterceptor]]
5656
] = [],
5757
default_workflow_query_reject_condition: Optional[
58-
temporalio.common.WorkflowQueryRejectCondition
58+
temporalio.common.QueryRejectCondition
5959
] = None,
6060
tls_config: Optional[TLSConfig] = None,
6161
retry_config: Optional[RetryConfig] = None,
@@ -105,14 +105,6 @@ async def connect(
105105
data_converter=data_converter,
106106
interceptors=interceptors,
107107
default_workflow_query_reject_condition=default_workflow_query_reject_condition,
108-
connect_options=ConnectOptions(
109-
target_url=connect_options.target_url,
110-
tls_config=connect_options.tls_config,
111-
retry_config=connect_options.retry_config,
112-
static_headers=connect_options.static_headers,
113-
identity=connect_options.identity,
114-
worker_binary_id=connect_options.worker_binary_id,
115-
),
116108
)
117109

118110
def __init__(
@@ -125,16 +117,12 @@ def __init__(
125117
Union[Interceptor, Callable[[OutboundInterceptor], OutboundInterceptor]]
126118
] = [],
127119
default_workflow_query_reject_condition: Optional[
128-
temporalio.common.WorkflowQueryRejectCondition
120+
temporalio.common.QueryRejectCondition
129121
] = None,
130-
connect_options: Optional[ConnectOptions] = None,
131122
):
132123
"""Create a Temporal client from a workflow service.
133124
134125
See :py:meth:`connect` for details on the parameters.
135-
136-
Note, connect_options in this initializer are only for tracking and are
137-
not used by this class in any way.
138126
"""
139127
# Iterate over interceptors in reverse building the impl
140128
self._impl: OutboundInterceptor = _ClientImpl(self)
@@ -153,18 +141,14 @@ def __init__(
153141
data_converter=data_converter,
154142
interceptors=interceptors,
155143
default_workflow_query_reject_condition=default_workflow_query_reject_condition,
156-
connect_options=connect_options,
157144
)
158145

159146
def options(self) -> ClientOptions:
160147
"""Options used to create this client as a dictionary.
161148
162149
This makes a shallow copy of the options each call.
163150
"""
164-
options = self._options.copy()
165-
if options["connect_options"]:
166-
options["connect_options"] = options["connect_options"].copy()
167-
return options
151+
return self._options.copy()
168152

169153
@property
170154
def service(self) -> temporalio.workflow_service.WorkflowService:
@@ -311,6 +295,9 @@ def get_workflow_handle(
311295
run_id: Run ID that will be used for all calls.
312296
first_execution_run_id: First execution run ID used for cancellation
313297
and termination.
298+
299+
Returns:
300+
The workflow handle.
314301
"""
315302
return WorkflowHandle(
316303
self,
@@ -321,17 +308,6 @@ def get_workflow_handle(
321308
)
322309

323310

324-
class ConnectOptions(typing_extensions.TypedDict):
325-
"""TypedDict of options originally passed to :py:class:`Client`."""
326-
327-
target_url: str
328-
tls_config: Optional[TLSConfig]
329-
retry_config: Optional[RetryConfig]
330-
static_headers: Mapping[str, str]
331-
identity: str
332-
worker_binary_id: str
333-
334-
335311
class ClientOptions(typing_extensions.TypedDict):
336312
"""TypedDict of options originally passed to :py:meth:`Client`."""
337313

@@ -342,9 +318,8 @@ class ClientOptions(typing_extensions.TypedDict):
342318
Union[Interceptor, Callable[[OutboundInterceptor], OutboundInterceptor]]
343319
]
344320
default_workflow_query_reject_condition: Optional[
345-
temporalio.common.WorkflowQueryRejectCondition
321+
temporalio.common.QueryRejectCondition
346322
]
347-
connect_options: Optional[ConnectOptions]
348323

349324

350325
T = TypeVar("T")
@@ -571,21 +546,21 @@ async def cancel(self) -> None:
571546

572547
async def describe(
573548
self,
574-
) -> "WorkflowDescription":
549+
) -> WorkflowDescription:
575550
"""Get workflow details.
576551
577552
This will get details for :py:attr:`run_id` if present. To use a
578553
different run ID, create a new handle with via
579554
:py:meth:`Client.get_workflow_handle`.
580555
581-
Returns:
582-
Workflow details.
583-
584556
.. warning::
585557
Handles created as a result of :py:meth:`Client.start_workflow` will
586558
describe the latest workflow with the same workflow ID even if it is
587559
unrelated to the started workflow.
588560
561+
Returns:
562+
Workflow details.
563+
589564
Raises:
590565
RPCError: Workflow details could not be fetched.
591566
"""
@@ -606,12 +581,19 @@ async def query(
606581
self,
607582
query: str,
608583
*args: Any,
609-
reject_condition: Optional[
610-
temporalio.common.WorkflowQueryRejectCondition
611-
] = None,
584+
reject_condition: Optional[temporalio.common.QueryRejectCondition] = None,
612585
) -> Any:
613586
"""Query the workflow.
614587
588+
This will query for :py:attr:`run_id` if present. To use a different
589+
run ID, create a new handle with via
590+
:py:meth:`Client.get_workflow_handle`.
591+
592+
.. warning::
593+
Handles created as a result of :py:meth:`Client.start_workflow` will
594+
query the latest workflow with the same workflow ID even if it is
595+
unrelated to the started workflow.
596+
615597
Args:
616598
query: Query name on the workflow.
617599
args: Query arguments.
@@ -624,15 +606,6 @@ async def query(
624606
Raises:
625607
WorkflowQueryRejectedError: A query reject condition was satisfied.
626608
RPCError: Workflow details could not be fetched.
627-
628-
This will query for :py:attr:`run_id` if present. To use a different
629-
run ID, create a new handle with via
630-
:py:meth:`Client.get_workflow_handle`.
631-
632-
.. warning::
633-
Handles created as a result of :py:meth:`Client.start_workflow` will
634-
query the latest workflow with the same workflow ID even if it is
635-
unrelated to the started workflow.
636609
"""
637610
return await self._client._impl.query_workflow(
638611
QueryWorkflowInput(
@@ -648,6 +621,15 @@ async def query(
648621
async def signal(self, name: str, *args: Any) -> None:
649622
"""Send a signal to the workflow.
650623
624+
This will signal for :py:attr:`run_id` if present. To use a different
625+
run ID, create a new handle with via
626+
:py:meth:`Client.get_workflow_handle`.
627+
628+
.. warning::
629+
Handles created as a result of :py:meth:`Client.start_workflow` will
630+
signal the latest workflow with the same workflow ID even if it is
631+
unrelated to the started workflow.
632+
651633
Args:
652634
name: Signal name on the workflow.
653635
args: Signal arguments.
@@ -657,15 +639,6 @@ async def signal(self, name: str, *args: Any) -> None:
657639
658640
Raises:
659641
RPCError: Workflow could not be signalled.
660-
661-
This will signal for :py:attr:`run_id` if present. To use a different
662-
run ID, create a new handle with via
663-
:py:meth:`Client.get_workflow_handle`.
664-
665-
.. warning::
666-
Handles created as a result of :py:meth:`Client.start_workflow` will
667-
signal the latest workflow with the same workflow ID even if it is
668-
unrelated to the started workflow.
669642
"""
670643
await self._client._impl.signal_workflow(
671644
SignalWorkflowInput(
@@ -683,13 +656,6 @@ async def terminate(
683656
) -> None:
684657
"""Terminate the workflow.
685658
686-
Args:
687-
args: Details to store on the termination.
688-
reason: Reason for the termination.
689-
690-
Raises:
691-
RPCError: Workflow could not be terminated.
692-
693659
This will issue a termination for :py:attr:`run_id` if present. This
694660
call will make sure to use the run chain starting from
695661
:py:attr:`first_execution_run_id` if present. To create handles with
@@ -699,6 +665,13 @@ async def terminate(
699665
Handles created as a result of :py:meth:`Client.start_workflow` with
700666
a start signal will terminate the latest workflow with the same
701667
workflow ID even if it is unrelated to the started workflow.
668+
669+
Args:
670+
args: Details to store on the termination.
671+
reason: Reason for the termination.
672+
673+
Raises:
674+
RPCError: Workflow could not be terminated.
702675
"""
703676
await self._client._impl.terminate_workflow(
704677
TerminateWorkflowInput(
@@ -718,6 +691,7 @@ def __init__(
718691
self,
719692
raw_message: temporalio.api.workflowservice.v1.DescribeWorkflowExecutionResponse,
720693
):
694+
"""Create a workflow description from a describe response."""
721695
self._raw_message = raw_message
722696
status = raw_message.workflow_execution_info.status
723697
self._status = WorkflowExecutionStatus(status) if status else None
@@ -801,6 +775,7 @@ def __init__(self, new_execution_run_id: str) -> None:
801775

802776
@property
803777
def new_execution_run_id(self) -> str:
778+
"""New execution run ID the workflow continued to"""
804779
return self._new_execution_run_id
805780

806781

@@ -856,7 +831,7 @@ class QueryWorkflowInput:
856831
run_id: Optional[str]
857832
query: str
858833
args: Iterable[Any]
859-
reject_condition: Optional[temporalio.common.WorkflowQueryRejectCondition]
834+
reject_condition: Optional[temporalio.common.QueryRejectCondition]
860835

861836

862837
@dataclass

temporalio/common.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ class RetryPolicy:
3636
"""List of error types that are not retryable."""
3737

3838
def apply_to_proto(self, proto: temporalio.api.common.v1.RetryPolicy) -> None:
39+
"""Apply the fields in this policy to the given proto object."""
3940
proto.initial_interval.FromTimedelta(self.initial_interval)
4041
proto.backoff_coefficient = self.backoff_coefficient
4142
proto.maximum_interval.FromTimedelta(
@@ -68,7 +69,7 @@ class WorkflowIDReusePolicy(IntEnum):
6869
"""See :py:attr:`temporalio.api.enums.v1.WorkflowIdReusePolicy.WORKFLOW_ID_REUSE_POLICY_REJECT_DUPLICATE`."""
6970

7071

71-
class WorkflowQueryRejectCondition(IntEnum):
72+
class QueryRejectCondition(IntEnum):
7273
"""Whether a query should be rejected in certain conditions.
7374
7475
See :py:class:`temporalio.api.enums.v1.QueryRejectCondition`.

temporalio/converter.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -421,6 +421,9 @@ def default() -> CompositeDataConverter:
421421
async def decode_payloads(
422422
payloads: Optional[temporalio.api.common.v1.Payloads], converter: DataConverter
423423
) -> List[Any]:
424+
"""Decode :py:class:`temporalio.api.common.v1.Payloads` with the given
425+
converter.
426+
"""
424427
if not payloads or not payloads.payloads:
425428
return []
426429
return await converter.decode(payloads.payloads)

0 commit comments

Comments
 (0)