velocity-python 0.1.55__tar.gz → 0.1.57__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.
Files changed (197) hide show
  1. {velocity_python-0.1.55 → velocity_python-0.1.57}/PKG-INFO +1 -1
  2. {velocity_python-0.1.55 → velocity_python-0.1.57}/pyproject.toml +1 -1
  3. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/__init__.py +1 -1
  4. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/db/core/engine.py +37 -3
  5. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/db/servers/mysql/__init__.py +7 -6
  6. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/db/servers/sqlserver/__init__.py +7 -8
  7. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity_python.egg-info/PKG-INFO +1 -1
  8. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity_python.egg-info/SOURCES.txt +2 -0
  9. velocity_python-0.1.57/tests/test_db_credentials_ssm_cascade.py +61 -0
  10. velocity_python-0.1.57/tests/test_jsonb_dict_adapter.py +82 -0
  11. {velocity_python-0.1.55 → velocity_python-0.1.57}/LICENSE +0 -0
  12. {velocity_python-0.1.55 → velocity_python-0.1.57}/README.md +0 -0
  13. {velocity_python-0.1.55 → velocity_python-0.1.57}/setup.cfg +0 -0
  14. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/aws/__init__.py +0 -0
  15. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/aws/amplify.py +0 -0
  16. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/aws/amplify_build.py +0 -0
  17. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/aws/assets/__init__.py +0 -0
  18. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/aws/assets/backfill.py +0 -0
  19. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/aws/assets/indexing.py +0 -0
  20. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/aws/assets/references.py +0 -0
  21. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/aws/assets/service.py +0 -0
  22. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/aws/assets/usage_index.py +0 -0
  23. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/aws/dirty_pipeline.py +0 -0
  24. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/aws/handlers/__init__.py +0 -0
  25. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/aws/handlers/base_handler.py +0 -0
  26. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/aws/handlers/context.py +0 -0
  27. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/aws/handlers/context_factory.py +0 -0
  28. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/aws/handlers/exceptions.py +0 -0
  29. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/aws/handlers/lambda_handler.py +0 -0
  30. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/aws/handlers/mixins/__init__.py +0 -0
  31. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/aws/handlers/mixins/data_service.py +0 -0
  32. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/aws/handlers/mixins/web_handler.py +0 -0
  33. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/aws/handlers/perf.py +0 -0
  34. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/aws/handlers/response.py +0 -0
  35. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/aws/handlers/sqs_handler.py +0 -0
  36. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/aws/s3.py +0 -0
  37. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/aws/ssm_config.py +0 -0
  38. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/aws/tests/__init__.py +0 -0
  39. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/aws/tests/test_base_handler_error_response.py +0 -0
  40. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/aws/tests/test_lambda_handler_json_serialization.py +0 -0
  41. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/aws/tests/test_response.py +0 -0
  42. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/db/__init__.py +0 -0
  43. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/db/core/__init__.py +0 -0
  44. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/db/core/async_support.py +0 -0
  45. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/db/core/column.py +0 -0
  46. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/db/core/database.py +0 -0
  47. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/db/core/decorators.py +0 -0
  48. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/db/core/result.py +0 -0
  49. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/db/core/row.py +0 -0
  50. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/db/core/sequence.py +0 -0
  51. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/db/core/table.py +0 -0
  52. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/db/core/transaction.py +0 -0
  53. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/db/core/view.py +0 -0
  54. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/db/exceptions.py +0 -0
  55. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/db/migrations.py +0 -0
  56. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/db/servers/__init__.py +0 -0
  57. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/db/servers/base/__init__.py +0 -0
  58. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/db/servers/base/initializer.py +0 -0
  59. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/db/servers/base/operators.py +0 -0
  60. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/db/servers/base/sql.py +0 -0
  61. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/db/servers/base/types.py +0 -0
  62. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/db/servers/mysql/operators.py +0 -0
  63. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/db/servers/mysql/reserved.py +0 -0
  64. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/db/servers/mysql/sql.py +0 -0
  65. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/db/servers/mysql/types.py +0 -0
  66. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/db/servers/postgres/__init__.py +0 -0
  67. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/db/servers/postgres/operators.py +0 -0
  68. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/db/servers/postgres/reserved.py +0 -0
  69. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/db/servers/postgres/sql.py +0 -0
  70. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/db/servers/postgres/types.py +0 -0
  71. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/db/servers/sqlite/__init__.py +0 -0
  72. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/db/servers/sqlite/operators.py +0 -0
  73. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/db/servers/sqlite/reserved.py +0 -0
  74. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/db/servers/sqlite/sql.py +0 -0
  75. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/db/servers/sqlite/types.py +0 -0
  76. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/db/servers/sqlserver/operators.py +0 -0
  77. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/db/servers/sqlserver/reserved.py +0 -0
  78. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/db/servers/sqlserver/sql.py +0 -0
  79. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/db/servers/sqlserver/types.py +0 -0
  80. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/db/servers/tablehelper.py +0 -0
  81. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/db/tests/__init__.py +0 -0
  82. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/db/tests/common_db_test.py +0 -0
  83. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/db/tests/postgres/__init__.py +0 -0
  84. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/db/tests/postgres/common.py +0 -0
  85. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/db/tests/postgres/conftest.py +0 -0
  86. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/db/tests/postgres/test_column.py +0 -0
  87. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/db/tests/postgres/test_connections.py +0 -0
  88. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/db/tests/postgres/test_database.py +0 -0
  89. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/db/tests/postgres/test_engine.py +0 -0
  90. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/db/tests/postgres/test_general_usage.py +0 -0
  91. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/db/tests/postgres/test_imports.py +0 -0
  92. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/db/tests/postgres/test_result.py +0 -0
  93. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/db/tests/postgres/test_row.py +0 -0
  94. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/db/tests/postgres/test_row_comprehensive.py +0 -0
  95. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/db/tests/postgres/test_schema_locking.py +0 -0
  96. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/db/tests/postgres/test_schema_locking_unit.py +0 -0
  97. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/db/tests/postgres/test_sequence.py +0 -0
  98. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/db/tests/postgres/test_sql_comprehensive.py +0 -0
  99. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/db/tests/postgres/test_table.py +0 -0
  100. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/db/tests/postgres/test_table_comprehensive.py +0 -0
  101. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/db/tests/postgres/test_transaction.py +0 -0
  102. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/db/tests/sql/__init__.py +0 -0
  103. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/db/tests/sql/common.py +0 -0
  104. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/db/tests/sql/test_postgres_select_advanced.py +0 -0
  105. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/db/tests/sql/test_postgres_select_variances.py +0 -0
  106. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/db/tests/test_cursor_rowcount_fix.py +0 -0
  107. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/db/tests/test_db_utils.py +0 -0
  108. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/db/tests/test_postgres.py +0 -0
  109. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/db/tests/test_postgres_unchanged.py +0 -0
  110. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/db/tests/test_process_error_robustness.py +0 -0
  111. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/db/tests/test_result_caching.py +0 -0
  112. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/db/tests/test_result_sql_aware.py +0 -0
  113. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/db/tests/test_row_get_missing_column.py +0 -0
  114. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/db/tests/test_schema_locking_initializers.py +0 -0
  115. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/db/tests/test_schema_locking_simple.py +0 -0
  116. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/db/tests/test_sql_builder.py +0 -0
  117. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/db/tests/test_tablehelper.py +0 -0
  118. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/db/tests/test_view_helper.py +0 -0
  119. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/db/utils.py +0 -0
  120. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/logging.py +0 -0
  121. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/misc/__init__.py +0 -0
  122. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/misc/conv/__init__.py +0 -0
  123. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/misc/conv/iconv.py +0 -0
  124. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/misc/conv/oconv.py +0 -0
  125. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/misc/db.py +0 -0
  126. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/misc/export.py +0 -0
  127. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/misc/format.py +0 -0
  128. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/misc/mail.py +0 -0
  129. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/misc/merge.py +0 -0
  130. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/misc/pdf.py +0 -0
  131. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/misc/tests/__init__.py +0 -0
  132. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/misc/tests/test_db.py +0 -0
  133. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/misc/tests/test_fix.py +0 -0
  134. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/misc/tests/test_format.py +0 -0
  135. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/misc/tests/test_iconv.py +0 -0
  136. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/misc/tests/test_merge.py +0 -0
  137. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/misc/tests/test_oconv.py +0 -0
  138. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/misc/tests/test_original_error.py +0 -0
  139. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/misc/tests/test_timer.py +0 -0
  140. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/misc/timer.py +0 -0
  141. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/misc/tools.py +0 -0
  142. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/payment/__init__.py +0 -0
  143. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/payment/authorizenet_adapter.py +0 -0
  144. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/payment/authorizenet_mirror.py +0 -0
  145. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/payment/base_adapter.py +0 -0
  146. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/payment/braintree_adapter.py +0 -0
  147. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/payment/braintree_mirror.py +0 -0
  148. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/payment/charge_rules.py +0 -0
  149. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/payment/stripe_adapter.py +0 -0
  150. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity/payment/stripe_mirror.py +0 -0
  151. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity_python.egg-info/dependency_links.txt +0 -0
  152. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity_python.egg-info/entry_points.txt +0 -0
  153. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity_python.egg-info/requires.txt +0 -0
  154. {velocity_python-0.1.55 → velocity_python-0.1.57}/src/velocity_python.egg-info/top_level.txt +0 -0
  155. {velocity_python-0.1.55 → velocity_python-0.1.57}/tests/test_amplify_build.py +0 -0
  156. {velocity_python-0.1.55 → velocity_python-0.1.57}/tests/test_asset_indexing.py +0 -0
  157. {velocity_python-0.1.55 → velocity_python-0.1.57}/tests/test_asset_references.py +0 -0
  158. {velocity_python-0.1.55 → velocity_python-0.1.57}/tests/test_assets_service.py +0 -0
  159. {velocity_python-0.1.55 → velocity_python-0.1.57}/tests/test_async_support.py +0 -0
  160. {velocity_python-0.1.55 → velocity_python-0.1.57}/tests/test_batch_operations.py +0 -0
  161. {velocity_python-0.1.55 → velocity_python-0.1.57}/tests/test_concurrency_safety.py +0 -0
  162. {velocity_python-0.1.55 → velocity_python-0.1.57}/tests/test_connection_pool.py +0 -0
  163. {velocity_python-0.1.55 → velocity_python-0.1.57}/tests/test_connection_resilience.py +0 -0
  164. {velocity_python-0.1.55 → velocity_python-0.1.57}/tests/test_context_job_descriptions.py +0 -0
  165. {velocity_python-0.1.55 → velocity_python-0.1.57}/tests/test_decorators.py +0 -0
  166. {velocity_python-0.1.55 → velocity_python-0.1.57}/tests/test_dirty_pipeline_fast_path.py +0 -0
  167. {velocity_python-0.1.55 → velocity_python-0.1.57}/tests/test_email_processing.py +0 -0
  168. {velocity_python-0.1.55 → velocity_python-0.1.57}/tests/test_iconv_money_to_cents.py +0 -0
  169. {velocity_python-0.1.55 → velocity_python-0.1.57}/tests/test_lambda_handler.py +0 -0
  170. {velocity_python-0.1.55 → velocity_python-0.1.57}/tests/test_lambda_handler_auth.py +0 -0
  171. {velocity_python-0.1.55 → velocity_python-0.1.57}/tests/test_mixins_import.py +0 -0
  172. {velocity_python-0.1.55 → velocity_python-0.1.57}/tests/test_n_plus_one.py +0 -0
  173. {velocity_python-0.1.55 → velocity_python-0.1.57}/tests/test_observability.py +0 -0
  174. {velocity_python-0.1.55 → velocity_python-0.1.57}/tests/test_payment_authorizenet_adapter.py +0 -0
  175. {velocity_python-0.1.55 → velocity_python-0.1.57}/tests/test_payment_braintree_adapter.py +0 -0
  176. {velocity_python-0.1.55 → velocity_python-0.1.57}/tests/test_payment_braintree_mirror.py +0 -0
  177. {velocity_python-0.1.55 → velocity_python-0.1.57}/tests/test_payment_profile_sorting.py +0 -0
  178. {velocity_python-0.1.55 → velocity_python-0.1.57}/tests/test_payment_stripe_adapter.py +0 -0
  179. {velocity_python-0.1.55 → velocity_python-0.1.57}/tests/test_pdf.py +0 -0
  180. {velocity_python-0.1.55 → velocity_python-0.1.57}/tests/test_prepared_statements.py +0 -0
  181. {velocity_python-0.1.55 → velocity_python-0.1.57}/tests/test_psycopg3_upgrade.py +0 -0
  182. {velocity_python-0.1.55 → velocity_python-0.1.57}/tests/test_query_cache.py +0 -0
  183. {velocity_python-0.1.55 → velocity_python-0.1.57}/tests/test_retry_side_effect_guard.py +0 -0
  184. {velocity_python-0.1.55 → velocity_python-0.1.57}/tests/test_return_default_safety.py +0 -0
  185. {velocity_python-0.1.55 → velocity_python-0.1.57}/tests/test_row_batch_update.py +0 -0
  186. {velocity_python-0.1.55 → velocity_python-0.1.57}/tests/test_row_cache_staleness.py +0 -0
  187. {velocity_python-0.1.55 → velocity_python-0.1.57}/tests/test_row_dirty_tracking.py +0 -0
  188. {velocity_python-0.1.55 → velocity_python-0.1.57}/tests/test_schema_migrations.py +0 -0
  189. {velocity_python-0.1.55 → velocity_python-0.1.57}/tests/test_security_hardening.py +0 -0
  190. {velocity_python-0.1.55 → velocity_python-0.1.57}/tests/test_server_cursor.py +0 -0
  191. {velocity_python-0.1.55 → velocity_python-0.1.57}/tests/test_single_autocommit_safety.py +0 -0
  192. {velocity_python-0.1.55 → velocity_python-0.1.57}/tests/test_spreadsheet_functions.py +0 -0
  193. {velocity_python-0.1.55 → velocity_python-0.1.57}/tests/test_sqs_per_record_transactions.py +0 -0
  194. {velocity_python-0.1.55 → velocity_python-0.1.57}/tests/test_ssm_config.py +0 -0
  195. {velocity_python-0.1.55 → velocity_python-0.1.57}/tests/test_sys_modified_count_postgres_demo.py +0 -0
  196. {velocity_python-0.1.55 → velocity_python-0.1.57}/tests/test_table_alter.py +0 -0
  197. {velocity_python-0.1.55 → velocity_python-0.1.57}/tests/test_where_clause_validation.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: velocity-python
3
- Version: 0.1.55
3
+ Version: 0.1.57
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
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "velocity-python"
7
- version = "0.1.55"
7
+ version = "0.1.57"
8
8
  authors = [
9
9
  { name="Velocity Team", email="info@codeclubs.org" },
10
10
  ]
@@ -1,4 +1,4 @@
1
- __version__ = version = "0.1.55"
1
+ __version__ = version = "0.1.57"
2
2
 
3
3
  import importlib as _importlib
4
4
 
@@ -421,13 +421,13 @@ class Engine:
421
421
  config = self.config.copy()
422
422
  if timeout_key not in config:
423
423
  config[timeout_key] = timeout_val
424
- return self.driver.connect(**config)
424
+ conn = self.driver.connect(**config)
425
425
 
426
426
  elif isinstance(self.config, str):
427
427
  conn_str = self.config
428
428
  if timeout_key not in conn_str:
429
429
  conn_str += f" {timeout_key}={timeout_val}"
430
- return self.driver.connect(conn_str)
430
+ conn = self.driver.connect(conn_str)
431
431
 
432
432
  elif isinstance(self.config, (tuple, list)):
433
433
  config_args = list(self.config)
@@ -436,16 +436,50 @@ class Engine:
436
436
  config_args[-1][timeout_key] = timeout_val
437
437
  else:
438
438
  config_args.append({timeout_key: timeout_val})
439
- return self.driver.connect(*config_args)
439
+ conn = self.driver.connect(*config_args)
440
440
 
441
441
  else:
442
442
  raise TypeError(
443
443
  f"Unhandled configuration parameter type: {type(self.config)}"
444
444
  )
445
445
 
446
+ self._register_connection_adapters(conn)
447
+ return conn
448
+
446
449
  except Exception as e:
447
450
  raise self.process_error(e)
448
451
 
452
+ def _register_connection_adapters(self, conn):
453
+ """
454
+ Register driver-specific type adapters on a freshly opened connection.
455
+
456
+ For PostgreSQL (psycopg v3) this teaches the connection to send a bare
457
+ ``dict`` as JSONB. psycopg has no built-in ``dict`` dumper, so without
458
+ this any dict passed for a JSON/JSONB column raises
459
+ ``cannot adapt type 'dict'``. Registering it here keeps velocity's
460
+ "dicts in, dicts out" contract: callers pass a dict, it lands as JSONB.
461
+
462
+ Only ``dict`` is mapped — ``list`` is intentionally left alone so it
463
+ keeps adapting to PostgreSQL arrays (``= ANY(%s)``, array columns).
464
+ Callers that already serialize to a JSON string keep working: a str is
465
+ sent as text and cast into the JSONB column.
466
+ """
467
+ if "postgre" not in self.sql.server.lower():
468
+ return
469
+ try:
470
+ from psycopg.types.json import JsonbDumper, JsonbBinaryDumper
471
+ except Exception:
472
+ return
473
+ try:
474
+ # Register both text and binary dumpers so dict adapts regardless of
475
+ # the negotiated parameter format (mirrors psycopg's own default
476
+ # registration for its Jsonb wrapper type).
477
+ conn.adapters.register_dumper(dict, JsonbDumper)
478
+ conn.adapters.register_dumper(dict, JsonbBinaryDumper)
479
+ except Exception:
480
+ # Never let adapter registration break connection establishment.
481
+ pass
482
+
449
483
  def transaction(self, func_or_cls=None):
450
484
  """
451
485
  Decorator that provides a Transaction. If `tx` is passed in, uses it; otherwise, creates a new one.
@@ -1,4 +1,5 @@
1
1
  import os
2
+ from velocity.aws.ssm_config import getenv as _getenv
2
3
  from ..base.initializer import BaseInitializer
3
4
  from velocity.db.core import engine
4
5
  from .sql import SQL
@@ -27,13 +28,13 @@ class MySQLInitializer(BaseInitializer):
27
28
  "MySQL connector not available. Install with: pip install mysql-connector-python"
28
29
  )
29
30
 
30
- # Base configuration from environment (if available)
31
+ # Base configuration from environment / SSM (same cascade as postgres)
31
32
  base_config = {
32
- "database": os.environ.get("DBDatabase"),
33
- "host": os.environ.get("DBHost"),
34
- "port": os.environ.get("DBPort"),
35
- "user": os.environ.get("DBUser"),
36
- "password": os.environ.get("DBPassword"),
33
+ "database": _getenv("DBDatabase"),
34
+ "host": _getenv("DBHost"),
35
+ "port": _getenv("DBPort"),
36
+ "user": _getenv("DBUser"),
37
+ "password": _getenv("DBPassword"),
37
38
  }
38
39
 
39
40
  # Remove None values
@@ -1,4 +1,5 @@
1
1
  import os
2
+ from velocity.aws.ssm_config import getenv as _getenv
2
3
  from ..base.initializer import BaseInitializer
3
4
  from velocity.db.core import engine
4
5
  from .sql import SQL
@@ -27,15 +28,13 @@ class SQLServerInitializer(BaseInitializer):
27
28
  "SQL Server connector not available. Install with: pip install python-tds"
28
29
  )
29
30
 
30
- # Base configuration from environment (if available)
31
+ # Base configuration from environment / SSM (same cascade as postgres)
31
32
  base_config = {
32
- "database": os.environ.get("DBDatabase"),
33
- "server": os.environ.get(
34
- "DBHost"
35
- ), # SQL Server uses 'server' instead of 'host'
36
- "port": os.environ.get("DBPort"),
37
- "user": os.environ.get("DBUser"),
38
- "password": os.environ.get("DBPassword"),
33
+ "database": _getenv("DBDatabase"),
34
+ "server": _getenv("DBHost"), # SQL Server uses 'server' instead of 'host'
35
+ "port": _getenv("DBPort"),
36
+ "user": _getenv("DBUser"),
37
+ "password": _getenv("DBPassword"),
39
38
  }
40
39
 
41
40
  # Remove None values
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: velocity-python
3
- Version: 0.1.55
3
+ Version: 0.1.57
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
@@ -158,10 +158,12 @@ tests/test_concurrency_safety.py
158
158
  tests/test_connection_pool.py
159
159
  tests/test_connection_resilience.py
160
160
  tests/test_context_job_descriptions.py
161
+ tests/test_db_credentials_ssm_cascade.py
161
162
  tests/test_decorators.py
162
163
  tests/test_dirty_pipeline_fast_path.py
163
164
  tests/test_email_processing.py
164
165
  tests/test_iconv_money_to_cents.py
166
+ tests/test_jsonb_dict_adapter.py
165
167
  tests/test_lambda_handler.py
166
168
  tests/test_lambda_handler_auth.py
167
169
  tests/test_mixins_import.py
@@ -0,0 +1,61 @@
1
+ #!/usr/bin/env python3
2
+ """DB credential resolution must go through the SSM->env cascade (ssm_config.getenv),
3
+ the same way the postgres initializer does, so MySQL/SQL Server work in SSM-only
4
+ environments rather than only reading raw os.environ.
5
+ """
6
+
7
+ import unittest
8
+ from unittest.mock import MagicMock, patch
9
+
10
+ from velocity.db.servers import mysql as mysql_server
11
+ from velocity.db.servers import sqlserver as sqlserver_server
12
+
13
+ FAKE = {
14
+ "DBDatabase": "ssm_db",
15
+ "DBHost": "ssm_host",
16
+ "DBPort": "5599",
17
+ "DBUser": "ssm_user",
18
+ "DBPassword": "ssm_pass",
19
+ }
20
+
21
+
22
+ class TestDbCredentialsSsmCascade(unittest.TestCase):
23
+ def test_mysql_resolves_credentials_via_getenv(self):
24
+ captured = {}
25
+
26
+ def fake_engine(driver, cfg, sql, **kwargs):
27
+ captured.update(cfg)
28
+ return MagicMock()
29
+
30
+ with patch.object(mysql_server, "_getenv", lambda key: FAKE.get(key)), patch.object(
31
+ mysql_server.engine, "Engine", fake_engine
32
+ ):
33
+ mysql_server.MySQLInitializer.initialize(None)
34
+
35
+ self.assertEqual(captured["database"], "ssm_db")
36
+ self.assertEqual(captured["host"], "ssm_host")
37
+ self.assertEqual(captured["port"], "5599")
38
+ self.assertEqual(captured["user"], "ssm_user")
39
+ self.assertEqual(captured["password"], "ssm_pass")
40
+
41
+ def test_sqlserver_resolves_credentials_via_getenv(self):
42
+ captured = {}
43
+
44
+ def fake_engine(driver, cfg, sql, **kwargs):
45
+ captured.update(cfg)
46
+ return MagicMock()
47
+
48
+ with patch.object(
49
+ sqlserver_server, "_getenv", lambda key: FAKE.get(key)
50
+ ), patch.object(sqlserver_server.engine, "Engine", fake_engine):
51
+ sqlserver_server.SQLServerInitializer.initialize(None)
52
+
53
+ self.assertEqual(captured["database"], "ssm_db")
54
+ self.assertEqual(captured["server"], "ssm_host") # SQL Server uses 'server'
55
+ self.assertEqual(captured["port"], "5599")
56
+ self.assertEqual(captured["user"], "ssm_user")
57
+ self.assertEqual(captured["password"], "ssm_pass")
58
+
59
+
60
+ if __name__ == "__main__":
61
+ unittest.main()
@@ -0,0 +1,82 @@
1
+ """Tests for automatic dict -> JSONB adaptation on PostgreSQL connections.
2
+
3
+ Regression for the production failure in client_payment_accounts upserts
4
+ (stripe/braintree/authorizenet mirrors): a bare ``dict`` passed for a JSONB
5
+ column raised ``psycopg.ProgrammingError: cannot adapt type 'dict'`` because
6
+ psycopg v3 ships no built-in dict dumper.
7
+
8
+ The engine now registers ``JsonbDumper`` for ``dict`` on each new PostgreSQL
9
+ connection, so callers keep velocity's "dicts in, dicts out" contract.
10
+ """
11
+
12
+ import os
13
+ from unittest.mock import MagicMock, patch
14
+
15
+ import pytest
16
+
17
+
18
+ _PG_ENV = {
19
+ "DBDatabase": "testdb",
20
+ "DBHost": "localhost",
21
+ "DBPort": "5432",
22
+ "DBUser": "user",
23
+ "DBPassword": "pass",
24
+ }
25
+
26
+
27
+ class TestDictJsonbAdapterRegistration:
28
+ @patch.dict(os.environ, _PG_ENV)
29
+ def test_dict_dumper_registered_on_postgres_connect(self):
30
+ from velocity.db.servers.postgres import initialize
31
+ from psycopg.types.json import JsonbDumper, JsonbBinaryDumper
32
+
33
+ conn = MagicMock(closed=False)
34
+ with patch("psycopg.connect", return_value=conn):
35
+ engine = initialize(pool_enabled=False)
36
+ engine.connect()
37
+
38
+ conn.adapters.register_dumper.assert_any_call(dict, JsonbDumper)
39
+ conn.adapters.register_dumper.assert_any_call(dict, JsonbBinaryDumper)
40
+
41
+ @patch.dict(os.environ, _PG_ENV)
42
+ def test_connection_still_returned_if_registration_fails(self):
43
+ """Adapter registration must never break connection establishment."""
44
+ from velocity.db.servers.postgres import initialize
45
+
46
+ conn = MagicMock(closed=False)
47
+ conn.adapters.register_dumper.side_effect = RuntimeError("boom")
48
+ with patch("psycopg.connect", return_value=conn):
49
+ engine = initialize(pool_enabled=False)
50
+ result = engine.connect()
51
+
52
+ assert result is conn
53
+
54
+
55
+ class TestJsonbDumperSerializesBareDict:
56
+ """The registered dumper must actually serialize a bare dict to JSONB."""
57
+
58
+ def test_text_dumper_dumps_bare_dict_to_json(self):
59
+ from psycopg.types.json import JsonbDumper
60
+
61
+ out = bytes(JsonbDumper(dict).dump({"card_payments": "active"}))
62
+ assert out == b'{"card_payments": "active"}'
63
+
64
+ def test_binary_dumper_dumps_bare_dict_to_jsonb(self):
65
+ from psycopg.types.json import JsonbBinaryDumper
66
+
67
+ out = bytes(JsonbBinaryDumper(dict).dump({"card_payments": "active"}))
68
+ # JSONB binary wire format is a 0x01 version byte followed by JSON text.
69
+ assert out[:1] == b"\x01"
70
+ assert b'"card_payments"' in out
71
+
72
+
73
+ class TestNonPostgresUnaffected:
74
+ def test_sqlite_connect_does_not_register_dict_dumper(self):
75
+ """Non-PostgreSQL engines must not attempt psycopg adapter registration."""
76
+ from velocity.db.servers.sqlite import initialize
77
+
78
+ engine = initialize(config={"database": ":memory:"})
79
+ conn = engine.connect()
80
+ # A sqlite3 connection has no `.adapters`; reaching it would have raised.
81
+ assert conn is not None
82
+ conn.close()