velocity-python 0.1.5__tar.gz → 0.1.8__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.8/PKG-INFO +332 -0
- velocity_python-0.1.8/README.md +270 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/pyproject.toml +5 -1
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/__init__.py +1 -1
- velocity_python-0.1.8/src/velocity/db/core/async_support.py +645 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/db/core/engine.py +14 -0
- velocity_python-0.1.8/src/velocity_python.egg-info/PKG-INFO +332 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity_python.egg-info/SOURCES.txt +2 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity_python.egg-info/requires.txt +2 -0
- velocity_python-0.1.8/tests/test_async_support.py +689 -0
- velocity_python-0.1.5/PKG-INFO +0 -1484
- velocity_python-0.1.5/README.md +0 -1426
- velocity_python-0.1.5/src/velocity_python.egg-info/PKG-INFO +0 -1484
- {velocity_python-0.1.5 → velocity_python-0.1.8}/LICENSE +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/setup.cfg +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/app/__init__.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/app/formbuilder/__init__.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/app/formbuilder/reshaper.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/app/invoices.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/app/orders.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/app/payments.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/app/purchase_orders.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/app/tests/__init__.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/app/tests/test_email_processing.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/app/tests/test_payment_profile_sorting.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/app/tests/test_spreadsheet_functions.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/app/validators/__init__.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/app/validators/formbuilder_template.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/aws/__init__.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/aws/amplify.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/aws/amplify_build.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/aws/handlers/__init__.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/aws/handlers/base_handler.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/aws/handlers/context.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/aws/handlers/context_factory.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/aws/handlers/exceptions.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/aws/handlers/lambda_handler.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/aws/handlers/mixins/__init__.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/aws/handlers/mixins/data_service.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/aws/handlers/mixins/web_handler.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/aws/handlers/perf.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/aws/handlers/response.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/aws/handlers/sqs_handler.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/aws/tests/__init__.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/aws/tests/test_base_handler_error_response.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/aws/tests/test_lambda_handler_json_serialization.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/aws/tests/test_response.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/db/__init__.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/db/core/__init__.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/db/core/column.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/db/core/database.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/db/core/decorators.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/db/core/result.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/db/core/row.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/db/core/sequence.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/db/core/table.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/db/core/transaction.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/db/core/view.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/db/exceptions.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/db/servers/__init__.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/db/servers/base/__init__.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/db/servers/base/initializer.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/db/servers/base/operators.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/db/servers/base/sql.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/db/servers/base/types.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/db/servers/mysql/__init__.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/db/servers/mysql/operators.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/db/servers/mysql/reserved.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/db/servers/mysql/sql.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/db/servers/mysql/types.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/db/servers/postgres/__init__.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/db/servers/postgres/operators.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/db/servers/postgres/reserved.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/db/servers/postgres/sql.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/db/servers/postgres/types.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/db/servers/sqlite/__init__.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/db/servers/sqlite/operators.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/db/servers/sqlite/reserved.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/db/servers/sqlite/sql.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/db/servers/sqlite/types.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/db/servers/sqlserver/__init__.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/db/servers/sqlserver/operators.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/db/servers/sqlserver/reserved.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/db/servers/sqlserver/sql.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/db/servers/sqlserver/types.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/db/servers/tablehelper.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/db/tests/__init__.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/db/tests/common_db_test.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/db/tests/postgres/__init__.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/db/tests/postgres/common.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/db/tests/postgres/test_column.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/db/tests/postgres/test_connections.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/db/tests/postgres/test_database.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/db/tests/postgres/test_engine.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/db/tests/postgres/test_general_usage.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/db/tests/postgres/test_imports.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/db/tests/postgres/test_result.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/db/tests/postgres/test_row.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/db/tests/postgres/test_row_comprehensive.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/db/tests/postgres/test_schema_locking.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/db/tests/postgres/test_schema_locking_unit.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/db/tests/postgres/test_sequence.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/db/tests/postgres/test_sql_comprehensive.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/db/tests/postgres/test_table.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/db/tests/postgres/test_table_comprehensive.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/db/tests/postgres/test_transaction.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/db/tests/sql/__init__.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/db/tests/sql/common.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/db/tests/sql/test_postgres_select_advanced.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/db/tests/sql/test_postgres_select_variances.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/db/tests/test_cursor_rowcount_fix.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/db/tests/test_db_utils.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/db/tests/test_postgres.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/db/tests/test_postgres_unchanged.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/db/tests/test_process_error_robustness.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/db/tests/test_result_caching.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/db/tests/test_result_sql_aware.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/db/tests/test_row_get_missing_column.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/db/tests/test_schema_locking_initializers.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/db/tests/test_schema_locking_simple.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/db/tests/test_sql_builder.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/db/tests/test_tablehelper.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/db/tests/test_view_helper.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/db/utils.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/logging.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/misc/__init__.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/misc/conv/__init__.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/misc/conv/iconv.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/misc/conv/oconv.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/misc/db.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/misc/export.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/misc/format.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/misc/mail.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/misc/merge.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/misc/tests/__init__.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/misc/tests/test_db.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/misc/tests/test_fix.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/misc/tests/test_format.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/misc/tests/test_iconv.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/misc/tests/test_merge.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/misc/tests/test_oconv.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/misc/tests/test_original_error.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/misc/tests/test_timer.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/misc/timer.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/misc/tools.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/payment/__init__.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/payment/authorizenet_adapter.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/payment/base_adapter.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/payment/braintree_adapter.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/payment/charge_rules.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/payment/demo_profiles.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/payment/profiles.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/payment/router.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity/payment/stripe_adapter.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity_python.egg-info/dependency_links.txt +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/src/velocity_python.egg-info/top_level.txt +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/tests/test_amplify_build.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/tests/test_batch_operations.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/tests/test_concurrency_safety.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/tests/test_connection_pool.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/tests/test_connection_resilience.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/tests/test_decorators.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/tests/test_formbuilder_reshaper.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/tests/test_formbuilder_template_validator.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/tests/test_iconv_money_to_cents.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/tests/test_lambda_handler.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/tests/test_lambda_handler_auth.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/tests/test_mixins_import.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/tests/test_n_plus_one.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/tests/test_observability.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/tests/test_payment_braintree_adapter.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/tests/test_payment_demo_profiles.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/tests/test_payment_profiles.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/tests/test_payment_router.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/tests/test_payment_stripe_adapter.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/tests/test_prepared_statements.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/tests/test_psycopg3_upgrade.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/tests/test_query_cache.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/tests/test_row_batch_update.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/tests/test_row_cache_staleness.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/tests/test_security_hardening.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/tests/test_sqs_per_record_transactions.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/tests/test_sys_modified_count_postgres_demo.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/tests/test_table_alter.py +0 -0
- {velocity_python-0.1.5 → velocity_python-0.1.8}/tests/test_where_clause_validation.py +0 -0
|
@@ -0,0 +1,332 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: velocity-python
|
|
3
|
+
Version: 0.1.8
|
|
4
|
+
Summary: A rapid application development library for interfacing with data storage
|
|
5
|
+
Author-email: Velocity Team <info@codeclubs.org>
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://codeclubs.org/projects/velocity
|
|
8
|
+
Project-URL: Documentation, https://codeclubs.org/projects/velocity
|
|
9
|
+
Project-URL: Bug Tracker, https://codeclubs.org/projects/velocity
|
|
10
|
+
Keywords: database,orm,sql,rapid-development,data-storage
|
|
11
|
+
Classifier: Development Status :: 4 - Beta
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: Topic :: Database
|
|
14
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
+
Classifier: Operating System :: OS Independent
|
|
21
|
+
Requires-Python: >=3.9
|
|
22
|
+
Description-Content-Type: text/markdown
|
|
23
|
+
License-File: LICENSE
|
|
24
|
+
Requires-Dist: sqlparse>=0.5.0
|
|
25
|
+
Provides-Extra: aws
|
|
26
|
+
Requires-Dist: boto3>=1.35.0; extra == "aws"
|
|
27
|
+
Requires-Dist: requests>=2.32.0; extra == "aws"
|
|
28
|
+
Provides-Extra: excel
|
|
29
|
+
Requires-Dist: openpyxl>=3.1.0; extra == "excel"
|
|
30
|
+
Provides-Extra: templates
|
|
31
|
+
Requires-Dist: jinja2>=3.1.0; extra == "templates"
|
|
32
|
+
Provides-Extra: http
|
|
33
|
+
Requires-Dist: requests>=2.32.0; extra == "http"
|
|
34
|
+
Provides-Extra: mysql
|
|
35
|
+
Requires-Dist: mysql-connector-python>=9.0.0; extra == "mysql"
|
|
36
|
+
Provides-Extra: sqlserver
|
|
37
|
+
Requires-Dist: python-tds>=1.15.0; extra == "sqlserver"
|
|
38
|
+
Provides-Extra: postgres
|
|
39
|
+
Requires-Dist: psycopg[binary]>=3.2.0; extra == "postgres"
|
|
40
|
+
Provides-Extra: payment
|
|
41
|
+
Requires-Dist: stripe>=12.0.0; extra == "payment"
|
|
42
|
+
Requires-Dist: braintree>=4.30.0; extra == "payment"
|
|
43
|
+
Provides-Extra: all
|
|
44
|
+
Requires-Dist: velocity-python[aws,excel,http,payment,postgres,templates]; extra == "all"
|
|
45
|
+
Provides-Extra: dev
|
|
46
|
+
Requires-Dist: pytest>=8.0.0; extra == "dev"
|
|
47
|
+
Requires-Dist: pytest-cov>=6.0.0; extra == "dev"
|
|
48
|
+
Requires-Dist: pytest-asyncio>=1.0.0; extra == "dev"
|
|
49
|
+
Requires-Dist: black>=24.0.0; extra == "dev"
|
|
50
|
+
Requires-Dist: flake8>=7.0.0; extra == "dev"
|
|
51
|
+
Requires-Dist: mypy>=1.10.0; extra == "dev"
|
|
52
|
+
Requires-Dist: pre-commit>=4.0.0; extra == "dev"
|
|
53
|
+
Provides-Extra: test
|
|
54
|
+
Requires-Dist: pytest>=8.0.0; extra == "test"
|
|
55
|
+
Requires-Dist: pytest-cov>=6.0.0; extra == "test"
|
|
56
|
+
Requires-Dist: pytest-mock>=3.14.0; extra == "test"
|
|
57
|
+
Requires-Dist: pytest-asyncio>=1.0.0; extra == "test"
|
|
58
|
+
Provides-Extra: docs
|
|
59
|
+
Requires-Dist: sphinx>=8.0.0; extra == "docs"
|
|
60
|
+
Requires-Dist: sphinx-rtd-theme>=3.0.0; extra == "docs"
|
|
61
|
+
Dynamic: license-file
|
|
62
|
+
|
|
63
|
+
# Velocity-Python
|
|
64
|
+
|
|
65
|
+
A rapid application development library for Python that eliminates boilerplate between your code and your database. Write business logic, not SQL plumbing.
|
|
66
|
+
|
|
67
|
+
```python
|
|
68
|
+
@engine.transaction
|
|
69
|
+
def create_order(tx, customer_email, items):
|
|
70
|
+
customer = tx.table("customers").find({"email": customer_email})
|
|
71
|
+
order = tx.table("orders").insert({
|
|
72
|
+
"customer_id": customer["sys_id"],
|
|
73
|
+
"status": "pending",
|
|
74
|
+
"total": sum(i["price"] for i in items),
|
|
75
|
+
})
|
|
76
|
+
tx.table("order_items").insert_many([
|
|
77
|
+
{"order_id": order["sys_id"], "product": i["name"], "price": i["price"]}
|
|
78
|
+
for i in items
|
|
79
|
+
])
|
|
80
|
+
return order
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
No connection management, no cursor juggling, no commit/rollback boilerplate. Velocity handles it all.
|
|
84
|
+
|
|
85
|
+
[](https://www.python.org/downloads/)
|
|
86
|
+
[](https://opensource.org/licenses/MIT)
|
|
87
|
+
|
|
88
|
+
---
|
|
89
|
+
|
|
90
|
+
## Why Velocity?
|
|
91
|
+
|
|
92
|
+
Most Python database libraries fall into two camps:
|
|
93
|
+
|
|
94
|
+
1. **Heavy ORMs** (SQLAlchemy, Django ORM) — powerful but complex. You write Python classes that map to tables, manage sessions, deal with migration frameworks, and learn a large API surface before writing your first query.
|
|
95
|
+
|
|
96
|
+
2. **Raw drivers** (psycopg, sqlite3) — full control, but you're writing SQL strings, managing connections, handling cursors, serializing parameters, and building your own transaction/error-handling patterns from scratch.
|
|
97
|
+
|
|
98
|
+
Velocity occupies the middle ground: **a thin, opinionated layer** that gives you the convenience of an ORM with the transparency of raw SQL. Tables are just names. Rows are just dicts. Transactions are just context managers. You don't define models — Velocity discovers your schema at runtime and adapts to it.
|
|
99
|
+
|
|
100
|
+
### Design Principles
|
|
101
|
+
|
|
102
|
+
| Principle | What It Means |
|
|
103
|
+
|-----------|---------------|
|
|
104
|
+
| **Convention over configuration** | Sensible defaults everywhere. Override only what you need. |
|
|
105
|
+
| **Dicts in, dicts out** | No custom model classes to learn. Rows are dictionaries. |
|
|
106
|
+
| **Transaction-scoped** | Every operation runs inside an explicit transaction. No surprise autocommit. |
|
|
107
|
+
| **Auto-schema** | Tables and columns are created on the fly in development. Locked down in production. |
|
|
108
|
+
| **Driver-agnostic** | PostgreSQL (primary), MySQL, SQLite, SQL Server — same API surface. |
|
|
109
|
+
| **Lambda-native** | Connection pooling, warm-start reuse, and SQS batch handling built in. |
|
|
110
|
+
|
|
111
|
+
---
|
|
112
|
+
|
|
113
|
+
## Installation
|
|
114
|
+
|
|
115
|
+
```bash
|
|
116
|
+
# Core (no database driver — useful for testing or SQLite)
|
|
117
|
+
pip install velocity-python
|
|
118
|
+
|
|
119
|
+
# PostgreSQL (recommended)
|
|
120
|
+
pip install velocity-python[postgres]
|
|
121
|
+
|
|
122
|
+
# With AWS Lambda support
|
|
123
|
+
pip install velocity-python[postgres,aws]
|
|
124
|
+
|
|
125
|
+
# Everything
|
|
126
|
+
pip install velocity-python[all]
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
### Available Extras
|
|
130
|
+
|
|
131
|
+
| Extra | Packages | Use Case |
|
|
132
|
+
|-------|----------|----------|
|
|
133
|
+
| `postgres` | `psycopg[binary]>=3.2.0` | PostgreSQL connections |
|
|
134
|
+
| `aws` | `boto3`, `requests` | Lambda handlers, SQS, Amplify |
|
|
135
|
+
| `excel` | `openpyxl` | Excel export |
|
|
136
|
+
| `templates` | `jinja2` | Template rendering |
|
|
137
|
+
| `http` | `requests` | HTTP utilities |
|
|
138
|
+
| `payment` | `stripe`, `braintree` | Payment processing |
|
|
139
|
+
| `mysql` | `mysql-connector-python` | MySQL connections |
|
|
140
|
+
| `sqlserver` | `python-tds` | SQL Server connections |
|
|
141
|
+
| `all` | All of the above | Full install |
|
|
142
|
+
|
|
143
|
+
**Requires Python 3.9+** and uses **psycopg v3** (not psycopg2) for PostgreSQL.
|
|
144
|
+
|
|
145
|
+
---
|
|
146
|
+
|
|
147
|
+
## Quick Start
|
|
148
|
+
|
|
149
|
+
### 1. Connect
|
|
150
|
+
|
|
151
|
+
```python
|
|
152
|
+
from velocity.db.servers.postgres import initialize
|
|
153
|
+
|
|
154
|
+
# From environment variables (DBHost, DBDatabase, DBUser, DBPassword)
|
|
155
|
+
engine = initialize()
|
|
156
|
+
|
|
157
|
+
# Or explicit config
|
|
158
|
+
engine = initialize(config={
|
|
159
|
+
"host": "localhost",
|
|
160
|
+
"dbname": "myapp",
|
|
161
|
+
"user": "postgres",
|
|
162
|
+
"password": "secret",
|
|
163
|
+
})
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
### 2. Use Transactions
|
|
167
|
+
|
|
168
|
+
```python
|
|
169
|
+
# As a decorator (recommended for Lambda handlers)
|
|
170
|
+
@engine.transaction
|
|
171
|
+
def get_active_users(tx):
|
|
172
|
+
return tx.table("users").select(where={"active": True}).all()
|
|
173
|
+
|
|
174
|
+
# As a context manager
|
|
175
|
+
with engine.transaction() as tx:
|
|
176
|
+
tx.table("users").insert({"name": "Alice", "email": "alice@example.com"})
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
### 3. CRUD Operations
|
|
180
|
+
|
|
181
|
+
```python
|
|
182
|
+
@engine.transaction
|
|
183
|
+
def demo(tx):
|
|
184
|
+
users = tx.table("users")
|
|
185
|
+
|
|
186
|
+
# Insert
|
|
187
|
+
row = users.insert({"name": "Bob", "email": "bob@example.com"})
|
|
188
|
+
|
|
189
|
+
# Read
|
|
190
|
+
user = users.row(row["sys_id"]) # by primary key
|
|
191
|
+
user = users.find({"email": "bob@example.com"}) # by lookup
|
|
192
|
+
|
|
193
|
+
# Update
|
|
194
|
+
user["name"] = "Robert" # immediate write-through
|
|
195
|
+
|
|
196
|
+
# Delete
|
|
197
|
+
users.delete({"sys_id": row["sys_id"]})
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
### 4. Bulk Operations
|
|
201
|
+
|
|
202
|
+
```python
|
|
203
|
+
@engine.transaction
|
|
204
|
+
def import_customers(tx, records):
|
|
205
|
+
tx.table("customers").insert_many(records) # multi-row INSERT
|
|
206
|
+
tx.table("customers").upsert_many(records, pk="email") # INSERT ... ON CONFLICT UPDATE
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
---
|
|
210
|
+
|
|
211
|
+
## Documentation
|
|
212
|
+
|
|
213
|
+
Full documentation is included in the `docs/` directory of the source distribution.
|
|
214
|
+
|
|
215
|
+
| Guide | File | Description |
|
|
216
|
+
|-------|------|-------------|
|
|
217
|
+
| Database ORM | `docs/database.md` | Connections, transactions, tables, rows, results, queries, schema management |
|
|
218
|
+
| Performance & Optimization | `docs/performance.md` | Connection pooling, batch operations, query caching, prepared statements, N+1 prevention, observability |
|
|
219
|
+
| Async Support | `docs/async.md` | AsyncTransaction, AsyncTable, AsyncResult, parallel queries with gather() |
|
|
220
|
+
| Configuration Reference | `docs/configuration.md` | All environment variables, engine options, and connection settings |
|
|
221
|
+
| AWS Lambda Handlers | `docs/aws-handlers.md` | LambdaHandler, SqsHandler, auth modes, per-record transactions |
|
|
222
|
+
| Payment Processing | `docs/payment.md` | Stripe and Braintree adapters, payment lifecycle |
|
|
223
|
+
| Utilities | `docs/utilities.md` | Excel export, data conversion, formatting, timers, email parsing |
|
|
224
|
+
| Testing Guide | `docs/TESTING.md` | Running tests, markers, coverage |
|
|
225
|
+
| Security | `docs/SECURITY.md` | Pre-commit hooks, credential scanning |
|
|
226
|
+
|
|
227
|
+
---
|
|
228
|
+
|
|
229
|
+
## Architecture
|
|
230
|
+
|
|
231
|
+
```
|
|
232
|
+
Engine (singleton — survives Lambda warm starts)
|
|
233
|
+
├── ConnectionPool (thread-safe, configurable min/max)
|
|
234
|
+
└── Transaction (one per request, borrows from pool)
|
|
235
|
+
├── Table (CRUD, batch ops, schema management)
|
|
236
|
+
│ ├── Row (dict-like, lazy-cache, write-through, batch_update)
|
|
237
|
+
│ └── Result (streaming cursor iteration, transforms)
|
|
238
|
+
├── View (create, grant, ensure)
|
|
239
|
+
└── Sequence (create, next, current, configure)
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
Transactions auto-commit on success, auto-rollback on exception. Connections are returned to the pool (or discarded on error). The Engine persists across Lambda invocations, so the pool stays warm.
|
|
243
|
+
|
|
244
|
+
---
|
|
245
|
+
|
|
246
|
+
## Multi-Database Support
|
|
247
|
+
|
|
248
|
+
| Database | Driver | Status |
|
|
249
|
+
|----------|--------|--------|
|
|
250
|
+
| PostgreSQL | `psycopg[binary]>=3.2.0` | Primary, fully tested |
|
|
251
|
+
| MySQL | `mysql-connector-python` | Supported |
|
|
252
|
+
| SQLite | `sqlite3` (stdlib) | Supported |
|
|
253
|
+
| SQL Server | `python-tds` | Supported |
|
|
254
|
+
|
|
255
|
+
```python
|
|
256
|
+
# PostgreSQL
|
|
257
|
+
from velocity.db.servers.postgres import initialize
|
|
258
|
+
engine = initialize()
|
|
259
|
+
|
|
260
|
+
# MySQL
|
|
261
|
+
from velocity.db.servers.mysql import initialize
|
|
262
|
+
engine = initialize()
|
|
263
|
+
|
|
264
|
+
# SQLite
|
|
265
|
+
from velocity.db.servers.sqlite import initialize
|
|
266
|
+
engine = initialize(config={"database": "myapp.db"})
|
|
267
|
+
|
|
268
|
+
# SQL Server
|
|
269
|
+
from velocity.db.servers.mssql import initialize
|
|
270
|
+
engine = initialize()
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
---
|
|
274
|
+
|
|
275
|
+
## Project Structure
|
|
276
|
+
|
|
277
|
+
```
|
|
278
|
+
velocity-python/
|
|
279
|
+
├── src/velocity/
|
|
280
|
+
│ ├── db/
|
|
281
|
+
│ │ ├── core/
|
|
282
|
+
│ │ │ ├── engine.py # Engine, ConnectionPool
|
|
283
|
+
│ │ │ ├── transaction.py # Transaction, query timing, caching
|
|
284
|
+
│ │ │ ├── table.py # Table CRUD, batch ops, schema
|
|
285
|
+
│ │ │ ├── row.py # Row (dict-like ORM object)
|
|
286
|
+
│ │ │ ├── result.py # Result (cursor wrapper, transforms)
|
|
287
|
+
│ │ │ ├── async_support.py # Async versions of core classes
|
|
288
|
+
│ │ │ ├── view.py # View management
|
|
289
|
+
│ │ │ ├── sequence.py # Sequence management
|
|
290
|
+
│ │ │ └── decorators.py # @create_missing, @return_default, etc.
|
|
291
|
+
│ │ └── servers/
|
|
292
|
+
│ │ ├── postgres/ # PostgreSQL dialect + initializer
|
|
293
|
+
│ │ ├── mysql/ # MySQL dialect
|
|
294
|
+
│ │ ├── sqlite/ # SQLite dialect
|
|
295
|
+
│ │ └── mssql/ # SQL Server dialect
|
|
296
|
+
│ ├── aws/
|
|
297
|
+
│ │ └── handlers/
|
|
298
|
+
│ │ ├── lambda_handler.py # HTTP Lambda handler
|
|
299
|
+
│ │ └── sqs_handler.py # SQS batch handler
|
|
300
|
+
│ ├── payment/
|
|
301
|
+
│ │ ├── base_adapter.py # Abstract payment interface
|
|
302
|
+
│ │ ├── stripe_adapter.py # Stripe implementation
|
|
303
|
+
│ │ └── braintree_adapter.py # Braintree implementation
|
|
304
|
+
│ └── misc/ # Utility modules
|
|
305
|
+
├── tests/ # 400+ unit tests
|
|
306
|
+
├── docs/ # Detailed documentation
|
|
307
|
+
└── pyproject.toml
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
---
|
|
311
|
+
|
|
312
|
+
## Development
|
|
313
|
+
|
|
314
|
+
```bash
|
|
315
|
+
# Install with dev dependencies
|
|
316
|
+
pip install -e ".[dev,test,postgres]"
|
|
317
|
+
|
|
318
|
+
# Run tests
|
|
319
|
+
pytest
|
|
320
|
+
|
|
321
|
+
# Run with coverage
|
|
322
|
+
pytest --cov=velocity --cov-report=html
|
|
323
|
+
|
|
324
|
+
# Run specific test file
|
|
325
|
+
pytest tests/test_connection_pool.py -v
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
---
|
|
329
|
+
|
|
330
|
+
## License
|
|
331
|
+
|
|
332
|
+
MIT
|
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
# Velocity-Python
|
|
2
|
+
|
|
3
|
+
A rapid application development library for Python that eliminates boilerplate between your code and your database. Write business logic, not SQL plumbing.
|
|
4
|
+
|
|
5
|
+
```python
|
|
6
|
+
@engine.transaction
|
|
7
|
+
def create_order(tx, customer_email, items):
|
|
8
|
+
customer = tx.table("customers").find({"email": customer_email})
|
|
9
|
+
order = tx.table("orders").insert({
|
|
10
|
+
"customer_id": customer["sys_id"],
|
|
11
|
+
"status": "pending",
|
|
12
|
+
"total": sum(i["price"] for i in items),
|
|
13
|
+
})
|
|
14
|
+
tx.table("order_items").insert_many([
|
|
15
|
+
{"order_id": order["sys_id"], "product": i["name"], "price": i["price"]}
|
|
16
|
+
for i in items
|
|
17
|
+
])
|
|
18
|
+
return order
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
No connection management, no cursor juggling, no commit/rollback boilerplate. Velocity handles it all.
|
|
22
|
+
|
|
23
|
+
[](https://www.python.org/downloads/)
|
|
24
|
+
[](https://opensource.org/licenses/MIT)
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## Why Velocity?
|
|
29
|
+
|
|
30
|
+
Most Python database libraries fall into two camps:
|
|
31
|
+
|
|
32
|
+
1. **Heavy ORMs** (SQLAlchemy, Django ORM) — powerful but complex. You write Python classes that map to tables, manage sessions, deal with migration frameworks, and learn a large API surface before writing your first query.
|
|
33
|
+
|
|
34
|
+
2. **Raw drivers** (psycopg, sqlite3) — full control, but you're writing SQL strings, managing connections, handling cursors, serializing parameters, and building your own transaction/error-handling patterns from scratch.
|
|
35
|
+
|
|
36
|
+
Velocity occupies the middle ground: **a thin, opinionated layer** that gives you the convenience of an ORM with the transparency of raw SQL. Tables are just names. Rows are just dicts. Transactions are just context managers. You don't define models — Velocity discovers your schema at runtime and adapts to it.
|
|
37
|
+
|
|
38
|
+
### Design Principles
|
|
39
|
+
|
|
40
|
+
| Principle | What It Means |
|
|
41
|
+
|-----------|---------------|
|
|
42
|
+
| **Convention over configuration** | Sensible defaults everywhere. Override only what you need. |
|
|
43
|
+
| **Dicts in, dicts out** | No custom model classes to learn. Rows are dictionaries. |
|
|
44
|
+
| **Transaction-scoped** | Every operation runs inside an explicit transaction. No surprise autocommit. |
|
|
45
|
+
| **Auto-schema** | Tables and columns are created on the fly in development. Locked down in production. |
|
|
46
|
+
| **Driver-agnostic** | PostgreSQL (primary), MySQL, SQLite, SQL Server — same API surface. |
|
|
47
|
+
| **Lambda-native** | Connection pooling, warm-start reuse, and SQS batch handling built in. |
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
|
|
51
|
+
## Installation
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
# Core (no database driver — useful for testing or SQLite)
|
|
55
|
+
pip install velocity-python
|
|
56
|
+
|
|
57
|
+
# PostgreSQL (recommended)
|
|
58
|
+
pip install velocity-python[postgres]
|
|
59
|
+
|
|
60
|
+
# With AWS Lambda support
|
|
61
|
+
pip install velocity-python[postgres,aws]
|
|
62
|
+
|
|
63
|
+
# Everything
|
|
64
|
+
pip install velocity-python[all]
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### Available Extras
|
|
68
|
+
|
|
69
|
+
| Extra | Packages | Use Case |
|
|
70
|
+
|-------|----------|----------|
|
|
71
|
+
| `postgres` | `psycopg[binary]>=3.2.0` | PostgreSQL connections |
|
|
72
|
+
| `aws` | `boto3`, `requests` | Lambda handlers, SQS, Amplify |
|
|
73
|
+
| `excel` | `openpyxl` | Excel export |
|
|
74
|
+
| `templates` | `jinja2` | Template rendering |
|
|
75
|
+
| `http` | `requests` | HTTP utilities |
|
|
76
|
+
| `payment` | `stripe`, `braintree` | Payment processing |
|
|
77
|
+
| `mysql` | `mysql-connector-python` | MySQL connections |
|
|
78
|
+
| `sqlserver` | `python-tds` | SQL Server connections |
|
|
79
|
+
| `all` | All of the above | Full install |
|
|
80
|
+
|
|
81
|
+
**Requires Python 3.9+** and uses **psycopg v3** (not psycopg2) for PostgreSQL.
|
|
82
|
+
|
|
83
|
+
---
|
|
84
|
+
|
|
85
|
+
## Quick Start
|
|
86
|
+
|
|
87
|
+
### 1. Connect
|
|
88
|
+
|
|
89
|
+
```python
|
|
90
|
+
from velocity.db.servers.postgres import initialize
|
|
91
|
+
|
|
92
|
+
# From environment variables (DBHost, DBDatabase, DBUser, DBPassword)
|
|
93
|
+
engine = initialize()
|
|
94
|
+
|
|
95
|
+
# Or explicit config
|
|
96
|
+
engine = initialize(config={
|
|
97
|
+
"host": "localhost",
|
|
98
|
+
"dbname": "myapp",
|
|
99
|
+
"user": "postgres",
|
|
100
|
+
"password": "secret",
|
|
101
|
+
})
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### 2. Use Transactions
|
|
105
|
+
|
|
106
|
+
```python
|
|
107
|
+
# As a decorator (recommended for Lambda handlers)
|
|
108
|
+
@engine.transaction
|
|
109
|
+
def get_active_users(tx):
|
|
110
|
+
return tx.table("users").select(where={"active": True}).all()
|
|
111
|
+
|
|
112
|
+
# As a context manager
|
|
113
|
+
with engine.transaction() as tx:
|
|
114
|
+
tx.table("users").insert({"name": "Alice", "email": "alice@example.com"})
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
### 3. CRUD Operations
|
|
118
|
+
|
|
119
|
+
```python
|
|
120
|
+
@engine.transaction
|
|
121
|
+
def demo(tx):
|
|
122
|
+
users = tx.table("users")
|
|
123
|
+
|
|
124
|
+
# Insert
|
|
125
|
+
row = users.insert({"name": "Bob", "email": "bob@example.com"})
|
|
126
|
+
|
|
127
|
+
# Read
|
|
128
|
+
user = users.row(row["sys_id"]) # by primary key
|
|
129
|
+
user = users.find({"email": "bob@example.com"}) # by lookup
|
|
130
|
+
|
|
131
|
+
# Update
|
|
132
|
+
user["name"] = "Robert" # immediate write-through
|
|
133
|
+
|
|
134
|
+
# Delete
|
|
135
|
+
users.delete({"sys_id": row["sys_id"]})
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
### 4. Bulk Operations
|
|
139
|
+
|
|
140
|
+
```python
|
|
141
|
+
@engine.transaction
|
|
142
|
+
def import_customers(tx, records):
|
|
143
|
+
tx.table("customers").insert_many(records) # multi-row INSERT
|
|
144
|
+
tx.table("customers").upsert_many(records, pk="email") # INSERT ... ON CONFLICT UPDATE
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
---
|
|
148
|
+
|
|
149
|
+
## Documentation
|
|
150
|
+
|
|
151
|
+
Full documentation is included in the `docs/` directory of the source distribution.
|
|
152
|
+
|
|
153
|
+
| Guide | File | Description |
|
|
154
|
+
|-------|------|-------------|
|
|
155
|
+
| Database ORM | `docs/database.md` | Connections, transactions, tables, rows, results, queries, schema management |
|
|
156
|
+
| Performance & Optimization | `docs/performance.md` | Connection pooling, batch operations, query caching, prepared statements, N+1 prevention, observability |
|
|
157
|
+
| Async Support | `docs/async.md` | AsyncTransaction, AsyncTable, AsyncResult, parallel queries with gather() |
|
|
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 |
|
|
160
|
+
| Payment Processing | `docs/payment.md` | Stripe and Braintree adapters, payment lifecycle |
|
|
161
|
+
| Utilities | `docs/utilities.md` | Excel export, data conversion, formatting, timers, email parsing |
|
|
162
|
+
| Testing Guide | `docs/TESTING.md` | Running tests, markers, coverage |
|
|
163
|
+
| Security | `docs/SECURITY.md` | Pre-commit hooks, credential scanning |
|
|
164
|
+
|
|
165
|
+
---
|
|
166
|
+
|
|
167
|
+
## Architecture
|
|
168
|
+
|
|
169
|
+
```
|
|
170
|
+
Engine (singleton — survives Lambda warm starts)
|
|
171
|
+
├── ConnectionPool (thread-safe, configurable min/max)
|
|
172
|
+
└── Transaction (one per request, borrows from pool)
|
|
173
|
+
├── Table (CRUD, batch ops, schema management)
|
|
174
|
+
│ ├── Row (dict-like, lazy-cache, write-through, batch_update)
|
|
175
|
+
│ └── Result (streaming cursor iteration, transforms)
|
|
176
|
+
├── View (create, grant, ensure)
|
|
177
|
+
└── Sequence (create, next, current, configure)
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
Transactions auto-commit on success, auto-rollback on exception. Connections are returned to the pool (or discarded on error). The Engine persists across Lambda invocations, so the pool stays warm.
|
|
181
|
+
|
|
182
|
+
---
|
|
183
|
+
|
|
184
|
+
## Multi-Database Support
|
|
185
|
+
|
|
186
|
+
| Database | Driver | Status |
|
|
187
|
+
|----------|--------|--------|
|
|
188
|
+
| PostgreSQL | `psycopg[binary]>=3.2.0` | Primary, fully tested |
|
|
189
|
+
| MySQL | `mysql-connector-python` | Supported |
|
|
190
|
+
| SQLite | `sqlite3` (stdlib) | Supported |
|
|
191
|
+
| SQL Server | `python-tds` | Supported |
|
|
192
|
+
|
|
193
|
+
```python
|
|
194
|
+
# PostgreSQL
|
|
195
|
+
from velocity.db.servers.postgres import initialize
|
|
196
|
+
engine = initialize()
|
|
197
|
+
|
|
198
|
+
# MySQL
|
|
199
|
+
from velocity.db.servers.mysql import initialize
|
|
200
|
+
engine = initialize()
|
|
201
|
+
|
|
202
|
+
# SQLite
|
|
203
|
+
from velocity.db.servers.sqlite import initialize
|
|
204
|
+
engine = initialize(config={"database": "myapp.db"})
|
|
205
|
+
|
|
206
|
+
# SQL Server
|
|
207
|
+
from velocity.db.servers.mssql import initialize
|
|
208
|
+
engine = initialize()
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
---
|
|
212
|
+
|
|
213
|
+
## Project Structure
|
|
214
|
+
|
|
215
|
+
```
|
|
216
|
+
velocity-python/
|
|
217
|
+
├── src/velocity/
|
|
218
|
+
│ ├── db/
|
|
219
|
+
│ │ ├── core/
|
|
220
|
+
│ │ │ ├── engine.py # Engine, ConnectionPool
|
|
221
|
+
│ │ │ ├── transaction.py # Transaction, query timing, caching
|
|
222
|
+
│ │ │ ├── table.py # Table CRUD, batch ops, schema
|
|
223
|
+
│ │ │ ├── row.py # Row (dict-like ORM object)
|
|
224
|
+
│ │ │ ├── result.py # Result (cursor wrapper, transforms)
|
|
225
|
+
│ │ │ ├── async_support.py # Async versions of core classes
|
|
226
|
+
│ │ │ ├── view.py # View management
|
|
227
|
+
│ │ │ ├── sequence.py # Sequence management
|
|
228
|
+
│ │ │ └── decorators.py # @create_missing, @return_default, etc.
|
|
229
|
+
│ │ └── servers/
|
|
230
|
+
│ │ ├── postgres/ # PostgreSQL dialect + initializer
|
|
231
|
+
│ │ ├── mysql/ # MySQL dialect
|
|
232
|
+
│ │ ├── sqlite/ # SQLite dialect
|
|
233
|
+
│ │ └── mssql/ # SQL Server dialect
|
|
234
|
+
│ ├── aws/
|
|
235
|
+
│ │ └── handlers/
|
|
236
|
+
│ │ ├── lambda_handler.py # HTTP Lambda handler
|
|
237
|
+
│ │ └── sqs_handler.py # SQS batch handler
|
|
238
|
+
│ ├── payment/
|
|
239
|
+
│ │ ├── base_adapter.py # Abstract payment interface
|
|
240
|
+
│ │ ├── stripe_adapter.py # Stripe implementation
|
|
241
|
+
│ │ └── braintree_adapter.py # Braintree implementation
|
|
242
|
+
│ └── misc/ # Utility modules
|
|
243
|
+
├── tests/ # 400+ unit tests
|
|
244
|
+
├── docs/ # Detailed documentation
|
|
245
|
+
└── pyproject.toml
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
---
|
|
249
|
+
|
|
250
|
+
## Development
|
|
251
|
+
|
|
252
|
+
```bash
|
|
253
|
+
# Install with dev dependencies
|
|
254
|
+
pip install -e ".[dev,test,postgres]"
|
|
255
|
+
|
|
256
|
+
# Run tests
|
|
257
|
+
pytest
|
|
258
|
+
|
|
259
|
+
# Run with coverage
|
|
260
|
+
pytest --cov=velocity --cov-report=html
|
|
261
|
+
|
|
262
|
+
# Run specific test file
|
|
263
|
+
pytest tests/test_connection_pool.py -v
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
---
|
|
267
|
+
|
|
268
|
+
## License
|
|
269
|
+
|
|
270
|
+
MIT
|
|
@@ -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.8"
|
|
8
8
|
authors = [
|
|
9
9
|
{ name="Velocity Team", email="info@codeclubs.org" },
|
|
10
10
|
]
|
|
@@ -31,6 +31,8 @@ dependencies = [
|
|
|
31
31
|
|
|
32
32
|
[project.urls]
|
|
33
33
|
Homepage = "https://codeclubs.org/projects/velocity"
|
|
34
|
+
Documentation = "https://codeclubs.org/projects/velocity"
|
|
35
|
+
"Bug Tracker" = "https://codeclubs.org/projects/velocity"
|
|
34
36
|
|
|
35
37
|
[project.optional-dependencies]
|
|
36
38
|
aws = [
|
|
@@ -65,6 +67,7 @@ all = [
|
|
|
65
67
|
dev = [
|
|
66
68
|
"pytest>=8.0.0",
|
|
67
69
|
"pytest-cov>=6.0.0",
|
|
70
|
+
"pytest-asyncio>=1.0.0",
|
|
68
71
|
"black>=24.0.0",
|
|
69
72
|
"flake8>=7.0.0",
|
|
70
73
|
"mypy>=1.10.0",
|
|
@@ -74,6 +77,7 @@ test = [
|
|
|
74
77
|
"pytest>=8.0.0",
|
|
75
78
|
"pytest-cov>=6.0.0",
|
|
76
79
|
"pytest-mock>=3.14.0",
|
|
80
|
+
"pytest-asyncio>=1.0.0",
|
|
77
81
|
]
|
|
78
82
|
docs = [
|
|
79
83
|
"sphinx>=8.0.0",
|