From 5e5e8be7e26348e8a0abc9e290a867e767ea6eb5 Mon Sep 17 00:00:00 2001 From: Ubuntu Date: Wed, 6 Aug 2025 16:51:04 +0000 Subject: [PATCH 1/2] Adding additional DynamoDB CRUD StepFunctions pytest --- python-test-samples/README.md | 1 + .../README.md | 449 ++++++++++++++++++ .../aws-stepfunctions-local-credentials.txt | 4 + .../img/dynamodb-crud-stepfunctions.png | Bin 0 -> 47727 bytes .../state-machine.json | 136 ++++++ .../tests/requirements.txt | 6 + 6 files changed, 596 insertions(+) create mode 100644 python-test-samples/dynamodb-crud-stepfunctions-local/README.md create mode 100755 python-test-samples/dynamodb-crud-stepfunctions-local/aws-stepfunctions-local-credentials.txt create mode 100644 python-test-samples/dynamodb-crud-stepfunctions-local/img/dynamodb-crud-stepfunctions.png create mode 100755 python-test-samples/dynamodb-crud-stepfunctions-local/state-machine.json create mode 100644 python-test-samples/dynamodb-crud-stepfunctions-local/tests/requirements.txt diff --git a/python-test-samples/README.md b/python-test-samples/README.md index e25b76f2..bd65ddee 100644 --- a/python-test-samples/README.md +++ b/python-test-samples/README.md @@ -14,6 +14,7 @@ This portion of the repository contains code samples for testing serverless appl |[API Gateway with Lambda and DynamoDB](./apigw-lambda-dynamodb)|This project contains unit and integration tests for a pattern using API Gateway, AWS Lambda and Amazon DynamoDB.| |[Schema and Contract Testing](./schema-and-contract-testing)|This project contains sample schema and contract tests for an event driven architecture.| |[Kinesis with Lambda and DynamoDB](./kinesis-lambda-dynamodb)|This project contains a example of testing an application with an Amazon Kinesis Data Stream.| +|[DynamoDB CRUD with StepFucntions Local](./dynamodb-crud-stepfunctions-local)|This project contains unit pytest running CRUD operations using StepFunctions and DynamoDB on local Docker containers.| |[SQS with Lambda](./apigw-sqs-lambda-sqs)|This project demonstrates testing SQS as a source and destination in an integration test| |[Step Functions Local](./step-functions-local)| An example of testing Step Functions workflow locally using pytest and Testcontainers | diff --git a/python-test-samples/dynamodb-crud-stepfunctions-local/README.md b/python-test-samples/dynamodb-crud-stepfunctions-local/README.md new file mode 100644 index 00000000..7dc0a603 --- /dev/null +++ b/python-test-samples/dynamodb-crud-stepfunctions-local/README.md @@ -0,0 +1,449 @@ +[![python: 3.10](https://img.shields.io/badge/Python-3.10-green)](https://img.shields.io/badge/Python-3.10-green) +[![AWS: Step Functions](https://img.shields.io/badge/AWS-Step%20Functions-orange)](https://img.shields.io/badge/AWS-Step%20Functions-orange) +[![Language: ASL](https://img.shields.io/badge/Language-ASL-blue)](https://img.shields.io/badge/Language-ASL-blue) +[![AWS: Lambda](https://img.shields.io/badge/AWS-Lambda-yellow)](https://img.shields.io/badge/AWS-Lambda-yellow) +[![AWS: SQS](https://img.shields.io/badge/AWS-SQS-green)](https://img.shields.io/badge/AWS-SQS-green) +[![test: pytest](https://img.shields.io/badge/Test-Pytest-red)](https://img.shields.io/badge/Test-Pytest-red) +[![test: local](https://img.shields.io/badge/Test-Local-red)](https://img.shields.io/badge/Test-Local-red) + +# AWS Step Functions: DynamoDB CRUD Operations with PyTest + +## Introduction + +This project demonstrates how to test AWS Step Functions state machines that perform DynamoDB CRUD operations locally using PyTest. It uses Docker containers to emulate both Step Functions and DynamoDB services, providing comprehensive testing of Create, Read, Update, Delete, and Initialize operations. + +The containers are started manually before running the tests, giving you full control over the testing environment and allowing for easier debugging and inspection of the services. + +--- + +## Contents + +- [AWS Step Functions: DynamoDB CRUD Operations with PyTest](#aws-step-functions-dynamodb-crud-operations-with-pytest) + - [Introduction](#introduction) + - [Contents](#contents) + - [Architecture Overview](#architecture-overview) + - [Project Structure](#project-structure) + - [Prerequisites](#prerequisites) + - [Test Scenarios](#test-scenarios) + - [About the Test Process](#about-the-test-process) + - [Testing Workflows](#testing-workflows) + - [Additional Resources](#additional-resources) + +--- + +## Architecture Overview + +

+ AWS Step Functions with DynamoDB CRUD Operations +

+ +Components: + +- Step Functions state machine for CRUD orchestration +- DynamoDB Local container for data persistence +- Choice state for operation routing +- PyTest fixtures for container lifecycle management + +

+ AWS Step Functions with DynamoDB CRUD States +

+ +--- + +## Project Structure + +``` +├── img/dynamodb-crud-stepfunctions.png _# visual architecture diagram_ +├── tests/ +│ ├── unit/src/test_step_functions_local.py _# python PyTest test definition_ +│ └── requirements.txt _# pip requirements dependencies file_ +├── aws-stepfunctions-local-credentials.txt _# Step Functions Docker image environment vars_ +├── README.md _# instructions file_ +└── state-machine.json _# json file containing DynamoDB CRUD state machine definition_ +``` + +--- + +## Prerequisites + +- Docker +- AWS CLI v2 (for debugging) +- Python 3.10 or newer +- Basic understanding of DynamoDB and Step Functions + +--- + +## Test Scenarios + +### 1. DynamoDB Table Initialization + +- Tests the table creation operation through Step Functions +- Validates successful table creation using AWS SDK DynamoDB createTable +- Verifies that the DynamoDB Init state is properly executed +- Used to set up the table structure before CRUD operations + +### 2. DynamoDB Create Operation + +- Tests item creation in the DynamoDB table +- Validates putItem operation through Step Functions DynamoDB integration +- Verifies that items are successfully stored with correct attributes +- Ensures the Choice state correctly routes to DynamoDB Create state + +### 3. DynamoDB Read Operation + +- Tests item retrieval from the DynamoDB table +- Validates getItem operation with proper key specification +- Verifies successful data retrieval and response structure +- Tests retry logic for DynamoDB exceptions + +### 4. DynamoDB Update Operation + +- Tests item modification in the DynamoDB table +- Validates updateItem operation with expression attributes +- Verifies successful attribute updates (Name and Age fields) +- Ensures proper handling of UpdateExpression and ExpressionAttributeNames + +### 5. DynamoDB Delete Operation + +- Tests item removal from the DynamoDB table +- Validates deleteItem operation through Step Functions +- Verifies successful item deletion with proper key specification +- Confirms clean removal without errors + +### 6. Complete CRUD Workflow Integration + +- Tests the full workflow: Init → Create → Read → Update → Read → Delete +- Validates end-to-end functionality with real DynamoDB operations +- Verifies data consistency across all operations +- Demonstrates comprehensive testing of the entire workflow + +### 7. Choice State Logic Validation + +- Tests the Choice state routing mechanism +- Validates that different Operation values route to correct states +- Verifies all possible operation paths (Create, Read, Update, Delete, Init) +- Ensures proper state machine flow control + +--- + +## About the Test Process + +The test process leverages PyTest fixtures to connect to pre-existing DynamoDB Local and Step Functions Local containers: + +1. **Service Verification**: The `dynamodb_container` and `sfn_container` fixtures verify that both services are running on their expected ports (8000 for DynamoDB, 8083 for Step Functions). Tests are skipped if services are not available. + +2. **Client Creation**: The `dynamodb_client` and `sfn_client` fixtures create Boto3 clients for both services and create the state machine using the definition from `state-machine.json`. + +3. **State Machine Creation**: The state machine is created with the real CRUD operations definition, including Choice state logic and DynamoDB integrations. If the state machine already exists, it reuses the existing one. + +4. **Test Execution**: When tests run, they call `execute_stepfunction` with different operation types (Init, Create, Read, Update, Delete) and monitor execution until completion. + +5. **Validation**: Each test verifies that: + - The execution completed with the expected status + - The correct DynamoDB operation state was executed + - Choice state routing worked properly + - DynamoDB operations completed successfully + - Data consistency is maintained across operations + +6. **External Container Management**: Unlike other testing approaches, the Docker containers are managed externally. You must start the containers before running tests and stop them manually afterward. + +**Important**: The tests assume that both DynamoDB Local (port 8000) and Step Functions Local (port 8083) are already running. If either service is unavailable, the tests will be skipped with appropriate messages. + +--- + +## Testing Workflows + +### Setup Docker Environment + +> Make sure Docker engine is running before running the tests. + +```shell +dynamodb-crud-stepfunctions-local$ docker version +Client: Docker Engine - Community + Version: 24.0.6 + API version: 1.43 +(...) +``` + +### Start Required Services + +Before running the tests, you need to start both DynamoDB Local and Step Functions Local containers: + +#### Start DynamoDB Local + +```shell +dynamodb-crud-stepfunctions-local$ +docker run -d --network host \ + --name dynamodb -p 8000:8000 \ + amazon/dynamodb-local -jar DynamoDBLocal.jar -sharedDb +``` + +#### Start Step Functions Local + +```shell +dynamodb-crud-stepfunctions-local$ +docker run -d --network host \ + --name stepfunctions -p 8083:8083 \ + --env-file aws-stepfunctions-local-credentials.txt \ + amazon/aws-stepfunctions-local +``` + +> Verify both containers are running: + +```shell +dynamodb-crud-stepfunctions-local$ +docker ps --filter "name=dynamodb" --filter "name=stepfunctions" +``` + +### Run the Unit Tests - End to end python test + +> Set up the python environment + +```shell +dynamodb-crud-stepfunctions-local$ cd tests +export AWS_ACCESS_KEY_ID='DUMMYIDEXAMPLE' +export AWS_SECRET_ACCESS_KEY='DUMMYEXAMPLEKEY' +export AWS_DEFAULT_REGION='us-east-1' +python3 -m venv venv +source venv/bin/activate +pip install --upgrade pip +pip install -r requirements.txt +``` + +> Verify services are running (optional) + +```shell +# Test DynamoDB Local +dynamodb-crud-stepfunctions-local/tests$ +aws dynamodb list-tables --endpoint-url http://127.0.0.1:8000 + +# Test Step Functions Local +dynamodb-crud-stepfunctions-local/tests$ +aws stepfunctions list-state-machines --endpoint-url http://127.0.0.1:8083 +``` + +#### Run the unit tests + +```shell +dynamodb-crud-stepfunctions-local/tests$ +python3 -m pytest -s unit/src/test_step_functions_local.py +``` + +Expected output: + +```shell +dynamodb-crud-stepfunctions-local/tests$ ython3 -m pytest -s unit/src/test_step_functions_local.py + ============================================================== test session starts ============================================================== +platform linux -- Python 3.10.12, pytest-8.4.1, pluggy-1.6.0 +rootdir: /home/ubuntu/environment/python-test-samples/dynamodb-crud-stepfunctions-local/tests +plugins: xdist-3.6.0, timeout-2.3.1 +collected 7 items + +unit/src/test_step_functions_local.py Step Functions Local is running on port 8083 +Current test file directory: /home/ubuntu/environment/python-test-samples/dynamodb-crud-stepfunctions-local/tests/u it/src +Found project root: /home/ubuntu/environment/python-test-samples/dynamodb-crud-stepfunctions-local +Created state machine: arn:aws:states:us-east-1:123456789012:stateMachine:CRUDDynamoDB +DynamoDB Local is running on port 8000 +DynamoDB client created for endpoint: http://127.0.0.1:8000 +Both Step Functions and DynamoDB services are responding correctly +DynamoDB Init response: {'Status': 'FAILED', 'Operation': 'Init', 'TableName': 'CRUDStepFunctions'} +Note: Init operation failed - this may be expected if table already exists +.DynamoDB Create response: {'Status': 'SUCCEEDED', 'Operation': 'Create', 'ItemId': 'test-item-123', 'ItemName': 'TestUser'} +.Item retrieved: {'Id': {'S': 'test-item-123'}, 'Name': {'S': 'TestUser'}} +DynamoDB Read response: {'Status': 'SUCCEEDED', 'Operation': 'Read', 'ItemId': 'test-item-123', 'ItemFound': True} +.DynamoDB Update response: {'Status': 'SUCCEEDED', 'Operation': 'Update', 'ItemId': 'test-item-123', 'ItemName': 'UpdatedTestUser', 'ItemAge': '30'} +.DynamoDB Delete response: {'Status': 'SUCCEEDED', 'Operation': 'Delete', 'ItemId': 'test-item-123'} +.Init operation failed - table may already exist, continuing with workflow +Complete CRUD workflow integration test passed +Operations completed: Init -> Create -> Read -> Update -> Read -> Delete +All CRUD operations (except possibly Init) completed successfully +.Choice state correctly handled 'Create' -> Status: SUCCEEDED +Choice state correctly handled 'Read' -> Status: SUCCEEDED +Choice state correctly handled 'Update' -> Status: SUCCEEDED +Choice state correctly handled 'Delete' -> Status: SUCCEEDED +Choice state correctly handled 'Init' -> Status: SUCCEEDED +Choice state logic validation completed successfully +All 5 operations were correctly processed by the Choice state +Note: Choice state routing validated - operation success depends on table state and data +. + + ============================================================== 7 passed in 18.64s ============================================================== +``` + +#### Clean up section + +> clean pyenv environment + +```sh +dynamodb-crud-stepfunctions-local/tests$ +deactivate +rm -rf venv/ +``` + +> unsetting variables + +```sh +dynamodb-crud-stepfunctions-local/tests$ +unset AWS_ACCESS_KEY_ID +unset AWS_SECRET_ACCESS_KEY +unset AWS_DEFAULT_REGION +``` + +> stop and clean docker containers + +```sh +dynamodb-crud-stepfunctions-local/tests$ +# Stop the containers +docker stop dynamodb stepfunctions + +# Remove the containers (optional) +docker rm dynamodb stepfunctions + +# Remove the images (optional) +docker rmi amazon/dynamodb-local +docker rmi amazon/aws-stepfunctions-local +``` + +#### Debug - PyTest Debugging + +For more detailed debugging in pytest: + +```sh +dynamodb-crud-stepfunctions-local/tests$ +# Run with verbose output +python -m pytest -s -v unit/src/test_step_functions_local.py + +# Run with debug logging +python -m pytest -s -v unit/src/test_step_functions_local.py --log-cli-level=DEBUG + +# List available individual test +python3 -m pytest unit/src/test_step_functions_local.py --collect-only + +# Run a specific pytest test +python -m pytest -s -v unit/src/test_step_functions_local.py::test_dynamodb_table_initialization +``` + +--- + +### Fast local development for Step Functions + +#### AWS CLI Commands for Manual Verification + +If you need to manually verify the state machine or execution details, you can use these commands: + +Note: Unlike other samples in this repository, these commands should be run from the project root directory `dynamodb-crud-stepfunctions-local`, not from within the `/tests` directory. This allows direct file paths without having to use "../" references. + +#### Configure environment variables + +```sh +dynamodb-crud-stepfunctions-local$ +export AWS_ACCESS_KEY_ID='DUMMYIDEXAMPLE' +export AWS_SECRET_ACCESS_KEY='DUMMYEXAMPLEKEY' +export AWS_DEFAULT_REGION='us-east-1' +``` + +#### Set up state machine manually + +```sh +dynamodb-crud-stepfunctions-local$ +# Running DynamoDB Local container +docker run -d --name dynamodb -p 8000:8000 \ + --network host \ + amazon/dynamodb-local -jar DynamoDBLocal.jar -sharedDb + +dynamodb-crud-stepfunctions-local$ +# Running Step Functions Local container with credentials +docker run -d --name stepfunctions -p 8083:8083 \ + --network host \ + --env-file aws-stepfunctions-local-credentials.txt \ + amazon/aws-stepfunctions-local +``` + +```sh +dynamodb-crud-stepfunctions-local$ +# Creating DynamoDB CRUD state machine +aws stepfunctions create-state-machine \ + --endpoint-url http://127.0.0.1:8083 \ + --name "CRUDDynamoDB" \ + --role-arn "arn:aws:iam::012345678901:role/DummyRole" \ + --region us-east-1 \ + --definition file://state-machine.json +``` + +#### Debug state machine - aws cli debugging + +```sh +dynamodb-crud-stepfunctions-local$ +# Get state machine ARN +aws stepfunctions list-state-machines --endpoint-url http://127.0.0.1:8083 + +# Check state machine definition +aws stepfunctions describe-state-machine --endpoint-url http://127.0.0.1:8083 \ + --state-machine-arn [STATE-MACHINE-ARN] + +# Execute CRUD operations: + +# Initialize DynamoDB table +aws stepfunctions start-execution \ + --endpoint-url http://127.0.0.1:8083 \ + --state-machine-arn "arn:aws:states:us-east-1:123456789012:stateMachine:CRUDDynamoDB" \ + --input '{"TableName": "CRUDStepFunctions", "Operation": "Init"}' + +# Create item +aws stepfunctions start-execution \ + --endpoint-url http://127.0.0.1:8083 \ + --state-machine-arn "arn:aws:states:us-east-1:123456789012:stateMachine:CRUDDynamoDB" \ + --input '{"TableName": "CRUDStepFunctions", "Operation": "Create", "ItemId": "125", "ItemName": "RobinOriginal"}' + +# Read item +aws stepfunctions start-execution \ + --endpoint-url http://127.0.0.1:8083 \ + --state-machine-arn "arn:aws:states:us-east-1:123456789012:stateMachine:CRUDDynamoDB" \ + --input '{"TableName": "CRUDStepFunctions", "Operation": "Read", "ItemId": "125"}' + +# Update item +aws stepfunctions start-execution \ + --endpoint-url http://127.0.0.1:8083 \ + --state-machine-arn "arn:aws:states:us-east-1:123456789012:stateMachine:CRUDDynamoDB" \ + --input '{"TableName": "CRUDStepFunctions", "Operation": "Update", "ItemId": "125", "ItemName": "RobinNew", "ItemAge": "56"}' + +# Delete item +aws stepfunctions start-execution \ + --endpoint-url http://127.0.0.1:8083 \ + --state-machine-arn "arn:aws:states:us-east-1:123456789012:stateMachine:CRUDDynamoDB" \ + --input '{"TableName": "CRUDStepFunctions", "Operation": "Delete", "ItemId": "125"}' + +# Check execution details +aws stepfunctions describe-execution --endpoint-url http://127.0.0.1:8083 \ + --execution-arn [STATE-MACHINE-EXECUTION-ARN] + +# Check execution history +aws stepfunctions get-execution-history --endpoint-url http://127.0.0.1:8083 \ + --execution-arn [STATE-MACHINE-EXECUTION-ARN] + +# Debug DynamoDB operations directly +aws dynamodb list-tables --endpoint-url http://127.0.0.1:8000 + +# Check table contents +aws dynamodb scan --endpoint-url http://127.0.0.1:8000 \ + --table-name CRUDStepFunctions + +# Check docker logs for debugging +docker logs dynamodb +docker logs stepfunctions +``` + +--- + +## Additional Resources + +- [Step Functions Local Guide](https://docs.aws.amazon.com/step-functions/latest/dg/sfn-local.html) +- [DynamoDB Local Documentation](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/DynamoDBLocal.html) +- [Step Functions DynamoDB Integration](https://docs.aws.amazon.com/step-functions/latest/dg/connect-dynamodb.html) +- [DynamoDB CRUD Operations](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/WorkingWithItems.html) +- [Amazon States Language Documentation](https://docs.aws.amazon.com/step-functions/latest/dg/concepts-amazon-states-language.html) +- [AWS Step Functions Developer Guide](https://docs.aws.amazon.com/step-functions/latest/dg/welcome.html) +- [PyTest Documentation](https://docs.pytest.org/) +- [Testcontainers Python Documentation](https://testcontainers-python.readthedocs.io/en/latest/) + +[Top](#contents) \ No newline at end of file diff --git a/python-test-samples/dynamodb-crud-stepfunctions-local/aws-stepfunctions-local-credentials.txt b/python-test-samples/dynamodb-crud-stepfunctions-local/aws-stepfunctions-local-credentials.txt new file mode 100755 index 00000000..2a80ded2 --- /dev/null +++ b/python-test-samples/dynamodb-crud-stepfunctions-local/aws-stepfunctions-local-credentials.txt @@ -0,0 +1,4 @@ +AWS_ACCESS_KEY_ID=DUMMYIDEXAMPLE +AWS_SECRET_ACCESS_KEY=DUMMYEXAMPLEKEY +AWS_DEFAULT_REGION=us-east-1 +DYNAMODB_ENDPOINT=http://127.0.0.1:8000 \ No newline at end of file diff --git a/python-test-samples/dynamodb-crud-stepfunctions-local/img/dynamodb-crud-stepfunctions.png b/python-test-samples/dynamodb-crud-stepfunctions-local/img/dynamodb-crud-stepfunctions.png new file mode 100644 index 0000000000000000000000000000000000000000..a5ddf9ab9f2ac9587055b4e971e0256deeb33fe9 GIT binary patch literal 47727 zcmeFZWmKHY);|b@1PdM@xCIDqA$S7;0whRqch|C;7kgY1W!GYu1GiR98J!wV$oOy{nqw5Asr&=p^U}2nd)m(h^Dt2#-Jr2uL)j zPvAW+Lx`#f2v6lL#l=6!h>KHwa0HrJ+L$6BNC(HOqi87i5@u*C$)Mr{eT*APrJ|wx z7>A>Uuq}xbABBuc*X94!NQ#I+ry20HWZO8rbcFZD;Z zo4$*Un~fpg2mX^`{>`CzPZWf=fui*Nl2r&ju^auy;z%>GG0HRF*+d^bYei;j6{k|^ zsU01~MM(H|4qHEy`}kwlI)bUl_xxcxlNFEIAAxEVCpYw2n^2H1G6ImWZ|w>J$26)Y zDVbdvdWN&x_w6%|dVzfo32%XYJ&8VXX>jDa*ex;wmmF1;Inq}M2FTTq1Am9Zpt4ny zDMp(5JaC4W9axXL5`Z)JhLn#%JbPH?;T^*XFlD{@=U8R99mHevJwalrnNMX(`<`rIvnH;ctWr+})@l`^hLBeB zQ-di4U%>{S@<$5xxS_2*0{l1?VRpi+wepr_ct1cn(Vd1~u@Xy_^M*`=N+!%-1Aj$Y zQeNlstDKb~A-iMG+u|_QP9wB39TrTq54*;u#K+4sVmD2okZ&_(_?mb=YgElCU;@hg zA%b&>m(LF=yFQ(TWY7Cklb0DOb$noF6g=;uKJX&hA0IFM#OvoB- zV;ZW!SD!-zpRtx9Y&%Szg+qjSlzeg1v;a~hsd<8-_RhQI0lTPm%v&pN?If{x#FnsVk!Lzt%ZH>LKiukD*b?ZUL1o8Ix>xHj!lT1Ne);xqhv zFI*9=yGRg71tWNjie?lEDD)f@o~X@_*pxlGUlUD_w%+KERW((D>g>+%-zqL7vS-AX z%!V~?mqQ$7%+vs>7%k6@Uh6YCleD`!xH>!*J-btES=8%%>ZOjOwo7DpRDy6x27|#K zwlRoY$v#pFEi*%Vh=vj#iLjC&q>0d|^kGbp71!e|r+!9s10!-E61Ea{ts>3)@gAax zQ9YILbB}tO^9EM2ERgs)*?>(0IYf+61M~Gq^is?{>BZ=tBQXY|Yexen`CZ?Xb zZb49wT_mNDnK(jffpSf@-;R*uSH{6TfV*lS#Df0*Cl?3*Yf9#yeWgr=Sk|A0uSll+ z&J1AoG(#PbT3Vf--`tVdI?R_(jtJZz>xECR<{nvJiZ>EH$bQ8SL&ZX7M*?#MN693~ zyrhrAb;ZZRA8Kuyka3rLfu|`!nu#(W+S_5XLbigwLb&3yf@UOm#90<8K|>rxCJp%h zGUj8P0u#M0%|0zTgD#y*%wh~rPmT$ZBL{x~3ms8(e~)KxcaM7Sa1Z56t!K<3M06oE znFBe6nR}V96xoyo7%6|us*vVm^JJvR=}NHXPALw5fGO%*T394myIXZwNWUVqinAsg z;VU`%uu3i$Xr{0_s$}_Y_T4PSEZQvjEVDqmo!muk?#RhD^ES_^@+rz`O^U1>gIsft zw3DA%wpr7L>LAfm^!AXSrn08bxcZ(4K2IbT)_TTj&6<%QYTc}sJ%wAOt>rx{yYDco zI18F(uDr0)A2}GK-qzSf-VSn3*xH-m&pt^C=44G0%89B=stW~uf#kiPs2W}0HQP z^!onV=nn7h?wa>>iL?~+(^JQ%Q_o*LpXcqs+{ZM2YEELuBV;_ot>spEVFBHW8AXwL zF!CpXkam&`a?V;#SWTGQ7?ByVa4(v8_0@L!o2~$3Y|9tdl4NQa$0w#$jOrIpYqx^(Z3|-y6Sa6X+#p+XhqmapR<;L_G21&E^BFaWUJdQ6!=B?_ z^^9(r)c(R=#UArMyWm%>11!8iR;+zvRAZrT>28(qx^-!%H334tDFJ}95x*oK0Y494 z({pS7*QR?ZWt&|-uC7i)E{p44ZfQfcr4Ev-DP4ElMlc%ZJm)$<1_0oG`{^irRli=K zHbl3ke$myqUd~y2XKLlVccESPKyPz#-*7v6qYSc2D3ypmsQHs0CUf}oP-hvkcQw?% zz`V5kb((T9Vv&E*v#Ei8Mixh5h6h>}Sr^%A9;gt=KF2%g)&L9yCxcr{`e4y50WCeg zH4ogy45$ll7ldceQ zF|0|vq<$sjEVsql%&Ff~0=@VG@*l(yB$vmC#3(`aeP&2W9chsgB>yzE)^4Rqx8HX|_CxW3Uv zM<=Cd#9q=fa#-3bb$>65-H@w~vq@r+v6H3Fevz{$znx0<3e>(fq*61nGLfomlQWRw zXqXS3n9q~S<;+3LA%92voi2M{?&f6>o(kIa*wuFGxMzS6^exmWy2YaDhxQ(=9kR}!Mj@G;`b76zHB7egOD`!2F9}r$8`G2dPDWVv zHODlID)!CU!FPomwTBJ-mt@eiggP@PqCs!INI_t?mx<5yZNg(hj0Bb~o#*AH9=I-w zLz&>vw9qNSyDC0QhjF}BI*df2d-}E1S))NC&{0wL;`Q+QoKfOIkI9 z?%Lbc7jtxTKo}}SQQuTowK}%8!eDb;H@IQQyZfrxtOj~8wg5htzHnCQRs$Cw{m6q@ zSGuXPY84djFDBN*`Y!yIc>M_GgA?^*s>CK2Til2Ub$rQ9KoyaSU?$aUfMd$xCTQ z!ImerV?KTH+JwjX6+Le?C7R&a*xG{gB||Rw{8cKCI>n@5{m%2VnHb}{Zj8u_^r-YL z{$$XxLw{vLLoR)Ky^p|#^IY;F_vY{uu&_&n=fNcid@@MX$VOJzQ#WJZd#B`GpuGzP zFZclFHx|`=A*+t71jEd7`}nhwx@Qd@$6Cu(71LMK>_?@wl>F+bf zzzM?K-fH9PW0Ujb^WN(!;#kkz5O$VDyk)U(8|ogn z`spHQhZ3*I*Rn>#s+UEmbs}HRNOkjDfanh9*EGQ#N;7`(F#d*y^e&bld+?vy|X3Ij_TLChDJaaXJHzeUmN}X^DjD`EzSP3lbzH5ycYZg*?*0& zbFy);|8LVw-7Wubru`cE*R;Rh>tEXm{aQ>w!O_wbPVg_X0GvX9ZSY&)f5;R1wTi$8 zOLtQn4GBwIQ#+?$bNKl9h1mbsk^gn3=6`1Lyn6l5ng1C1pP54JzxebIzWqxmfAzwp z0zemH|69TUbh>EMTm%GB1Q`i26?eqFCbUL#b=A!VSP_5TcP{J~(oB!g(5U@z=uMSG z;~3kNGsHwCwaVt8JhK+QUb8|XC8=sRCt_gdXE?9W-`N|)$vhzrf8qbae?T=^98XDx zDes+CBe1CIV%8jd_wWE*xXL(bSu#F&*sHqG@+`R%o`hXFr5hT(i)ckeL={Cq!ug1R zOoi}Q(^$;Fk;U~V{r`OYd!!YW>i9D7U(fvAX%GhQ?b;MV|bdM$Lk?0u3JVE>y04YF~*#?&Ykzq;}NjoX%9sls)~o`uw$H=`&=)6K{Hz+4n0ozc}ECM<~&)5Flf0WfS9k|T)-$h*b${DT_ip{ zc+>PzxNm(cwVpme6d|xfq4fH|XR`W}>ovha%Y$F3Ck%j}%(OQp4d^CwGI75}>kc%I z0C3sNlu`>F_e9t~Ji`70TX52^g*D%_N2CjO`WjdX{NZI-(EWyjg+}F}m&TD#fp?So z=f07iv*P2aS!;dXXs$~iq(Lb=r>g z>(zp7C3jsge{I-h23otBnbsdxMHnc$nb9k_(?i<^e(?3h@!6wee~JPW>d7}%6qfYM zC8$&_P!ABthCE-qtOq}RSltI=>`oVP3t$W1O3yGL*|&@Bw!h75O+WU>|E%`7-#A}%t+?3MNNN<1#mZZU$E9^WwZ6m~oaTRflAk49h1=XyN*=Np8Jb~AyL z#Uzu|daFYXZl(y-1A+Q3ae_HMvc z-QjwPE=hH-ZH)fibxVMH^KCZ$f!+x|JNCnM74VA`r64lCe2cdPtpeF=E0o}hxV-{k+h~UQH!;e8ZBF$TO^oJ^y+qRL{ zT=>GL>cE2A3GP@6iGkm^Zq0MuappbsT4SsNRAHI2*k|!dQm8?^PTjuU-PsByg&Z-r%$ zXGw5%ucrn}yzZ7hUvGUIo)F$XRhDzs3`DKQr*KO{;|Xs%+9*12BWP+m$=eiy=jNk#Gdy`X$Jf9dMBYtZF=~7PJ**wo(A> zJ}sEF3{=~U5ZtgJ9p_m*+l1BB=v(atGmx3@&VEI0bpkskG%lRr?2cN*@cSKaCfgtjSy(L76c4zd43QljXV*xC5-3K4DV*~FY z)4i!&yh#Y-+AMB+UK1J94bU9cm9%#tlGk*7vRDNAOHKD?4U$ToQzzgX8_*Njf~)q% z^_g{hsP7tR<04qWTVAiHoLT3-h`D`(K?p$RJI`sjkfLgs=%ueP?K?)C`$Z;iVn2S4 zt)%Y!$?mvllj%tb;PL_*FnsgVevea0OsC@Q>~Qq3un@BlJpq8=qwj6;#g|>+JQIJ% zoUE;w&!2)v^ovkE&XJY9n<&sH1l&Vg&>z+xJVI5vv1)jAc2aqG3-u`@glAa zjq5~9yj^S~ObSmg@T$@LPf&J}hjit~1dwqgD zK2xw^DHGUzr+eaT&Yg*dGA6Rb_W(n`x>}A#L>pK~dmH$0nhHGz`gV7GAL6AxDNel2 zxJfhrf~|XN4vl@VcX01d)u(I$Z~CQC{|;DO}c|(6ox-r{=pSuGjQ&J2Q-v%|IQGWR;@~I(AJ>I$*DtLoGDN zEzoHg(C_~Zpj{&;5=gb_d2r+7z6K>f=ZYt4Is`%S!Pjs2HhaxySTnD2GJHmKz$dW* z$4pE+c8yn4hdDKkJVH0g3W+uD0RGz^44;=m_x`KxR&@bRN>f7HXbk@Pw^!gYt0h>= zs={%zN3I-YZ$QhJd2J*jLZ+~uSSOc$}ppI#h->hM#crgdu2VTpYaLa2KI*R1raZyN8SDv2do{wyv&2hs5pk z{LX(hax*-Y+aM6*xBP&^7bzVNBkiZ9V;0*=mG6Lf&@d)50+ z+yk{b56hX0u_6yV1{U@TX-=cUQRZ|yjXfYz;~LChn-4#CfDaRM@)uZj>)a@#|4E7e z@_419$O3f7b}g&LUkQXJLA$(#*d;f4>H(O?x{YYN!8@=(@I~RFx$m(^``fE8=>?5) z$CypI={IXS5arh%sT=zDgLF_u5L#$++IpSHrK~3ac+-yE&zidOA*ii;O)kx?w_o*? za8N&{#&suE=t4&FfR^$hPJU8A-lr`X3VzsLIn-aerraOLQtYv`I|9ZJ99@Hbs=Rn% zI@)gF`MxW^mb;r$DLaw%KPjI<7C2jp-#_-6zj?S8hpPK*Z?!HxV3>P0hjeIMnmBm9i($l}|GCk*d7Fg}HX$_?^y2*ra~BbPVL5Aj%^#K?kaIBP}8eEzQm8jF7blA-E;VtJZuhqV7p!I2HMsj}g)ktBrtnUIzaakQAxA0V1 z5j>Ss;THt$*BUK$x|h&R5$)zgH~Sg7VW>A$zs2y);DyRHB@LjP+|$H;lG%qP?Y={K zuX?abX<=M}`v*s(60nPhH{syh%kx)i&jDr(3iz!6An^9<6fwrj z{7c0`=vj(luti*F+}c+&CjIajG4k0vqOuletJDR-W$DZMPfO z{aIUI2=`{Zr^TQ0z(ZOf0KG52>(rE3dSc~EbKba>yEJfezEap%_y@ds!^;G^ZX>v| zsnx;0V$L`5t{1&FS^e%6<$cz%Xy5Tg7aA-D!-^Dn^P2Wi4G;r5>p2x*+b|Vyw;;O6 zP`QTwn+6YjYAshkRtx6vXfqUSk60*ZZxWmiqK^SSJKb~bp2WXtdk;RfaKB0}XvfC_ zqoVZYKBH%tTEng^K$x%brI~kr$T-vnqe7e0`y;#wA0+I5m(8`r*GE>yOhUWgaeR)` zZ~&g|#fPH>4DA=Lg_t+{ri=^hyG6kpY`_didu(p@!8W)$H?EBR;qV_=fE% z!H2bS1#MkbO1aO*QX@ys7wwm@IO|)g0C$4)>c16;sBkr0qjQZ8U?qz3GQ!6ciX0J+ya)|p*x4n z!@BrB*LgQ>>UI!(z~Nx;VXLuqJ4M|(r`iRf^TSDoP09S1y0f2WuOoLp6z$n+u)b4> zK%tDEr_^PLZz6{tVp_LfRKqZ^VR}*o!&`^Hm!(*q{MxsfG0!t#Sf_=0{%oZ9uwXb9 zT|vN1)qP)?zP&%=6+yG}xG{9MM*a(M@ij5ULWRIy{O0*7KkpR~g54_t=mQW;6{Vn? zlQ%F3J;dEXA*l>)@>gs(seoq%9#VF3z&n{7-g#bJin(_0lzyL4>EF@;W7)6VGz!ED zGK_mnAdK}AUlZVEo%tS?$kE#5xzJqyuok(Vj~eO)Y=#oxGZ=9gu07?iO_}s`&aDLP zW}UxQ2dW*TEl_p-eCd0g&!i7%w6EFz+`+TWdRUtvLc}D#(Z-ZZsN9;#Yoor&@n*w> z?;xrP`UA6|4WO94)Xdzop9Zhm-uo)pVE(gQ(=Y#3nTCBVDT>#&7!7tk%Y^IP&_>y0 zMI&@SA_Hn>^{2(ocnak6)pfrcmt^TZvE{X$Bfj5A^=w~vE5?pIn9>%wNL?;yp%C%y zE3>KfP(`&?-^a)$KeD(K8ODGTN9vQl?s=~Y*Zx`B&sw_k^|tz#3kq@psV(d^_VR`3 zxnxz^Ox^`+rp(kju7N9W*9IRvI3E3uBtk?{Bs0`bPt^u`?dQZv+lGDYf$rDA4Q<*! z_DX;%_@xWHZ`qFj@Y*J!IF|hpU@oh#2Y>{=vib?3DFE%VC3IG}n4eLy0Q$3a} ztF}8+;WJtANoMe;{chyGC2+O4kkVV~Q-v;o8(*G;EF;rOS|WkE_O1UZb;Bz{M7TZ)jm zn)uY5X8O(_ZaJTFdy1l@{7WtGzN41DY*zW0cc?7p8im@@USv<7EyAyo1mVvp%*@S{ zi+p+Zow`Qd3VgAv0r~+Bsojs13z(xwLkHKpDqJ2XoI&r?3s#)`QbYw_MN-ZS5gg#O zEZv-1fqXtF@~$3q6aQ0%aXz-b!Q1ldv94~=U(9D@UwZoBI4%Zd*1ibD$6g>Ef+viJ zTp-T=qvO#dm&{F-!y-IZ)h*W4)_q713&9sHxe4IX{vt0ywJ=E=LrVp-*J`y3^gK{4 zki6m43DvU8%Bbks{f#ZPmuY`~={_e&ENt;}-|qz;QG;l-(|2q97z7_8duz_@Vt8#9 zPg`dXv6n_`bPli-K=b}Wf;H@EpgjpbF$u6RFT<>r60uvXD=O+e1Vh47DOUF z?IQ0-thNBm$6denoWeV}&!l$eAg|PPjs({;FbFI$=TE|aJHrk~!{w~PpUp!tFS3aK zPgZ32SR+WBReC<;+pk{m_UOmi#2z2Vgx!vgGg6bss-QRMnCluwPb$k_~-Yt+^J$vI7!3Jo_rQyu0N)D<{zI;Xc z?eT9BQPe;T^;Bn#;Hj*Nq-m9YpAFn?VPpI114P+;iw7MSAaB;z*- z(Y*9TF}8oG><1+HDHi!3o&P<>`UT7W-#&C}-RTsyzbKlXt)y&Ti|I_t;Qs?3h#DaK z1vB!$4I8ZYG&0I0sQ9Q{v(foSA~a%-6q=V_t6MSrz|}+ky8(zwB1Eer{`~#4iwZs? zs1cwq?D$VG3TMCvT+uaEQI0=|I88>NDH&Feod2U=1sMlKfFt`GenLRR+lEN(6u9MPKr|U`{V` z+6gI#Xe;HAAqvZR+tgmnaLQ;mZd+$I+g%waXC|L~Xmm}|MTzi+!FQuY<>bT|zP$^5 zN;R;v4NWf^63!Nq-~RMI>ce>#%$1tJQ3Dw%FvG##eM&#Q4wajm4!J89e)C7Dgt z3`vpC#3i;od9heBDg=I$HqSKlNw4dvm4rt5t^;gn93mWtH>3vzKNc=HIvH_N&v%sb4-DJg?XIyBzqH z6prE+YOzc>&5&~>DrC1K$%@f3Cl`N2VD7Rvz3uWe*#7`2HdGSeq>h{nP{P}ua9(?n z5HuxO%_z zqs|{Zq=HZ0Hc*tGVW?Nxg4e$|3qi82A=RL<;U7NaY~4l;TV-aN(ac>ewYJkW6&?ZX zo;*Z_P4<1U_7TQZ;hP<#<= zt8EDs9Sb2%b42K@Wlh`*{&sY|mo^$*IUwj1GA%kLx7u0BNR<&5yVuLvjh0DZ9=Bx1 z@#F~O@0?LU0wH?(Tc{Y*s<`OmsCxxKA@P1ra@ROxLG*k&sbz}h49y#@-AxIz>7G1H z4AN+M*Z3nfuh*4^XerhM6=m9)eMUwG<6+e$+_l4IjX^AqmR&9pKi&6Pyb3kl3B)rV zng1t-(7~}kn=Ym!F)5N3Yd=B7t6pXk~LjUpn@koSYaKk=U52lv7SqLuho6KURP_AYrYnf zE-6>O4|$`#bP|VVQ{NR)bh+!uB9gU<-G23?W9pd=*pcEsEZwT)RY5lqX^MB_K(?62 z%(aq(oGYiTS)m<77gNwim6uQa-<3_jA$S7iau5?W!iQtABUwzP!cwafMXpsr9O{{| zICKO`vAmTdGL=dNbep&CJHRLw=lbk}sC8+_jzBJrX$?$i>pzpssk>O1(3_rTRj^#R zogNok{GF=*bNLZBZYxCD0u9BCu*G-`u%VCQP*}udbo3Fx5N@z+)r}w3E%Iya-_fLx zg#hZz?Wr0}6zMn|QP$Jy3*r8Pt*P@BN)B;(*#0-3z>Wmh6sw6|;sF|y36<0Typ1F+ z{7U1iO4-ISv|9H*vY0LV{bs-C)bGRa6JAq1buey*yRDJr(HXveE; zO)@v`{_#?XcJsLfe9n-CJ$O`~Jfw#v(M;&Na$krO^FO;O!gq_%dp@?qi&*rf6G`(K zZ8K>+#y$n5W^Kj$m`BB{ST3UJCbqdMQqKJr!d&>;3}^mhNGQJ;QjjxZdUj}Ot=+vd zQ5pFkZ9h$eYx^cq)Ty9stEA++vb+P3l#qGNyhS8Ke~Sf`**961oYFy1(!MIQODWY! zn27BhlYS8!XN+yG2W`Br+O*C6a}}P@>y(HFoYd+U)`dYeWme{-xLBJ-m0@d zf(_OgST(aJF4K3Pb9G@!DcIfT0Bj{m#4vXLax7u^)!M)3>i!ek^3RU6?FP3pGPbW^Hj#?frI+xrYp`WL& z5#ZpK?czO);El_HQsIMzcF(}QDp%RRqGQF3>9i=61(SYToo`oEJ1Ku*V6xIV`w@)$ znpaWI+P(4oKQ&#y101;hZfZsKKF94DUdsa<_9ga3OgWh_@j40v*A8@zB#6gdE4Jr! zA5HbRgG*h1*br&2zgAHuzo{ph)9P+KkaS&iI7=v1zIWBB;@PXc-k^yT=r^nmVK-N# z`#QgO=mK40v|0nft3igDuXCR>xOW*>`&};sy4TTE_VN(C z5TJ?4BOhDey?{H5VD)rib^*j98A~1omp515{Nqe)gi5^@TNm2{WkE!OBBN%pJA|3X z4w@^&TUQ%9QuFzy6>Ytb*@<`Y4(j@b zPd_kqs4uHS`l4LoSK)4gRe>~QRgQaB)8C!eZS$>`7h$z!>KZtc7qA}Z6`JF^U;EB( zFm8?;cGtQ&uxda&jShw%(TtpM5;eb6KP{}dC5FfB=p(f!kde2v%`wi*Y2&r-lDfo? z_G_*f6M|RkvNWoK$hK^6Eydu$B&bHys`Eg!Z3tL!I>%bIqDBGGI|ntSX$O3#^yoL| z-?;Mt&;<(%7c7hK#XDPw8+gIXXk8bxQsbvTj#8+Cm=~3mKTk6V9BYWLKdu=7D;N}cNSt&|& z_~enuUB)wpA5uX!Vpo=sWY`}!p5tAekZ0^=IrPgv;Q1*_%+y7ZJTavPf>|CLK-i`y zy-t(lFXQhksS*5+;5tD%yxUitkpA(<=NBY8g0<<&{g2AJfw_g<720+$BKz!CT&U1! zP8e-4$jvsLJKH~v(RiewcHa%WFE270daSqi?BQ8vF1b1o^8$X?MXPgs)q;PC8Lm8v zYSV?oMytqj6+euv%)h~ORIa_&`G@d4`_5m2%k}3>W!t$y5QAuS@-Vn?3tu8>@sq07 zDI-=(+C`Glbr9mK=;k?%n#T*-L3CtK2QdBQf5q+{$Ebl?oI~?t8zX zyAU2+p8LJz1t$v{^A2tg%@hf`wKtvMQ8)zsYN{&KKxhl57cM6RC&p4&RS9ecsvYft z+Fy7abGw!gCvB*Fpd z2*_&B{0t`>)}OhK|8yJO+}!pe{)~X!6$noZyo%`rw{Z~1MN|Rp*Av+b;KF&xOc6

cJr-3Ff%^mR5kwY|GZ9X!np9-cc&FWPUaH|EiWCkks+u8{RvNV_+O zOiP<)Rwh#@=cwI=m6m||hKhpF*w7>Rl{G&CQG=w`hCSA4*7uWkkC)9t;pa(YaP8Va zjo?6)l@ir|nOEMnCgIUw;(-yAP^|PL>}_D1yx&xoBklA_%#pAE|96KQ`uFT=dob8IFW-SJ?WF z>O=Erc>$6FbNCs`6w%J?7O7a>zSB1gE^K7NM7W$BuDEW{>2Q{ciQ~IRV9Sg|c{X__ zhvt*?jbrOOZ1G)Ry5=S%8)vQ{JgF0eBVZO4IF{Ls17G9TSV72sJT8$cZsb=#IlXFx zHyAtnjl_>9`j&onI(Z4MnX>BjPI&J?Zzu>$R_Wi`vX3s|_ubgI<{T&`DVrzrGB!h( zevZEyyT+nYKV1n=85dbq4>8w{poB+^$G9&G+;t0=F&pBYso5jdxKu@59bg!B3LBqV z`EZiR0_93k;2uyk4kJc&f}Fo;ENs7AYQe~4e6DiEq&Gpif4u&T;f%0)oufld;UvP4 z(AqkzlBdN0IIDu2m}zW&RVgdX z5vv&0xI(QsCdFcDCA$8O0JZ4G57{fiGnHr?*zsr+xz`2UbZ;%0Ysnw3FBt=r z9}ZceIZKT%7ppZNlQ96+xxFsDIGV#N$X>8VTT>2_-OY;HK)i8#0DLMk>p;K#qu<>6<2X&6m7NkoXuQ-g<)3a{aB zmjyv^#mn(_m6He)@iaT4w+eADlL9m(xNiJ~(acA6ICzGOvk@E`k9Z&4`0mYpUfBqB z>$i;o5=T^)w=a%wN6aydQ_h*uy5gk{lr4LF)9)fOfMMKlPSBuTo`5hIe-I*lS34p+ zeyP9GR+NGvlTb%hS_@}VXn!I^{iWY`ecA64j7|nPS+}!yy?yE7x)aql3#YLPb(}BM zD*BITyCzo+L5Tgd>US{vS<2gTId$~|X9^-$rsFT5bG{YggNr|A-2y+7{s%Y9NH5_m9us&3pIGA*!YH6s`XzCVM@ zMr;@403Ut=_hV0zM;`fs@Jnl~^X-!kl7$rESCQZ*s7`0MYvC+?^`pqi!-E983tHs2 zpJF`iF&wSbPi-y@~e45)v$&Ol4( zaS+fK4TAe#D4cQabt4#lkExbdGL!T780W&Jrlcil!{3P#udXn5=ltA@C6)8C*%rNG z{Ae+k^eW3)mUB@vg%Km%qXQ5|q2D!DyCn^JT4qarVM%NmDx;3OmOvJ-BPggDl(B8uF-5b$V)e1&rVV?`xF({H2R zcZJ1++^)0CVvGh`7x!BC4u15_O$Oxf0*dah0!nJSB~6Ta8vFE3M|IJ9h_03h>d9F6s{* zK7(vI?udGtO}!Ku$F;JVpf_3DWMQS8+jgK7ZBAoDUj7b;8Yi!vq24Li*s$D}Z3S8_ z=gHsF6G=9f;UyRZhcO4N!I+x8*O(OY;GtOdTolsr9{*qZ) zi>KT%7OThImiP0HK_-2J_Hf(7cNW|Aw0xEk(d=#3K6rc=UAk9 z!hsMHbvA)V4V_xIyOu8Kf2Fd)qKxO2{gS$vKc4xB<$Gsg5&3X~^7`MXA8GNw`-H(t zCAFXI19z@a_!kceBj~urzS4Znr?UFYhqFIp7x`3cEOy>W#qK*XQ$sPCoyU$Pw9xHd z%Te!kocdTZAlLicmv!gOuS@}Y<9h?r%$jNB$y#{jMD8e>Mx3h!%PtJn>?hFjWb)Q} z^!yhD^#6!KBV3>{mY8UvDmz!fU*6)CYd5D|Y#qSnL7?DxZv5@>_u+oHkJ8YA^QUvY ze-Ca2RzW(Gj%Re)Yy_y>*I0{Qt8{+&zUSTD5%;4+_tG;UcnT$cFWZIoVYAS6!mfBZ zldQi9UWrjZ?TDDBz24>aoH{l?i19sXYUR`Sc?;azDyN3O@i#OJo*`yOKn;dS)m=gl z%hvohf_bEJO(%|_DZv$S%mB?O`lS@tiVY4;cyWYyA>+JbVbX z^?FHppd3)%0k^oraV9-}*RN+^28DGg*>#d5u#9oGu;GxgJ z*oq6bWsAq`t%wgN*=<~`OZ`vt2O4D3P?3~U@sW&L#G>)e#maAc%5x40=VSum61kTB zkcHG=?wSj&_T}+Tq8jA%1pS0S-{tYh_O*Z&`&)vNLcIJW6-2?$I}tyG8vZ<#t&$hP%0T}V$ebR#j|MW&QQor3yKbWVgdnZn56 z=)euG+4WAWJtkqO?sUT$L?=6uD$9lX=XtsgENY1ZraiS+FW3kR0Ni0UG3p_c%FKH7 zmPM5KWAe%R_YC0;k!&P4E(1@pY@72G($VK`t4h{^!LN3ofn>%b)G}s`j~rO|zq|88 zN=qocg%%Uox|B&Q0pUkx1Fz(Byu-;8BdTxa^6NQJkky|1v1(WQWBVL_X119gbnRz~ zN2ewdXQ~9;3;-hv^S49Q33oL1m@+o_r+2=pvBSSi2CpzIyAB@cU~m!BBB`C_y%#Y` z)Xkfj*b~4^02Cn{vA}EDd!u>Ba?yj0b*h)|D%LH<9U3j)HfUDbZeC8LSEL5B(lB;! z-kL4-yvM|_%}pKeFXmbd8UFH`Ma(H2^txKobV-O56SWW(iSnvPsx4k!k9hI$3$K60 zkbt%1Ufuk6bYUVlwK_b%%@u{tjC)Yk;A6;}rrM6pGcUrdkX)x5fLFSq`C#XTIVY^i zda))KOFIw%H?9M?t93G$dV%~FZ{$s+YU5jvOHsUMb}4%!7W_6AG&Vlt{jm#bgtp9& zr8fX)2i7b%^wu-SUNgL;!td9!@BDrY7l@oQ}1H!elxd3!B)Hc$sQU&RQwYC zdOles%WSeSbf~mXow2sD$eci&4QUf2pHTHA9awyX+E^Dui-q+5JwkL%WuvC8B(8K- z{&&tN%<2LkLdq?8gXr6oA5M#oL-xm0i}|Zx3!epxJ(zhna{9mby;Nr{%o8Ha>{Vjh z+hT0VMh&?MY1tX69B3*JSMHY#FBhMc}CWcM5CiEHve{ zMJ<#@Vy?>1eFNL3Ik>e5X2*41hkh#AOMUN|m+y|!hw0}=^(IXGt00`S3w4AhTyK#J zLl`DAeh|dGlAfgWm60w!tur{+172-^kr18 zL(OK*_C@yu>(SAt8r$uGG-sW~V8-)7;0<^3uzH9C+i6;?uP;Zpwb^Uk0dZ5^z8;2B zr-L(puSZ6^A$icp{w05$w zOHp4kvO4)AYkJGrY~qs++lDZO;A(kL4T+f*vx12aKj3XI&~v^a@SUS6LsnB#Rp^WmNmSQ&ATstiCrV{4`>9~N}>eMUH3mkG1`$TdK(oo60k*Fb(OMIhTNX`5I>KNz(r+}(Y!44E+5V&o7?K$I%Jyk@FZgP zTe+@HHqz2^<_^14cI&3FJT_~DVs6MLbS2+VZm9w|O>Gk@(ai0{J zeecg@ym9+&z~jn4w@#|^6o6MLd?XIb3^VHK)5^~kf<7_FXoeqY>UopY+_+MyHOgP@>%$+Qr2yDV&`vUQW z+=8h#mTC7Z)ymYx90GDPgV6V@lU!q>oK}Nf5q_h^fi`z-sFOnHU`*{sg{wu z>hjgmil>P;qc>o%7l8k{=~{VzJeN+JTq=bjvIzKjHmZ&^Kagm4SR^JXXN(# zal+lf6&y<^Jdi~F)WE}0je4hWBpj75oc~Ud(ObA{CO0JTTm#*z8yt)rdL#f1G273A0*CW&vJ9Tl*a54Hi~ z6la#l8k{Tm5Xed1BUc}D>tDb?$8hqpHnA4_V)$kNE!#WC{QQ<_L*myV$s=U7H>&>^ zdtdz))!(hHh=PEGfJlP~NK1D~N_VG7moU@-10pHi-6`Fj(p^J$4~;O?5b|!m=Q+=F z&ify{*Y*C$=DKF~UVD93-0NQV*z>XGXDhTvxVoJRwmy}fT(5`RXhQ-<_!(Wa40$8M zn}bMpJTirlSA0-eF@5X+PjSAziPX1$88l@vCAlO~1#-2^l@Hc;X?!z;>IBpT&%4*- zJv<~yi}IAMdr0`lKi2Oqa;VzyZP#|sEDDZY8$MVXC2t=$T;e~}el`}rnHTMa&(yFJ zH%94O0yow5GE`N)98U@5wIZLvjYWw!-n~etJ6G9^%zjMh@b zu)fPwuhrAm&4l#uI#;QIRZ1sfr^Wr=pJthI^LH!QcaT`#>dA{wQ#}LC%Z^gYFGWE` z6<0`H^jg)q)xUnFz%n}cMyT2V1vr2C)E~pu1@UcfG|?LOD5kQip?R%atq?xA`VvNjdrUtTeC1h>S(hLjie z^7Y9)CzguBN-5{TDb1vi^$-ATa)6Lu?1hk&XzRVIMTc-FdRx0=0B(is<50A}_l96& zB#!y@y#Ug3Xp{cOCb*v8{70XH4C6JR;JlFn=0ok)lD&cynaP=jTb%Tib(7^h5=WVJ z&*uhuG;r;gFO|>zuRpq{+Pbt?ek90Xt}(xRe;PGb_A2RSwEd>Wx`lC&s1on$#3f$y zrR?IU#$?UF=NTuvww6VdG>9XQ*5C6FQ*GILF+ypnuX;VF*>|n2HPf`Gz=oo%{ zqlyx7UU-m@mT#t%;tRucm{*L&KA=W*Tp#XKhF0ud2A_d88if_?UACt&WM`Y563>Ad z63v9@yeMeUWhEhWj}|xn)=gU2&kmgL$4O}$zVJP4&&?s%jX;Avgk>hCkfTn}dGTy| zL3xFEtTZUz7(EwKSD#>x{jlS{V?gwX$)Q@PpV-=a=r-&mTkl{mr(qMg(?`bNj+@`_ zxKsSukqPHPbxL>=*K%w?%yz)~v>0=*+NOHNmp+1Kf9J}R!>0MJ>03A09Ag;oxm2lI zvDxPZciZx$EbG$Mo6=P@-8!2+9i1&G2#Gee zqT-WTYLWX5u&u=eqkS>B$Y~BLra>x)Jz&M0Q+|9DKS6%mMEQ{giAMae0Q>WVi*htd zbjkv+oOtkTDOtnD%{9(B-dsZgLO_{t%w*Da4yu3^2xM)pn@lz2(s#5PmxOGFWU9iX z_Re!^@|wK)V)LV6ZPPv zIheViNO7Q~pzkfx%zi;LN&HcM?iZi*m`meS(wOV{hLf^m=nZB%)yQ9`m6uOO`(c7rcAa!{HO+!R+dyb~?hDI*FYWQLmf!_j$S%|n?Oy9LxWfoY+D3zHT zaC1%?)+&|p?^vps(A51LJhYe} z**0Gwl+0yMa1H{*jU;h_5)Hl6pTK};A#0P0`Mf1rL!(#VVktp9QqJu)4S1R1TN(dt+B4S)D37+ilndlBs zpmqn=plKDT=IYwnt3}JVyr5Y(1>w1*|H3gd_5V1U_GT2l);4El-wMN;^Jnf}vcpkO zmxLh(+iEtU2?E%E+Y!$^nQne&+l1#yUvvk5abcT=l59@1S>31(itQlQAWa=uxPEj$ zYQS2@wUpIlxIqyPmdn!NGUYYt6V-x6PC*Klab80_r{mnV`|D%jNy_))IA7YQgJh{w zGC8@{nCM}^_IcG|j-?j;cD40nlna5nvQq^y+XcTng0+q#1g->~g`1!2)bY*f@!8sJ zHAb84UrG_9q|d{9^h>q{pi_-SZ%KpA?72$B?(h)3VijTxdDclj7 z7o%5Y8okX&UH=*eb^0b*NM{GS!DSY$O&YUI50@_%x zy~tlH906u<%?(I(G-#3`tEY}xzV2PAOWOq5cnByKE$2T}<;W*&LZjz}7b_>it+48P zbpo!bn~&|rz5~k}q3=G9PV;;F4A=-|eU!Ni+u$x~Zvjl*KgEN*^3nZV)Trfg#&&yC z)ol7Mlc<|PBu7Q5GBQ{rM^EQoCyJioi$g_vUPY<)!a{tPtjW6_o0SjM%J+0n1xqseAE(-e*D+td5vIg@HKGhqQ_2+NQx(jIb~9Io+?#Sg#&@Mh z^O;|aa_gcoJ^1|)Cg#>R9oZz)e2P;Q$$sp+g(8GMYd63oL~A`~{|07bnS4 z4)&IkDx?R-`VmD zNodMBv~FrP_)WUQIKYzp1?JCsEKKVuwkRI&f%Sy~y}4=m_r2 z;T4;i`m+N>Ud*h);*w--*A0LLL$XGW-~@AL)KG?}>iVaO#YUB{&1!iVkiZ$!zlWJ_ z5(DQnJ`@#8SdtxuQ?k;a351>UCOf3{d*Z_*PZKp;UYL3wT6#H$&vy$u^@Jfd4@MY= z7MoztGSDORoZ(MsmlKZU>wnQ{)PYV9WzAL|H=itUAJ6f1>*{T*fj3cBYtHq6Z`I&7 zz5u>v24si(Xe55Sp>K9<8T{Zm*48%4Zliysd8&anY5b#l*uKdsbM$ebbRGy~%6~vk zCZBxzT-~7fySkj>`*l zIaKSVxWGL=%5}FMojHeDr`a=i+G4ApY&{;FU|*!5jjS)8qT(U<*18wys^M&94-{J% zh{CIH3ZKBaE#vR`>fZK!bkIN-X!Wmo@h-64GOvh?_Nv*28+MT9+R121D zhgJF$X5rR`qSr^d|DA7OK>-}L8?T)4Eu5GF1Ia|j2)=Xbb*aFT5==p0Z`CYP)T3-$ zeDaCBt!`AeoLg=!PKaJj@r@7c$Mg<1&f}6%D1c_IT!2)=Vy8PD7u?A3fcC5DY~#g5X9;WnR03i@sFvh@wY~?JIWE z1w3*^-jB{>cl_>_IM|rR#QSIZ|*)BnLaw*9dNJs8d+)@9iA9=m3EQ>6OI%lDLDZ@2fZC#$9|yPVj;bh3~Oy63u7)LB1NBA&ezxR`%epF$ROHVcF6 zmF#P8*2)Y#zIznl-Mi^YxlFJkUA~YkL^Um4pQagrqUrk!(mUhh?Ylgf&Mp|{v}R9z z;}4-d7}el8v{a0JAa}bnlvMj5AzU($qhKN0 zVI`#(=5An6Z?}u*zExqdP%h6>8U{-x!i*CZtTP0gxLpsXl#~inZ9+PMRy@$QI8F{A zxYoe_p|cUVGwi@eJ1oo(ETVK57+>*5%FNy{16tW`#N9{eB+WR-!= zb;Mvlp|*&1G0keIyD7jOHYn9bw4JbJOv#Ze_q|z0n(7l*z)IZ_%4EF zbs^D=_GsSL`w_n)Kef$s9A_+73&?cwxk7DfLyq&?oitD?hstQi@X}sXE85lcZ8AFI znv;#a0)^hv-wxI_i8t@r>Nw;P&TUM()nX7^^lpR#zLbZpRXEMx-o_j>rBS){quYeoPR-DlPD(3+2<4k+0GLr(Q$Fw1LD*|Ip#oS@UEL7D!0u7%;;$WE`cdp%PT(k% zvyczCCW(|>25EgZ&7ji+2*Ws={;ajO{UpnuIV7q|rC`#y(_=N9>eUTOWgXPg^UQC; zp%UJZOU5#sqZxLWCYz*RqjZ<4o12m;Zk2E^8x>s<@9a4?Z*~*1WNR5{v0YDHwh56v zoZx5TCC+9K-Mp8sRqI%%&y&MRrPm4-A+hz}W=sH@nTR)#S#La!`dhe>qj~xfG#9L$qbp3@ zK#9srUzE}7#Q#WZD%{Y=+a`?mW+*Xz|9e`FwscVR&_&S_-`28D!1hBp_lU)!U!kR} zweDX>PcqrCq&XV;YLf*VV9fjk30=0MCp}%i1JT!K?ZXul2f@5zI%-4}Nb7@7xbS8y zJc7#qzKJg68lovRzxNZ_uT8V_YRnt3;@(%I6{muPN-y@c(HE2RN^N;nwi)P|wBMIg zZBDa;doumsR3`~;X0({;d0!iB*w78plq!d~t^C99i%5=m9LGrDjMJxuG$h$9+4r2o zD-xgmEK!M!I|bppZIk@Nm3h?rEI$~qYx+d-GB8OkB{^6JQ>IyZqHs|>E?n($+>PL) zB@G0+gQJPzO{K@KZd4WSa>E!Z#>U}W+rMETbX{6RJ#&$s9 z{PQ}tm7QV2_p*l?nkKqeK>{H6e~2EUBK9fg0ERXdP=NcrNfKO~U(QSJqbWQF133c2 z(tjU?CTR*wOpn2li@=}0XM}=r7;K5X`uuJaGPcBLZp#JxVZg;jk7Qa*Svix%iaW;H zz$wVRzo3-a&|lJ4|7E<#A%fuh%nZ`Ri2me}_&{~UPE*||=Y9&fdf??FUe=6E)0{$- zBx)ppY9Yw1d2S<1-+5ks7gp!Ipk)HP&S#JeKI&95uX4Feikx*ipvCPynJddstbpuC zeEOrhk$U*WXneKeYv0$}auu|y$}_1Po<}wv&(qSf)~!kS5mUlS{ae_L#z-TYKXdG%XA-c8sAYfzNO>j*7e~-NEnVA&_3GifNifeNPC08Ka>*LM84i_$iYlJg6K{*{ zUm1FpdP?7aer7U5i91!5?-Yu}My-pnMdrYBSg2SdOzQO~n7C8yY?h=>WXeR|d_txe z_A-Rha%U;{l>hIUs((co+o8xW0nd&xeyhO2aFVUp(|?bgDjyj);v)9NQzy%D^@>)y z4?Fa2X1?}y)^eJS(8fW?Fb$R`kUWkblgHIU}8&mVF$#fz4^_KFmj33)-x7<{K#F9^( zSchSg3i^8j4`yV7{YF7U#g_?3%H8^Nd)F1Zf}Fzlo zw07f-GQ4j$scB@U8P0gZc?}FrmH--SA_;WMW(2WE=RP7DbaeAcb0clp^>3^4dS`?d62dJ5mZ(XX>#dmwm05(+N=>wvek#u~8<~Vd<+I69h$5>0JW~8KX_SHm zNr^QGhq4t(qyIqj$>>||#ur5bNpJL9&k_~-LF?xC7~E@ ztwNar>7M>`>B%=oXwlbhc}!un>>+QbIe862cWExlG$e`}!IdSumM;t_LH-fzd< z%@opwt>(whQp$>z*+ec6!Nm4}G=bZ1S zze^gB8k7C4Q3vy#Vh9A45{;VMegS-S8|dG4|5}T@F!?Ov?{i1}8@qmv?dvbwW)MIo zda+^p3*WwM!q6LD8bI{6c@xh+trEiU+g~aAE>9B>e(nRxyl&uVIsvy>@dpa@yu4YeaZxixN4*ujH@^zF5#5ymS z+gof$&TmzYH(p%?(yI_rWuFgU12E1|g2xg@U(p4MgQPK_N{L%5H!L&t11&%gIe0(o zw9q!J>ib)}{5jsXJ+cM*1eZW7z7xB&oDXNPE2j^Vg%utP&0aa%#Tl0401#B6THb|r zdgYhl-DqprlTMoMCi6~n*-^#0w{}^lNfJty8WIPW{tax!SjN^}Nnio;FFyDRBF~q6 z{NlnR&ghC=nUSq?b)py|ltFPqk69q@aZu%0F34{vj#P$nS0c-4Ys*RhTS7fX;cWP6 z<$68gPEwVwT`pa~V$Ozh8(tIu#(_s;w%?4L&C%C?wS%1Wb#qD{lm`p6hN((qkkS4e z2Sp{!j{C$<)TIbaD~ET^Cj0A06odE;Qm0qH6+md3=W69Q(K(^qrMn;BMj`z}gi8JH z<*I;nPx4#OE`ss7?!3Xe*1QnV(_;Y>d~gR99#Rgf)`W~#cAfMWO7$u|zw2sq?e6}D zy@;(90o-_v&rKCS74OR=zUr9<3C9pL6Z3~8o)4!BLub^c-s|lAAu>ROrfZxI>T9ts8KZJ3{iHU%ll#Q~<2)&TPPNV3-)y5^*;`VRfIC-XmK z)g3V-N1@-{!10D+E3r~|)8n0wi7Uub^lKRtq+3qDP1;OJ(%Bq{RMw?Vb`Z7J^<<6Z zPZ5#**sS#(Yf$^}5hPoxykHTcK{~my@zCLwBhuN1ixq>9!~}<^7I@p10vkE0toDU$ z%fZPU%mqQ!m78j|&G_YFJGsBfPKt9WIXA^8`fLD+MxQvz%#w<|qquFRc>3LavF8~Y z*D^R-w@$yA;ly6(`YE-z743A9I3+T-f6(hVXgx2JR%;eHZ;{3Q_bbK(&n>YYwVg14BTPK%Z-6=+@*O`YU|8ug z;b@X`y3q0T1Gl4yjn?#F@(q zv7OwyJIQOXV71tA%oo;ZdrEZhkaM*AHE9bR;*ci(5cuePNys(Pnk$pP)GGjX$lng8 zq@4t0LxRtHOv&yHmf)d6G*y7cW90d$Fb~tIiebhX{}F}n6+Ea&pQc^Ey|0k&#-1%` z`ijoI`?R;%GH!DwK1-veDW6^qTBC8OARnQwc~oVGXhgJ<*HYeB!r(R(&Zd2x@n+hs z4ED=%1_-r4kMw=)1Udq1cW7qn#zUfQnWZFeT->0Wpnw6&CK7x2l@hv|@8hlhL_WM6 z-Y0Ak67)9D=4d79Ezdw}Inz)(fdR%nPk3TKdw5by1;@k(HX3Q{$79}os z(jg5NLyqfHlWuL3Os7ZT%EnU9$1J}EbhrU{SJ>>uS8h^D>|zU6Lg+`T^Pv3~!pSbW z^4*PtFQd&dgI>+bXp@@NFGDajm3(|>c}e$N4RK0 zz;AiMAYG$m_9jeX?r6;e>?11SmYT*XQbX|q42yTK>=%5)LzWNw%?5DmJ0U@jl$s4x zEeS=tfhk>b*~$WnrI~8jThfzp&(EQRYLSpWBD7{5}>s5z?4aVO2# z>@Qwfmf(h+m(6#i0>snLO>$(K8%6%n3(}fE&d2pY>wRwc!7fV8;o|!pA`3|=;@MAT z0tYhK7lkADVaOo+Mp>>XG18_yPzV0XRi#Tv#x>fhpQCYDd59Yb#Phi~?qD8o}91$G(~{fsq;m3?M^b zCz3zKSIJ8}iwIM6z1_Ogu*rt#m%e81Im#Lte5{4b9=8RKf+NSYu$4r!yj|4x-(B6h zIWYGPx~#v0=fAA(`nFiBI{F@A-7=7)(Ndx`pR;jcvYP?!9Sc-ly`x98Yh>6VEYub4 zN6rA435a_nQw`8Al(8B9RtXX@mnWA4hKoulf47sTn7 z>^Q*O=LwP+DuxFlSo3yC|9K{PDO!eWesu`Xi3@9ii{OsXBj^%%K4iOz9Mb2 zgPAdt%@3pZBM0O5e&(u33g-~qr(DN+hDW$~T{6m_l+QciZ27YhuohWw+)QFq1^j$s zBbXXboz?IaOZN{AgzQ9+jMm)nLw*kFjMW*D9XGhwVHMWF?n1RgOvr**fCra`S+^-q zAiSzNam`6Vt=yD#+N`CA8urloM+V^c4!M`VD8yn%V&8ZHf9L@raOYFlThw8{?;+2w z@E4zFxJXng@iYcGc%RNZB;ww|9ZJ8loSXJzZgEhOWrEwCZFMsT0~#Z^?wuv(;nG>OVpHE z4iuR^IeH?4KXOZO_n6f=-Igu-%MOeyONYd!#!X@$V_OkbO3Re-`8qV7Y}#pC$xcdn zO0D}vwDjlgA6W^#Dqjq6&V$o6kwF`DKjqkI)y?%5c_pm3DqOBGO7~#t>+c(Y*7uPk z3HXZyFy7b2E0Jpgb}8+YDUFl!kyQ%O;iOrFj6ywJN0-RVMak6v1g$YT+Sp~soYqN< zP3N{j^_>Ah@TiO8qLm~0vXw+l=%wR`5PTA>f}TP%b2&*wAZFVvWSPOW;y4KZr#SyF z?GSwm;3+%RDFQ30jMP6A%1ImnME_C?m`oh{yVF^m2ePGI^YeFQBpC%)*F0@gs}s;* z-ICEf2uZm#uG1-rYmS%vM2*e%6JRj#FCl_V zDxhZ}ZN$!HwL{MSu7r=17j`&CG|$%j7XOuMC|&qh*owOzY}B_j?)C6LVPbc@Zb)xX zZ>0Dr`EpVxf5Dsx3U#XNadUwNFffpk^H>F1z}$2zQZoqw9vl$storHdi1?Y8>p*uR z2LI6@^|5>0)!XEY>`BBKCo*8fp8jIO=Mj&s<}n4`!*gEca1rcbWKWFph?bVnxhSHt z8C#6ADQe&(V&>iYhV`e$YVkHO1J2PEsN0$@Q;Z9w!+$-IlOM1LMn&+0qc`L`T7V~B z0B1~c|MGy#!_o<9Pa_G#qQ7jB+Ru&w%!Ri#`uwJSTjg=|F;b;&N!e9WJp|!}NzXz! z4&1elpmXxY_;!+HLt$)VyQ^DC8|a4CZ(KYk-w7Q^IF#K(YyR2!15PmjK50HO8Xc+o zO-fKL@}x2(R0XlU)rr-{cJmw~hth85Ihmg8c&gClWK4t<<@{9q0P?JXSDQ1dc;0`d zWeU9KA7TmSRgq0r>=m0`Lvr<^ppxNwm5L-hVU(0P4fL z^5)rqVRtzZXMgfC<)u*_MZV#3CyfF|nJ<1l5#v;*7En9IwQTy)9rRr15_U;0aDLJm z9rq+&*OBsRQx;wnm)=&SnGFJucYB?XJQFu!x!yfH+I+Le(0kJ!Es<|C)+dLvS2?4@|vxXnAO_`$MbJ^z><;`(sAv}h0HDp8pZ^TSeOju}gBFK|M1aSP zDYLlPbUW#qSPH4;36L*Xuhyzc|MI4IY_2xn(Fl`{VKp#Bmql@_7JDt*R>}Ohb(ysFw)m1|d#K~qY zT2cRz-uquqf`hoFqMa18H!C*!K=y;3y)gKWOInk#kZs$sz{^EGLp}s5fzNhB*vhlg zO*_dew1Ake-em^&$|QtjewB=RFUChSJ1f}eVwFBGTOF*JTHqZWdcL9jU#iiZ^on+lc$gW0< z{IXkb80V>SU;b(5NPcm%R46PjFidKBZX@ZwSdx_N3I|AtHz_nVb6*QOh6U!CFsF4A z|83b!bmXlEw~U7qIDE9gi?tg`LGWZL@xQaxzjP^pu*8_}l6*KwGw`4A_)owB_zA$I zgxfn{_+K9I?`*&hWP`Luy!S}|*0%V^NsRsi*Wu><82`S5|N1Vz$7TN{S)%E=XZ?un8h(!^|F$ehd!xX+9s6xY+uVP) z?XuPwnlCS#qJ^Td*a$Me-XLh_fyvR((sqRy-fdL4Uku(oaCmMr7$P1P`ElKDiz-jc zFB!lSm_hBsa#SDJBL!zU?e3-W(RJ# zdS8EOpXPkUd$j}^Yix%cBLD^P6~WTl%Z1h2(Uk-3vFddEvbLN3;8m_g8(cf^kZzrs z<)@d7@f~B{f8pPLKPQ-)x2gF3!Z?Jf?pMTek{yz!zOy>dNeg@j5=0De>W!D3XJ6H~ z9@!QjwY&_in0zT$W#@g>yy{;)CghQ8uIGJ!(M6MD^Lj=PG!nHzYzfBE$|LA%AhV29 z*Vr4f3e~>aKKOn3`g*EB2tWO*1?ErwaNQ?HxwJ*Y{c;R)4C(@*+ojla6<}Xy0D3UsTNep)@KXyyN}BC3^-! zZq9jDpWyuCBVVd3hx~r`+iq6ig54W&yR#@-I)2MCUc?O?)8yTsBF$F%!?xRFXIf9K zI>2HXUB!m?`+vTp2v7hI%o(PP#k2Ok0;<5T?p=`PqGLj$$V`s3dbh)UaI*p$6HFNM zMZ6!1esWT(*Re@ish3GgY?kmOx!qj&cHa1)v>p>^1Cq{v<@U#rDgH)H`u|q_!b$Y5D(pBpT1SZFB)Db-@yeQy#;;~xX=53zp zAlb0Ed>n7+*zSu=qg@~2v9yUaBMZLn6aI_y_fMd(pDc4@E)j{$tOZN+VU_IlsB0Up z%qx}PO&0{VQopW{b7M)yR>w1}l8gw*!bq9*jxZ8ni`|a}j zpDwJ7d2n@@QvAR`PJ|HO(%;K^d(UKs@|LQbW5J6;#nR_O$igMMAJ@~S!Bb%sd~S}> z&bOEK?T}qO^cz`J7t74=zfV{Io2`ptxhtW3*3NZ!y{l;(%5Dyi?np%aNEDZnN8&uC z3_@j7tlT;IWjR|Ajl;A1EJmqy^% zN-^~U2hQ4p>U$83lru!9B(W_ZPTc;$pXxYBr#@v5InZ@}-C}TmyZV4RYv5rEKuPWQ zw%60;Ug}9snC#oPo8%8~ncJ>6{&bQ5{kWzTq^xO>SzO-co~GFd2f{#g6FDq~?tMO< z;qAg~XN1>zP7z7s;>W%(Y0firG37Oz?e|Caag8X?*AM|okiUD1-e`%#ukF0xDYIh( ztf^4cFJ58r#L#ie#_3W!b-{-KVmqGbmoG0+_$N*3x<7C!r~Gj%jyhuUn~p}rHmB2Cd=)4{8wug%FZvCjAXU! zTQBxKj1&d~6BLNkzgS|qO{K6XneA9c9iI)cl>4a;IwmwPQ7_%h)TgsF&hksI&6z}$ z%J$suzOr`{bDM2mQP1GtNi->nLfnXVDXffs6Ou^DEj23ZxeehOItjZXX!jBLNFK@6 z(;Uu|7Y*7odU0u;4!DVL$91gP zXO*@ceXt#|lcMR}wNf49X2|)bVtaspX&v(^rSO9SsbfFo(-^^hp4OB8^ecjsL}SVb z;IJFEd%?CYSi`UIOxIe6_`~adR-?Y~+Bl4J<`>FZf8bqzh^r~| zHsge26)oREtVxEvncm&t>n zxASzYHGq%;+xv+LIu1cP-$8q&sf{GN{8~4zV#y-j5yNOJ@lPoZ*Zm{F52sgw;5bY# zfA{TTJFb4VMlqGGTS1n^i-ZU&se5hUga!>E{l%v3Od_R!;8f{59YXfWV*=j=!VGZM zgl-Rk|CaQ6O7ec@h2L#BqUF4|4#gem+;7=H$!1mHBb5Ji&_I4O9yqyYg?_7+f7SkQ z-zv+}T0@Xv`D-lC+Qt|WX78E90s(ihONth;3W5c$e`6g>WVI<=0{PR;NN)oq=r6Ep zv6G^3Wozl}yMTn~iSRyI0*xKX#*lX_e9}+1P+7X|Bxw8i2i%}|*s(Qmdzk~?>!^wK zza$@NxtVkuw?%rmnQgyW!D8{4A1XqE+hr<14N0^JZz#b0A)w@9m-q}>#GjN9_+3#; zKYSg_+YJ(d7szCLI@|vDqQgV-cO`-ROJZog=SGJvi%T6b{O!4doMlSg!j$ki9`) zbAe4lXF?0~KU7<`rj;j!JpD5vp#9=24^=_O@XNRbW9{Au@4HQBLd1-?Xvfk2*6 z0t^uuD3D9=yqZ3Qr`&l>aP>6YHMV|_KYv)!trM5%5xfq6dEqLX zCU;uw&)FE3|REjBWtR9ufDRIHi0S!FCSjT+j z`H8Gk+&$oNWe_4U#*d@uxq*A&M&|{+EU6ydAEF|qXyEQ)89RL%o?J>lA7XHxon_gO z{%NK1b6UPrnC;5^hZAiwXrUz+&Gwt=HZGi6 zRQ2D&SB+yAX)GwJg9Ss2+ULD<33WEbB<$B5Hh+HbU}#C$0-O(nsq0sVa@@3qmt5+V zwqfgpf=d757@&BFD(fkH#`bD4A{?rMvv12GRSJc^$l+9kEX5M6Zu~-!5d}H{neuku zV~gKY3J$YxlH!x{5Zh(!dcV)LoD&w=XY_@heNogmagWR{AzZ|Odt( zTLY*BMe@!CB*?G&?L7kiy+Ewl#GZvO#sp%1e~qCK{6W@^NAy6--Gp?K=;L! z`-vxv--E?-9UbNry!$>5$%1)nyB$Yzc=as4{`~s8Bs8V%HZ#l$w+XmD*4~B5uSTRK zIX$HCoPzCQ|m5#(hIC48p-RD z7j$Iy?iD!6_tEaEA>J9ITzrCB6e0^y)B5WCgKtyfI%)#2T^>J7qA50oTXzm+bAbc0q-_r(?qpp#|(co@Dyk?aJ7Ebx2jiT#bG6Wj@Zjbrf;I-3Y@#UlG8KA)8@ z78R({ziFzQyf!iMfnPs#iG?HfN52UfJaL7=;50buZ`<8A%hj^o>*N+S^F;0KG=_Z) zA0~ZsT`TsXiA9=f7QRd{nS+ADy<8)W9~TtwEL@&$Yx_csbcZI3j-_T4jPlgDlw^D4 zL{$4{mlO|{#qpV&DHwFbMzy%zfdtNC8qkitNLd}b2SCV!s9Ejv3~Bo#Gppo>k0Re_dcX@vW}%g{g5^-K2r zUT$;ZK#7pVy@3foARvf8x`Sf4FVaA&!Go5d7&BihvpzP$StZj0u(!@>*X}0AU%koS|gC5*Oi*0C=rNGH;~FidK-(9 zW+PVrG80GPqKAuFXGzlt`QnaGCt5Vi##|nhG*lGJ{9DehQqXkUtl?Mc z!R)Ipm7fgC8ix=38)Nnmb8Sbq_9?1(eoT|OZg~N9Ho~?msuc=|>Jd(VQ=c50n_Q+K#nEe`|= zvaK4RffVF)Xpr||s3pOMzJVH>cT z1XhPf1h$J(CfBMPd`u}zKquKeVty_#oQKUX0*c4@Jo_!>mDFD{pph+r+VRV*37&uz z^{Xt9c>8j;ftEHys62QgN}1Gq4)X{jqRaF{tNwBGNn2dtI@`(%VjHE5PF1_Zmf1cx zaT!MIwA{y+hn6!*zb%cvbq6X?+lSc(r!HgNE&#`s>2l6Z74lw(uW%qy+Xu zi01q@Y}bXh@-qRNM&W)CP3RxyG^B&PcuKy8qE<4{QDp?ghA>aa?l%3$#Y@^$rP^03 zsuQ6#qwK4{yUg+A;HqL*n*#g22X4&@Pha@X^!9i-pbc2l_L*luT*zZS$mLsr>fBPy zMmq7b$1_~|sz}x9LqxNm+_%b92t}xmycwLa3l|Px|`O!k;j2 z4Sl~o{Do7j=Ys{B(97?dc3a_v$Kk_j^fGU zGMcs4@k}nxH5S`PA5q{b0zc9GO2^=d=B`7TSZff31W_J>EAOy>Z}FFX>i!}tkc{Y> z*u4Mbu`uUdv+~puL6u7z-K8)#n(_ePfM?}#X=fH(ntjV)Sen?B&1_%uag+7-B=LHJ zb&Zss-{ywLl3m+DN)x*V(u4r7Cs2cz!$WCyFT57k>wPQI_tRbRtiPW%6TKOH8jHtG z5X%#&1jQS?B$G-$uxNpOTg?dkB~cvz!8i$LX-SGnDJVHxU{LzD1!}nn4$`SvJwAT& zgyHLFaZ$B%-e-0#_Hb-YKE!$|#BW=m!)wvDene6I)^=4B#Fjk%vn3}TePfB)Dt@2Z z&y8T6E#qks9(J3`S{mQ4FzkXOkKh`_lMj8!@zq(j;-F0{F!~#~-Hq47!yM?r{%yjA z1sd36v^~#s=|KO){i4vbdi;23RVKK3{HUUd2_CGVw!;`O zY9ISFbcnf`@z1L-Mt(xiDRny4WQiq)eApNw5(uCAx0q^VRiE>q8r-qo$QkAGB%Av+ zY<;?SkQH#5H%-_#VUzBVKAnt@P$b*vKDzt1axY5NRie+u7(1Io>OE~t9&a{RyKC0` z+A*+4d(b+x3=`dVKM+eD4eo5A+TviBW2v3C>`CtRZpS+K74f?1eU+&39G`-dC!xOZ z&2G-YmeVyz{v)Y=P49$fgF{D_!ma`>>Q?+Syj`HH$8z!-ihOv}5D@USZB@K%{R4a` zf*?oG2>YUP7i_t6!2)h!iNHfh~T(zxxkVr(cxp2nBTdDF$1errCJSzR zs8K%YjZ&rA)k-Llo~QM*4?kbHyQ_dKh@y4*t>6{dkfToK{GCxD^R4UJuaoP_?5W^; zC-jWa6Mb^c*(p@*A}#*Qw|d6%K3OTFo^QRA%TWH$M(>b63TAH-3u0)5BEV znYAHN=rPf3=_CkbAZi@9H>MrDWYb%!ZyRT9wJ2d8fAecXrSq|HXSIV|=$>7TEh;c~ zyrP$4&b$XuBXT_3(RWkNsNN8~W%2?FP~DeLO{J(LOq~cysnEy!z_fcci|-U*^9(ch zd`7vQ)Id(CuPN%YHE_q**@~8zzXo(yF8D7L`#vx)pbFg}OV-Ik`||_Ev5oxr$!B=Dn8XA{zTJ|I~zhS zrURG19L^5jM!a*AIw^GKJwuRR3_KjxtVf-RjEAh8esb!3y|Hl+_l8*Bg$-B!bPo8@ z`M<^hAd*zio>1W6y@zUKH!7l*@_oE7b=nv%zPQD2MZ_15AmN^5{Zny!+^qSG4WsT< zNb;JfwpA+O95VA3m2!f0s^i^uGQZps3>~$nu|h!lBS~!weA)i>Y!3fJo6TkwKctVu z$R~Qo_8s<_!6&x?dCr{KHK8G2-lT3^TV4tdR_>3pz0ty*d^DNEur1x6GZ+VcyGF%( zm$EL*_ENI|B-wHmW)OM1Q8PhyY5FI_S9!mVZrKyIHf+ycd%yI_w5`Sw7IOU*%pL|IdC3};d)(lNMj-@T#0lvqw(kEfR0`ac#TSu!5Zfehp_v^jA zk4#?y)0Y z$uwoY>?5#s5m@JoiT~-DFG-?Q9`++G>OjaiND5aPW038a z1x0_L@@1U}v7LS+`}+xuC7xFG$6c2wMrJGTM=L<^QH?Kf30AxLCzo@*_}5`DB22>vE?iS&kW zXEnGg3{SbZOAn3$)8k*l^PU3bOdb6KZ=YUk7`iSy1F^MTXm7OYU1sA>Rnh47)kh14 zZ2rTW-;Zd&yLVgKWQwj`8?T|xaEc>t^kXX~7W0i|r~Q3*y`O@5h=;ySPZqmL9b++;_W9; zw|zVV{LlE=Uin%g;Nk=~5VJ~$fz0u*7r&oi(=5^%RsAe9o80===42DI5pF`9aQCZP zv_Y)H=Jg-9f;`b0zTYx)11RWk_0q?zsJOjJzP476_r0yPBS>aBt-S7E#g!Gj$dXTz zujT=qFJ#kvpPHg#T0?i*)!2{!;oB4ek;?`jC&Zk4*$LXViNJKkvT+bB!k)z^O7xqs zkz_*Tu(tvjK38u~-aSPrLHLUXMKmxibDHiT6R1%oQ#H~RV-k!UYHX%PxALX_s_m-v zfN>XNO}T=uL+FGtG{m?JU$TD)h8n+pJ!~!ny`m(o`6`)YH)WD4nHiT;N($bJikq=h z(&6v~i*y<9zInQ%u;U{dto&(j;x*HV3d)K$_$>|N_A_#Da!o{|6+(9%!W*0<;BY3& zOVWXX)>7@5MFjmVdU7BNE*XXoI}9aAWimE$)iUa~aUlJW9Sz|1knc23l3LunOJOY` z1Dm^0ZY?~j=o5<^Cy<*9 z%i88Y-1(r8&0S@daL#TyGfQ+beqjDWl>TrBD^QIakg*H?4YcelH8lFi0U4O6*6>&z z+%sdyuO-V*Z7!Iz@Q#o-pbBMyyM3g9Mvfu|(9x!*z22m#al22&~F@&i2c$wkLB!FcWu z&ralKN==mBVKr(btum)SIA&2WcNio=b}U~U!BgBWiVgJ*dr3}7Pu!#+sV>*@na{^+ zBOc(w4>8Q;=S=OJXA$<#nEzCs8EGRgUBaF|WvS=rFRxVe7_60RtdRGL!9Yx*4ZEeR zs3yYVpS=MuCVoZypZ2c&9m@87XG|g4McE=m_88gM7CRN$*JR(bj(wL%c4JqHUb00Z zOCsyo*CJ$@K^V)}qdxbjx8D2%-{X56&5!pyb1&E2_jR4ub)L`jbkv$%lTgKTYPOa} z25w1xKUi~U6V9{njX`>&yvp3uF$0O79p_A-8#fX7sl?BCD1t^@n$|CT&ZtEhy+uwh z2n<~@4@!uno`*S;wsIjDKD!Xpd!uVF>8E=^UrK=&ohc#TMc-3k zSTIdauV6k^Dd2qbq;c--&}CA54r}CqY!7&=@y)uBK3mf}?d2>PvlBK0bur>!p0D;s zNLMI-e=|~7+_N7my6=Jhdf>dm#)d6MGbT;o`SR~DmhK3xlyOgQ<7pGpUtA^aJ|5@h zZ{a{Y9h4||2eR9rQtvh~O<7_no8k1~>DxF0R4sJ+jpN$YZ>6-Q)74KLds1EUnDe!`)_K%$J=$ySx0h zvUD>^+Yiz5bsuaB2l6sGq0x!bDB3yZt?78^#ogdam%-u{kQ9RLlQ7F1&cu-4kGZ$^MWAHnrt(>Wh`oLVmO}N*$`VoNWWR;nmgnl(E2~WH zV>%3j&-t<4$P$v#N6Dw_IPE(l>5J&RcO~xJ*vrG-Y%4^*Q-=*+^Dm!5<{MBK5;f^jiTXloxX~-<5*S>K_6^!S z8(m!HPnnBQ!|O4}7LmQLg`vX)^uFuL6k=E}0mInnGO zo}JEiuTIiYS!juYj;}&4I#lF1+U;|iM0S*B8We3|o#vK3m(KqvHlLN$;h3vxMSe&} z6I}8%n)m>{JL7jxw{0bLB_Z5gwYxV1g$?M~KT}pW8?SQ0`(_umYa8hs?s6BJ+-F%q zi#-m@L0moiM&X!H0kuGr!Sj^Xd+!!~{Y@q+*ALueDxbA>$gOo?t4{=aGL0hS(oXs( zAT$Ig5!(g>PWhcO{4=Eof{df?75mlgMw;HL47&#~o5*!ZT5P@T8z(s5TOD|jWH|rk z!%D%E`AH}EOCkjQ{Z(t8_@T_COVZ#U*AFDgwj%2Cy|S?fooe*R4W5*D5}8g)HV$#q z=^-}pv8wIT?v_2&Z%{@qwS^T&buTW)HtciL0^lEgqjbO9n z!qbETQbKICy2Nrt2crzXeW%V&14(*@F}h~36=Au)L3gCessypE0&;UAL3-jBJmC>3!ort)9u1!~Ya$VO z;V)t_X;v0CbI@>$W4{}2HN_mhefq6N$NPTCavH?-SoF2?JpEH99f8#sHs8IbVF}r$ zLa$f%_9PNbnE!JiU}5@r1??hDWx0c(!)CQgQsE_Bet*t50qY^v{WWdGo`Q2SU?wq> zdfl>+cejE&NH!t%HRXdTUUp_YB1O{^L;^cazF3&a8N8A~NDnj3IXy@wvw#wdhHIC) zR#{kVAe0Svp)6#EBQVmKamMp2ffBx^y`jl?JO6Ck^ zTnw+@Y346>eMdhhk9Hd(8jlNv=EVf6aH<+5>6zmCqr`RHs~QL&P*Yb$s7SR@=((zA zC4tLQ1Ji14ilvZzhvVX|yUy&q(WlV!bRdm40b>of-T6kFq-lN|{*H4JL(ctonKcy)H_=0$pzzov0$ ziUOi}BiDk$o<^0Qll!r5N?mbCce{c3@PyKjIsa^qZFo<_IjhD{Ci2@xhifWzgHo?2 z$Gq~4|7E+wb^#ZFTd5S5NPgMt$M-yp0Gd5BU(P(zu9^`jKk=Tz2mg<0%0g5WWLcaR zbbUCEv{P~9#EQ7QpZIh3u?_tcRqy)8J0z53A;c`JfUFlXgrkzC0Cno8YyMEU5huOT z*0V^e=kcyH-T|?m?i&zdXa@jVc(MslG)4#GIHk=nFI2JKid zS={MpD4(3aE@I1rAB~fjX!Xd~J`|bo`YeIMqH5$~egp8j? z8ie7KNtQm)RB%@KwOcxw!5YrKa64E16$)70w_1=v9MmD=_gSg)EP5>O6LDgBP*Z~h zXpZbfcV`pu=Q>J9Z41Mswmz@|TDOOA%(2Fy3Sc(fYb+R?#K-xASwxZ&-J`zPWuPlE zoAlczkyxp9<(+5A$@H3zoYKtR(@Jv0c8Q$hoXvD;IlFm)agLA(jga1W{3GdAzRfa`+-sVXwqli+Quy2rw(HG0-Q412P}Rp4ygtFaI8M zt(o_Oz*ZsSd+qEvRSp@BYHPyL*k8WAS1_*zLY3Q=h1omrIT~?nZe(JY>Y-D^9e{=k z@*4>vyuub@R^biVAiZ&JB;wG5oVI*`6Q|g94FW2@#CaE$5`p{wrhu4AuNfM2YI%4Z z@Ex}5pPYa+r6Uvzwi$Src0nPRkP=h@W(I_MQw%YkHLM3fj-qLFCFlG%{(xO1P6HQ; zQ=%osZgx5O3;FKPoFgmo9x6o7UW%b2bVVdTfwP%vd*ifzxVhXG1LD4t<7mn!yEWL% z6$TvFuLEJ$uK_VbxE8d$=-3DOCqGE5NQY|Qx+EecfBA-n3W^(T>6LWlwaBz%@}D#S zC%+0L236kb75d*dO}^ij5t1iE$4&0E0L8E9wT}Vc4-WNlrQqRRT65(6OzW``TEQ&( z{4xA*=AS6*sz9_d%|6LRy#_^Ht;W0lOmbxJNJ;2|+3BP@`P%uj=@I#Qozn1WQ54|p zyiG1!^Hs0ls6%ITs?{)dXX~R?wk?Lmm7wp=#P@I8WUc1{d_@;ulsDqE4y9n@ZlY#_ z{tY3Nh|`cXyKZH*uNj(h$K+1Ro#186yWi>B^jPs^XY*H}!MeeCp4#Enkap6IM5rX6 zGt=@!Le|F9Rq&0#C%_aJbc(L^SH}jfx`D^r)^p)6kYnOGy2575KU7)Mt@y3@Y!d|# zX12!>@3JmUfE2#SF>K^U1%j~i#4led5Ct8a?YdL+wKJ1FFprerJhYSi^`!sTH!l$U z#-OM-1yq@4?xa%$CFx$7Jou1loK(sfn>GUNl%d#1OjgD=94MwI>zl?*jAJ}rM_R9; zxoLYIh;bRfd=eMOCck-jO;cs-va5~2)nTz-49yZ3({6(oR-H%vz5f zROq;d!_6IPsmYCXsYoBv9Tpqe-JUI?Xx>=?Mv7abN9?-wo28e?Mqp_pBi4Wl(-(Ey zpkU3N5%6ty2o8Hty)d5f-%UB*S$y8_=%3C7H|earAo6 z$`tpc3dGl+TS@2&2qTsSqXf(1cu?AmXw!Hlz)bP;#SFyF+Or$s>Q;qSQM(b^(PDvK zOR7QFhA23z&&f|_V%+jOLM#L$Ro9a5Mdh^a%RwNQJ+n!&y<${a$}WrHIFO*6 zdIaw@-|Nt9N#D2>Y(yCd_drjf@Ti8^HqMjJFb@73e*>YGaShWx_sbQ#tdbj`gr?^s zQ_W5iI`2xpxf_otW^H@AdvC!oomZa0Zp~pQ8+AHfpnaX#Yh+d$;V?bq8bWfJP^4}_ zZE=j*9u-u95-VoSK|Q{x?qBzbLyE4IySVDf8?Be0+2oD;ea{Qz_6hxqS(t zdW8}4j6Vjs#dnH@u&8p>)?Ke}2^Dh{=ix(fddkhsdvhRs79}$^m~%kL^P)xhFXGG7 zXNl_B#mIsOMMe-H5A}vm6VwYr+dbvHy1a&idn6X(GS*SOk=mHq1dZZc z)0U2Yaxg8|HNwP)7Hp>uQO_Z?q5(+h$C+abj7=fFKxk`2s?Q~$|GE`OMTc1ANtiA@ zlE73+%aM`L5Eq>DSt?87P+n&)aj5)w!9u8?#_SZfle&#Ip`BXW$bG1TMMbR9m#R19=c5l3o@`TyY_0!B#Qv0VuyFD zGVdAt`p&QY$sB}ImUZnq#2AAVvTavXBAmmvqCidCdiYjD&8)G{@@ZV1b`@xRIro99 zC5$-d@5O$~v2JrXNrT7BiWae(*8*(=k^n$34cp`50X>79AW$}w(X zIH60T#rK2l5~wmPoYvUO%pDY>C#%yuTP5GjGKBAt0libBW6kogmkuT9!DL*QhG_)mD?P zrJSO{8&zcK+%SrX=DnxC}4uYDQB4v9%NAk zWO+{^Ll%Q;=cT0H$ZB*mtx3j%n+_Dxo`7R?{v1RQ-gSBG#mcBJ0bxYv?N7egE^c0C zEEI{Ns^YNBw5PC-jLNb3joQmWBI873H*SUD!K=Of1m1Lo9s9A@eu`a))|R}!cjr*^ z8=Be!#HC4S(uZeVD5$Ibfgbc#f0{$>T8m##dVlUXt0_dhts>422LrgL9##>?h?*+N zGeJ(vf0iR))ItTB(`1wgh>*H!PHQGVygbT@6DAhJ0%j8+JyEMEJqIcyAL3;!J~Q!P zaaHZEwFxCj$@^LE!+J~FbSjuIXY2n?*fh!d{1E*}$N;>v=}dWdxw{Djz=6EvugkAZ zb^ri3>XKmZd_5?D>Wbo;I}!$N#AN!LdJPO!>~bO>h%EhjOA$wIC$+&P@aF&;v@ zeYbm(6+8%EdEkEPh0eiQwVdFtTR+iXP#Fc{>C)2+PWD50uT!2O!;`ee0O@{GIYlz5 z=(nAjCXX=(om8vK<9H6VbVA>>J#u)gF*^nYfoB)0=duilysRZtu@UIr|2Xa>kO_9$ zc76Q>g0Ph$%oCh=g=ZuZn}eE#yOx=}tI9lQh7WHe*a5{qtuB`LHY5`Y$hfj3-K$Q# zzxNj|LyBkJ1|s+DWBOt=f>um)NUBnD(FtCX1E>H|9eB2Cfd!58d~m)-7wqd%9rk17p#dD3Hefx2GHu(9PvRklFs(oC`v) zxc(&?l|SYZD@zZ$ad@73{YbL{aMSJ;cX*QjUF(k(1YHK*jNTA>c%(Uo@b^C0HXql5PGzH>B#jb!M;CEPWG!3_yaYl3I&yQw=Zsb4|F!Z{I@jm z6ObajA-3yz^(Xy~9YHMI0LT=XPGudzJ^$be?VGpf@&60K0Nm4+19`-8;_V~IL{$oa zvwuqD&;5xAV;gWY<<_m@_!G35e! Date: Wed, 6 Aug 2025 16:51:57 +0000 Subject: [PATCH 2/2] Adding additional DynamoDB CRUD StepFunctions pytest Typo --- python-test-samples/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python-test-samples/README.md b/python-test-samples/README.md index bd65ddee..2ff528d7 100644 --- a/python-test-samples/README.md +++ b/python-test-samples/README.md @@ -14,7 +14,7 @@ This portion of the repository contains code samples for testing serverless appl |[API Gateway with Lambda and DynamoDB](./apigw-lambda-dynamodb)|This project contains unit and integration tests for a pattern using API Gateway, AWS Lambda and Amazon DynamoDB.| |[Schema and Contract Testing](./schema-and-contract-testing)|This project contains sample schema and contract tests for an event driven architecture.| |[Kinesis with Lambda and DynamoDB](./kinesis-lambda-dynamodb)|This project contains a example of testing an application with an Amazon Kinesis Data Stream.| -|[DynamoDB CRUD with StepFucntions Local](./dynamodb-crud-stepfunctions-local)|This project contains unit pytest running CRUD operations using StepFunctions and DynamoDB on local Docker containers.| +|[DynamoDB CRUD with StepFunctions Local](./dynamodb-crud-stepfunctions-local)|This project contains unit pytest running CRUD operations using StepFunctions and DynamoDB on local Docker containers.| |[SQS with Lambda](./apigw-sqs-lambda-sqs)|This project demonstrates testing SQS as a source and destination in an integration test| |[Step Functions Local](./step-functions-local)| An example of testing Step Functions workflow locally using pytest and Testcontainers |