boto3-assist 0.35.0__tar.gz → 0.36.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- boto3_assist-0.36.0/CHANGELOG.md +101 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/PKG-INFO +1 -1
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/pyproject.toml +1 -1
- boto3_assist-0.36.0/src/boto3_assist/__init__.py +10 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/src/boto3_assist/connection.py +85 -6
- boto3_assist-0.36.0/src/boto3_assist/connection_pool.py +179 -0
- boto3_assist-0.36.0/src/boto3_assist/dynamodb/__init__.py +9 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/src/boto3_assist/dynamodb/dynamodb.py +215 -168
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/src/boto3_assist/dynamodb/dynamodb_connection.py +2 -0
- boto3_assist-0.36.0/src/boto3_assist/s3/__init__.py +9 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/src/boto3_assist/s3/s3.py +43 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/src/boto3_assist/s3/s3_connection.py +2 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/src/boto3_assist/sqs/sqs_connection.py +43 -0
- boto3_assist-0.36.0/src/boto3_assist/version.py +1 -0
- boto3_assist-0.36.0/tests/test_connection_pool.py +325 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/tests/unit/models_tests/models/user.py +11 -1
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/tests/unit/models_tests/serializable_model_user_test.py +2 -0
- boto3_assist-0.35.0/src/boto3_assist/version.py +0 -1
- boto3_assist-0.35.0/tests/unit/utilities/__init__.py +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/.env.docker +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/.env.docker.001 +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/.env.docker.nosql.workbench +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/.env.unittest +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/.gitignore +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/.vscode/launch.json +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/.vscode/settings.json +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/.vscode/tasks.json +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/.windsurf/rules/cascade.yaml +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/LICENSE-EXPLAINED.txt +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/LICENSE.txt +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/README.md +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/aws_regions_with_status.csv +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/aws_regions_with_status.json +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/devops/build.py +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/devops/readme.md +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/docs/design-patterns.md +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/docs/help/dynamodb/001-guide-single-table-design.md +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/docs/help/dynamodb/002-guide-defining-models.md +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/docs/help/dynamodb/003-guide-service-layers.md +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/docs/help/dynamodb/004-guide-testing-with-moto.md +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/docs/help/dynamodb/005-guide-projections-and-reserved-keywords.md +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/docs/help/dynamodb/006-guide-how-dynamodb-stores-data.md +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/docs/help/dynamodb/007-guide-batch-operations.md +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/docs/help/dynamodb/008-guide-transactions.md +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/docs/help/dynamodb/009-guide-conditional-writes.md +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/docs/help/dynamodb/010-guide-update-expressions.md +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/docs/issues/BOTO3_ASSIST_BEFORE_AFTER.md +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/docs/issues/BOTO3_ASSIST_DECIMAL_PATTERN.md +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/docs/issues/BOTO3_ASSIST_IMPLEMENTATION_CHECKLIST.md +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/docs/overview.md +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/docs/roadmap.md +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/docs/tech-debt.md +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/docs/unit-test-patterns.md +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/examples/__init__.py +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/examples/cloudwatch/log_report.py +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/examples/dynamodb/QUICK_REFERENCE_KEY_DEBUGGING.md +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/examples/dynamodb/batch_operations_example.py +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/examples/dynamodb/conditional_writes_example.py +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/examples/dynamodb/debug_keys_example.py +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/examples/dynamodb/decimal_conversion_example.py +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/examples/dynamodb/models/order_item_model.py +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/examples/dynamodb/models/order_model.py +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/examples/dynamodb/models/product_model.py +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/examples/dynamodb/models/user_model.py +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/examples/dynamodb/models/user_post_model.py +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/examples/dynamodb/order_example/main.py +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/examples/dynamodb/order_example/products.json +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/examples/dynamodb/services/order_item_service.py +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/examples/dynamodb/services/order_service.py +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/examples/dynamodb/services/product_service.py +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/examples/dynamodb/services/table_service.py +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/examples/dynamodb/services/user_post_service.py +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/examples/dynamodb/services/user_service.py +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/examples/dynamodb/services/user_service_client_example.py +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/examples/dynamodb/services/user_service_resource_example.py +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/examples/dynamodb/transactions_example.py +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/examples/dynamodb/update_expressions_example.py +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/examples/dynamodb/user_post_example/main.py +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/examples/ec2/regions_report.py +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/module-headers.txt +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/mypy.ini +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/publish_to_pypi.py +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/publish_to_pypi.sh +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/pysetup.py +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/pysetup.sh +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/requirements.dev.txt +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/requirements.txt +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/run-checks.sh +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/run-unit-tests.sh +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/src/boto3_assist/aws_config.py +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/src/boto3_assist/aws_lambda/event_info.py +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/src/boto3_assist/aws_lambda/mock_context.py +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/src/boto3_assist/boto3session.py +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/src/boto3_assist/cloudwatch/cloudwatch_connection.py +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/src/boto3_assist/cloudwatch/cloudwatch_connection_tracker.py +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/src/boto3_assist/cloudwatch/cloudwatch_log_connection.py +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/src/boto3_assist/cloudwatch/cloudwatch_logs.py +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/src/boto3_assist/cloudwatch/cloudwatch_query.py +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/src/boto3_assist/cognito/cognito_authorizer.py +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/src/boto3_assist/cognito/cognito_connection.py +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/src/boto3_assist/cognito/cognito_utility.py +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/src/boto3_assist/cognito/jwks_cache.py +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/src/boto3_assist/cognito/user.py +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/src/boto3_assist/connection_tracker.py +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/src/boto3_assist/dynamodb/dynamodb_helpers.py +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/src/boto3_assist/dynamodb/dynamodb_importer.py +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/src/boto3_assist/dynamodb/dynamodb_index.py +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/src/boto3_assist/dynamodb/dynamodb_iservice.py +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/src/boto3_assist/dynamodb/dynamodb_key.py +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/src/boto3_assist/dynamodb/dynamodb_model_base.py +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/src/boto3_assist/dynamodb/dynamodb_model_base_interfaces.py +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/src/boto3_assist/dynamodb/dynamodb_re_indexer.py +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/src/boto3_assist/dynamodb/dynamodb_reindexer.py +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/src/boto3_assist/dynamodb/dynamodb_reserved_words.py +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/src/boto3_assist/dynamodb/dynamodb_reserved_words.txt +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/src/boto3_assist/dynamodb/readme.md +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/src/boto3_assist/dynamodb/troubleshooting.md +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/src/boto3_assist/ec2/ec2_connection.py +0 -0
- {boto3_assist-0.35.0/src/boto3_assist → boto3_assist-0.36.0/src/boto3_assist/environment_services}/__init__.py +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/src/boto3_assist/environment_services/environment_loader.py +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/src/boto3_assist/environment_services/environment_variables.py +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/src/boto3_assist/erc/__init__.py +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/src/boto3_assist/erc/ecr_connection.py +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/src/boto3_assist/errors/custom_exceptions.py +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/src/boto3_assist/http_status_codes.py +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/src/boto3_assist/models/serializable_model.py +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/src/boto3_assist/role_assumption_mixin.py +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/src/boto3_assist/s3/s3_bucket.py +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/src/boto3_assist/s3/s3_event_data.py +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/src/boto3_assist/s3/s3_object.py +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/src/boto3_assist/securityhub/securityhub.py +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/src/boto3_assist/securityhub/securityhub_connection.py +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/src/boto3_assist/session_setup_mixin.py +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/src/boto3_assist/sqs/__init__.py +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/src/boto3_assist/sqs/sqs_queue.py +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/src/boto3_assist/ssm/connection.py +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/src/boto3_assist/ssm/parameter_store/parameter_store.py +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/src/boto3_assist/utilities/datetime_utility.py +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/src/boto3_assist/utilities/decimal_conversion_utility.py +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/src/boto3_assist/utilities/dictionary_utility.py +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/src/boto3_assist/utilities/file_operations.py +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/src/boto3_assist/utilities/http_utility.py +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/src/boto3_assist/utilities/logging_utility.py +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/src/boto3_assist/utilities/numbers_utility.py +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/src/boto3_assist/utilities/serialization_utility.py +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/src/boto3_assist/utilities/string_utility.py +0 -0
- {boto3_assist-0.35.0/src/boto3_assist/environment_services → boto3_assist-0.36.0/tests}/__init__.py +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/tests/integration/cross_account_connection_test.py +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/tests/integration/tenant.py +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/tests/integration/tenant_services.py +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/tests/unit/aws_config_test.py +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/tests/unit/common/db_test_helpers.py +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/tests/unit/dynamodb/decimal_backward_compatibility_test.py +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/tests/unit/dynamodb/decimal_conversion_integration_test.py +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/tests/unit/dynamodb/test_dynamodb_key_to_dict.py +0 -0
- {boto3_assist-0.35.0/tests → boto3_assist-0.36.0/tests/unit/dynamodb_tests}/__init__.py +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/tests/unit/dynamodb_tests/db_models/cms/base.py +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/tests/unit/dynamodb_tests/db_models/cms/content_block.py +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/tests/unit/dynamodb_tests/db_models/cms/page.py +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/tests/unit/dynamodb_tests/db_models/cms/template.py +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/tests/unit/dynamodb_tests/db_models/simple_model.py +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/tests/unit/dynamodb_tests/db_models/task.py +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/tests/unit/dynamodb_tests/db_models/user_model.py +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/tests/unit/dynamodb_tests/db_models/user_required_fields_model.py +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/tests/unit/dynamodb_tests/dynamodb_batch_operations_test.py +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/tests/unit/dynamodb_tests/dynamodb_conditional_test.py +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/tests/unit/dynamodb_tests/dynamodb_fail_if_exists_test.py +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/tests/unit/dynamodb_tests/dynamodb_model_base_test.py +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/tests/unit/dynamodb_tests/dynamodb_model_merge_test.py +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/tests/unit/dynamodb_tests/dynamodb_model_projections_test.py +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/tests/unit/dynamodb_tests/dynamodb_model_serializtion_test.py +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/tests/unit/dynamodb_tests/dynamodb_moto_sorting_test.py +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/tests/unit/dynamodb_tests/dynamodb_primary_key_get_test.py +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/tests/unit/dynamodb_tests/dynamodb_primary_key_sort_test.py +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/tests/unit/dynamodb_tests/dynamodb_query_test.py +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/tests/unit/dynamodb_tests/dynamodb_reindex_test.py +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/tests/unit/dynamodb_tests/dynamodb_transactions_test.py +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/tests/unit/dynamodb_tests/dynamodb_update_expressions_test.py +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/tests/unit/examples_test/README.md +0 -0
- {boto3_assist-0.35.0/tests/unit/dynamodb_tests → boto3_assist-0.36.0/tests/unit/examples_test}/__init__.py +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/tests/unit/examples_test/order_service_test.py +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/tests/unit/examples_test/user_service_test.py +0 -0
- {boto3_assist-0.35.0/tests/unit/examples_test → boto3_assist-0.36.0/tests/unit/lambda_tests}/__init__.py +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/tests/unit/lambda_tests/event_info_test.py +0 -0
- {boto3_assist-0.35.0/tests/unit/lambda_tests → boto3_assist-0.36.0/tests/unit/models_tests}/__init__.py +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/tests/unit/models_tests/models/person.py +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/tests/unit/models_tests/serializable_model_person_test.py +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/tests/unit/models_tests/serializable_model_wide_test.py +0 -0
- {boto3_assist-0.35.0/tests/unit/models_tests → boto3_assist-0.36.0/tests/unit/parameter_store}/__init__.py +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/tests/unit/parameter_store/parameter_store_test.py +0 -0
- {boto3_assist-0.35.0/tests/unit/parameter_store → boto3_assist-0.36.0/tests/unit/s3}/__init__.py +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/tests/unit/s3/files/test.txt +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/tests/unit/s3/s3_event_data_test.py +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/tests/unit/s3/s3_file_delete_test.py +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/tests/unit/s3/s3_file_upload_test.py +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/tests/unit/session_tests/test_boto3_session_manager.py +0 -0
- {boto3_assist-0.35.0/tests/unit/s3 → boto3_assist-0.36.0/tests/unit/utilities}/__init__.py +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/tests/unit/utilities/case_transformation/files/user_import.json +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/tests/unit/utilities/case_transformation/test_case_transformation.py +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/tests/unit/utilities/decimal_conversion_utility_test.py +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/tests/unit/utilities/serialization_utility_test.py +0 -0
- {boto3_assist-0.35.0 → boto3_assist-0.36.0}/tests/unit/utilities/string_utility_test.py +0 -0
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to boto3-assist will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [0.36.0] - 2026-01-25
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
- **Connection Pooling** - New `ConnectionPool` class for reusing boto3 sessions across Lambda invocations
|
|
12
|
+
- Singleton pattern caches sessions by service, profile, region, and endpoint
|
|
13
|
+
- Significantly improves Lambda performance by reducing connection overhead
|
|
14
|
+
- `ConnectionPool.get_instance()` - Get singleton pool instance
|
|
15
|
+
- `ConnectionPool.get_session()` - Get or create cached session
|
|
16
|
+
- `ConnectionPool.reset()` - Clear cache (for testing)
|
|
17
|
+
- `ConnectionPool.get_stats()` - Pool statistics
|
|
18
|
+
|
|
19
|
+
- **Factory Methods** - New recommended pattern for creating connections
|
|
20
|
+
- `Connection.from_pool()` - Create connection using pool (recommended for Lambda)
|
|
21
|
+
- `DynamoDB.from_pool()` - Create DynamoDB connection using pool
|
|
22
|
+
- `S3.from_pool()` - Create S3 connection using pool
|
|
23
|
+
- `SQSConnection.from_pool()` - Create SQS connection using pool
|
|
24
|
+
- All service classes support `use_connection_pool` parameter
|
|
25
|
+
|
|
26
|
+
- **Package Exports** - Added `__init__.py` files for cleaner imports
|
|
27
|
+
- `from boto3_assist import Connection, ConnectionPool`
|
|
28
|
+
- `from boto3_assist.dynamodb import DynamoDB`
|
|
29
|
+
- `from boto3_assist.s3 import S3`
|
|
30
|
+
- `from boto3_assist.sqs import SQSConnection`
|
|
31
|
+
|
|
32
|
+
### Changed
|
|
33
|
+
- **Deprecation Warning** - Connections created without pooling now show deprecation warning
|
|
34
|
+
- Warning guides users to new `.from_pool()` pattern
|
|
35
|
+
- Default will change to `use_connection_pool=True` in v2.0.0
|
|
36
|
+
- Existing code continues to work unchanged
|
|
37
|
+
|
|
38
|
+
### Backward Compatibility
|
|
39
|
+
- ✅ All existing code works without modification
|
|
40
|
+
- ✅ Deprecation warnings are informational only
|
|
41
|
+
- ✅ No breaking changes in this release
|
|
42
|
+
|
|
43
|
+
### Migration Guide
|
|
44
|
+
```python
|
|
45
|
+
# DynamoDB
|
|
46
|
+
# Old pattern (still works, shows deprecation warning)
|
|
47
|
+
db = DynamoDB()
|
|
48
|
+
# New pattern (recommended for Lambda)
|
|
49
|
+
db = DynamoDB.from_pool()
|
|
50
|
+
|
|
51
|
+
# S3
|
|
52
|
+
# Old pattern (still works, shows deprecation warning)
|
|
53
|
+
s3 = S3()
|
|
54
|
+
# New pattern (recommended for Lambda)
|
|
55
|
+
s3 = S3.from_pool()
|
|
56
|
+
|
|
57
|
+
# SQS
|
|
58
|
+
# Old pattern (still works, shows deprecation warning)
|
|
59
|
+
sqs = SQSConnection()
|
|
60
|
+
# New pattern (recommended for Lambda)
|
|
61
|
+
sqs = SQSConnection.from_pool()
|
|
62
|
+
|
|
63
|
+
# Explicit opt-in (any service)
|
|
64
|
+
db = DynamoDB(use_connection_pool=True)
|
|
65
|
+
s3 = S3(use_connection_pool=True)
|
|
66
|
+
sqs = SQSConnection(use_connection_pool=True)
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### Testing
|
|
70
|
+
- Added 16 new tests for connection pooling
|
|
71
|
+
- All 107 tests passing (91 DynamoDB + 16 connection pool)
|
|
72
|
+
- Comprehensive backward compatibility testing
|
|
73
|
+
|
|
74
|
+
## [0.35.0] - Previous Release
|
|
75
|
+
|
|
76
|
+
### Features
|
|
77
|
+
- DynamoDB operations (save, query, update, batch, transactions)
|
|
78
|
+
- Session management with role assumption
|
|
79
|
+
- Decimal conversion for DynamoDB
|
|
80
|
+
- Conditional expressions
|
|
81
|
+
- Update expressions (SET, ADD, REMOVE)
|
|
82
|
+
- Transaction support
|
|
83
|
+
- Batch operations
|
|
84
|
+
- Connection tracking and monitoring
|
|
85
|
+
|
|
86
|
+
---
|
|
87
|
+
|
|
88
|
+
## Upgrade Notes
|
|
89
|
+
|
|
90
|
+
### From 0.35.0 to 0.36.0
|
|
91
|
+
No breaking changes. Optionally migrate to `.from_pool()` pattern for better Lambda performance.
|
|
92
|
+
|
|
93
|
+
### Future Breaking Changes
|
|
94
|
+
- **v2.0.0** (planned): `use_connection_pool=True` will become the default
|
|
95
|
+
- To preserve old behavior in v2.0.0: `Connection(service_name="...", use_connection_pool=False)`
|
|
96
|
+
- Timeline: 6+ months from v0.36.0 release
|
|
97
|
+
|
|
98
|
+
---
|
|
99
|
+
|
|
100
|
+
[0.36.0]: https://github.com/geekcafe/boto3-assist/compare/v0.35.0...v0.36.0
|
|
101
|
+
[0.35.0]: https://github.com/geekcafe/boto3-assist/releases/tag/v0.35.0
|
|
@@ -5,6 +5,7 @@ MIT License. See Project Root for the license information.
|
|
|
5
5
|
"""
|
|
6
6
|
|
|
7
7
|
from typing import Optional, List
|
|
8
|
+
import warnings
|
|
8
9
|
|
|
9
10
|
from aws_lambda_powertools import Logger
|
|
10
11
|
from botocore.config import Config
|
|
@@ -13,6 +14,7 @@ from boto3_assist.environment_services.environment_variables import (
|
|
|
13
14
|
EnvironmentVariables,
|
|
14
15
|
)
|
|
15
16
|
from boto3_assist.connection_tracker import ConnectionTracker
|
|
17
|
+
from boto3_assist.connection_pool import ConnectionPool
|
|
16
18
|
|
|
17
19
|
|
|
18
20
|
logger = Logger()
|
|
@@ -35,6 +37,7 @@ class Connection:
|
|
|
35
37
|
assume_role_chain: Optional[List[str]] = None,
|
|
36
38
|
assume_role_duration_seconds: Optional[int] = 3600,
|
|
37
39
|
config: Optional[Config] = None,
|
|
40
|
+
use_connection_pool: bool = False,
|
|
38
41
|
) -> None:
|
|
39
42
|
self.__aws_profile = aws_profile
|
|
40
43
|
self.__aws_region = aws_region
|
|
@@ -47,6 +50,8 @@ class Connection:
|
|
|
47
50
|
self.__assume_role_chain = assume_role_chain
|
|
48
51
|
self.__assume_role_duration_seconds = assume_role_duration_seconds
|
|
49
52
|
self.__config = config
|
|
53
|
+
self.__use_connection_pool = use_connection_pool
|
|
54
|
+
|
|
50
55
|
if self.__service_name is None:
|
|
51
56
|
raise RuntimeError(
|
|
52
57
|
"Service Name is not available. The service name is required."
|
|
@@ -54,6 +59,18 @@ class Connection:
|
|
|
54
59
|
|
|
55
60
|
self.raise_on_error: bool = True
|
|
56
61
|
|
|
62
|
+
# Issue deprecation warning if not using connection pool
|
|
63
|
+
if not use_connection_pool:
|
|
64
|
+
warnings.warn(
|
|
65
|
+
f"Creating {service_name} Connection without connection pooling. "
|
|
66
|
+
"This creates a new boto3 session on each instantiation, which can impact "
|
|
67
|
+
"Lambda performance. Consider using Connection.from_pool() or "
|
|
68
|
+
"use_connection_pool=True for better performance in Lambda functions. "
|
|
69
|
+
"The default will change to use_connection_pool=True in boto3-assist v2.0.0.",
|
|
70
|
+
DeprecationWarning,
|
|
71
|
+
stacklevel=2,
|
|
72
|
+
)
|
|
73
|
+
|
|
57
74
|
def setup(self, setup_source: Optional[str] = None) -> None:
|
|
58
75
|
"""
|
|
59
76
|
Setup the environment. Automatically called via init.
|
|
@@ -139,12 +156,74 @@ class Connection:
|
|
|
139
156
|
logger.debug("Setting Service Name")
|
|
140
157
|
self.__service_name = value
|
|
141
158
|
|
|
159
|
+
@classmethod
|
|
160
|
+
def from_pool(
|
|
161
|
+
cls,
|
|
162
|
+
service_name: str,
|
|
163
|
+
aws_profile: Optional[str] = None,
|
|
164
|
+
aws_region: Optional[str] = None,
|
|
165
|
+
aws_end_point_url: Optional[str] = None,
|
|
166
|
+
config: Optional[Config] = None,
|
|
167
|
+
**kwargs,
|
|
168
|
+
) -> "Connection":
|
|
169
|
+
"""
|
|
170
|
+
Create connection using connection pool (recommended for Lambda).
|
|
171
|
+
|
|
172
|
+
This is the recommended pattern for Lambda functions as it reuses
|
|
173
|
+
boto3 sessions across invocations in warm containers, reducing
|
|
174
|
+
connection overhead and improving performance.
|
|
175
|
+
|
|
176
|
+
Args:
|
|
177
|
+
service_name: AWS service name (e.g., 's3', 'dynamodb', 'sqs')
|
|
178
|
+
aws_profile: AWS profile name (optional)
|
|
179
|
+
aws_region: AWS region (optional)
|
|
180
|
+
aws_end_point_url: Custom endpoint URL (optional, for moto testing)
|
|
181
|
+
config: Botocore Config object (optional)
|
|
182
|
+
**kwargs: Additional Connection parameters
|
|
183
|
+
|
|
184
|
+
Returns:
|
|
185
|
+
Connection instance configured to use connection pool
|
|
186
|
+
|
|
187
|
+
Example:
|
|
188
|
+
>>> # Recommended pattern for Lambda
|
|
189
|
+
>>> conn = Connection.from_pool(service_name="dynamodb")
|
|
190
|
+
>>> client = conn.session.client
|
|
191
|
+
>>>
|
|
192
|
+
>>> # Subsequent calls reuse the same session
|
|
193
|
+
>>> conn2 = Connection.from_pool(service_name="dynamodb")
|
|
194
|
+
>>> assert conn.session is conn2.session
|
|
195
|
+
"""
|
|
196
|
+
return cls(
|
|
197
|
+
service_name=service_name,
|
|
198
|
+
aws_profile=aws_profile,
|
|
199
|
+
aws_region=aws_region,
|
|
200
|
+
aws_end_point_url=aws_end_point_url,
|
|
201
|
+
config=config,
|
|
202
|
+
use_connection_pool=True,
|
|
203
|
+
**kwargs,
|
|
204
|
+
)
|
|
205
|
+
|
|
142
206
|
@property
|
|
143
207
|
def session(self) -> Boto3SessionManager:
|
|
144
208
|
"""Session"""
|
|
145
|
-
if self.
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
209
|
+
if self.__use_connection_pool:
|
|
210
|
+
# Use connection pool for session management
|
|
211
|
+
pool = ConnectionPool.get_instance()
|
|
212
|
+
return pool.get_session(
|
|
213
|
+
service_name=self.service_name,
|
|
214
|
+
aws_profile=self.aws_profile,
|
|
215
|
+
aws_region=self.aws_region,
|
|
216
|
+
aws_endpoint_url=self.end_point_url,
|
|
217
|
+
config=self.__config,
|
|
218
|
+
assume_role_arn=self.__assume_role_arn,
|
|
219
|
+
assume_role_chain=self.__assume_role_chain,
|
|
220
|
+
assume_role_duration_seconds=self.__assume_role_duration_seconds,
|
|
221
|
+
)
|
|
222
|
+
else:
|
|
223
|
+
# Legacy behavior: create session on demand
|
|
224
|
+
if self.__session is None:
|
|
225
|
+
self.setup(setup_source="session init")
|
|
226
|
+
|
|
227
|
+
if self.__session is None:
|
|
228
|
+
raise RuntimeError("Session is not available")
|
|
229
|
+
return self.__session
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Geek Cafe, LLC
|
|
3
|
+
Maintainers: Eric Wilson
|
|
4
|
+
MIT License. See Project Root for the license information.
|
|
5
|
+
|
|
6
|
+
Connection pooling for boto3 sessions to improve Lambda performance.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from typing import Dict, Optional
|
|
10
|
+
from aws_lambda_powertools import Logger
|
|
11
|
+
from .boto3session import Boto3SessionManager
|
|
12
|
+
|
|
13
|
+
logger = Logger()
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class ConnectionPool:
|
|
17
|
+
"""
|
|
18
|
+
Singleton connection pool for reusing boto3 sessions.
|
|
19
|
+
|
|
20
|
+
Recommended for Lambda functions to minimize connection overhead and
|
|
21
|
+
improve performance in warm containers.
|
|
22
|
+
|
|
23
|
+
Example:
|
|
24
|
+
>>> pool = ConnectionPool.get_instance()
|
|
25
|
+
>>> session = pool.get_session(service_name="dynamodb")
|
|
26
|
+
>>> client = session.client
|
|
27
|
+
|
|
28
|
+
# Subsequent calls reuse the same session
|
|
29
|
+
>>> session2 = pool.get_session(service_name="dynamodb")
|
|
30
|
+
>>> assert session is session2 # Same instance
|
|
31
|
+
"""
|
|
32
|
+
|
|
33
|
+
_instance: Optional["ConnectionPool"] = None
|
|
34
|
+
|
|
35
|
+
def __init__(self):
|
|
36
|
+
"""Initialize connection pool. Use get_instance() instead."""
|
|
37
|
+
self._connections: Dict[str, Boto3SessionManager] = {}
|
|
38
|
+
|
|
39
|
+
@classmethod
|
|
40
|
+
def get_instance(cls) -> "ConnectionPool":
|
|
41
|
+
"""
|
|
42
|
+
Get singleton instance of the connection pool.
|
|
43
|
+
|
|
44
|
+
Returns:
|
|
45
|
+
ConnectionPool: Singleton instance
|
|
46
|
+
"""
|
|
47
|
+
if cls._instance is None:
|
|
48
|
+
logger.debug("Creating new ConnectionPool instance")
|
|
49
|
+
cls._instance = ConnectionPool()
|
|
50
|
+
return cls._instance
|
|
51
|
+
|
|
52
|
+
def get_session(
|
|
53
|
+
self,
|
|
54
|
+
service_name: str,
|
|
55
|
+
aws_profile: Optional[str] = None,
|
|
56
|
+
aws_region: Optional[str] = None,
|
|
57
|
+
aws_endpoint_url: Optional[str] = None,
|
|
58
|
+
**kwargs,
|
|
59
|
+
) -> Boto3SessionManager:
|
|
60
|
+
"""
|
|
61
|
+
Get or create cached session for service.
|
|
62
|
+
|
|
63
|
+
Sessions are cached based on service_name, profile, region, and endpoint.
|
|
64
|
+
Subsequent calls with the same parameters return the cached session.
|
|
65
|
+
|
|
66
|
+
Args:
|
|
67
|
+
service_name: AWS service name (e.g., 's3', 'dynamodb', 'sqs')
|
|
68
|
+
aws_profile: AWS profile name (optional)
|
|
69
|
+
aws_region: AWS region (optional, defaults to environment/config)
|
|
70
|
+
aws_endpoint_url: Custom endpoint URL (optional, useful for moto testing)
|
|
71
|
+
**kwargs: Additional Boto3SessionManager parameters
|
|
72
|
+
|
|
73
|
+
Returns:
|
|
74
|
+
Boto3SessionManager: Cached or newly created session manager
|
|
75
|
+
|
|
76
|
+
Example:
|
|
77
|
+
>>> pool = ConnectionPool.get_instance()
|
|
78
|
+
>>> # First call creates new session
|
|
79
|
+
>>> s3_session = pool.get_session(service_name="s3")
|
|
80
|
+
>>> # Second call returns cached session
|
|
81
|
+
>>> s3_session2 = pool.get_session(service_name="s3")
|
|
82
|
+
>>> assert s3_session is s3_session2
|
|
83
|
+
"""
|
|
84
|
+
key = self._make_key(service_name, aws_profile, aws_region, aws_endpoint_url)
|
|
85
|
+
|
|
86
|
+
if key not in self._connections:
|
|
87
|
+
logger.debug(
|
|
88
|
+
f"Creating new session for {service_name}",
|
|
89
|
+
extra={
|
|
90
|
+
"service_name": service_name,
|
|
91
|
+
"aws_profile": aws_profile,
|
|
92
|
+
"aws_region": aws_region,
|
|
93
|
+
"cache_key": key,
|
|
94
|
+
},
|
|
95
|
+
)
|
|
96
|
+
self._connections[key] = Boto3SessionManager(
|
|
97
|
+
service_name=service_name,
|
|
98
|
+
aws_profile=aws_profile,
|
|
99
|
+
aws_region=aws_region,
|
|
100
|
+
aws_endpoint_url=aws_endpoint_url,
|
|
101
|
+
**kwargs,
|
|
102
|
+
)
|
|
103
|
+
else:
|
|
104
|
+
logger.debug(
|
|
105
|
+
f"Reusing cached session for {service_name}",
|
|
106
|
+
extra={
|
|
107
|
+
"service_name": service_name,
|
|
108
|
+
"cache_key": key,
|
|
109
|
+
"total_cached_sessions": len(self._connections),
|
|
110
|
+
},
|
|
111
|
+
)
|
|
112
|
+
|
|
113
|
+
return self._connections[key]
|
|
114
|
+
|
|
115
|
+
def reset(self):
|
|
116
|
+
"""
|
|
117
|
+
Reset all connections in the pool.
|
|
118
|
+
|
|
119
|
+
This clears all cached sessions. Useful for testing or when you need
|
|
120
|
+
to force recreation of all connections.
|
|
121
|
+
|
|
122
|
+
Warning:
|
|
123
|
+
This should only be used in testing scenarios. In production Lambda
|
|
124
|
+
functions, connections should persist across invocations.
|
|
125
|
+
|
|
126
|
+
Example:
|
|
127
|
+
>>> pool = ConnectionPool.get_instance()
|
|
128
|
+
>>> pool.get_session(service_name="s3")
|
|
129
|
+
>>> pool.reset() # Clear all cached sessions
|
|
130
|
+
>>> # Next call will create new session
|
|
131
|
+
>>> pool.get_session(service_name="s3")
|
|
132
|
+
"""
|
|
133
|
+
logger.debug(f"Resetting connection pool ({len(self._connections)} sessions)")
|
|
134
|
+
self._connections.clear()
|
|
135
|
+
|
|
136
|
+
def get_stats(self) -> Dict[str, int]:
|
|
137
|
+
"""
|
|
138
|
+
Get statistics about the connection pool.
|
|
139
|
+
|
|
140
|
+
Returns:
|
|
141
|
+
Dict with pool statistics:
|
|
142
|
+
- total_connections: Number of cached sessions
|
|
143
|
+
- services: Number of unique services
|
|
144
|
+
|
|
145
|
+
Example:
|
|
146
|
+
>>> pool = ConnectionPool.get_instance()
|
|
147
|
+
>>> pool.get_session(service_name="s3")
|
|
148
|
+
>>> pool.get_session(service_name="dynamodb")
|
|
149
|
+
>>> stats = pool.get_stats()
|
|
150
|
+
>>> print(stats)
|
|
151
|
+
{'total_connections': 2, 'services': 2}
|
|
152
|
+
"""
|
|
153
|
+
services = set()
|
|
154
|
+
for key in self._connections.keys():
|
|
155
|
+
service_name = key.split(":")[0]
|
|
156
|
+
services.add(service_name)
|
|
157
|
+
|
|
158
|
+
return {"total_connections": len(self._connections), "services": len(services)}
|
|
159
|
+
|
|
160
|
+
@staticmethod
|
|
161
|
+
def _make_key(
|
|
162
|
+
service_name: str,
|
|
163
|
+
profile: Optional[str],
|
|
164
|
+
region: Optional[str],
|
|
165
|
+
endpoint: Optional[str],
|
|
166
|
+
) -> str:
|
|
167
|
+
"""
|
|
168
|
+
Create cache key from connection parameters.
|
|
169
|
+
|
|
170
|
+
Args:
|
|
171
|
+
service_name: AWS service name
|
|
172
|
+
profile: AWS profile name (or None)
|
|
173
|
+
region: AWS region (or None)
|
|
174
|
+
endpoint: Custom endpoint URL (or None)
|
|
175
|
+
|
|
176
|
+
Returns:
|
|
177
|
+
str: Cache key for this combination of parameters
|
|
178
|
+
"""
|
|
179
|
+
return f"{service_name}:{profile}:{region}:{endpoint}"
|