Skip to content

Commit 4280b5b

Browse files
author
Alex Wang
committed
merge
2 parents 071bc9b + 169d2d8 commit 4280b5b

File tree

56 files changed

+1581
-8252
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

56 files changed

+1581
-8252
lines changed

.github/model/lambda.json

Lines changed: 0 additions & 7864 deletions
This file was deleted.

.github/workflows/ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ jobs:
2828
python-version: ${{ matrix.python-version }}
2929
- name: Install Hatch
3030
run: |
31-
python -m pip install --upgrade hatch
31+
python -m pip install hatch==1.15.0
3232
- uses: webfactory/ssh-agent@v0.9.1
3333
with:
3434
ssh-private-key: ${{ secrets.SDK_KEY }}

.github/workflows/deploy-examples.yml

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -60,10 +60,6 @@ jobs:
6060
role-session-name: pythonTestingLibraryGitHubIntegrationTest
6161
aws-region: ${{ env.AWS_REGION }}
6262

63-
- name: Install custom Lambda model
64-
run: |
65-
aws configure add-model --service-model file://.github/model/lambda.json --service-name lambda
66-
6763
- name: Install Hatch
6864
run: pip install hatch
6965

.github/workflows/scorecard.yml

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
# This workflow uses actions that are not certified by GitHub. They are provided
2+
# by a third-party and are governed by separate terms of service, privacy
3+
# policy, and support documentation.
4+
5+
name: Scorecard supply-chain security
6+
on:
7+
# For Branch-Protection check. Only the default branch is supported. See
8+
# https://github.com/ossf/scorecard/blob/main/docs/checks.md#branch-protection
9+
branch_protection_rule:
10+
# To guarantee Maintained check is occasionally updated. See
11+
# https://github.com/ossf/scorecard/blob/main/docs/checks.md#maintained
12+
schedule:
13+
- cron: '16 22 * * 4'
14+
push:
15+
branches: [ "main" ]
16+
17+
# Declare default permissions as read only.
18+
permissions: read-all
19+
20+
jobs:
21+
analysis:
22+
name: Scorecard analysis
23+
runs-on: ubuntu-latest
24+
# `publish_results: true` only works when run from the default branch. conditional can be removed if disabled.
25+
if: github.event.repository.default_branch == github.ref_name || github.event_name == 'pull_request'
26+
permissions:
27+
# Needed to upload the results to code-scanning dashboard.
28+
security-events: write
29+
# Needed to publish results and get a badge (see publish_results below).
30+
id-token: write
31+
# Uncomment the permissions below if installing in a private repository.
32+
# contents: read
33+
# actions: read
34+
35+
steps:
36+
- name: "Checkout code"
37+
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
38+
with:
39+
persist-credentials: false
40+
41+
- name: "Run analysis"
42+
uses: ossf/scorecard-action@f49aabe0b5af0936a0987cfb85d86b75731b0186 # v2.4.1
43+
with:
44+
results_file: results.sarif
45+
results_format: sarif
46+
# (Optional) "write" PAT token. Uncomment the `repo_token` line below if:
47+
# - you want to enable the Branch-Protection check on a *public* repository, or
48+
# - you are installing Scorecard on a *private* repository
49+
# To create the PAT, follow the steps in https://github.com/ossf/scorecard-action?tab=readme-ov-file#authentication-with-fine-grained-pat-optional.
50+
# repo_token: ${{ secrets.SCORECARD_TOKEN }}
51+
52+
# Public repositories:
53+
# - Publish results to OpenSSF REST API for easy access by consumers
54+
# - Allows the repository to include the Scorecard badge.
55+
# - See https://github.com/ossf/scorecard-action#publishing-results.
56+
# For private repositories:
57+
# - `publish_results` will always be set to `false`, regardless
58+
# of the value entered here.
59+
publish_results: true
60+
61+
# (Optional) Uncomment file_mode if you have a .gitattributes with files marked export-ignore
62+
# file_mode: git
63+
64+
# Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF
65+
# format to the repository Actions tab.
66+
- name: "Upload artifact"
67+
uses: actions/upload-artifact@4cec3d8aa04e39d1a68397de0c4cd6fb9dce8ec1 # v4.6.1
68+
with:
69+
name: SARIF file
70+
path: results.sarif
71+
retention-days: 5
72+
73+
# Upload the results to GitHub's code scanning dashboard (optional).
74+
# Commenting out will disable upload of results to your repo's Code Scanning dashboard
75+
- name: "Upload to code-scanning"
76+
uses: github/codeql-action/upload-sarif@v3
77+
with:
78+
sarif_file: results.sarif

README.md

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
1-
# aws-durable-functions-sdk-python
1+
# AWS Durable Execution Testing SDK for Python
22

3-
[![PyPI - Version](https://img.shields.io/pypi/v/aws-durable-functions-sdk-python.svg)](https://pypi.org/project/aws-durable-functions-sdk-python)
4-
[![PyPI - Python Version](https://img.shields.io/pypi/pyversions/aws-durable-functions-sdk-python.svg)](https://pypi.org/project/aws-durable-functions-sdk-python)
3+
[![PyPI - Version](https://img.shields.io/pypi/v/aws-durable-execution-sdk-python-testing.svg)](https://pypi.org/project/aws-durable-execution-sdk-python-testing)
4+
[![PyPI - Python Version](https://img.shields.io/pypi/pyversions/aws-durable-execution-sdk-python-testing.svg)](https://pypi.org/project/aws-durable-execution-sdk-python-testing)
5+
6+
7+
[![OpenSSF Scorecard](https://api.scorecard.dev/projects/github.com/aws/aws-durable-execution-sdk-python-testing/badge)](https://scorecard.dev/viewer/?uri=github.com/aws/aws-durable-execution-sdk-python-testing)
58

69
-----
710

@@ -17,27 +20,27 @@
1720
## Installation
1821

1922
```console
20-
pip install aws-durable-functions-sdk-python-testing
23+
pip install aws-durable-execution-sdk-python-testing
2124
```
2225

2326
## Overview
2427

25-
Use the Durable Functions Python Testing Framework to test your Python Durable Functions locally.
28+
Use the AWS Durable Execution Testing SDK for Python to test your Python durable functions locally.
2629

27-
The test framework contains a local runner, so you can run and test your Durable Function locally
30+
The test framework contains a local runner, so you can run and test your durable function locally
2831
before you deploy it.
2932

3033
## Quick Start
3134

32-
### A Durable Function under test
35+
### A durable function under test
3336

3437
```python
35-
from durable_executions_python_language_sdk.context import (
38+
from aws_durable_execution_sdk_python.context import (
3639
DurableContext,
3740
durable_step,
3841
durable_with_child_context,
3942
)
40-
from durable_executions_python_language_sdk.execution import durable_execution
43+
from aws_durable_execution_sdk_python.execution import durable_execution
4144
from aws_durable_execution_sdk_python.config import Duration
4245

4346

examples/cli.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,6 @@ def get_aws_config():
258258
def get_lambda_client():
259259
"""Get configured Lambda client."""
260260
config = get_aws_config()
261-
LambdaClient.load_preview_botocore_models()
262261
return boto3.client(
263262
"lambda",
264263
endpoint_url=config["lambda_endpoint"],
@@ -345,6 +344,7 @@ def deploy_function(example_name: str, function_name: str | None = None):
345344
lambda_client.update_function_code,
346345
FunctionName=function_name,
347346
ZipFile=zip_content,
347+
max_retries=8,
348348
)
349349
retry_on_resource_conflict(
350350
lambda_client.update_function_configuration, **function_config

examples/examples-catalog.json

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -346,6 +346,17 @@
346346
},
347347
"path": "./src/map/map_with_failure_tolerance.py"
348348
},
349+
{
350+
"name": "Map Completion Config",
351+
"description": "Reproduces issue where map with minSuccessful loses failure count",
352+
"handler": "map_completion.handler",
353+
"integration": true,
354+
"durableConfig": {
355+
"RetentionPeriodInDays": 7,
356+
"ExecutionTimeout": 300
357+
},
358+
"path": "./src/map/map_completion.py"
359+
},
349360
{
350361
"name": "Parallel with Max Concurrency",
351362
"description": "Parallel operation with maxConcurrency limit",
@@ -445,6 +456,94 @@
445456
},
446457
"path": "./src/none_results/none_results.py"
447458
},
459+
{
460+
"name": "Callback Success",
461+
"description": "Creating a callback ID for external systems to use",
462+
"handler": "callback_simple.handler",
463+
"integration": true,
464+
"durableConfig": {
465+
"RetentionPeriodInDays": 7,
466+
"ExecutionTimeout": 300
467+
},
468+
"path": "./src/callback/callback_simple.py"
469+
},
470+
{
471+
"name": "Callback Success None",
472+
"description": "Creating a callback ID for external systems to use",
473+
"handler": "callback_simple.handler",
474+
"integration": true,
475+
"durableConfig": {
476+
"RetentionPeriodInDays": 7,
477+
"ExecutionTimeout": 300
478+
},
479+
"path": "./src/callback/callback_simple.py"
480+
},
481+
{
482+
"name": "Create Callback Heartbeat",
483+
"description": "Demonstrates callback failure scenarios where the error propagates and is handled by framework",
484+
"handler": "callback_heartbeat.handler",
485+
"integration": true,
486+
"durableConfig": {
487+
"RetentionPeriodInDays": 7,
488+
"ExecutionTimeout": 300
489+
},
490+
"path": "./src/callback/callback_heartbeat.py"
491+
},
492+
{
493+
"name": "Create Callback Mixed Operations",
494+
"description": "Demonstrates createCallback mixed with steps, waits, and other operations",
495+
"handler": "callback_mixed_ops.handler",
496+
"integration": true,
497+
"durableConfig": {
498+
"RetentionPeriodInDays": 7,
499+
"ExecutionTimeout": 300
500+
},
501+
"path": "./src/callback/callback_mixed_ops.py"
502+
},
503+
{
504+
"name": "Create Callback Custom Serdes",
505+
"description": "Demonstrates createCallback with custom serialization/deserialization for Date objects",
506+
"handler": "callback_serdes.handler",
507+
"integration": true,
508+
"durableConfig": {
509+
"RetentionPeriodInDays": 7,
510+
"ExecutionTimeout": 300
511+
},
512+
"path": "./src/callback/callback_serdes.py"
513+
},
514+
{
515+
"name": "No Replay Execution",
516+
"description": "Execution with simples steps and without replay",
517+
"handler": "no_replay_execution.handler",
518+
"integration": true,
519+
"durableConfig": {
520+
"RetentionPeriodInDays": 7,
521+
"ExecutionTimeout": 300
522+
},
523+
"path": "./src/no_replay_execution/no_replay_execution.py"
524+
},
525+
{
526+
"name": "Run In Child Context With Failing Step",
527+
"description": "Demonstrates runInChildContext with a failing step followed by a successful wait",
528+
"handler": "run_in_child_context_step_failure.handler",
529+
"integration": true,
530+
"durableConfig": {
531+
"RetentionPeriodInDays": 7,
532+
"ExecutionTimeout": 300
533+
},
534+
"path": "./src/run_in_child_context/run_in_child_context_step_failure.py"
535+
},
536+
{
537+
"name": "Comprehensive Operations",
538+
"description": "Complex multi-operation example demonstrating all major operations",
539+
"handler": "comprehensive_operations.handler",
540+
"integration": true,
541+
"durableConfig": {
542+
"RetentionPeriodInDays": 7,
543+
"ExecutionTimeout": 300
544+
},
545+
"path": "./src/comprehensive_operations/comprehensive_operations.py"
546+
},
448547
{
449548
"name": "Create Callback Concurrency",
450549
"description": "Demonstrates multiple concurrent createCallback operations using context.parallel",
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
from typing import TYPE_CHECKING, Any
2+
3+
from aws_durable_execution_sdk_python.config import CallbackConfig, Duration
4+
from aws_durable_execution_sdk_python.context import DurableContext
5+
from aws_durable_execution_sdk_python.execution import durable_execution
6+
7+
8+
if TYPE_CHECKING:
9+
from aws_durable_execution_sdk_python.types import Callback
10+
11+
12+
@durable_execution
13+
def handler(_event: Any, context: DurableContext) -> str:
14+
callback_config = CallbackConfig(
15+
timeout=Duration.from_seconds(60), heartbeat_timeout=Duration.from_seconds(10)
16+
)
17+
18+
callback: Callback[str] = context.create_callback(
19+
name="heartbeat_callback", config=callback_config
20+
)
21+
22+
return callback.result()
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
"""Demonstrates createCallback mixed with steps, waits, and other operations."""
2+
3+
import time
4+
from typing import Any
5+
6+
from aws_durable_execution_sdk_python.config import CallbackConfig, Duration
7+
from aws_durable_execution_sdk_python.context import DurableContext
8+
from aws_durable_execution_sdk_python.execution import durable_execution
9+
10+
11+
@durable_execution
12+
def handler(_event: Any, context: DurableContext) -> dict[str, Any]:
13+
"""Handler demonstrating createCallback mixed with other operations."""
14+
15+
step_result: dict[str, Any] = context.step(
16+
lambda _: {"userId": 123, "name": "John Doe"},
17+
name="fetch-data",
18+
)
19+
20+
callback_config = CallbackConfig(timeout=Duration.from_minutes(1))
21+
callback = context.create_callback(
22+
name="process-user",
23+
config=callback_config,
24+
)
25+
26+
# Mix callback with step and wait operations
27+
context.wait(Duration.from_seconds(1), name="initial-wait")
28+
29+
callback_result = callback.result()
30+
31+
return {
32+
"stepResult": step_result,
33+
"callbackResult": callback_result,
34+
"completed": True,
35+
}

0 commit comments

Comments
 (0)