Skip to content

fix: Rewrite Type Handling#63

Merged
natemort merged 1 commit intocadence-workflow:mainfrom
natemort:workflow_params
Jan 29, 2026
Merged

fix: Rewrite Type Handling#63
natemort merged 1 commit intocadence-workflow:mainfrom
natemort:workflow_params

Conversation

@natemort
Copy link
Member

Move type handling logic from activity.py to fn_signature.py, providing utilities for understanding a functions parameters and converting calls/payloads to match the function's signature.

Use this new logic in Workflows, to support any number of typed parameters.

Rewrite the Activity decorators to be fully type-safe. Introduce @activity.method and @activity.impl to satisfy type safety while allowing for interface types or classes that contain activities. These definitions are quite complicated for a few reasons:

  • We allow both activity.defn and activity.defn(), which means we need to handle both being or returning a decorator
  • We allow both async and non-async activity definitions, which we need to handle the result of differently (Awaitable[T] vs T).
    • If a function returns Awaitable[T] we don't want to return Awaitable[Awaitable[T]].
  • We support both standalone functions and methods.
    • When a method is accessed the __get__ special method is invoked, which returns the function with the self parameter already filled.
    • If it's accessed via ClassName.foo then __get__ is invoked with None, and the returned function doesn't have the filled self parameter.
  • To support overriding an activity definition (such as making an interface that has the definitions), we need the subclass to have a property that's an identical ActivityDefinition. Otherwise it's not a valid subclass.
    • The activity.impl decorator was added to support this. Maybe it makes more sense to call it override.

Fix type-safety for Workflows. This only addresses the annotations and doesn't provide a type-safe invocation mechanism like what is supported with Activities. That will be explored in a future diff.

What changed?

  • Refactor function inspection to share between Workflows and Activities
  • Rewrite activity typing to be fully type-safe.
    • Pycharm is broadly confused by it, but mypy approves.
  • Use new typing support to handle Workflows with parameters.

Why?

  • Fix type-safety for Workflows.
  • Support multiple parameters in Workflows.

How did you test it?

  • Integration and unit tests

Potential risks

  • This is a breaking change.

Release notes

Documentation Changes

Copy link
Member Author

@natemort natemort left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed offline

Comment on lines 169 to 171
def __call__(
self, fn: Union[Callable[_P1, Awaitable[_R1]], Callable[_P2, _R2]]
) -> Union[AsyncActivityDefinition[_P1, _R1], SyncActivityDefinition[_P2, _R2]]:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no need to specify typing in the implementation since typing is already hinted in the overload.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The implementation references the various type parameters unfortunately :( .


class ActivityDefinitionOptions(TypedDict, total=False):
name: str
class ActivityDefinition(Protocol[P, R]):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why does ActivityDefinition needs to have call method? I think this is where introduced all the sync/async branches.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Without __call__ we'd be transforming their functions into something that isn't Callable. They'd no longer be able to directly invoke any decorated functions

Move type handling logic from activity.py to fn_signature.py, providing utilities for understanding a functions parameters and converting calls/payloads to match the function's signature.

Use this new logic in Workflows, to support any number of typed parameters.

Rewrite the Activity decorators to be fully type-safe. Introduce `@activity.method` and `@activity.impl` to satisfy type safety while allowing for interface types or classes that contain activities.

Fix type-safety for Workflows. This only addresses the annotations and doesn't provide a type-safe invocation mechanism like what is supported with Activities.
@natemort natemort merged commit 09fd459 into cadence-workflow:main Jan 29, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants