velocity-python 0.1.88__tar.gz → 0.1.89__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.88/src/velocity_python.egg-info → velocity_python-0.1.89}/PKG-INFO +1 -1
- {velocity_python-0.1.88 → velocity_python-0.1.89}/pyproject.toml +1 -1
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/__init__.py +1 -1
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/aws/__init__.py +1 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/aws/amplify_build.py +3 -1
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/aws/assets/__init__.py +1 -1
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/aws/assets/backfill.py +7 -3
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/aws/assets/indexing.py +11 -4
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/aws/assets/references.py +10 -4
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/aws/assets/service.py +19 -9
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/aws/assets/usage_index.py +4 -2
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/aws/deploy/operations.py +15 -8
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/aws/deploy/policies.py +15 -7
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/aws/deploy/reconcile.py +13 -7
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/aws/deploy/targets.py +9 -3
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/aws/dirty_pipeline.py +2 -4
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/aws/handlers/base_handler.py +3 -1
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/aws/handlers/context.py +3 -3
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/aws/handlers/exceptions.py +8 -1
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/aws/handlers/mixins/data_service.py +93 -27
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/aws/handlers/sqs_handler.py +1 -3
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/aws/s3.py +3 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/aws/ssm_config.py +37 -28
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/aws/tests/test_amplify_build_shim.py +7 -5
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/aws/tests/test_base_handler_error_response.py +14 -5
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/aws/tests/test_deploy_policies.py +6 -2
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/aws/tests/test_deploy_reconcile.py +27 -16
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/aws/tests/test_response.py +6 -4
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/db/core/async_support.py +43 -14
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/db/core/decorators.py +22 -7
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/db/core/engine.py +98 -50
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/db/core/row.py +13 -4
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/db/core/table.py +135 -54
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/db/core/transaction.py +24 -11
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/db/core/view.py +3 -1
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/db/maintenance.py +30 -7
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/db/migrations.py +78 -30
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/db/servers/mysql/sql.py +2 -2
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/db/servers/postgres/__init__.py +13 -3
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/db/servers/postgres/sql.py +2 -6
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/db/servers/sqlserver/sql.py +12 -6
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/db/servers/tablehelper.py +2 -4
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/db/tests/postgres/test_schema_locking.py +24 -9
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/db/tests/test_process_error_robustness.py +16 -3
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/db/tests/test_sql_builder.py +5 -1
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/misc/conv/iconv.py +3 -1
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/misc/export.py +6 -1
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/misc/mail.py +4 -1
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/misc/pdf.py +1 -1
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/payment/authorizenet_adapter.py +42 -26
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/payment/authorizenet_mirror.py +12 -8
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/payment/braintree_adapter.py +21 -17
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/payment/braintree_mirror.py +15 -11
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/payment/stripe_adapter.py +56 -26
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/payment/stripe_mirror.py +8 -6
- {velocity_python-0.1.88 → velocity_python-0.1.89/src/velocity_python.egg-info}/PKG-INFO +1 -1
- {velocity_python-0.1.88 → velocity_python-0.1.89}/tests/test_amplify_build.py +18 -3
- {velocity_python-0.1.88 → velocity_python-0.1.89}/tests/test_asset_indexing.py +18 -6
- {velocity_python-0.1.88 → velocity_python-0.1.89}/tests/test_asset_references.py +18 -10
- {velocity_python-0.1.88 → velocity_python-0.1.89}/tests/test_assets_service.py +12 -4
- {velocity_python-0.1.88 → velocity_python-0.1.89}/tests/test_async_support.py +10 -12
- {velocity_python-0.1.88 → velocity_python-0.1.89}/tests/test_column_tx_arg.py +3 -1
- {velocity_python-0.1.88 → velocity_python-0.1.89}/tests/test_concurrency_safety.py +22 -7
- {velocity_python-0.1.88 → velocity_python-0.1.89}/tests/test_connection_pool.py +33 -10
- {velocity_python-0.1.88 → velocity_python-0.1.89}/tests/test_connection_resilience.py +107 -67
- {velocity_python-0.1.88 → velocity_python-0.1.89}/tests/test_context_job_descriptions.py +52 -38
- {velocity_python-0.1.88 → velocity_python-0.1.89}/tests/test_db_credentials_ssm_cascade.py +7 -5
- {velocity_python-0.1.88 → velocity_python-0.1.89}/tests/test_db_maintenance.py +9 -3
- {velocity_python-0.1.88 → velocity_python-0.1.89}/tests/test_delete_hook_fk_blocked.py +3 -1
- {velocity_python-0.1.88 → velocity_python-0.1.89}/tests/test_dirty_pipeline_fast_path.py +4 -2
- {velocity_python-0.1.88 → velocity_python-0.1.89}/tests/test_enqueue_send_failures.py +10 -6
- {velocity_python-0.1.88 → velocity_python-0.1.89}/tests/test_json_columns.py +17 -7
- {velocity_python-0.1.88 → velocity_python-0.1.89}/tests/test_lambda_handler_masquerade.py +6 -2
- {velocity_python-0.1.88 → velocity_python-0.1.89}/tests/test_n_plus_one.py +11 -5
- {velocity_python-0.1.88 → velocity_python-0.1.89}/tests/test_nosql_translation.py +1 -5
- {velocity_python-0.1.88 → velocity_python-0.1.89}/tests/test_observability.py +10 -2
- {velocity_python-0.1.88 → velocity_python-0.1.89}/tests/test_payment_authorizenet_adapter.py +4 -2
- {velocity_python-0.1.88 → velocity_python-0.1.89}/tests/test_payment_braintree_adapter.py +1 -1
- {velocity_python-0.1.88 → velocity_python-0.1.89}/tests/test_payment_braintree_mirror.py +1 -1
- {velocity_python-0.1.88 → velocity_python-0.1.89}/tests/test_payment_mirror_empty_table.py +5 -1
- {velocity_python-0.1.88 → velocity_python-0.1.89}/tests/test_payment_stripe_adapter.py +37 -12
- {velocity_python-0.1.88 → velocity_python-0.1.89}/tests/test_pdf.py +38 -14
- {velocity_python-0.1.88 → velocity_python-0.1.89}/tests/test_prepared_statements.py +9 -3
- {velocity_python-0.1.88 → velocity_python-0.1.89}/tests/test_psycopg3_upgrade.py +18 -7
- {velocity_python-0.1.88 → velocity_python-0.1.89}/tests/test_query_cache.py +3 -1
- {velocity_python-0.1.88 → velocity_python-0.1.89}/tests/test_row_cache_staleness.py +20 -7
- {velocity_python-0.1.88 → velocity_python-0.1.89}/tests/test_schema_migrations.py +141 -49
- {velocity_python-0.1.88 → velocity_python-0.1.89}/tests/test_security_hardening.py +24 -6
- {velocity_python-0.1.88 → velocity_python-0.1.89}/tests/test_server_cursor.py +7 -1
- {velocity_python-0.1.88 → velocity_python-0.1.89}/tests/test_single_autocommit_safety.py +3 -1
- {velocity_python-0.1.88 → velocity_python-0.1.89}/tests/test_spreadsheet_functions.py +3 -1
- {velocity_python-0.1.88 → velocity_python-0.1.89}/tests/test_sqlite_backend.py +12 -6
- {velocity_python-0.1.88 → velocity_python-0.1.89}/tests/test_sqs_per_record_transactions.py +11 -6
- {velocity_python-0.1.88 → velocity_python-0.1.89}/tests/test_ssm_config.py +1 -1
- {velocity_python-0.1.88 → velocity_python-0.1.89}/tests/test_store_user_data.py +6 -2
- {velocity_python-0.1.88 → velocity_python-0.1.89}/tests/test_table_alter.py +56 -14
- {velocity_python-0.1.88 → velocity_python-0.1.89}/tests/test_transaction_class_wrapping.py +2 -6
- {velocity_python-0.1.88 → velocity_python-0.1.89}/tests/test_transaction_commit_and_ownership.py +12 -5
- {velocity_python-0.1.88 → velocity_python-0.1.89}/tests/test_transaction_edge_cases.py +24 -13
- {velocity_python-0.1.88 → velocity_python-0.1.89}/LICENSE +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/README.md +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/setup.cfg +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/aws/amplify.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/aws/deploy/__init__.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/aws/deploy/config.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/aws/handlers/__init__.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/aws/handlers/context_factory.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/aws/handlers/lambda_handler.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/aws/handlers/masquerade.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/aws/handlers/mixins/__init__.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/aws/handlers/mixins/web_handler.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/aws/handlers/perf.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/aws/handlers/response.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/aws/tests/__init__.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/aws/tests/test_amplify_build_policy_size.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/aws/tests/test_lambda_handler_json_serialization.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/db/__init__.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/db/core/__init__.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/db/core/column.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/db/core/database.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/db/core/jsonproxy.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/db/core/result.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/db/core/sequence.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/db/exceptions.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/db/servers/__init__.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/db/servers/base/__init__.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/db/servers/base/initializer.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/db/servers/base/operators.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/db/servers/base/sql.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/db/servers/base/types.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/db/servers/mysql/__init__.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/db/servers/mysql/operators.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/db/servers/mysql/reserved.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/db/servers/mysql/types.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/db/servers/postgres/operators.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/db/servers/postgres/reserved.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/db/servers/postgres/types.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/db/servers/sqlite/__init__.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/db/servers/sqlite/operators.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/db/servers/sqlite/reserved.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/db/servers/sqlite/sql.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/db/servers/sqlite/types.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/db/servers/sqlserver/__init__.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/db/servers/sqlserver/operators.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/db/servers/sqlserver/reserved.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/db/servers/sqlserver/types.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/db/tests/__init__.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/db/tests/common_db_test.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/db/tests/postgres/__init__.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/db/tests/postgres/common.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/db/tests/postgres/conftest.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/db/tests/postgres/test_column.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/db/tests/postgres/test_connections.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/db/tests/postgres/test_database.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/db/tests/postgres/test_engine.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/db/tests/postgres/test_general_usage.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/db/tests/postgres/test_imports.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/db/tests/postgres/test_result.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/db/tests/postgres/test_row.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/db/tests/postgres/test_row_comprehensive.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/db/tests/postgres/test_schema_locking_unit.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/db/tests/postgres/test_sequence.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/db/tests/postgres/test_sql_comprehensive.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/db/tests/postgres/test_table.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/db/tests/postgres/test_table_comprehensive.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/db/tests/postgres/test_transaction.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/db/tests/sql/__init__.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/db/tests/sql/common.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/db/tests/sql/test_postgres_select_advanced.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/db/tests/sql/test_postgres_select_variances.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/db/tests/test_cursor_rowcount_fix.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/db/tests/test_db_utils.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/db/tests/test_postgres.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/db/tests/test_postgres_unchanged.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/db/tests/test_result_caching.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/db/tests/test_result_sql_aware.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/db/tests/test_row_get_missing_column.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/db/tests/test_schema_locking_initializers.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/db/tests/test_schema_locking_simple.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/db/tests/test_tablehelper.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/db/tests/test_view_helper.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/db/utils.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/logging.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/misc/__init__.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/misc/conv/__init__.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/misc/conv/oconv.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/misc/db.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/misc/format.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/misc/merge.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/misc/tests/__init__.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/misc/tests/test_db.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/misc/tests/test_fix.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/misc/tests/test_format.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/misc/tests/test_iconv.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/misc/tests/test_merge.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/misc/tests/test_oconv.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/misc/tests/test_original_error.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/misc/tests/test_timer.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/misc/timer.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/misc/tools.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/nosql/__init__.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/nosql/core/__init__.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/nosql/core/capabilities.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/nosql/core/store.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/nosql/core/where.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/nosql/exceptions.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/nosql/servers/__init__.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/nosql/servers/base/__init__.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/nosql/servers/cassandra/__init__.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/nosql/servers/cassandra/translation.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/nosql/servers/couchbase/__init__.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/nosql/servers/couchbase/translation.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/nosql/servers/dynamodb/__init__.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/nosql/servers/dynamodb/translation.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/nosql/servers/elasticsearch/__init__.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/nosql/servers/elasticsearch/translation.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/nosql/servers/memory/__init__.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/nosql/servers/mongodb/__init__.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/nosql/servers/mongodb/translation.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/nosql/servers/redis/__init__.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/payment/__init__.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/payment/base_adapter.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity/payment/charge_rules.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity_python.egg-info/SOURCES.txt +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity_python.egg-info/dependency_links.txt +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity_python.egg-info/entry_points.txt +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity_python.egg-info/requires.txt +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/src/velocity_python.egg-info/top_level.txt +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/tests/test_activity_tracking_aborted_tx.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/tests/test_batch_operations.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/tests/test_decorators.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/tests/test_email_processing.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/tests/test_get_cognito_user_provider.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/tests/test_http_handler_rollback.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/tests/test_iconv_money_to_cents.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/tests/test_identifier_injection_guard.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/tests/test_jsonb_dict_adapter.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/tests/test_lambda_handler.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/tests/test_lambda_handler_auth.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/tests/test_masquerade_grant.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/tests/test_mixins_import.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/tests/test_nosql_dynamodb.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/tests/test_nosql_memory.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/tests/test_nosql_mongodb.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/tests/test_nosql_redis.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/tests/test_nosql_where.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/tests/test_on_commit.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/tests/test_payment_profile_sorting.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/tests/test_restricted_direct_tables.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/tests/test_retry_side_effect_guard.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/tests/test_return_default_safety.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/tests/test_row_batch_update.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/tests/test_sys_modified_count_postgres_demo.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/tests/test_where_clause_validation.py +0 -0
- {velocity_python-0.1.88 → velocity_python-0.1.89}/tests/test_write_hook_create_flow.py +0 -0
|
@@ -157,4 +157,6 @@ def update_lambda_layers_to_latest(
|
|
|
157
157
|
if app is None:
|
|
158
158
|
app = AmplifyProject(app_id)
|
|
159
159
|
target = _AmplifyProjectTarget(app, branch)
|
|
160
|
-
_update_layers_new(
|
|
160
|
+
_update_layers_new(
|
|
161
|
+
target, function_names=function_names, lambda_client=lambda_client
|
|
162
|
+
)
|
|
@@ -55,7 +55,9 @@ def build_backfill_asset_data(
|
|
|
55
55
|
"name": filename,
|
|
56
56
|
"type": file_ext,
|
|
57
57
|
"etag": _clean_etag(object_info.get("ETag") or (head_info or {}).get("ETag")),
|
|
58
|
-
"filesize": _coerce_int(
|
|
58
|
+
"filesize": _coerce_int(
|
|
59
|
+
object_info.get("Size") or (head_info or {}).get("ContentLength")
|
|
60
|
+
),
|
|
59
61
|
"hash": metadata.get("hash"),
|
|
60
62
|
"thumbnail_key": metadata.get("thumbnail_key"),
|
|
61
63
|
"client": None if key.startswith("site/uploads") else key.split("/", 1)[0],
|
|
@@ -106,7 +108,9 @@ def backfill_asset_records(
|
|
|
106
108
|
continue
|
|
107
109
|
tx.table("images").upsert(row, {"key": row["key"]})
|
|
108
110
|
stored = tx.table("images").find({"key": row["key"]})
|
|
109
|
-
inserted_assets.append(
|
|
111
|
+
inserted_assets.append(
|
|
112
|
+
normalize_asset_record(stored.to_dict() if stored else row)
|
|
113
|
+
)
|
|
110
114
|
|
|
111
115
|
return inserted_assets, AssetBackfillSummary(
|
|
112
116
|
scanned=scanned,
|
|
@@ -149,4 +153,4 @@ def _copy_if_present(source: Mapping[str, Any], keys: list[str]) -> dict[str, An
|
|
|
149
153
|
result[key] = str(value).lower() in {"1", "true", "yes", "y"}
|
|
150
154
|
else:
|
|
151
155
|
result[key] = value
|
|
152
|
-
return result
|
|
156
|
+
return result
|
|
@@ -2,7 +2,10 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
from typing import Any, Mapping
|
|
4
4
|
|
|
5
|
-
from velocity.aws.assets.references import
|
|
5
|
+
from velocity.aws.assets.references import (
|
|
6
|
+
AssetReference,
|
|
7
|
+
extract_asset_references_from_record,
|
|
8
|
+
)
|
|
6
9
|
from velocity.aws.assets.usage_index import (
|
|
7
10
|
AssetUsage,
|
|
8
11
|
AssetUsageReconciliation,
|
|
@@ -63,7 +66,9 @@ def reconcile_form_builder_template_asset_usages(
|
|
|
63
66
|
source_record_label=_build_source_record_label(source_row),
|
|
64
67
|
last_source_modified=_as_string(source_row.get("sys_modified")),
|
|
65
68
|
last_indexed_by=last_indexed_by,
|
|
66
|
-
asset_id_resolver=lambda reference: resolve_asset_id_for_reference(
|
|
69
|
+
asset_id_resolver=lambda reference: resolve_asset_id_for_reference(
|
|
70
|
+
tx, reference
|
|
71
|
+
),
|
|
67
72
|
)
|
|
68
73
|
existing = load_asset_usages(
|
|
69
74
|
tx,
|
|
@@ -89,7 +94,9 @@ def load_asset_usages(tx, *, source_table: str, source_sys_id: str) -> list[Asse
|
|
|
89
94
|
return [_row_to_asset_usage(row) for row in rows]
|
|
90
95
|
|
|
91
96
|
|
|
92
|
-
def apply_asset_usage_reconciliation(
|
|
97
|
+
def apply_asset_usage_reconciliation(
|
|
98
|
+
tx, reconciliation: AssetUsageReconciliation
|
|
99
|
+
) -> None:
|
|
93
100
|
table = tx.table("asset_usage_index")
|
|
94
101
|
if not table.exists():
|
|
95
102
|
return
|
|
@@ -224,4 +231,4 @@ def _as_string(value: Any) -> str | None:
|
|
|
224
231
|
if value is None:
|
|
225
232
|
return None
|
|
226
233
|
text = str(value).strip()
|
|
227
|
-
return text or None
|
|
234
|
+
return text or None
|
|
@@ -14,7 +14,9 @@ _STORAGE_KEY_KEYS = ("storage_key", "storageKey", "key", "s3_key", "s3Key")
|
|
|
14
14
|
_NESTED_VALUE_KEYS = ("asset", "image", "media", "value")
|
|
15
15
|
_HTML_ASSET_ID_ATTRS = ("data-asset-id", "asset-id", "data-asset")
|
|
16
16
|
_HTML_URL_ATTRS = ("src", "href", "data-src")
|
|
17
|
-
_S3_HOST_RE = re.compile(
|
|
17
|
+
_S3_HOST_RE = re.compile(
|
|
18
|
+
r"(^|\.)s3[.-][a-z0-9-]+\.amazonaws\.com$|(^|\.)s3\.amazonaws\.com$"
|
|
19
|
+
)
|
|
18
20
|
|
|
19
21
|
|
|
20
22
|
@dataclass(frozen=True)
|
|
@@ -26,7 +28,9 @@ class AssetReference:
|
|
|
26
28
|
source_field_type: str | None = None
|
|
27
29
|
raw_value: str | None = None
|
|
28
30
|
|
|
29
|
-
def dedupe_key(
|
|
31
|
+
def dedupe_key(
|
|
32
|
+
self,
|
|
33
|
+
) -> tuple[str | None, str | None, str | None, str | None, str | None]:
|
|
30
34
|
return (
|
|
31
35
|
self.source_field_type,
|
|
32
36
|
self.source_field,
|
|
@@ -44,7 +48,9 @@ class _AssetReferenceHtmlParser(HTMLParser):
|
|
|
44
48
|
|
|
45
49
|
def handle_starttag(self, tag: str, attrs: list[tuple[str, str | None]]) -> None:
|
|
46
50
|
attr_map = {name: value for name, value in attrs if value}
|
|
47
|
-
if tag not in _MEDIA_TAGS and not any(
|
|
51
|
+
if tag not in _MEDIA_TAGS and not any(
|
|
52
|
+
key in attr_map for key in _HTML_ASSET_ID_ATTRS
|
|
53
|
+
):
|
|
48
54
|
return
|
|
49
55
|
reference = _reference_from_mapping(
|
|
50
56
|
attr_map,
|
|
@@ -260,4 +266,4 @@ def _storage_key_from_url(url: str | None) -> str | None:
|
|
|
260
266
|
parts = path.split("/", 1)
|
|
261
267
|
return parts[1] if len(parts) == 2 else None
|
|
262
268
|
return path or None
|
|
263
|
-
return None
|
|
269
|
+
return None
|
|
@@ -107,12 +107,16 @@ def list_assets(
|
|
|
107
107
|
where["!%key"] = "%-thumb%"
|
|
108
108
|
if search:
|
|
109
109
|
where["%key"] = f"%{search}%"
|
|
110
|
-
rows =
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
110
|
+
rows = (
|
|
111
|
+
tx.table("images")
|
|
112
|
+
.select(
|
|
113
|
+
where=where or None,
|
|
114
|
+
orderby=orderby,
|
|
115
|
+
start=start,
|
|
116
|
+
qty=qty,
|
|
117
|
+
)
|
|
118
|
+
.all()
|
|
119
|
+
)
|
|
116
120
|
return [normalize_asset_record(row) for row in rows]
|
|
117
121
|
|
|
118
122
|
|
|
@@ -214,7 +218,11 @@ def _read_source_bytes(source: Any) -> bytes | None:
|
|
|
214
218
|
if isinstance(source, Mapping):
|
|
215
219
|
if "data" in source and isinstance(source["data"], str):
|
|
216
220
|
return _decode_data_url(source["data"])
|
|
217
|
-
if
|
|
221
|
+
if (
|
|
222
|
+
"file" in source
|
|
223
|
+
and isinstance(source["file"], Mapping)
|
|
224
|
+
and "data" in source["file"]
|
|
225
|
+
):
|
|
218
226
|
return _decode_data_url(source["file"]["data"])
|
|
219
227
|
if hasattr(source, "data") and isinstance(source.data, str):
|
|
220
228
|
return _decode_data_url(source.data)
|
|
@@ -245,7 +253,9 @@ def _sanitize_destination_part(value: str) -> str:
|
|
|
245
253
|
|
|
246
254
|
def _sanitize_relative_path(path: str) -> str:
|
|
247
255
|
path = (path or "").strip().lstrip("./").replace("\\", "/")
|
|
248
|
-
parts = [
|
|
256
|
+
parts = [
|
|
257
|
+
segment for segment in path.split("/") if segment and segment not in {".", ".."}
|
|
258
|
+
]
|
|
249
259
|
return "/".join(parts)
|
|
250
260
|
|
|
251
261
|
|
|
@@ -272,4 +282,4 @@ def _as_int(value: Any) -> int | None:
|
|
|
272
282
|
def _as_bool_or_none(value: Any) -> bool | None:
|
|
273
283
|
if value is None:
|
|
274
284
|
return None
|
|
275
|
-
return bool(value)
|
|
285
|
+
return bool(value)
|
|
@@ -99,7 +99,9 @@ def _build_asset_usage(
|
|
|
99
99
|
if not asset_id:
|
|
100
100
|
return None
|
|
101
101
|
if not reference.source_field or not reference.source_field_type:
|
|
102
|
-
raise ValueError(
|
|
102
|
+
raise ValueError(
|
|
103
|
+
"AssetReference must include source_field and source_field_type"
|
|
104
|
+
)
|
|
103
105
|
return AssetUsage(
|
|
104
106
|
asset_id=asset_id,
|
|
105
107
|
source_table=source_table,
|
|
@@ -121,4 +123,4 @@ def _dedupe_usages(usages: Iterable[AssetUsage]) -> list[AssetUsage]:
|
|
|
121
123
|
|
|
122
124
|
|
|
123
125
|
def _usage_sort_key(usage: AssetUsage) -> tuple[str, str, str, str]:
|
|
124
|
-
return usage.identity_key()
|
|
126
|
+
return usage.identity_key()
|
|
@@ -35,10 +35,7 @@ def retryable_call(
|
|
|
35
35
|
error = exc.response.get("Error", {})
|
|
36
36
|
error_code = error.get("Code", "")
|
|
37
37
|
message = error.get("Message", "")
|
|
38
|
-
if (
|
|
39
|
-
error_code in THROTTLE_ERROR_CODES
|
|
40
|
-
or "rate exceeded" in message.lower()
|
|
41
|
-
):
|
|
38
|
+
if error_code in THROTTLE_ERROR_CODES or "rate exceeded" in message.lower():
|
|
42
39
|
if attempt < max_attempts:
|
|
43
40
|
print(
|
|
44
41
|
f"Throttling detected. Retry {attempt}/{max_attempts} after {delay}s..."
|
|
@@ -268,7 +265,9 @@ def update_function_layers_to_latest(
|
|
|
268
265
|
)
|
|
269
266
|
|
|
270
267
|
if not response:
|
|
271
|
-
print(
|
|
268
|
+
print(
|
|
269
|
+
f"[ERROR] Failed to get configuration for function {function_name}"
|
|
270
|
+
)
|
|
272
271
|
continue
|
|
273
272
|
|
|
274
273
|
current_layers = response.get("Layers", [])
|
|
@@ -654,7 +653,9 @@ def ensure_api_cors_header(
|
|
|
654
653
|
return
|
|
655
654
|
resources = {
|
|
656
655
|
r["path"]: r["id"]
|
|
657
|
-
for r in apigw_client.get_resources(restApiId=api_id, limit=500).get(
|
|
656
|
+
for r in apigw_client.get_resources(restApiId=api_id, limit=500).get(
|
|
657
|
+
"items", []
|
|
658
|
+
)
|
|
658
659
|
}
|
|
659
660
|
header_key = "method.response.header.Access-Control-Allow-Headers"
|
|
660
661
|
changed = False
|
|
@@ -681,14 +682,20 @@ def ensure_api_cors_header(
|
|
|
681
682
|
httpMethod="OPTIONS",
|
|
682
683
|
statusCode="200",
|
|
683
684
|
patchOperations=[
|
|
684
|
-
{
|
|
685
|
+
{
|
|
686
|
+
"op": "replace",
|
|
687
|
+
"path": "/responseParameters/" + header_key,
|
|
688
|
+
"value": new_value,
|
|
689
|
+
}
|
|
685
690
|
],
|
|
686
691
|
)
|
|
687
692
|
print(f"[INFO] cors: added {header} to CORS Allow-Headers on {path}")
|
|
688
693
|
changed = True
|
|
689
694
|
if changed:
|
|
690
695
|
apigw_client.create_deployment(
|
|
691
|
-
restApiId=api_id,
|
|
696
|
+
restApiId=api_id,
|
|
697
|
+
stageName=stage,
|
|
698
|
+
description=f"CORS header {header} (build.py)",
|
|
692
699
|
)
|
|
693
700
|
print(f"[INFO] cors: redeployed API stage {stage}")
|
|
694
701
|
else:
|
|
@@ -170,7 +170,9 @@ def _prune_oldest_nondefault_version(iam_client, policy_arn: str) -> None:
|
|
|
170
170
|
)
|
|
171
171
|
|
|
172
172
|
|
|
173
|
-
def sync_managed_policy_document(
|
|
173
|
+
def sync_managed_policy_document(
|
|
174
|
+
iam_client, policy_arn: str, policy_document: Any
|
|
175
|
+
) -> None:
|
|
174
176
|
"""Ensure the managed policy contains every desired statement (additive).
|
|
175
177
|
|
|
176
178
|
The policy document is the union of what is already on the policy and the
|
|
@@ -190,7 +192,9 @@ def sync_managed_policy_document(iam_client, policy_arn: str, policy_document: A
|
|
|
190
192
|
desired_document = _merge_policy_statements(
|
|
191
193
|
current_document, _normalize_policy_document(policy_document)
|
|
192
194
|
)
|
|
193
|
-
if json.dumps(current_document, sort_keys=True) == json.dumps(
|
|
195
|
+
if json.dumps(current_document, sort_keys=True) == json.dumps(
|
|
196
|
+
desired_document, sort_keys=True
|
|
197
|
+
):
|
|
194
198
|
return
|
|
195
199
|
|
|
196
200
|
_ensure_policy_document_size(policy["PolicyName"], desired_document)
|
|
@@ -269,7 +273,9 @@ def ensure_app_policy(
|
|
|
269
273
|
|
|
270
274
|
added = [s for key, s in desired_keys.items() if key not in current_keys]
|
|
271
275
|
removed = [s for key, s in current_keys.items() if key not in desired_keys]
|
|
272
|
-
print(
|
|
276
|
+
print(
|
|
277
|
+
f"Reconciling policy {policy_name}: +{len(added)} statement(s), -{len(removed)}"
|
|
278
|
+
)
|
|
273
279
|
for statement in added:
|
|
274
280
|
print(f" + {json.dumps(statement, sort_keys=True)}")
|
|
275
281
|
for statement in removed:
|
|
@@ -286,11 +292,13 @@ def ensure_app_policy(
|
|
|
286
292
|
return policy_arn
|
|
287
293
|
|
|
288
294
|
|
|
289
|
-
def attach_role_policies(
|
|
295
|
+
def attach_role_policies(
|
|
296
|
+
iam_client, role_name: str, policy_arns: Iterable[str]
|
|
297
|
+
) -> None:
|
|
290
298
|
"""Attach each policy to the role if not already attached."""
|
|
291
|
-
attached = retryable_call(
|
|
292
|
-
|
|
293
|
-
]
|
|
299
|
+
attached = retryable_call(
|
|
300
|
+
iam_client.list_attached_role_policies, RoleName=role_name
|
|
301
|
+
)["AttachedPolicies"]
|
|
294
302
|
attached_arns = {policy["PolicyArn"] for policy in attached}
|
|
295
303
|
for policy_arn in policy_arns:
|
|
296
304
|
if policy_arn in attached_arns:
|
|
@@ -34,9 +34,7 @@ def _ensure_shared_policies(
|
|
|
34
34
|
iam_client, account_id: str, config: DeploymentConfig, policy_mode: str
|
|
35
35
|
):
|
|
36
36
|
"""Create/sync the shared baseline policy; returns (baseline_arn)."""
|
|
37
|
-
baseline_arn =
|
|
38
|
-
f"arn:aws:iam::{account_id}:policy/{policy_ops.BASELINE_POLICY_NAME}"
|
|
39
|
-
)
|
|
37
|
+
baseline_arn = f"arn:aws:iam::{account_id}:policy/{policy_ops.BASELINE_POLICY_NAME}"
|
|
40
38
|
baseline_document = policy_ops.baseline_lambda_policy_document(account_id)
|
|
41
39
|
if policy_mode == "legacy-union":
|
|
42
40
|
baseline_document = config.build_lambda_policy_document(baseline_document)
|
|
@@ -52,7 +50,9 @@ def _ensure_shared_policies(
|
|
|
52
50
|
)
|
|
53
51
|
time.sleep(10)
|
|
54
52
|
else:
|
|
55
|
-
policy_ops.sync_managed_policy_document(
|
|
53
|
+
policy_ops.sync_managed_policy_document(
|
|
54
|
+
iam_client, baseline_arn, baseline_document
|
|
55
|
+
)
|
|
56
56
|
return baseline_arn
|
|
57
57
|
|
|
58
58
|
|
|
@@ -117,7 +117,9 @@ def run_deployment(
|
|
|
117
117
|
current_layers = function.get("Layers") or []
|
|
118
118
|
if current_layers:
|
|
119
119
|
try:
|
|
120
|
-
layers_value = list(
|
|
120
|
+
layers_value = list(
|
|
121
|
+
resolve_latest_layer_arns(lambda_client, current_layers)
|
|
122
|
+
)
|
|
121
123
|
except Exception as exc:
|
|
122
124
|
print(
|
|
123
125
|
f"[WARN] Unable to resolve latest layers for {function_name}: {exc}. "
|
|
@@ -196,7 +198,9 @@ def run_deployment(
|
|
|
196
198
|
)
|
|
197
199
|
|
|
198
200
|
|
|
199
|
-
def update_lambda_layers_to_latest(
|
|
201
|
+
def update_lambda_layers_to_latest(
|
|
202
|
+
target, function_names=None, lambda_client=None
|
|
203
|
+
) -> None:
|
|
200
204
|
"""Bump layers to latest for named functions, or all of the target's."""
|
|
201
205
|
from velocity.aws.deploy.operations import update_function_layers_to_latest
|
|
202
206
|
|
|
@@ -207,7 +211,9 @@ def update_lambda_layers_to_latest(target, function_names=None, lambda_client=No
|
|
|
207
211
|
if len(function_names) == 1:
|
|
208
212
|
print(f"[INFO] Updating layers for specific function: {function_names[0]}")
|
|
209
213
|
else:
|
|
210
|
-
print(
|
|
214
|
+
print(
|
|
215
|
+
"[INFO] No specific function provided, scanning all functions in the application..."
|
|
216
|
+
)
|
|
211
217
|
functions = list(target.list_functions())
|
|
212
218
|
function_names = [function["FunctionName"] for function in functions]
|
|
213
219
|
if not function_names:
|
|
@@ -32,7 +32,9 @@ def _normalize_project_root(project_root: Union[str, Path]) -> Path:
|
|
|
32
32
|
return Path(project_root).resolve()
|
|
33
33
|
|
|
34
34
|
|
|
35
|
-
def get_amplify_app_id_and_branch(
|
|
35
|
+
def get_amplify_app_id_and_branch(
|
|
36
|
+
project_root: Union[str, Path] = ".",
|
|
37
|
+
) -> Tuple[str, str]:
|
|
36
38
|
root = _normalize_project_root(project_root)
|
|
37
39
|
|
|
38
40
|
branch = os.environ.get("AWS_BRANCH")
|
|
@@ -86,7 +88,9 @@ def get_amplify_app_id_and_branch(project_root: Union[str, Path] = ".") -> Tuple
|
|
|
86
88
|
|
|
87
89
|
print(f"[INFO] Amplify App ID from file: {app_id}")
|
|
88
90
|
except Exception as exc:
|
|
89
|
-
raise RuntimeError(
|
|
91
|
+
raise RuntimeError(
|
|
92
|
+
f"Error reading team-provider-info.json for App ID: {exc}"
|
|
93
|
+
)
|
|
90
94
|
|
|
91
95
|
return app_id, branch
|
|
92
96
|
|
|
@@ -157,7 +161,9 @@ class AmplifyTarget(BaseTarget):
|
|
|
157
161
|
):
|
|
158
162
|
super().__init__()
|
|
159
163
|
if app_id is None or branch is None:
|
|
160
|
-
resolved_app_id, resolved_branch = get_amplify_app_id_and_branch(
|
|
164
|
+
resolved_app_id, resolved_branch = get_amplify_app_id_and_branch(
|
|
165
|
+
project_root
|
|
166
|
+
)
|
|
161
167
|
app_id = app_id or resolved_app_id
|
|
162
168
|
branch = branch or resolved_branch
|
|
163
169
|
self.app_id = app_id
|
|
@@ -43,9 +43,7 @@ def get_excluded_tables(tx, context) -> set[str]:
|
|
|
43
43
|
return set()
|
|
44
44
|
|
|
45
45
|
return {
|
|
46
|
-
line.strip()
|
|
47
|
-
for line in str(raw_value).splitlines()
|
|
48
|
-
if line and line.strip()
|
|
46
|
+
line.strip() for line in str(raw_value).splitlines() if line and line.strip()
|
|
49
47
|
}
|
|
50
48
|
|
|
51
49
|
|
|
@@ -115,4 +113,4 @@ def clear_stale_dirty_rows(
|
|
|
115
113
|
def quote_identifier(identifier: str) -> str:
|
|
116
114
|
if not isinstance(identifier, str) or not _IDENTIFIER_RE.match(identifier):
|
|
117
115
|
raise ValueError(f"Invalid SQL identifier: {identifier!r}")
|
|
118
|
-
return f'"{identifier}"'
|
|
116
|
+
return f'"{identifier}"'
|
|
@@ -332,7 +332,9 @@ class BaseHandler:
|
|
|
332
332
|
response.alert(user_message, title=title)
|
|
333
333
|
return True
|
|
334
334
|
|
|
335
|
-
def _is_transient_db_disconnect(
|
|
335
|
+
def _is_transient_db_disconnect(
|
|
336
|
+
self, exc: Exception = None, *args, **kwargs
|
|
337
|
+
) -> bool:
|
|
336
338
|
"""Return True if an exception looks like a transient DB disconnect.
|
|
337
339
|
|
|
338
340
|
This is intentionally message-based so it works even if the originating
|
|
@@ -598,9 +598,9 @@ class Context:
|
|
|
598
598
|
# Carry a caller-supplied human-readable description onto
|
|
599
599
|
# the job activity row (None when omitted) so scheduled /
|
|
600
600
|
# program-object jobs are identifiable in the activity log.
|
|
601
|
-
"description":
|
|
602
|
-
|
|
603
|
-
|
|
601
|
+
"description": (
|
|
602
|
+
item.get("description") if isinstance(item, dict) else None
|
|
603
|
+
),
|
|
604
604
|
}
|
|
605
605
|
)
|
|
606
606
|
messages.append({"Id": id, "MessageBody": to_json(message)})
|
|
@@ -32,7 +32,14 @@ class AlertError(AppError):
|
|
|
32
32
|
self.log_to_cloudwatch = log_to_cloudwatch
|
|
33
33
|
return
|
|
34
34
|
|
|
35
|
-
if
|
|
35
|
+
if (
|
|
36
|
+
isinstance(message, dict)
|
|
37
|
+
and title is None
|
|
38
|
+
and toast is False
|
|
39
|
+
and variant is None
|
|
40
|
+
and log_to_cloudwatch is False
|
|
41
|
+
and not payload
|
|
42
|
+
):
|
|
36
43
|
super().__init__(message)
|
|
37
44
|
self.log_to_cloudwatch = log_to_cloudwatch
|
|
38
45
|
return
|