velocity-python 0.1.92__tar.gz → 0.1.94__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.92/src/velocity_python.egg-info → velocity_python-0.1.94}/PKG-INFO +4 -2
- {velocity_python-0.1.92 → velocity_python-0.1.94}/README.md +1 -1
- {velocity_python-0.1.92 → velocity_python-0.1.94}/pyproject.toml +5 -1
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/__init__.py +1 -1
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/aws/handlers/mixins/__init__.py +3 -0
- velocity_python-0.1.94/src/velocity/aws/handlers/mixins/job_handler.py +175 -0
- velocity_python-0.1.94/src/velocity/aws/job_results.py +453 -0
- velocity_python-0.1.94/src/velocity/misc/pdf.py +494 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94/src/velocity_python.egg-info}/PKG-INFO +4 -2
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity_python.egg-info/SOURCES.txt +4 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity_python.egg-info/requires.txt +3 -0
- velocity_python-0.1.94/tests/test_job_handler.py +162 -0
- velocity_python-0.1.94/tests/test_job_results.py +243 -0
- velocity_python-0.1.94/tests/test_pdf.py +384 -0
- velocity_python-0.1.92/src/velocity/misc/pdf.py +0 -217
- velocity_python-0.1.92/tests/test_pdf.py +0 -178
- {velocity_python-0.1.92 → velocity_python-0.1.94}/LICENSE +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/setup.cfg +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/aws/__init__.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/aws/amplify.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/aws/amplify_build.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/aws/assets/__init__.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/aws/assets/backfill.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/aws/assets/indexing.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/aws/assets/references.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/aws/assets/service.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/aws/assets/usage_index.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/aws/deploy/__init__.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/aws/deploy/config.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/aws/deploy/operations.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/aws/deploy/policies.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/aws/deploy/reconcile.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/aws/deploy/targets.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/aws/dirty_pipeline.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/aws/handlers/__init__.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/aws/handlers/base_handler.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/aws/handlers/context.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/aws/handlers/context_factory.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/aws/handlers/exceptions.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/aws/handlers/lambda_handler.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/aws/handlers/masquerade.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/aws/handlers/mixins/data_service.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/aws/handlers/mixins/web_handler.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/aws/handlers/perf.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/aws/handlers/response.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/aws/handlers/sqs_handler.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/aws/s3.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/aws/ssm_config.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/aws/tests/__init__.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/aws/tests/test_amplify_build_policy_size.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/aws/tests/test_amplify_build_shim.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/aws/tests/test_base_handler_error_response.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/aws/tests/test_deploy_policies.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/aws/tests/test_deploy_reconcile.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/aws/tests/test_lambda_handler_json_serialization.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/aws/tests/test_response.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/db/__init__.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/db/core/__init__.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/db/core/async_support.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/db/core/column.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/db/core/database.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/db/core/decorators.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/db/core/engine.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/db/core/jsonproxy.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/db/core/result.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/db/core/row.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/db/core/sequence.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/db/core/table.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/db/core/transaction.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/db/core/view.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/db/exceptions.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/db/maintenance.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/db/migrations.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/db/servers/__init__.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/db/servers/base/__init__.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/db/servers/base/initializer.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/db/servers/base/operators.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/db/servers/base/sql.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/db/servers/base/types.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/db/servers/mysql/__init__.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/db/servers/mysql/operators.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/db/servers/mysql/reserved.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/db/servers/mysql/sql.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/db/servers/mysql/types.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/db/servers/postgres/__init__.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/db/servers/postgres/operators.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/db/servers/postgres/reserved.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/db/servers/postgres/sql.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/db/servers/postgres/types.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/db/servers/sqlite/__init__.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/db/servers/sqlite/operators.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/db/servers/sqlite/reserved.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/db/servers/sqlite/sql.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/db/servers/sqlite/types.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/db/servers/sqlserver/__init__.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/db/servers/sqlserver/operators.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/db/servers/sqlserver/reserved.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/db/servers/sqlserver/sql.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/db/servers/sqlserver/types.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/db/servers/tablehelper.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/db/tests/__init__.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/db/tests/common_db_test.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/db/tests/postgres/__init__.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/db/tests/postgres/common.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/db/tests/postgres/conftest.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/db/tests/postgres/test_column.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/db/tests/postgres/test_connections.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/db/tests/postgres/test_database.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/db/tests/postgres/test_engine.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/db/tests/postgres/test_general_usage.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/db/tests/postgres/test_imports.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/db/tests/postgres/test_result.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/db/tests/postgres/test_row.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/db/tests/postgres/test_row_comprehensive.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/db/tests/postgres/test_schema_locking.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/db/tests/postgres/test_schema_locking_unit.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/db/tests/postgres/test_sequence.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/db/tests/postgres/test_sql_comprehensive.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/db/tests/postgres/test_table.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/db/tests/postgres/test_table_comprehensive.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/db/tests/postgres/test_transaction.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/db/tests/sql/__init__.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/db/tests/sql/common.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/db/tests/sql/test_postgres_select_advanced.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/db/tests/sql/test_postgres_select_variances.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/db/tests/test_cursor_rowcount_fix.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/db/tests/test_db_utils.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/db/tests/test_postgres.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/db/tests/test_postgres_unchanged.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/db/tests/test_process_error_robustness.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/db/tests/test_result_caching.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/db/tests/test_result_sql_aware.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/db/tests/test_row_get_missing_column.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/db/tests/test_schema_locking_initializers.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/db/tests/test_schema_locking_simple.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/db/tests/test_sql_builder.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/db/tests/test_tablehelper.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/db/tests/test_view_helper.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/db/utils.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/logging.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/misc/__init__.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/misc/conv/__init__.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/misc/conv/iconv.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/misc/conv/oconv.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/misc/db.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/misc/export.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/misc/format.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/misc/mail.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/misc/merge.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/misc/tests/__init__.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/misc/tests/test_db.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/misc/tests/test_fix.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/misc/tests/test_format.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/misc/tests/test_iconv.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/misc/tests/test_merge.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/misc/tests/test_oconv.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/misc/tests/test_original_error.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/misc/tests/test_timer.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/misc/timer.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/misc/tools.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/nosql/__init__.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/nosql/core/__init__.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/nosql/core/capabilities.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/nosql/core/store.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/nosql/core/where.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/nosql/exceptions.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/nosql/servers/__init__.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/nosql/servers/base/__init__.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/nosql/servers/cassandra/__init__.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/nosql/servers/cassandra/translation.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/nosql/servers/couchbase/__init__.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/nosql/servers/couchbase/translation.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/nosql/servers/dynamodb/__init__.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/nosql/servers/dynamodb/translation.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/nosql/servers/elasticsearch/__init__.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/nosql/servers/elasticsearch/translation.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/nosql/servers/memory/__init__.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/nosql/servers/mongodb/__init__.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/nosql/servers/mongodb/translation.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/nosql/servers/redis/__init__.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/payment/__init__.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/payment/authorizenet_adapter.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/payment/authorizenet_mirror.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/payment/base_adapter.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/payment/braintree_adapter.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/payment/braintree_mirror.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/payment/charge_rules.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/payment/stripe_adapter.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/payment/stripe_mirror.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity_python.egg-info/dependency_links.txt +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity_python.egg-info/entry_points.txt +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity_python.egg-info/top_level.txt +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/tests/test_activity_tracking_aborted_tx.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/tests/test_amplify_build.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/tests/test_asset_indexing.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/tests/test_asset_references.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/tests/test_assets_service.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/tests/test_async_support.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/tests/test_batch_operations.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/tests/test_column_tx_arg.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/tests/test_concurrency_safety.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/tests/test_connection_pool.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/tests/test_connection_resilience.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/tests/test_context_job_descriptions.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/tests/test_db_credentials_ssm_cascade.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/tests/test_db_maintenance.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/tests/test_decorators.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/tests/test_delete_hook_fk_blocked.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/tests/test_dirty_pipeline_fast_path.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/tests/test_email_processing.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/tests/test_enqueue_send_failures.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/tests/test_get_cognito_user_provider.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/tests/test_http_handler_rollback.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/tests/test_iconv_money_to_cents.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/tests/test_identifier_injection_guard.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/tests/test_json_columns.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/tests/test_jsonb_dict_adapter.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/tests/test_lambda_handler.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/tests/test_lambda_handler_auth.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/tests/test_lambda_handler_masquerade.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/tests/test_masquerade_grant.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/tests/test_mixins_import.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/tests/test_n_plus_one.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/tests/test_nosql_dynamodb.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/tests/test_nosql_memory.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/tests/test_nosql_mongodb.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/tests/test_nosql_redis.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/tests/test_nosql_translation.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/tests/test_nosql_where.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/tests/test_observability.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/tests/test_on_commit.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/tests/test_payment_authorizenet_adapter.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/tests/test_payment_braintree_adapter.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/tests/test_payment_braintree_mirror.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/tests/test_payment_mirror_empty_table.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/tests/test_payment_profile_sorting.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/tests/test_payment_stripe_adapter.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/tests/test_prepared_statements.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/tests/test_psycopg3_upgrade.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/tests/test_query_cache.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/tests/test_restricted_direct_tables.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/tests/test_retry_side_effect_guard.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/tests/test_return_default_safety.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/tests/test_row_batch_update.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/tests/test_row_cache_staleness.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/tests/test_schema_migrations.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/tests/test_security_hardening.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/tests/test_server_cursor.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/tests/test_single_autocommit_safety.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/tests/test_spreadsheet_functions.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/tests/test_sqlite_backend.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/tests/test_sqs_per_record_transactions.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/tests/test_ssm_config.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/tests/test_store_user_data.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/tests/test_sys_modified_count_postgres_demo.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/tests/test_table_alter.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/tests/test_transaction_class_wrapping.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/tests/test_transaction_commit_and_ownership.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/tests/test_transaction_edge_cases.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/tests/test_where_clause_validation.py +0 -0
- {velocity_python-0.1.92 → velocity_python-0.1.94}/tests/test_write_hook_create_flow.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: velocity-python
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.94
|
|
4
4
|
Summary: A rapid application development library for interfacing with data storage
|
|
5
5
|
Author-email: Velocity Team <info@codeclubs.org>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -35,6 +35,8 @@ Provides-Extra: templates
|
|
|
35
35
|
Requires-Dist: jinja2>=3.1.0; extra == "templates"
|
|
36
36
|
Provides-Extra: pdf
|
|
37
37
|
Requires-Dist: pdfkit>=1.0.0; extra == "pdf"
|
|
38
|
+
Provides-Extra: pdf-weasyprint
|
|
39
|
+
Requires-Dist: weasyprint>=60.0; extra == "pdf-weasyprint"
|
|
38
40
|
Provides-Extra: http
|
|
39
41
|
Requires-Dist: requests>=2.32.0; extra == "http"
|
|
40
42
|
Provides-Extra: mysql
|
|
@@ -248,7 +250,7 @@ Full documentation is included in the `docs/` directory of the source distributi
|
|
|
248
250
|
| Performance & Optimization | `docs/performance.md` | Connection pooling, batch operations, query caching, prepared statements, N+1 prevention, observability |
|
|
249
251
|
| Async Support | `docs/async.md` | AsyncTransaction, AsyncTable, AsyncResult, parallel queries with gather() |
|
|
250
252
|
| Configuration Reference | `docs/configuration.md` | All environment variables, engine options, and connection settings |
|
|
251
|
-
| AWS Lambda Handlers | `docs/aws-handlers.md` | LambdaHandler, SqsHandler, auth modes, per-record transactions |
|
|
253
|
+
| AWS Lambda Handlers | `docs/aws-handlers.md` | LambdaHandler, SqsHandler, auth modes, per-record transactions, async jobs (JobHandler + job result stores) |
|
|
252
254
|
| NoSQL Adapters | `docs/nosql.md` | Redis, DynamoDB, MongoDB, Elasticsearch, Cassandra, Couchbase behind one capability-honest contract |
|
|
253
255
|
| Payment Processing | `docs/payment.md` | Stripe and Braintree adapters, payment lifecycle |
|
|
254
256
|
| Utilities | `docs/utilities.md` | Excel export, data conversion, formatting, timers, email parsing |
|
|
@@ -156,7 +156,7 @@ Full documentation is included in the `docs/` directory of the source distributi
|
|
|
156
156
|
| Performance & Optimization | `docs/performance.md` | Connection pooling, batch operations, query caching, prepared statements, N+1 prevention, observability |
|
|
157
157
|
| Async Support | `docs/async.md` | AsyncTransaction, AsyncTable, AsyncResult, parallel queries with gather() |
|
|
158
158
|
| Configuration Reference | `docs/configuration.md` | All environment variables, engine options, and connection settings |
|
|
159
|
-
| AWS Lambda Handlers | `docs/aws-handlers.md` | LambdaHandler, SqsHandler, auth modes, per-record transactions |
|
|
159
|
+
| AWS Lambda Handlers | `docs/aws-handlers.md` | LambdaHandler, SqsHandler, auth modes, per-record transactions, async jobs (JobHandler + job result stores) |
|
|
160
160
|
| NoSQL Adapters | `docs/nosql.md` | Redis, DynamoDB, MongoDB, Elasticsearch, Cassandra, Couchbase behind one capability-honest contract |
|
|
161
161
|
| Payment Processing | `docs/payment.md` | Stripe and Braintree adapters, payment lifecycle |
|
|
162
162
|
| Utilities | `docs/utilities.md` | Excel export, data conversion, formatting, timers, email parsing |
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "velocity-python"
|
|
7
|
-
version = "0.1.
|
|
7
|
+
version = "0.1.94"
|
|
8
8
|
authors = [
|
|
9
9
|
{ name="Velocity Team", email="info@codeclubs.org" },
|
|
10
10
|
]
|
|
@@ -57,6 +57,10 @@ templates = [
|
|
|
57
57
|
pdf = [
|
|
58
58
|
"pdfkit>=1.0.0",
|
|
59
59
|
]
|
|
60
|
+
# Maintained HTML→PDF engine; native libs (Pango/Cairo) come from the OS or a layer.
|
|
61
|
+
pdf-weasyprint = [
|
|
62
|
+
"weasyprint>=60.0",
|
|
63
|
+
]
|
|
60
64
|
http = [
|
|
61
65
|
"requests>=2.32.0",
|
|
62
66
|
]
|
{velocity_python-0.1.92 → velocity_python-0.1.94}/src/velocity/aws/handlers/mixins/__init__.py
RENAMED
|
@@ -5,13 +5,16 @@ This package provides mixins for common Lambda handler patterns:
|
|
|
5
5
|
- WebHandler: Activity tracking, logging, and error handling
|
|
6
6
|
- ButtonHandler: Dynamic button action handler loading
|
|
7
7
|
- DataServiceMixin: Generic CRUD operations for database-backed APIs
|
|
8
|
+
- JobHandler: get-job-status / download-job-result / cancel-job for async jobs
|
|
8
9
|
"""
|
|
9
10
|
|
|
10
11
|
from .web_handler import WebHandler, ButtonHandler
|
|
11
12
|
from .data_service import DataServiceMixin
|
|
13
|
+
from .job_handler import JobHandler
|
|
12
14
|
|
|
13
15
|
__all__ = [
|
|
14
16
|
"WebHandler",
|
|
15
17
|
"ButtonHandler",
|
|
16
18
|
"DataServiceMixin",
|
|
19
|
+
"JobHandler",
|
|
17
20
|
]
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
"""JobHandler — the web-tier half of asynchronous jobs.
|
|
2
|
+
|
|
3
|
+
velocity-react's job watcher (``JobProgressPortal`` + ``startJobWatcher``) polls
|
|
4
|
+
three ``/event`` actions after a response carries ``jobs.events``:
|
|
5
|
+
|
|
6
|
+
* ``get-job-status`` → ``{"job_status": {job_id, status, message, batch_id, updated}}``
|
|
7
|
+
* ``download-job-result`` → a ``file-download`` (or ``redirect``) response action
|
|
8
|
+
* ``cancel-job`` → flags the job ``CancelRequested`` for the worker
|
|
9
|
+
|
|
10
|
+
They are identical for every app, so they live here (extracted from
|
|
11
|
+
BackOfficeEvents). Mix into the HTTP handler alongside ``WebHandler``::
|
|
12
|
+
|
|
13
|
+
class HttpEventHandler(ButtonHandler, JobHandler, WebHandler, LambdaHandler):
|
|
14
|
+
...
|
|
15
|
+
|
|
16
|
+
A button action that wants the watcher enqueues, then announces the job::
|
|
17
|
+
|
|
18
|
+
result = context.enqueue("zip-invoices", payload)
|
|
19
|
+
job_id = result["Successful"][0]["Id"]
|
|
20
|
+
context.response().jobs.start(job_id=job_id, label="Zipping invoices")
|
|
21
|
+
|
|
22
|
+
and the worker persists its output with ``velocity.aws.job_results.store_job_result``.
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
from __future__ import annotations
|
|
26
|
+
|
|
27
|
+
import datetime
|
|
28
|
+
import json
|
|
29
|
+
from typing import Any, Dict, Optional
|
|
30
|
+
|
|
31
|
+
from velocity.aws.handlers.exceptions import AlertError
|
|
32
|
+
from velocity.aws.job_results import (
|
|
33
|
+
deliver_job_result,
|
|
34
|
+
job_result_files,
|
|
35
|
+
parse_job_message,
|
|
36
|
+
)
|
|
37
|
+
from velocity.misc.format import to_json
|
|
38
|
+
|
|
39
|
+
TERMINAL_JOB_STATUSES = frozenset({"Completed", "Failed", "Cancelled"})
|
|
40
|
+
# Statuses that can only persist this long because the worker died without
|
|
41
|
+
# running onError (Lambda timeout / OOM): synthesize Failed so the UI moves on.
|
|
42
|
+
STALE_JOB_STATUSES = frozenset({"Running", "Initialized"})
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
class JobHandler:
|
|
46
|
+
JOB_ACTIVITY_TABLE = "aws_job_activity"
|
|
47
|
+
JOB_STALE_AFTER = datetime.timedelta(minutes=16)
|
|
48
|
+
|
|
49
|
+
# ── helpers ───────────────────────────────────────────────────────────────
|
|
50
|
+
|
|
51
|
+
def _job_id_from(self, context) -> str:
|
|
52
|
+
payload = context.payload() or {}
|
|
53
|
+
job_id = payload.get("job_id") if isinstance(payload, dict) else None
|
|
54
|
+
if not job_id:
|
|
55
|
+
raise AlertError("job_id is required")
|
|
56
|
+
return str(job_id)
|
|
57
|
+
|
|
58
|
+
def _find_job(self, tx, job_id: str):
|
|
59
|
+
return tx.table(self.JOB_ACTIVITY_TABLE).find({"job_id": job_id})
|
|
60
|
+
|
|
61
|
+
def _job_is_stale(self, job) -> bool:
|
|
62
|
+
if (job.get("status") or "") not in STALE_JOB_STATUSES:
|
|
63
|
+
return False
|
|
64
|
+
ts = job.get("sys_modified") or job.get("initial_timestamp")
|
|
65
|
+
if ts is None:
|
|
66
|
+
return False
|
|
67
|
+
now = datetime.datetime.now(datetime.timezone.utc)
|
|
68
|
+
if ts.tzinfo is None:
|
|
69
|
+
ts = ts.replace(tzinfo=datetime.timezone.utc)
|
|
70
|
+
return (now - ts) > self.JOB_STALE_AFTER
|
|
71
|
+
|
|
72
|
+
@staticmethod
|
|
73
|
+
def _job_status_body(
|
|
74
|
+
job_id: str,
|
|
75
|
+
status: str,
|
|
76
|
+
message: Optional[Dict[str, Any]],
|
|
77
|
+
job=None,
|
|
78
|
+
) -> Dict[str, Any]:
|
|
79
|
+
body = {"job_id": job_id, "status": status, "message": message}
|
|
80
|
+
if job is not None:
|
|
81
|
+
body["batch_id"] = job.get("batch_id")
|
|
82
|
+
body["updated"] = job.get("sys_modified")
|
|
83
|
+
return {"job_status": body}
|
|
84
|
+
|
|
85
|
+
# ── actions ───────────────────────────────────────────────────────────────
|
|
86
|
+
|
|
87
|
+
def OnActionGetJobStatus(self, tx, context):
|
|
88
|
+
"""Current status + message for one job (polled by the job watcher)."""
|
|
89
|
+
job_id = self._job_id_from(context)
|
|
90
|
+
job = self._find_job(tx, job_id)
|
|
91
|
+
if not job:
|
|
92
|
+
context.response().set_body(
|
|
93
|
+
self._job_status_body(
|
|
94
|
+
job_id, "NotFound", {"detail": "Job not found"}
|
|
95
|
+
)
|
|
96
|
+
)
|
|
97
|
+
return
|
|
98
|
+
|
|
99
|
+
if self._job_is_stale(job):
|
|
100
|
+
context.response().set_body(
|
|
101
|
+
self._job_status_body(
|
|
102
|
+
job_id,
|
|
103
|
+
"Failed",
|
|
104
|
+
{
|
|
105
|
+
"detail": "Job timed out — the server ran out of time or memory.",
|
|
106
|
+
"error": "Lambda timed out or was killed (OOM)",
|
|
107
|
+
},
|
|
108
|
+
job,
|
|
109
|
+
)
|
|
110
|
+
)
|
|
111
|
+
return
|
|
112
|
+
|
|
113
|
+
message = parse_job_message(job.get("message")) or None
|
|
114
|
+
context.response().set_body(
|
|
115
|
+
self._job_status_body(job_id, job.get("status") or "", message, job)
|
|
116
|
+
)
|
|
117
|
+
|
|
118
|
+
def OnActionDownloadJobResult(self, tx, context):
|
|
119
|
+
"""Deliver a completed job's file via the store that holds it."""
|
|
120
|
+
job_id = self._job_id_from(context)
|
|
121
|
+
job = self._find_job(tx, job_id)
|
|
122
|
+
if not job:
|
|
123
|
+
raise AlertError("Job result not found")
|
|
124
|
+
|
|
125
|
+
files = job_result_files(job.get("message"))
|
|
126
|
+
if not files:
|
|
127
|
+
raise AlertError("Job result is not ready")
|
|
128
|
+
|
|
129
|
+
# One file per job result; descriptors without a store are legacy
|
|
130
|
+
# BackOffice S3 entries.
|
|
131
|
+
descriptor = dict(files[0])
|
|
132
|
+
descriptor.setdefault("store", "s3" if descriptor.get("bucket") else "db")
|
|
133
|
+
deliver_job_result(tx, context, descriptor)
|
|
134
|
+
context.response().toast("Download ready.")
|
|
135
|
+
|
|
136
|
+
def OnActionCancelJob(self, tx, context):
|
|
137
|
+
"""Ask the worker to stop: status CancelRequested + message flag.
|
|
138
|
+
|
|
139
|
+
Workers poll ``context.is_job_cancel_requested(tx)`` between units of
|
|
140
|
+
work and call ``context.mark_job_cancelled`` when they honour it.
|
|
141
|
+
"""
|
|
142
|
+
job_id = self._job_id_from(context)
|
|
143
|
+
job = self._find_job(tx, job_id)
|
|
144
|
+
if not job:
|
|
145
|
+
raise AlertError("Job not found")
|
|
146
|
+
|
|
147
|
+
current = job.get("status") or ""
|
|
148
|
+
if current in TERMINAL_JOB_STATUSES:
|
|
149
|
+
raise AlertError(f"Job is already {current.lower()}")
|
|
150
|
+
|
|
151
|
+
payload = context.payload() or {}
|
|
152
|
+
message = parse_job_message(job.get("message"))
|
|
153
|
+
message.update(
|
|
154
|
+
{
|
|
155
|
+
"detail": payload.get("detail")
|
|
156
|
+
or payload.get("reason")
|
|
157
|
+
or "Cancellation requested by user",
|
|
158
|
+
"cancel_requested": True,
|
|
159
|
+
}
|
|
160
|
+
)
|
|
161
|
+
tx.table(self.JOB_ACTIVITY_TABLE).update(
|
|
162
|
+
{
|
|
163
|
+
"status": "CancelRequested",
|
|
164
|
+
"message": to_json(message),
|
|
165
|
+
"sys_modified": datetime.datetime.now(),
|
|
166
|
+
"sys_modified_by": (context.session() or {}).get("email_address"),
|
|
167
|
+
},
|
|
168
|
+
{"job_id": job_id},
|
|
169
|
+
)
|
|
170
|
+
context.response().set_body(
|
|
171
|
+
self._job_status_body(job_id, "CancelRequested", message)
|
|
172
|
+
)
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
__all__ = ["JobHandler", "TERMINAL_JOB_STATUSES", "STALE_JOB_STATUSES"]
|