From 23892f37f1dab660c65e03bf6571bc7dec5503b2 Mon Sep 17 00:00:00 2001 From: Dan Davison Date: Mon, 17 Feb 2025 23:10:32 -0500 Subject: [PATCH 01/16] Manual lint fixes --- pyproject.toml | 12 +++++++----- temporalio/api/cloud/cloudservice/v1/__init__.py | 4 ++-- temporalio/api/operatorservice/v1/__init__.py | 4 ++-- temporalio/api/testservice/v1/__init__.py | 4 ++-- temporalio/api/workflowservice/v1/__init__.py | 4 ++-- temporalio/common.py | 2 +- temporalio/converter.py | 2 +- temporalio/runtime.py | 2 +- temporalio/testing/_workflow.py | 12 ++++++------ temporalio/worker/_activity.py | 4 ++-- temporalio/worker/_replayer.py | 2 +- temporalio/worker/_worker.py | 4 ++-- temporalio/worker/workflow_sandbox/_restrictions.py | 3 ++- temporalio/workflow.py | 6 +++--- tests/conftest.py | 8 ++++---- tests/test_client.py | 2 +- tests/testing/test_activity.py | 4 ++-- tests/worker/test_activity.py | 2 +- tests/worker/test_workflow.py | 6 ++---- tests/worker/workflow_sandbox/test_runner.py | 6 +++--- 20 files changed, 47 insertions(+), 46 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index d29dc2df..71991f79 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -54,11 +54,11 @@ dev = [ [tool.poe.tasks] build-develop = "uv run maturin develop --uv" build-develop-with-release = { cmd = "uv run maturin develop --release --uv" } -format = [{cmd = "uv run ruff check --select I --fix"}, {cmd = "uv run ruff format"}, ] +format = [{cmd = "uv run ruff check --fix"}, {cmd = "uv run ruff format"}, ] gen-docs = "uv run python scripts/gen_docs.py" gen-protos = "uv run python scripts/gen_protos.py" lint = [ - {cmd = "uv run ruff check --select I"}, + {cmd = "uv run ruff check"}, {cmd = "uv run ruff format --check"}, {ref = "lint-types"}, {cmd = "uv run pyright"}, @@ -72,6 +72,11 @@ lint-types = "uv run mypy --namespace-packages --check-untyped-defs ." run-bench = "uv run python scripts/run_bench.py" test = "uv run pytest" +[tool.ruff] +target-version = "py39" +exclude = ["*_pb2.py"] +lint.ignore = ["E741"] + [tool.pytest.ini_options] asyncio_mode = "auto" @@ -183,9 +188,6 @@ exclude = [ "temporalio/bridge/testing.py", ] -[tool.ruff] -target-version = "py39" - [build-system] requires = ["maturin>=1.0,<2.0"] build-backend = "maturin" diff --git a/temporalio/api/cloud/cloudservice/v1/__init__.py b/temporalio/api/cloud/cloudservice/v1/__init__.py index 4ae8e6aa..c0cd0e87 100644 --- a/temporalio/api/cloud/cloudservice/v1/__init__.py +++ b/temporalio/api/cloud/cloudservice/v1/__init__.py @@ -194,9 +194,9 @@ # gRPC is optional try: - import grpc + import grpc # noqa # type: ignore - from .service_pb2_grpc import ( + from .service_pb2_grpc import ( # noqa: F401 CloudServiceServicer, CloudServiceStub, add_CloudServiceServicer_to_server, diff --git a/temporalio/api/operatorservice/v1/__init__.py b/temporalio/api/operatorservice/v1/__init__.py index f6cd76fb..3758d3e8 100644 --- a/temporalio/api/operatorservice/v1/__init__.py +++ b/temporalio/api/operatorservice/v1/__init__.py @@ -56,9 +56,9 @@ # gRPC is optional try: - import grpc + import grpc # noqa # type: ignore - from .service_pb2_grpc import ( + from .service_pb2_grpc import ( # noqa: F401 OperatorServiceServicer, OperatorServiceStub, add_OperatorServiceServicer_to_server, diff --git a/temporalio/api/testservice/v1/__init__.py b/temporalio/api/testservice/v1/__init__.py index 8539030d..65d3c035 100644 --- a/temporalio/api/testservice/v1/__init__.py +++ b/temporalio/api/testservice/v1/__init__.py @@ -22,9 +22,9 @@ # gRPC is optional try: - import grpc + import grpc # noqa # type: ignore - from .service_pb2_grpc import ( + from .service_pb2_grpc import ( # noqa: F401 TestServiceServicer, TestServiceStub, add_TestServiceServicer_to_server, diff --git a/temporalio/api/workflowservice/v1/__init__.py b/temporalio/api/workflowservice/v1/__init__.py index b5e22d32..cbfb4990 100644 --- a/temporalio/api/workflowservice/v1/__init__.py +++ b/temporalio/api/workflowservice/v1/__init__.py @@ -278,9 +278,9 @@ # gRPC is optional try: - import grpc + import grpc # noqa # type: ignore - from .service_pb2_grpc import ( + from .service_pb2_grpc import ( # noqa: F401 WorkflowServiceServicer, WorkflowServiceStub, add_WorkflowServiceServicer_to_server, diff --git a/temporalio/common.py b/temporalio/common.py index e073aaec..10c17a29 100644 --- a/temporalio/common.py +++ b/temporalio/common.py @@ -30,7 +30,7 @@ ) import google.protobuf.internal.containers -from typing_extensions import ClassVar, NamedTuple, Self, TypeAlias, get_origin +from typing_extensions import NamedTuple, Self, TypeAlias, get_origin import temporalio.api.common.v1 import temporalio.api.enums.v1 diff --git a/temporalio/converter.py b/temporalio/converter.py index 37e7641d..ad152d8b 100644 --- a/temporalio/converter.py +++ b/temporalio/converter.py @@ -926,7 +926,7 @@ def from_failure( stack_trace = encoded_attributes.get("stack_trace") if isinstance(stack_trace, str): failure.stack_trace = stack_trace - except: + except Exception: pass err: temporalio.exceptions.FailureError diff --git a/temporalio/runtime.py b/temporalio/runtime.py index fe6a26ca..c11cb009 100644 --- a/temporalio/runtime.py +++ b/temporalio/runtime.py @@ -207,7 +207,7 @@ def _on_logs( # just in case) try: message += f" {log.fields}" - except: + except Exception: pass record = self.logger.makeRecord( name, diff --git a/temporalio/testing/_workflow.py b/temporalio/testing/_workflow.py index d6992a06..1589179f 100644 --- a/temporalio/testing/_workflow.py +++ b/temporalio/testing/_workflow.py @@ -215,10 +215,10 @@ async def start_local( ), server, ) - except: + except Exception: try: await server.shutdown() - except: + except Exception: logger.warn( "Failed stopping local server on client connection failure", exc_info=True, @@ -326,10 +326,10 @@ async def start_time_skipping( ), server, ) - except: + except Exception: try: await server.shutdown() - except: + except Exception: logger.warn( "Failed stopping test server on client connection failure", exc_info=True, @@ -474,13 +474,13 @@ async def time_skipping_unlocked(self) -> AsyncIterator[None]: await self.client.test_service.lock_time_skipping( temporalio.api.testservice.v1.LockTimeSkippingRequest() ) - except: + except Exception: # Lock it back, swallowing error try: await self.client.test_service.lock_time_skipping( temporalio.api.testservice.v1.LockTimeSkippingRequest() ) - except: + except Exception: logger.exception("Failed locking time skipping after error") raise diff --git a/temporalio/worker/_activity.py b/temporalio/worker/_activity.py index 9c4889c9..e32f486e 100644 --- a/temporalio/worker/_activity.py +++ b/temporalio/worker/_activity.py @@ -518,7 +518,7 @@ async def _run_activity( if running_activity.last_heartbeat_task: try: await running_activity.last_heartbeat_task - except: + except Exception: # Should never happen because it's trapped in-task temporalio.activity.logger.exception( "Final heartbeat task didn't trap error" @@ -750,7 +750,7 @@ def _execute_sync_activity( if isinstance(heartbeat, SharedHeartbeatSender): # To make mypy happy heartbeat_sender = heartbeat - heartbeat_fn = lambda *details: heartbeat_sender.send_heartbeat( + heartbeat_fn = lambda *details: heartbeat_sender.send_heartbeat( # noqa: E731 info.task_token, *details ) else: diff --git a/temporalio/worker/_replayer.py b/temporalio/worker/_replayer.py index 05f65cbd..f3f7d6f2 100644 --- a/temporalio/worker/_replayer.py +++ b/temporalio/worker/_replayer.py @@ -156,7 +156,7 @@ async def workflow_replay_iterator( replayed. """ try: - last_replay_failure: Optional[Exception] + last_replay_failure: Optional[Exception] = None last_replay_complete = asyncio.Event() # Create eviction hook diff --git a/temporalio/worker/_worker.py b/temporalio/worker/_worker.py index 4c34a950..9baf64ef 100644 --- a/temporalio/worker/_worker.py +++ b/temporalio/worker/_worker.py @@ -504,7 +504,7 @@ async def raise_on_shutdown(): if self._config["on_fatal_error"]: try: await self._config["on_fatal_error"](exception) - except: + except Exception: logger.warning("Fatal error handler failed") except asyncio.CancelledError as user_cancel_err: @@ -560,7 +560,7 @@ async def raise_on_shutdown(): # Do final shutdown try: await self._bridge_worker.finalize_shutdown() - except: + except Exception: # Ignore errors here that can arise in some tests where the bridge # worker still has a reference pass diff --git a/temporalio/worker/workflow_sandbox/_restrictions.py b/temporalio/worker/workflow_sandbox/_restrictions.py index fdc12680..c1217469 100644 --- a/temporalio/worker/workflow_sandbox/_restrictions.py +++ b/temporalio/worker/workflow_sandbox/_restrictions.py @@ -933,7 +933,8 @@ def __init__( def bind_f(instance: _RestrictedProxy, obj: Any) -> Callable: def i_op(self: Any, other: Any) -> _RestrictedProxy: - f(self, other) # type: ignore + # TODO: wat + f(self, other) # type: ignore # noqa: F821 return instance return i_op.__get__(obj, type(obj)) # type: ignore diff --git a/temporalio/workflow.py b/temporalio/workflow.py index 0a298a03..8c7e62b7 100644 --- a/temporalio/workflow.py +++ b/temporalio/workflow.py @@ -1660,8 +1660,8 @@ def _assert_dynamic_handler_args( if ( not arg_types or len(arg_types) != 2 - or arg_types[0] != str - or arg_types[1] != Sequence[temporalio.common.RawValue] + or arg_types[0] is not str + or arg_types[1] is not Sequence[temporalio.common.RawValue] ): raise RuntimeError( "Dynamic handler must have 3 arguments: self, str, and Sequence[temporalio.common.RawValue]" @@ -4273,7 +4273,7 @@ class ContinueAsNewError(BaseException): def __init__(self, *args: object) -> None: """Direct instantiation is disabled. Use :py:func:`continue_as_new`.""" - if type(self) == ContinueAsNewError: + if type(self) is ContinueAsNewError: raise RuntimeError("Cannot instantiate ContinueAsNewError directly") super().__init__(*args) diff --git a/tests/conftest.py b/tests/conftest.py index 1c8bbf9d..426a2aa5 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -25,6 +25,10 @@ # Unless specifically overridden, we expect tests to run under protobuf 4.x/5.x lib import google.protobuf +from temporalio.client import Client +from temporalio.testing import WorkflowEnvironment +from tests.helpers.worker import ExternalPythonWorker, ExternalWorker + protobuf_version = google.protobuf.__version__ if os.getenv("TEMPORAL_TEST_PROTO3"): assert protobuf_version.startswith( @@ -35,10 +39,6 @@ "5." ), f"Expected protobuf 4.x/5.x, got {protobuf_version}" -from temporalio.client import Client -from temporalio.testing import WorkflowEnvironment -from tests.helpers.worker import ExternalPythonWorker, ExternalWorker - def pytest_addoption(parser): parser.addoption( diff --git a/tests/test_client.py b/tests/test_client.py index 43ec631a..49a32ba1 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -381,7 +381,7 @@ async def test_query(client: Client, worker: ExternalWorker): await handle.result() assert "some query arg" == await handle.query("some query", "some query arg") # Try a query not on the workflow - with pytest.raises(WorkflowQueryFailedError) as err: + with pytest.raises(WorkflowQueryFailedError): await handle.query("does not exist") diff --git a/tests/testing/test_activity.py b/tests/testing/test_activity.py index 29b66c77..9c53386c 100644 --- a/tests/testing/test_activity.py +++ b/tests/testing/test_activity.py @@ -68,7 +68,7 @@ def via_thread(): while not activity.is_cancelled(): time.sleep(0.2) time.sleep(0.2) - except: + except Exception: raise RuntimeError("Unexpected") except CancelledError: nonlocal properly_cancelled @@ -108,5 +108,5 @@ async def assert_equals(a: str, b: str) -> None: except Exception as err: actual_err = err - assert type(expected_err) == type(actual_err) + assert type(expected_err) is type(actual_err) assert str(expected_err) == str(actual_err) diff --git a/tests/worker/test_activity.py b/tests/worker/test_activity.py index b17a0650..b6037432 100644 --- a/tests/worker/test_activity.py +++ b/tests/worker/test_activity.py @@ -589,7 +589,7 @@ class SomeClass2: async def test_activity_type_hints(client: Client, worker: ExternalWorker): - activity_param1: SomeClass2 + activity_param1: Optional[SomeClass2] = None @activity.defn async def some_activity(param1: SomeClass2, param2: str) -> str: diff --git a/tests/worker/test_workflow.py b/tests/worker/test_workflow.py index 665a5393..d5b32afb 100644 --- a/tests/worker/test_workflow.py +++ b/tests/worker/test_workflow.py @@ -52,8 +52,6 @@ from temporalio.bridge.proto.workflow_completion import WorkflowActivationCompletion from temporalio.client import ( Client, - RPCError, - RPCStatusCode, WorkflowExecutionStatus, WorkflowFailureError, WorkflowHandle, @@ -2184,7 +2182,7 @@ async def status() -> str: # Send stack trace query trace = await handle.query("__enhanced_stack_trace") - assert type(trace) == EnhancedStackTrace + assert type(trace) is EnhancedStackTrace assert "never_completing_coroutine" in [ loc.function_name for stack in trace.stacks for loc in stack.locations @@ -2225,7 +2223,7 @@ async def status() -> str: # test that a coroutine only has the source as its stack - assert type(trace) == EnhancedStackTrace + assert type(trace) is EnhancedStackTrace assert "never_completing_coroutine" in [ loc.function_name for stack in trace.stacks for loc in stack.locations diff --git a/tests/worker/workflow_sandbox/test_runner.py b/tests/worker/workflow_sandbox/test_runner.py index 14b2c94c..cf831149 100644 --- a/tests/worker/workflow_sandbox/test_runner.py +++ b/tests/worker/workflow_sandbox/test_runner.py @@ -7,6 +7,9 @@ import os import time import uuid + +# This used to fail because our __init__ couldn't handle metaclass init +import zipfile from dataclasses import dataclass from datetime import date, datetime, timedelta from enum import IntEnum @@ -33,9 +36,6 @@ # runtime only _ = os.name -# This used to fail because our __init__ couldn't handle metaclass init -import zipfile - class MyZipFile(zipfile.ZipFile): pass From ccd473bc544f89b22f2761a4a84d139ae83e96e1 Mon Sep 17 00:00:00 2001 From: Dan Davison Date: Mon, 17 Feb 2025 23:12:23 -0500 Subject: [PATCH 02/16] ignore pb2 grpc --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 71991f79..1106e34f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -74,7 +74,7 @@ test = "uv run pytest" [tool.ruff] target-version = "py39" -exclude = ["*_pb2.py"] +exclude = ["*_pb2.py", "*_pb2_grpc.py"] lint.ignore = ["E741"] From 3905905dbb2b50bb4fcb8dbd47a7f89b3ebd6b52 Mon Sep 17 00:00:00 2001 From: Dan Davison Date: Mon, 17 Feb 2025 23:15:47 -0500 Subject: [PATCH 03/16] tweak --- pyproject.toml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 1106e34f..25cb67f8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -60,15 +60,16 @@ gen-protos = "uv run python scripts/gen_protos.py" lint = [ {cmd = "uv run ruff check"}, {cmd = "uv run ruff format --check"}, - {ref = "lint-types"}, - {cmd = "uv run pyright"}, + {ref = "lint-types-mypy"}, + {ref = "lint-types-pyright"}, {ref = "lint-docs"}, ] bridge-lint = { cmd = "cargo clippy -- -D warnings", cwd = "temporalio/bridge" } # TODO(cretz): Why does pydocstyle complain about @overload missing docs after # https://github.com/PyCQA/pydocstyle/pull/511? lint-docs = "uv run pydocstyle --ignore-decorators=overload" -lint-types = "uv run mypy --namespace-packages --check-untyped-defs ." +lint-types-mypy = "uv run mypy --namespace-packages --check-untyped-defs ." +lint-types-pyright = "uv run pyright" run-bench = "uv run python scripts/run_bench.py" test = "uv run pytest" From 602844375ed8f8cf28101b8f2fe5e0915115c7a9 Mon Sep 17 00:00:00 2001 From: Dan Davison Date: Mon, 17 Feb 2025 23:18:00 -0500 Subject: [PATCH 04/16] uv run ruff check --fix --- scripts/gen_protos.py | 10 +++++----- temporalio/activity.py | 2 +- temporalio/bridge/client.py | 1 - temporalio/bridge/worker.py | 1 - temporalio/worker/_worker.py | 2 +- tests/conftest.py | 2 -- tests/test_converter.py | 1 - tests/worker/workflow_sandbox/test_importer.py | 2 +- 8 files changed, 8 insertions(+), 13 deletions(-) diff --git a/scripts/gen_protos.py b/scripts/gen_protos.py index 61d2709f..6928dead 100644 --- a/scripts/gen_protos.py +++ b/scripts/gen_protos.py @@ -6,7 +6,7 @@ import tempfile from functools import partial from pathlib import Path -from typing import List, Mapping, Optional +from typing import List, Mapping base_dir = Path(__file__).parent.parent proto_dir = ( @@ -25,8 +25,8 @@ v for v in proto_dir.glob("**/*.proto") if not str(v).startswith(str(testsrv_proto_dir / "dependencies")) - and not "health" in str(v) - and not "google" in str(v) + and "health" not in str(v) + and "google" not in str(v) ] proto_paths.extend(test_proto_dir.glob("**/*.proto")) proto_paths.extend(additional_proto_dir.glob("**/*.proto")) @@ -95,7 +95,7 @@ def fix_generated_output(base_path: Path): message_names = sorted(message_names) if message_names: f.write( - f'\n__all__ = [\n "' + '",\n "'.join(message_names) + '",\n]\n' + '\n__all__ = [\n "' + '",\n "'.join(message_names) + '",\n]\n' ) # gRPC imports if "service_pb2_grpc" in imports: @@ -115,7 +115,7 @@ def fix_generated_output(base_path: Path): message_names.append(message) # __all__ message_names = sorted(message_names) - f.write(f' __all__.extend(["' + '", "'.join(message_names) + '"])\n') + f.write(' __all__.extend(["' + '", "'.join(message_names) + '"])\n') f.write("except ImportError:\n pass") diff --git a/temporalio/activity.py b/temporalio/activity.py index 281cfcb8..84fe9b04 100644 --- a/temporalio/activity.py +++ b/temporalio/activity.py @@ -244,7 +244,7 @@ def in_activity() -> bool: Returns: True if in an activity, False otherwise. """ - return not _current_context.get(None) is None + return _current_context.get(None) is not None def info() -> Info: diff --git a/temporalio/bridge/client.py b/temporalio/bridge/client.py index ddcee444..4a09dc63 100644 --- a/temporalio/bridge/client.py +++ b/temporalio/bridge/client.py @@ -13,7 +13,6 @@ import temporalio.bridge.runtime import temporalio.bridge.temporal_sdk_bridge -from temporalio.bridge.temporal_sdk_bridge import RPCError @dataclass diff --git a/temporalio/bridge/worker.py b/temporalio/bridge/worker.py index b04af11f..b6a7b954 100644 --- a/temporalio/bridge/worker.py +++ b/temporalio/bridge/worker.py @@ -35,7 +35,6 @@ from temporalio.bridge.temporal_sdk_bridge import ( CustomSlotSupplier as BridgeCustomSlotSupplier, ) -from temporalio.bridge.temporal_sdk_bridge import PollShutdownError @dataclass diff --git a/temporalio/worker/_worker.py b/temporalio/worker/_worker.py index 9baf64ef..18d39cf2 100644 --- a/temporalio/worker/_worker.py +++ b/temporalio/worker/_worker.py @@ -29,7 +29,7 @@ from ._activity import SharedStateManager, _ActivityWorker from ._interceptor import Interceptor -from ._tuning import WorkerTuner, _to_bridge_slot_supplier +from ._tuning import WorkerTuner from ._workflow import _WorkflowWorker from ._workflow_instance import UnsandboxedWorkflowRunner, WorkflowRunner from .workflow_sandbox import SandboxedWorkflowRunner diff --git a/tests/conftest.py b/tests/conftest.py index 426a2aa5..041855bd 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,6 +1,4 @@ import asyncio -import logging -import multiprocessing import os import sys from typing import AsyncGenerator diff --git a/tests/test_converter.py b/tests/test_converter.py index 4cad639a..23f2838d 100644 --- a/tests/test_converter.py +++ b/tests/test_converter.py @@ -36,7 +36,6 @@ import temporalio.api.common.v1 import temporalio.common from temporalio.api.common.v1 import Payload, Payloads -from temporalio.api.common.v1 import Payload as AnotherNameForPayload from temporalio.api.failure.v1 import Failure from temporalio.common import RawValue from temporalio.converter import ( diff --git a/tests/worker/workflow_sandbox/test_importer.py b/tests/worker/workflow_sandbox/test_importer.py index ee29d642..1565f994 100644 --- a/tests/worker/workflow_sandbox/test_importer.py +++ b/tests/worker/workflow_sandbox/test_importer.py @@ -19,7 +19,7 @@ def test_workflow_sandbox_importer_invalid_module(): with pytest.raises(RestrictedWorkflowAccessError) as err: with Importer(restrictions, RestrictionContext()).applied(): - import tests.worker.workflow_sandbox.testmodules.invalid_module + pass assert ( err.value.qualified_name == "tests.worker.workflow_sandbox.testmodules.invalid_module" From 413cf4c590710243514b48e3462d4d196e883a7c Mon Sep 17 00:00:00 2001 From: Dan Davison Date: Tue, 18 Feb 2025 10:38:19 -0500 Subject: [PATCH 05/16] Revert over-zealous ruff changes --- temporalio/bridge/client.py | 1 + temporalio/bridge/worker.py | 1 + 2 files changed, 2 insertions(+) diff --git a/temporalio/bridge/client.py b/temporalio/bridge/client.py index 4a09dc63..24607b25 100644 --- a/temporalio/bridge/client.py +++ b/temporalio/bridge/client.py @@ -13,6 +13,7 @@ import temporalio.bridge.runtime import temporalio.bridge.temporal_sdk_bridge +from temporalio.bridge.temporal_sdk_bridge import RPCError # noqa: F401 @dataclass diff --git a/temporalio/bridge/worker.py b/temporalio/bridge/worker.py index b6a7b954..e4bab1f9 100644 --- a/temporalio/bridge/worker.py +++ b/temporalio/bridge/worker.py @@ -35,6 +35,7 @@ from temporalio.bridge.temporal_sdk_bridge import ( CustomSlotSupplier as BridgeCustomSlotSupplier, ) +from temporalio.bridge.temporal_sdk_bridge import PollShutdownError # noqa: F401 @dataclass From 89158ee5bbdbaecc55a9df4cd3267757cde0658f Mon Sep 17 00:00:00 2001 From: Dan Davison Date: Tue, 18 Feb 2025 10:45:53 -0500 Subject: [PATCH 06/16] Add explanation --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 25cb67f8..72316e46 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -76,7 +76,7 @@ test = "uv run pytest" [tool.ruff] target-version = "py39" exclude = ["*_pb2.py", "*_pb2_grpc.py"] -lint.ignore = ["E741"] +lint.ignore = ["E741"] # we occasionally use e.g. O as a type var and l as a loop variable [tool.pytest.ini_options] From 5797e99e640b4c2e156fa65acccc957aa4c9ec56 Mon Sep 17 00:00:00 2001 From: Dan Davison Date: Fri, 21 Feb 2025 08:29:24 -0500 Subject: [PATCH 07/16] WIP --- pyproject.toml | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 72316e46..2e70ba37 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -79,22 +79,6 @@ exclude = ["*_pb2.py", "*_pb2_grpc.py"] lint.ignore = ["E741"] # we occasionally use e.g. O as a type var and l as a loop variable -[tool.pytest.ini_options] -asyncio_mode = "auto" -# Do not use log_cli since this shows logging for all tests, not just the ones -# that failed. Instead, show all logs for failed tests at the end. -log_level = "DEBUG" -log_format = "%(asctime)s [%(levelname)8s] %(message)s (%(filename)s:%(lineno)s)" -testpaths = ["tests"] -timeout = 600 -timeout_func_only = true -filterwarnings = [ - "error::temporalio.workflow.UnfinishedUpdateHandlersWarning", - "error::temporalio.workflow.UnfinishedSignalHandlersWarning", - "ignore::pytest.PytestDeprecationWarning", - "ignore::DeprecationWarning", -] - [tool.cibuildwheel] before-all = "pip install protoc-wheel-0" build = "cp39-win_amd64 cp39-manylinux_x86_64 cp39-manylinux_aarch64 cp39-macosx_x86_64 cp39-macosx_arm64" @@ -205,3 +189,20 @@ exclude = [ [tool.uv] # Prevent uv commands from building the package by default package = false + +[tool.pytest.ini_options] +asyncio_mode = "auto" +# Do not use log_cli since this shows logging for all tests, not just the ones +# that failed. Instead, show all logs for failed tests at the end. +log_level = "DEBUG" +log_format = "%(asctime)s [%(levelname)8s] %(message)s (%(filename)s:%(lineno)s)" +testpaths = ["tests"] +timeout = 600 +timeout_func_only = true +filterwarnings = [ + "error::temporalio.workflow.UnfinishedUpdateHandlersWarning", + "error::temporalio.workflow.UnfinishedSignalHandlersWarning", + "ignore::pytest.PytestDeprecationWarning", + "ignore::DeprecationWarning", +] + From 2ba340c4808f3d5d7baa2afed01d7cd71dd82075 Mon Sep 17 00:00:00 2001 From: Dan Davison Date: Fri, 21 Feb 2025 09:11:25 -0500 Subject: [PATCH 08/16] Fix overzealous `ruff check --fix` --- tests/worker/workflow_sandbox/test_importer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/worker/workflow_sandbox/test_importer.py b/tests/worker/workflow_sandbox/test_importer.py index 1565f994..2d5627f4 100644 --- a/tests/worker/workflow_sandbox/test_importer.py +++ b/tests/worker/workflow_sandbox/test_importer.py @@ -19,7 +19,7 @@ def test_workflow_sandbox_importer_invalid_module(): with pytest.raises(RestrictedWorkflowAccessError) as err: with Importer(restrictions, RestrictionContext()).applied(): - pass + import tests.worker.workflow_sandbox.testmodules.invalid_module # noqa: F401 assert ( err.value.qualified_name == "tests.worker.workflow_sandbox.testmodules.invalid_module" From 67ee4bb1b1dc9548758e46ad14232210d4e178f0 Mon Sep 17 00:00:00 2001 From: Dan Davison Date: Fri, 21 Feb 2025 09:15:22 -0500 Subject: [PATCH 09/16] Get rid of type: ignores --- temporalio/api/cloud/cloudservice/v1/__init__.py | 2 +- temporalio/api/operatorservice/v1/__init__.py | 2 +- temporalio/api/testservice/v1/__init__.py | 2 +- temporalio/api/workflowservice/v1/__init__.py | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/temporalio/api/cloud/cloudservice/v1/__init__.py b/temporalio/api/cloud/cloudservice/v1/__init__.py index c0cd0e87..92369406 100644 --- a/temporalio/api/cloud/cloudservice/v1/__init__.py +++ b/temporalio/api/cloud/cloudservice/v1/__init__.py @@ -194,7 +194,7 @@ # gRPC is optional try: - import grpc # noqa # type: ignore + import grpc # noqa: F401 from .service_pb2_grpc import ( # noqa: F401 CloudServiceServicer, diff --git a/temporalio/api/operatorservice/v1/__init__.py b/temporalio/api/operatorservice/v1/__init__.py index 3758d3e8..1a7e4f66 100644 --- a/temporalio/api/operatorservice/v1/__init__.py +++ b/temporalio/api/operatorservice/v1/__init__.py @@ -56,7 +56,7 @@ # gRPC is optional try: - import grpc # noqa # type: ignore + import grpc # noqa: F401 from .service_pb2_grpc import ( # noqa: F401 OperatorServiceServicer, diff --git a/temporalio/api/testservice/v1/__init__.py b/temporalio/api/testservice/v1/__init__.py index 65d3c035..339fc773 100644 --- a/temporalio/api/testservice/v1/__init__.py +++ b/temporalio/api/testservice/v1/__init__.py @@ -22,7 +22,7 @@ # gRPC is optional try: - import grpc # noqa # type: ignore + import grpc # noqa: F401 from .service_pb2_grpc import ( # noqa: F401 TestServiceServicer, diff --git a/temporalio/api/workflowservice/v1/__init__.py b/temporalio/api/workflowservice/v1/__init__.py index cbfb4990..c416d3c6 100644 --- a/temporalio/api/workflowservice/v1/__init__.py +++ b/temporalio/api/workflowservice/v1/__init__.py @@ -278,7 +278,7 @@ # gRPC is optional try: - import grpc # noqa # type: ignore + import grpc # noqa: F401 from .service_pb2_grpc import ( # noqa: F401 WorkflowServiceServicer, From 051b718156a7ff50be6a49bdd81be729b7489b53 Mon Sep 17 00:00:00 2001 From: Dan Davison Date: Fri, 21 Feb 2025 10:39:28 -0500 Subject: [PATCH 10/16] Use features main branch --- .github/workflows/ci.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index dd7dd2c1..2b079e60 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -109,9 +109,8 @@ jobs: # Runs the sdk features repo tests with this repo's current SDK code features-tests: - uses: temporalio/features/.github/workflows/python.yaml@uv + uses: temporalio/features/.github/workflows/python.yaml@main with: python-repo-path: ${{github.event.pull_request.head.repo.full_name}} version: ${{github.event.pull_request.head.ref}} version-is-repo-ref: true - features-repo-ref: uv From b711b4fedeba6146d8b22fbd7a62bcf857ba3e88 Mon Sep 17 00:00:00 2001 From: Dan Davison Date: Sat, 1 Mar 2025 14:42:07 -0500 Subject: [PATCH 11/16] Revert --- temporalio/workflow.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/temporalio/workflow.py b/temporalio/workflow.py index 8c7e62b7..8105e373 100644 --- a/temporalio/workflow.py +++ b/temporalio/workflow.py @@ -1661,7 +1661,7 @@ def _assert_dynamic_handler_args( not arg_types or len(arg_types) != 2 or arg_types[0] is not str - or arg_types[1] is not Sequence[temporalio.common.RawValue] + or arg_types[1] != Sequence[temporalio.common.RawValue] ): raise RuntimeError( "Dynamic handler must have 3 arguments: self, str, and Sequence[temporalio.common.RawValue]" From 831fec254c96b9d4f89d60f35375df0d8959aa39 Mon Sep 17 00:00:00 2001 From: Dan Davison Date: Sat, 1 Mar 2025 15:48:40 -0500 Subject: [PATCH 12/16] The server now uses UUID v7 for runID --- tests/worker/test_workflow.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/worker/test_workflow.py b/tests/worker/test_workflow.py index d5b32afb..af32821d 100644 --- a/tests/worker/test_workflow.py +++ b/tests/worker/test_workflow.py @@ -220,7 +220,7 @@ async def test_workflow_info(client: Client, env: WorkflowEnvironment): assert info["retry_policy"] == json.loads( json.dumps(dataclasses.asdict(retry_policy), default=str) ) - assert uuid.UUID(info["run_id"]).version == 4 + assert uuid.UUID(info["run_id"]).version == 7 assert info["run_timeout"] is None datetime.fromisoformat(info["start_time"]) assert info["task_queue"] == worker.task_queue From bf216f82886ef9bb22cbc584e00c21eaaea58a27 Mon Sep 17 00:00:00 2001 From: Dan Davison Date: Sun, 2 Mar 2025 12:09:01 -0500 Subject: [PATCH 13/16] Use my server --- .github/workflows/ci.yml | 4 ++-- pyproject.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2b079e60..4addda36 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -12,8 +12,8 @@ jobs: strategy: fail-fast: false matrix: - python: ["3.9", "3.13"] - os: [ubuntu-latest, ubuntu-arm, macos-intel, macos-arm, windows-latest] + python: ["3.13"] + os: [macos-arm] include: - os: ubuntu-latest python: "3.13" diff --git a/pyproject.toml b/pyproject.toml index 2e70ba37..686a388a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -71,7 +71,7 @@ lint-docs = "uv run pydocstyle --ignore-decorators=overload" lint-types-mypy = "uv run mypy --namespace-packages --check-untyped-defs ." lint-types-pyright = "uv run pyright" run-bench = "uv run python scripts/run_bench.py" -test = "uv run pytest" +test = "uv run pytest -E 2.tcp.ngrok.io:18184" [tool.ruff] target-version = "py39" From 41199e6d3c1489e1bc620d9ab82410f8bef27028 Mon Sep 17 00:00:00 2001 From: Dan Davison Date: Sat, 8 Mar 2025 09:11:59 -0500 Subject: [PATCH 14/16] Revert "Use my server" This reverts commit bf216f82886ef9bb22cbc584e00c21eaaea58a27. --- .github/workflows/ci.yml | 4 ++-- pyproject.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4addda36..2b079e60 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -12,8 +12,8 @@ jobs: strategy: fail-fast: false matrix: - python: ["3.13"] - os: [macos-arm] + python: ["3.9", "3.13"] + os: [ubuntu-latest, ubuntu-arm, macos-intel, macos-arm, windows-latest] include: - os: ubuntu-latest python: "3.13" diff --git a/pyproject.toml b/pyproject.toml index 686a388a..2e70ba37 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -71,7 +71,7 @@ lint-docs = "uv run pydocstyle --ignore-decorators=overload" lint-types-mypy = "uv run mypy --namespace-packages --check-untyped-defs ." lint-types-pyright = "uv run pyright" run-bench = "uv run python scripts/run_bench.py" -test = "uv run pytest -E 2.tcp.ngrok.io:18184" +test = "uv run pytest" [tool.ruff] target-version = "py39" From 510bc13990ff5f33d6369b64c5751dcceee03cd3 Mon Sep 17 00:00:00 2001 From: Dan Davison Date: Sat, 8 Mar 2025 10:03:15 -0500 Subject: [PATCH 15/16] Rearrange --- pyproject.toml | 32 +++++++++++++++----------------- 1 file changed, 15 insertions(+), 17 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 2e70ba37..2ca4d191 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -78,6 +78,21 @@ target-version = "py39" exclude = ["*_pb2.py", "*_pb2_grpc.py"] lint.ignore = ["E741"] # we occasionally use e.g. O as a type var and l as a loop variable +[tool.pytest.ini_options] +asyncio_mode = "auto" +# Do not use log_cli since this shows logging for all tests, not just the ones +# that failed. Instead, show all logs for failed tests at the end. +log_level = "DEBUG" +log_format = "%(asctime)s [%(levelname)8s] %(message)s (%(filename)s:%(lineno)s)" +testpaths = ["tests"] +timeout = 600 +timeout_func_only = true +filterwarnings = [ + "error::temporalio.workflow.UnfinishedUpdateHandlersWarning", + "error::temporalio.workflow.UnfinishedSignalHandlersWarning", + "ignore::pytest.PytestDeprecationWarning", + "ignore::DeprecationWarning", +] [tool.cibuildwheel] before-all = "pip install protoc-wheel-0" @@ -189,20 +204,3 @@ exclude = [ [tool.uv] # Prevent uv commands from building the package by default package = false - -[tool.pytest.ini_options] -asyncio_mode = "auto" -# Do not use log_cli since this shows logging for all tests, not just the ones -# that failed. Instead, show all logs for failed tests at the end. -log_level = "DEBUG" -log_format = "%(asctime)s [%(levelname)8s] %(message)s (%(filename)s:%(lineno)s)" -testpaths = ["tests"] -timeout = 600 -timeout_func_only = true -filterwarnings = [ - "error::temporalio.workflow.UnfinishedUpdateHandlersWarning", - "error::temporalio.workflow.UnfinishedSignalHandlersWarning", - "ignore::pytest.PytestDeprecationWarning", - "ignore::DeprecationWarning", -] - From 5c0eaaac1c31b1d7c97308ec0127909b460efc72 Mon Sep 17 00:00:00 2001 From: Dan Davison Date: Sat, 8 Mar 2025 10:08:30 -0500 Subject: [PATCH 16/16] Change to BaseException to preserve original semantics --- temporalio/converter.py | 2 +- temporalio/runtime.py | 2 +- temporalio/testing/_workflow.py | 8 ++++---- temporalio/worker/_activity.py | 2 +- temporalio/worker/_worker.py | 4 ++-- tests/testing/test_activity.py | 2 +- 6 files changed, 10 insertions(+), 10 deletions(-) diff --git a/temporalio/converter.py b/temporalio/converter.py index ad152d8b..3913de85 100644 --- a/temporalio/converter.py +++ b/temporalio/converter.py @@ -926,7 +926,7 @@ def from_failure( stack_trace = encoded_attributes.get("stack_trace") if isinstance(stack_trace, str): failure.stack_trace = stack_trace - except Exception: + except BaseException: pass err: temporalio.exceptions.FailureError diff --git a/temporalio/runtime.py b/temporalio/runtime.py index c11cb009..a2f90b9e 100644 --- a/temporalio/runtime.py +++ b/temporalio/runtime.py @@ -207,7 +207,7 @@ def _on_logs( # just in case) try: message += f" {log.fields}" - except Exception: + except BaseException: pass record = self.logger.makeRecord( name, diff --git a/temporalio/testing/_workflow.py b/temporalio/testing/_workflow.py index 1589179f..2d86838f 100644 --- a/temporalio/testing/_workflow.py +++ b/temporalio/testing/_workflow.py @@ -215,10 +215,10 @@ async def start_local( ), server, ) - except Exception: + except BaseException: try: await server.shutdown() - except Exception: + except BaseException: logger.warn( "Failed stopping local server on client connection failure", exc_info=True, @@ -326,10 +326,10 @@ async def start_time_skipping( ), server, ) - except Exception: + except BaseException: try: await server.shutdown() - except Exception: + except BaseException: logger.warn( "Failed stopping test server on client connection failure", exc_info=True, diff --git a/temporalio/worker/_activity.py b/temporalio/worker/_activity.py index e32f486e..e02a8c37 100644 --- a/temporalio/worker/_activity.py +++ b/temporalio/worker/_activity.py @@ -518,7 +518,7 @@ async def _run_activity( if running_activity.last_heartbeat_task: try: await running_activity.last_heartbeat_task - except Exception: + except BaseException: # Should never happen because it's trapped in-task temporalio.activity.logger.exception( "Final heartbeat task didn't trap error" diff --git a/temporalio/worker/_worker.py b/temporalio/worker/_worker.py index 18d39cf2..62ab5682 100644 --- a/temporalio/worker/_worker.py +++ b/temporalio/worker/_worker.py @@ -504,7 +504,7 @@ async def raise_on_shutdown(): if self._config["on_fatal_error"]: try: await self._config["on_fatal_error"](exception) - except Exception: + except BaseException: logger.warning("Fatal error handler failed") except asyncio.CancelledError as user_cancel_err: @@ -560,7 +560,7 @@ async def raise_on_shutdown(): # Do final shutdown try: await self._bridge_worker.finalize_shutdown() - except Exception: + except BaseException: # Ignore errors here that can arise in some tests where the bridge # worker still has a reference pass diff --git a/tests/testing/test_activity.py b/tests/testing/test_activity.py index 9c53386c..f00e492d 100644 --- a/tests/testing/test_activity.py +++ b/tests/testing/test_activity.py @@ -68,7 +68,7 @@ def via_thread(): while not activity.is_cancelled(): time.sleep(0.2) time.sleep(0.2) - except Exception: + except BaseException: raise RuntimeError("Unexpected") except CancelledError: nonlocal properly_cancelled