velocity-python 0.1.87__tar.gz → 0.1.88__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.
- {velocity_python-0.1.87/src/velocity_python.egg-info → velocity_python-0.1.88}/PKG-INFO +1 -1
- {velocity_python-0.1.87 → velocity_python-0.1.88}/pyproject.toml +1 -1
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/__init__.py +1 -1
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/aws/handlers/context.py +31 -1
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/db/core/engine.py +6 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/db/core/transaction.py +75 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88/src/velocity_python.egg-info}/PKG-INFO +1 -1
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity_python.egg-info/SOURCES.txt +1 -0
- velocity_python-0.1.88/tests/test_on_commit.py +216 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/LICENSE +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/README.md +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/setup.cfg +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/aws/__init__.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/aws/amplify.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/aws/amplify_build.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/aws/assets/__init__.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/aws/assets/backfill.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/aws/assets/indexing.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/aws/assets/references.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/aws/assets/service.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/aws/assets/usage_index.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/aws/deploy/__init__.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/aws/deploy/config.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/aws/deploy/operations.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/aws/deploy/policies.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/aws/deploy/reconcile.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/aws/deploy/targets.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/aws/dirty_pipeline.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/aws/handlers/__init__.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/aws/handlers/base_handler.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/aws/handlers/context_factory.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/aws/handlers/exceptions.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/aws/handlers/lambda_handler.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/aws/handlers/masquerade.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/aws/handlers/mixins/__init__.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/aws/handlers/mixins/data_service.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/aws/handlers/mixins/web_handler.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/aws/handlers/perf.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/aws/handlers/response.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/aws/handlers/sqs_handler.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/aws/s3.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/aws/ssm_config.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/aws/tests/__init__.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/aws/tests/test_amplify_build_policy_size.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/aws/tests/test_amplify_build_shim.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/aws/tests/test_base_handler_error_response.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/aws/tests/test_deploy_policies.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/aws/tests/test_deploy_reconcile.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/aws/tests/test_lambda_handler_json_serialization.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/aws/tests/test_response.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/db/__init__.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/db/core/__init__.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/db/core/async_support.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/db/core/column.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/db/core/database.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/db/core/decorators.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/db/core/jsonproxy.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/db/core/result.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/db/core/row.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/db/core/sequence.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/db/core/table.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/db/core/view.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/db/exceptions.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/db/maintenance.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/db/migrations.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/db/servers/__init__.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/db/servers/base/__init__.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/db/servers/base/initializer.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/db/servers/base/operators.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/db/servers/base/sql.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/db/servers/base/types.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/db/servers/mysql/__init__.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/db/servers/mysql/operators.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/db/servers/mysql/reserved.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/db/servers/mysql/sql.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/db/servers/mysql/types.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/db/servers/postgres/__init__.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/db/servers/postgres/operators.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/db/servers/postgres/reserved.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/db/servers/postgres/sql.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/db/servers/postgres/types.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/db/servers/sqlite/__init__.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/db/servers/sqlite/operators.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/db/servers/sqlite/reserved.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/db/servers/sqlite/sql.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/db/servers/sqlite/types.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/db/servers/sqlserver/__init__.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/db/servers/sqlserver/operators.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/db/servers/sqlserver/reserved.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/db/servers/sqlserver/sql.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/db/servers/sqlserver/types.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/db/servers/tablehelper.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/db/tests/__init__.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/db/tests/common_db_test.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/db/tests/postgres/__init__.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/db/tests/postgres/common.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/db/tests/postgres/conftest.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/db/tests/postgres/test_column.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/db/tests/postgres/test_connections.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/db/tests/postgres/test_database.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/db/tests/postgres/test_engine.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/db/tests/postgres/test_general_usage.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/db/tests/postgres/test_imports.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/db/tests/postgres/test_result.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/db/tests/postgres/test_row.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/db/tests/postgres/test_row_comprehensive.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/db/tests/postgres/test_schema_locking.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/db/tests/postgres/test_schema_locking_unit.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/db/tests/postgres/test_sequence.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/db/tests/postgres/test_sql_comprehensive.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/db/tests/postgres/test_table.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/db/tests/postgres/test_table_comprehensive.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/db/tests/postgres/test_transaction.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/db/tests/sql/__init__.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/db/tests/sql/common.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/db/tests/sql/test_postgres_select_advanced.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/db/tests/sql/test_postgres_select_variances.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/db/tests/test_cursor_rowcount_fix.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/db/tests/test_db_utils.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/db/tests/test_postgres.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/db/tests/test_postgres_unchanged.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/db/tests/test_process_error_robustness.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/db/tests/test_result_caching.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/db/tests/test_result_sql_aware.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/db/tests/test_row_get_missing_column.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/db/tests/test_schema_locking_initializers.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/db/tests/test_schema_locking_simple.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/db/tests/test_sql_builder.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/db/tests/test_tablehelper.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/db/tests/test_view_helper.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/db/utils.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/logging.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/misc/__init__.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/misc/conv/__init__.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/misc/conv/iconv.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/misc/conv/oconv.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/misc/db.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/misc/export.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/misc/format.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/misc/mail.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/misc/merge.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/misc/pdf.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/misc/tests/__init__.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/misc/tests/test_db.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/misc/tests/test_fix.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/misc/tests/test_format.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/misc/tests/test_iconv.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/misc/tests/test_merge.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/misc/tests/test_oconv.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/misc/tests/test_original_error.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/misc/tests/test_timer.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/misc/timer.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/misc/tools.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/nosql/__init__.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/nosql/core/__init__.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/nosql/core/capabilities.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/nosql/core/store.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/nosql/core/where.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/nosql/exceptions.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/nosql/servers/__init__.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/nosql/servers/base/__init__.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/nosql/servers/cassandra/__init__.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/nosql/servers/cassandra/translation.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/nosql/servers/couchbase/__init__.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/nosql/servers/couchbase/translation.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/nosql/servers/dynamodb/__init__.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/nosql/servers/dynamodb/translation.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/nosql/servers/elasticsearch/__init__.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/nosql/servers/elasticsearch/translation.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/nosql/servers/memory/__init__.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/nosql/servers/mongodb/__init__.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/nosql/servers/mongodb/translation.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/nosql/servers/redis/__init__.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/payment/__init__.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/payment/authorizenet_adapter.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/payment/authorizenet_mirror.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/payment/base_adapter.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/payment/braintree_adapter.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/payment/braintree_mirror.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/payment/charge_rules.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/payment/stripe_adapter.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/payment/stripe_mirror.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity_python.egg-info/dependency_links.txt +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity_python.egg-info/entry_points.txt +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity_python.egg-info/requires.txt +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity_python.egg-info/top_level.txt +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/tests/test_activity_tracking_aborted_tx.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/tests/test_amplify_build.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/tests/test_asset_indexing.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/tests/test_asset_references.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/tests/test_assets_service.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/tests/test_async_support.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/tests/test_batch_operations.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/tests/test_column_tx_arg.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/tests/test_concurrency_safety.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/tests/test_connection_pool.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/tests/test_connection_resilience.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/tests/test_context_job_descriptions.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/tests/test_db_credentials_ssm_cascade.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/tests/test_db_maintenance.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/tests/test_decorators.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/tests/test_delete_hook_fk_blocked.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/tests/test_dirty_pipeline_fast_path.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/tests/test_email_processing.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/tests/test_enqueue_send_failures.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/tests/test_get_cognito_user_provider.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/tests/test_http_handler_rollback.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/tests/test_iconv_money_to_cents.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/tests/test_identifier_injection_guard.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/tests/test_json_columns.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/tests/test_jsonb_dict_adapter.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/tests/test_lambda_handler.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/tests/test_lambda_handler_auth.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/tests/test_lambda_handler_masquerade.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/tests/test_masquerade_grant.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/tests/test_mixins_import.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/tests/test_n_plus_one.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/tests/test_nosql_dynamodb.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/tests/test_nosql_memory.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/tests/test_nosql_mongodb.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/tests/test_nosql_redis.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/tests/test_nosql_translation.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/tests/test_nosql_where.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/tests/test_observability.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/tests/test_payment_authorizenet_adapter.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/tests/test_payment_braintree_adapter.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/tests/test_payment_braintree_mirror.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/tests/test_payment_mirror_empty_table.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/tests/test_payment_profile_sorting.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/tests/test_payment_stripe_adapter.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/tests/test_pdf.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/tests/test_prepared_statements.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/tests/test_psycopg3_upgrade.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/tests/test_query_cache.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/tests/test_restricted_direct_tables.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/tests/test_retry_side_effect_guard.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/tests/test_return_default_safety.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/tests/test_row_batch_update.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/tests/test_row_cache_staleness.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/tests/test_schema_migrations.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/tests/test_security_hardening.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/tests/test_server_cursor.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/tests/test_single_autocommit_safety.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/tests/test_spreadsheet_functions.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/tests/test_sqlite_backend.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/tests/test_sqs_per_record_transactions.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/tests/test_ssm_config.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/tests/test_store_user_data.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/tests/test_sys_modified_count_postgres_demo.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/tests/test_table_alter.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/tests/test_transaction_class_wrapping.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/tests/test_transaction_commit_and_ownership.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/tests/test_transaction_edge_cases.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/tests/test_where_clause_validation.py +0 -0
- {velocity_python-0.1.87 → velocity_python-0.1.88}/tests/test_write_hook_create_flow.py +0 -0
|
@@ -485,13 +485,43 @@ class Context:
|
|
|
485
485
|
def was_job_cancelled(self):
|
|
486
486
|
return self._job_cancelled_flag
|
|
487
487
|
|
|
488
|
-
def enqueue(
|
|
488
|
+
def enqueue(
|
|
489
|
+
self,
|
|
490
|
+
action,
|
|
491
|
+
payload={},
|
|
492
|
+
user=None,
|
|
493
|
+
suppress_job_activity=False,
|
|
494
|
+
transaction=None,
|
|
495
|
+
):
|
|
489
496
|
"""
|
|
490
497
|
Enqueue jobs to SQS with independent job activity tracking.
|
|
491
498
|
|
|
492
499
|
This method uses its own transaction for aws_job_activity updates to ensure
|
|
493
500
|
job tracking is never rolled back with other operations.
|
|
501
|
+
|
|
502
|
+
When ``transaction`` (a velocity Transaction) is provided, the entire
|
|
503
|
+
enqueue — job-activity bookkeeping and the SQS send — is deferred until
|
|
504
|
+
that transaction commits, via ``Transaction.on_commit``. Use this
|
|
505
|
+
whenever the queued job will read back rows written in the same
|
|
506
|
+
transaction: sending immediately races the SQS consumer against the
|
|
507
|
+
COMMIT, and the consumer can win and find nothing (this dropped a
|
|
508
|
+
production Braintree webhook). If the transaction rolls back, nothing
|
|
509
|
+
is enqueued.
|
|
510
|
+
|
|
511
|
+
(The parameter is named ``transaction`` rather than ``tx`` because the
|
|
512
|
+
``@engine.transaction`` class decorator auto-wraps any method with a
|
|
513
|
+
``tx`` parameter and would inject its own transaction here.)
|
|
494
514
|
"""
|
|
515
|
+
if transaction is not None:
|
|
516
|
+
transaction.on_commit(
|
|
517
|
+
lambda: self.enqueue(
|
|
518
|
+
action,
|
|
519
|
+
payload=payload,
|
|
520
|
+
user=user,
|
|
521
|
+
suppress_job_activity=suppress_job_activity,
|
|
522
|
+
)
|
|
523
|
+
)
|
|
524
|
+
return {"deferred_until_commit": True}
|
|
495
525
|
batch_id = str(uuid.uuid4())
|
|
496
526
|
results = {"batch_id": batch_id}
|
|
497
527
|
queue = boto3.resource("sqs").get_queue_by_name(
|
|
@@ -650,6 +650,12 @@ class Engine:
|
|
|
650
650
|
loop_start = time.perf_counter()
|
|
651
651
|
while True:
|
|
652
652
|
try:
|
|
653
|
+
# Each attempt must start with no stale on_commit
|
|
654
|
+
# callbacks from a previous failed attempt — not every
|
|
655
|
+
# retry path rolls back (the transient-connection path
|
|
656
|
+
# discards the connection instead), and the re-run
|
|
657
|
+
# function registers its own callbacks again.
|
|
658
|
+
_tx.discard_on_commit_callbacks()
|
|
653
659
|
result = function(*args, **kwds)
|
|
654
660
|
# Commit INSIDE the retry envelope so a commit-time
|
|
655
661
|
# serialization failure / deadlock / deferred-constraint
|
|
@@ -194,6 +194,12 @@ class Transaction:
|
|
|
194
194
|
# fresh transaction and lose the prior uncommitted statements without
|
|
195
195
|
# any error. Reset on connect/commit/rollback.
|
|
196
196
|
self._in_progress = False
|
|
197
|
+
# R32 — Callables to run once, after the transaction's work is durably
|
|
198
|
+
# committed (see on_commit()). Discarded on rollback and whenever a
|
|
199
|
+
# dead connection is dropped, so callbacks from a failed attempt never
|
|
200
|
+
# fire; the @engine.transaction retry envelope also clears them before
|
|
201
|
+
# each attempt so a re-run function re-registers from a clean slate.
|
|
202
|
+
self._on_commit_callbacks = []
|
|
197
203
|
|
|
198
204
|
def __str__(self):
|
|
199
205
|
config = mask_config_for_display(self.engine.config)
|
|
@@ -248,6 +254,9 @@ class Transaction:
|
|
|
248
254
|
dead = self.connection
|
|
249
255
|
self.connection = None
|
|
250
256
|
self._in_progress = False
|
|
257
|
+
# Uncommitted work is gone; anything queued to run after its commit
|
|
258
|
+
# must never fire.
|
|
259
|
+
self._on_commit_callbacks = []
|
|
251
260
|
if dead is None:
|
|
252
261
|
return
|
|
253
262
|
if self.__pooled:
|
|
@@ -306,6 +315,9 @@ class Transaction:
|
|
|
306
315
|
the pool instead of being closed.
|
|
307
316
|
"""
|
|
308
317
|
if not self.connection:
|
|
318
|
+
# No DB work happened, so there is nothing to commit — but the
|
|
319
|
+
# transaction still completed; run any on_commit callbacks.
|
|
320
|
+
self._fire_on_commit_callbacks()
|
|
309
321
|
return
|
|
310
322
|
if debug:
|
|
311
323
|
print(f"<<< {id(self)} close connection.")
|
|
@@ -565,6 +577,67 @@ class Transaction:
|
|
|
565
577
|
"query_time_ms": round(self._query_time_ms, 1),
|
|
566
578
|
},
|
|
567
579
|
)
|
|
580
|
+
# Fire after the DB work is durable (or when there was no DB work at
|
|
581
|
+
# all — a transaction that only registered callbacks still completes).
|
|
582
|
+
# A commit-time DB error raises above, so callbacks from a failed
|
|
583
|
+
# commit never run here.
|
|
584
|
+
self._fire_on_commit_callbacks()
|
|
585
|
+
|
|
586
|
+
def on_commit(self, callback):
|
|
587
|
+
"""Register a callable to run once, after this transaction commits.
|
|
588
|
+
|
|
589
|
+
Use this for side effects that must not become visible before the
|
|
590
|
+
transaction's DB work does — e.g. sending an SQS message that a
|
|
591
|
+
consumer will immediately read back from the database. Sending inside
|
|
592
|
+
the open transaction races the consumer against the commit; deferring
|
|
593
|
+
with ``on_commit`` closes that race::
|
|
594
|
+
|
|
595
|
+
@engine.transaction
|
|
596
|
+
def handler(tx, context):
|
|
597
|
+
row = tx.table("webhooks").new({...})
|
|
598
|
+
tx.on_commit(lambda: context.enqueue(..., payload={"webhook_id": row.sys_id}))
|
|
599
|
+
|
|
600
|
+
Semantics:
|
|
601
|
+
|
|
602
|
+
* Callbacks run in registration order, once, immediately after a
|
|
603
|
+
successful COMMIT (``commit()``/``close()``/decorator exit). If the
|
|
604
|
+
transaction never touched the database, they run when it completes.
|
|
605
|
+
* They are discarded — never run — on ``rollback()``, when a dead
|
|
606
|
+
connection is dropped, and before each ``@engine.transaction`` retry
|
|
607
|
+
attempt (the re-run function registers its own again).
|
|
608
|
+
* A callback exception is logged and does not propagate: the commit is
|
|
609
|
+
already durable, so raising would misreport a committed transaction
|
|
610
|
+
as failed (and e.g. make a webhook caller retry a done request).
|
|
611
|
+
Callbacks needing delivery guarantees must handle their own errors.
|
|
612
|
+
"""
|
|
613
|
+
if not callable(callback):
|
|
614
|
+
raise TypeError("on_commit callback must be callable")
|
|
615
|
+
# getattr-guarded: some tests (and potential subclasses) build a
|
|
616
|
+
# Transaction without running __init__.
|
|
617
|
+
callbacks = getattr(self, "_on_commit_callbacks", None)
|
|
618
|
+
if callbacks is None:
|
|
619
|
+
callbacks = self._on_commit_callbacks = []
|
|
620
|
+
callbacks.append(callback)
|
|
621
|
+
return callback
|
|
622
|
+
|
|
623
|
+
def discard_on_commit_callbacks(self):
|
|
624
|
+
"""Drop any registered on_commit callbacks without running them."""
|
|
625
|
+
self._on_commit_callbacks = []
|
|
626
|
+
|
|
627
|
+
def _fire_on_commit_callbacks(self):
|
|
628
|
+
callbacks = getattr(self, "_on_commit_callbacks", None)
|
|
629
|
+
self._on_commit_callbacks = []
|
|
630
|
+
if not callbacks:
|
|
631
|
+
return
|
|
632
|
+
for callback in callbacks:
|
|
633
|
+
try:
|
|
634
|
+
callback()
|
|
635
|
+
except Exception:
|
|
636
|
+
_logger.exception(
|
|
637
|
+
"on_commit callback %r failed; the transaction is already "
|
|
638
|
+
"committed, so the error is logged and not raised",
|
|
639
|
+
callback,
|
|
640
|
+
)
|
|
568
641
|
|
|
569
642
|
def rollback(self):
|
|
570
643
|
"""
|
|
@@ -576,6 +649,8 @@ class Transaction:
|
|
|
576
649
|
self.connection.rollback()
|
|
577
650
|
# Transaction is clean again — no uncommitted work pending.
|
|
578
651
|
self._in_progress = False
|
|
652
|
+
# The work these were waiting on is rolled back — never run them.
|
|
653
|
+
self._on_commit_callbacks = []
|
|
579
654
|
|
|
580
655
|
def is_aborted(self):
|
|
581
656
|
"""Return True if the connection is in a failed/aborted transaction.
|
|
@@ -219,6 +219,7 @@ tests/test_nosql_redis.py
|
|
|
219
219
|
tests/test_nosql_translation.py
|
|
220
220
|
tests/test_nosql_where.py
|
|
221
221
|
tests/test_observability.py
|
|
222
|
+
tests/test_on_commit.py
|
|
222
223
|
tests/test_payment_authorizenet_adapter.py
|
|
223
224
|
tests/test_payment_braintree_adapter.py
|
|
224
225
|
tests/test_payment_braintree_mirror.py
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
"""Transaction.on_commit and Context.enqueue(tx=...) — post-commit side effects.
|
|
2
|
+
|
|
3
|
+
Motivation: sending an SQS message inside a still-open transaction races the
|
|
4
|
+
consumer against the COMMIT; the consumer can read the database before the
|
|
5
|
+
producer's rows are visible (this dropped a production Braintree webhook).
|
|
6
|
+
``tx.on_commit`` defers such side effects until the work is durable, and
|
|
7
|
+
``Context.enqueue(..., transaction=tx)`` uses it to defer the whole enqueue.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
import unittest
|
|
11
|
+
from unittest.mock import MagicMock, patch
|
|
12
|
+
|
|
13
|
+
from velocity.db import exceptions
|
|
14
|
+
from velocity.db.core.engine import Engine
|
|
15
|
+
from velocity.db.core.transaction import Transaction
|
|
16
|
+
from velocity.aws.handlers import context as handler_context
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def _make_tx(connection=None):
|
|
20
|
+
engine = MagicMock()
|
|
21
|
+
engine.pool_enabled = False
|
|
22
|
+
connection = connection if connection is not None else MagicMock()
|
|
23
|
+
return Transaction(engine, connection), connection
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class TransactionOnCommitTests(unittest.TestCase):
|
|
27
|
+
def test_callbacks_fire_in_order_after_commit(self):
|
|
28
|
+
tx, _ = _make_tx()
|
|
29
|
+
fired = []
|
|
30
|
+
tx.on_commit(lambda: fired.append("first"))
|
|
31
|
+
tx.on_commit(lambda: fired.append("second"))
|
|
32
|
+
self.assertEqual([], fired) # nothing runs before commit
|
|
33
|
+
tx.commit()
|
|
34
|
+
self.assertEqual(["first", "second"], fired)
|
|
35
|
+
|
|
36
|
+
def test_callbacks_fire_only_once(self):
|
|
37
|
+
tx, _ = _make_tx()
|
|
38
|
+
fired = []
|
|
39
|
+
tx.on_commit(lambda: fired.append(1))
|
|
40
|
+
tx.commit()
|
|
41
|
+
tx.commit() # e.g. close() after an explicit commit
|
|
42
|
+
self.assertEqual([1], fired)
|
|
43
|
+
|
|
44
|
+
def test_rollback_discards_callbacks(self):
|
|
45
|
+
tx, _ = _make_tx()
|
|
46
|
+
fired = []
|
|
47
|
+
tx.on_commit(lambda: fired.append(1))
|
|
48
|
+
tx.rollback()
|
|
49
|
+
tx.commit()
|
|
50
|
+
self.assertEqual([], fired)
|
|
51
|
+
|
|
52
|
+
def test_close_without_db_work_still_fires(self):
|
|
53
|
+
tx, _ = _make_tx(connection=False)
|
|
54
|
+
tx.connection = None # transaction never touched the database
|
|
55
|
+
fired = []
|
|
56
|
+
tx.on_commit(lambda: fired.append(1))
|
|
57
|
+
tx.close()
|
|
58
|
+
self.assertEqual([1], fired)
|
|
59
|
+
|
|
60
|
+
def test_commit_time_db_error_does_not_fire(self):
|
|
61
|
+
tx, connection = _make_tx()
|
|
62
|
+
connection.commit.side_effect = RuntimeError("deadlock at COMMIT")
|
|
63
|
+
tx.engine.process_error.side_effect = lambda e: exceptions.DbRetryTransaction(
|
|
64
|
+
str(e)
|
|
65
|
+
)
|
|
66
|
+
fired = []
|
|
67
|
+
tx.on_commit(lambda: fired.append(1))
|
|
68
|
+
with self.assertRaises(exceptions.DbRetryTransaction):
|
|
69
|
+
tx.commit()
|
|
70
|
+
self.assertEqual([], fired)
|
|
71
|
+
# The retry envelope rolls back next; the callback must stay discarded.
|
|
72
|
+
tx.rollback()
|
|
73
|
+
connection.commit.side_effect = None
|
|
74
|
+
tx.commit()
|
|
75
|
+
self.assertEqual([], fired)
|
|
76
|
+
|
|
77
|
+
def test_callback_exception_is_swallowed_and_rest_run(self):
|
|
78
|
+
tx, _ = _make_tx()
|
|
79
|
+
fired = []
|
|
80
|
+
|
|
81
|
+
def _explodes():
|
|
82
|
+
raise ValueError("boom")
|
|
83
|
+
|
|
84
|
+
tx.on_commit(_explodes)
|
|
85
|
+
tx.on_commit(lambda: fired.append("still ran"))
|
|
86
|
+
with self.assertLogs("velocity.db.transaction", level="ERROR"):
|
|
87
|
+
tx.commit()
|
|
88
|
+
self.assertEqual(["still ran"], fired)
|
|
89
|
+
|
|
90
|
+
def test_dead_connection_discard_clears_callbacks(self):
|
|
91
|
+
tx, _ = _make_tx()
|
|
92
|
+
fired = []
|
|
93
|
+
tx.on_commit(lambda: fired.append(1))
|
|
94
|
+
tx._discard_dead_connection()
|
|
95
|
+
tx.commit()
|
|
96
|
+
self.assertEqual([], fired)
|
|
97
|
+
|
|
98
|
+
def test_non_callable_rejected(self):
|
|
99
|
+
tx, _ = _make_tx()
|
|
100
|
+
with self.assertRaises(TypeError):
|
|
101
|
+
tx.on_commit("not callable")
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
class ExecFunctionRetryTests(unittest.TestCase):
|
|
105
|
+
def test_retry_attempt_does_not_replay_previous_attempts_callbacks(self):
|
|
106
|
+
"""A failed attempt's callbacks must never fire; only the committed
|
|
107
|
+
attempt's do — and exactly once."""
|
|
108
|
+
tx, _ = _make_tx()
|
|
109
|
+
engine = MagicMock()
|
|
110
|
+
engine.MAX_RETRIES = 3
|
|
111
|
+
fired = []
|
|
112
|
+
attempts = {"n": 0}
|
|
113
|
+
|
|
114
|
+
def function():
|
|
115
|
+
attempts["n"] += 1
|
|
116
|
+
attempt = attempts["n"]
|
|
117
|
+
tx.on_commit(lambda: fired.append(attempt))
|
|
118
|
+
if attempt == 1:
|
|
119
|
+
raise exceptions.DbRetryTransaction("serialization failure")
|
|
120
|
+
|
|
121
|
+
with patch("velocity.db.core.engine.time.sleep"):
|
|
122
|
+
Engine.exec_function(engine, function, tx, _owns_tx=True)
|
|
123
|
+
|
|
124
|
+
self.assertEqual(2, attempts["n"])
|
|
125
|
+
self.assertEqual([2], fired) # attempt 1's callback discarded
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
class EnqueueDeferredTests(unittest.TestCase):
|
|
129
|
+
class _FakeQueue:
|
|
130
|
+
def __init__(self):
|
|
131
|
+
self.sent = []
|
|
132
|
+
|
|
133
|
+
def send_messages(self, Entries):
|
|
134
|
+
self.sent.extend(Entries)
|
|
135
|
+
return {"Successful": [{"Id": e["Id"]} for e in Entries], "Failed": []}
|
|
136
|
+
|
|
137
|
+
class _FakeContext:
|
|
138
|
+
def __init__(self):
|
|
139
|
+
self.jobs = []
|
|
140
|
+
|
|
141
|
+
def session(self):
|
|
142
|
+
return {"email_address": "owner@example.com"}
|
|
143
|
+
|
|
144
|
+
def create_job(self, job_data=None):
|
|
145
|
+
self.jobs.append(job_data)
|
|
146
|
+
|
|
147
|
+
def fail_enqueue(self, **kwargs):
|
|
148
|
+
raise AssertionError("no send failures expected")
|
|
149
|
+
|
|
150
|
+
# Bind the real method so the deferred callback re-enters it.
|
|
151
|
+
enqueue = handler_context.Context.enqueue
|
|
152
|
+
|
|
153
|
+
def _patched(self, queue):
|
|
154
|
+
class _Resource:
|
|
155
|
+
def get_queue_by_name(self, QueueName):
|
|
156
|
+
return queue
|
|
157
|
+
|
|
158
|
+
return (
|
|
159
|
+
patch.dict(
|
|
160
|
+
handler_context.os.environ,
|
|
161
|
+
{"SqsWorkQueue": "example-queue"},
|
|
162
|
+
clear=False,
|
|
163
|
+
),
|
|
164
|
+
patch.object(handler_context.boto3, "resource", return_value=_Resource()),
|
|
165
|
+
)
|
|
166
|
+
|
|
167
|
+
def test_enqueue_with_tx_defers_until_commit(self):
|
|
168
|
+
ctx = self._FakeContext()
|
|
169
|
+
queue = self._FakeQueue()
|
|
170
|
+
tx, _ = _make_tx()
|
|
171
|
+
|
|
172
|
+
env_patch, boto_patch = self._patched(queue)
|
|
173
|
+
with env_patch, boto_patch:
|
|
174
|
+
result = ctx.enqueue(
|
|
175
|
+
"process-braintree-webhook",
|
|
176
|
+
payload={"webhook_id": 1116},
|
|
177
|
+
transaction=tx,
|
|
178
|
+
)
|
|
179
|
+
# Nothing sent or tracked while the transaction is open.
|
|
180
|
+
self.assertEqual({"deferred_until_commit": True}, result)
|
|
181
|
+
self.assertEqual([], queue.sent)
|
|
182
|
+
self.assertEqual([], ctx.jobs)
|
|
183
|
+
|
|
184
|
+
tx.commit()
|
|
185
|
+
|
|
186
|
+
self.assertEqual(1, len(queue.sent))
|
|
187
|
+
self.assertEqual(1, len(ctx.jobs))
|
|
188
|
+
self.assertIn("process-braintree-webhook", queue.sent[0]["MessageBody"])
|
|
189
|
+
|
|
190
|
+
def test_enqueue_with_tx_rollback_sends_nothing(self):
|
|
191
|
+
ctx = self._FakeContext()
|
|
192
|
+
queue = self._FakeQueue()
|
|
193
|
+
tx, _ = _make_tx()
|
|
194
|
+
|
|
195
|
+
env_patch, boto_patch = self._patched(queue)
|
|
196
|
+
with env_patch, boto_patch:
|
|
197
|
+
ctx.enqueue("some-action", payload={"x": 1}, transaction=tx)
|
|
198
|
+
tx.rollback()
|
|
199
|
+
tx.commit()
|
|
200
|
+
|
|
201
|
+
self.assertEqual([], queue.sent)
|
|
202
|
+
self.assertEqual([], ctx.jobs)
|
|
203
|
+
|
|
204
|
+
def test_enqueue_without_tx_sends_immediately(self):
|
|
205
|
+
ctx = self._FakeContext()
|
|
206
|
+
queue = self._FakeQueue()
|
|
207
|
+
|
|
208
|
+
env_patch, boto_patch = self._patched(queue)
|
|
209
|
+
with env_patch, boto_patch:
|
|
210
|
+
ctx.enqueue("some-action", payload={"x": 1})
|
|
211
|
+
|
|
212
|
+
self.assertEqual(1, len(queue.sent))
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
if __name__ == "__main__":
|
|
216
|
+
unittest.main()
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/aws/handlers/context_factory.py
RENAMED
|
File without changes
|
|
File without changes
|
{velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/aws/handlers/lambda_handler.py
RENAMED
|
File without changes
|
|
File without changes
|
{velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/aws/handlers/mixins/__init__.py
RENAMED
|
File without changes
|
{velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/aws/handlers/mixins/data_service.py
RENAMED
|
File without changes
|
{velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/aws/handlers/mixins/web_handler.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/aws/tests/test_amplify_build_shim.py
RENAMED
|
File without changes
|
|
File without changes
|
{velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/aws/tests/test_deploy_policies.py
RENAMED
|
File without changes
|
{velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/aws/tests/test_deploy_reconcile.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/db/servers/base/initializer.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/db/servers/mysql/operators.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/db/servers/postgres/__init__.py
RENAMED
|
File without changes
|
{velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/db/servers/postgres/operators.py
RENAMED
|
File without changes
|
{velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/db/servers/postgres/reserved.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/db/servers/sqlite/__init__.py
RENAMED
|
File without changes
|
{velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/db/servers/sqlite/operators.py
RENAMED
|
File without changes
|
{velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/db/servers/sqlite/reserved.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/db/servers/sqlserver/__init__.py
RENAMED
|
File without changes
|
{velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/db/servers/sqlserver/operators.py
RENAMED
|
File without changes
|
{velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/db/servers/sqlserver/reserved.py
RENAMED
|
File without changes
|
|
File without changes
|
{velocity_python-0.1.87 → velocity_python-0.1.88}/src/velocity/db/servers/sqlserver/types.py
RENAMED
|
File without changes
|
|
File without changes
|