velocity-python 0.1.81__tar.gz → 0.1.83__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 (217) hide show
  1. {velocity_python-0.1.81 → velocity_python-0.1.83}/PKG-INFO +1 -1
  2. {velocity_python-0.1.81 → velocity_python-0.1.83}/pyproject.toml +1 -1
  3. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/__init__.py +1 -1
  4. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/aws/amplify_build.py +50 -1
  5. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity_python.egg-info/PKG-INFO +1 -1
  6. {velocity_python-0.1.81 → velocity_python-0.1.83}/tests/test_amplify_build.py +103 -0
  7. {velocity_python-0.1.81 → velocity_python-0.1.83}/LICENSE +0 -0
  8. {velocity_python-0.1.81 → velocity_python-0.1.83}/README.md +0 -0
  9. {velocity_python-0.1.81 → velocity_python-0.1.83}/setup.cfg +0 -0
  10. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/aws/__init__.py +0 -0
  11. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/aws/amplify.py +0 -0
  12. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/aws/assets/__init__.py +0 -0
  13. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/aws/assets/backfill.py +0 -0
  14. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/aws/assets/indexing.py +0 -0
  15. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/aws/assets/references.py +0 -0
  16. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/aws/assets/service.py +0 -0
  17. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/aws/assets/usage_index.py +0 -0
  18. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/aws/dirty_pipeline.py +0 -0
  19. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/aws/handlers/__init__.py +0 -0
  20. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/aws/handlers/base_handler.py +0 -0
  21. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/aws/handlers/context.py +0 -0
  22. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/aws/handlers/context_factory.py +0 -0
  23. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/aws/handlers/exceptions.py +0 -0
  24. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/aws/handlers/lambda_handler.py +0 -0
  25. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/aws/handlers/masquerade.py +0 -0
  26. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/aws/handlers/mixins/__init__.py +0 -0
  27. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/aws/handlers/mixins/data_service.py +0 -0
  28. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/aws/handlers/mixins/web_handler.py +0 -0
  29. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/aws/handlers/perf.py +0 -0
  30. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/aws/handlers/response.py +0 -0
  31. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/aws/handlers/sqs_handler.py +0 -0
  32. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/aws/s3.py +0 -0
  33. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/aws/ssm_config.py +0 -0
  34. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/aws/tests/__init__.py +0 -0
  35. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/aws/tests/test_base_handler_error_response.py +0 -0
  36. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/aws/tests/test_lambda_handler_json_serialization.py +0 -0
  37. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/aws/tests/test_response.py +0 -0
  38. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/db/__init__.py +0 -0
  39. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/db/core/__init__.py +0 -0
  40. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/db/core/async_support.py +0 -0
  41. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/db/core/column.py +0 -0
  42. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/db/core/database.py +0 -0
  43. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/db/core/decorators.py +0 -0
  44. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/db/core/engine.py +0 -0
  45. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/db/core/jsonproxy.py +0 -0
  46. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/db/core/result.py +0 -0
  47. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/db/core/row.py +0 -0
  48. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/db/core/sequence.py +0 -0
  49. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/db/core/table.py +0 -0
  50. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/db/core/transaction.py +0 -0
  51. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/db/core/view.py +0 -0
  52. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/db/exceptions.py +0 -0
  53. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/db/maintenance.py +0 -0
  54. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/db/migrations.py +0 -0
  55. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/db/servers/__init__.py +0 -0
  56. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/db/servers/base/__init__.py +0 -0
  57. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/db/servers/base/initializer.py +0 -0
  58. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/db/servers/base/operators.py +0 -0
  59. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/db/servers/base/sql.py +0 -0
  60. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/db/servers/base/types.py +0 -0
  61. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/db/servers/mysql/__init__.py +0 -0
  62. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/db/servers/mysql/operators.py +0 -0
  63. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/db/servers/mysql/reserved.py +0 -0
  64. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/db/servers/mysql/sql.py +0 -0
  65. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/db/servers/mysql/types.py +0 -0
  66. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/db/servers/postgres/__init__.py +0 -0
  67. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/db/servers/postgres/operators.py +0 -0
  68. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/db/servers/postgres/reserved.py +0 -0
  69. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/db/servers/postgres/sql.py +0 -0
  70. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/db/servers/postgres/types.py +0 -0
  71. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/db/servers/sqlite/__init__.py +0 -0
  72. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/db/servers/sqlite/operators.py +0 -0
  73. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/db/servers/sqlite/reserved.py +0 -0
  74. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/db/servers/sqlite/sql.py +0 -0
  75. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/db/servers/sqlite/types.py +0 -0
  76. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/db/servers/sqlserver/__init__.py +0 -0
  77. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/db/servers/sqlserver/operators.py +0 -0
  78. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/db/servers/sqlserver/reserved.py +0 -0
  79. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/db/servers/sqlserver/sql.py +0 -0
  80. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/db/servers/sqlserver/types.py +0 -0
  81. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/db/servers/tablehelper.py +0 -0
  82. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/db/tests/__init__.py +0 -0
  83. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/db/tests/common_db_test.py +0 -0
  84. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/db/tests/postgres/__init__.py +0 -0
  85. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/db/tests/postgres/common.py +0 -0
  86. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/db/tests/postgres/conftest.py +0 -0
  87. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/db/tests/postgres/test_column.py +0 -0
  88. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/db/tests/postgres/test_connections.py +0 -0
  89. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/db/tests/postgres/test_database.py +0 -0
  90. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/db/tests/postgres/test_engine.py +0 -0
  91. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/db/tests/postgres/test_general_usage.py +0 -0
  92. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/db/tests/postgres/test_imports.py +0 -0
  93. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/db/tests/postgres/test_result.py +0 -0
  94. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/db/tests/postgres/test_row.py +0 -0
  95. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/db/tests/postgres/test_row_comprehensive.py +0 -0
  96. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/db/tests/postgres/test_schema_locking.py +0 -0
  97. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/db/tests/postgres/test_schema_locking_unit.py +0 -0
  98. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/db/tests/postgres/test_sequence.py +0 -0
  99. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/db/tests/postgres/test_sql_comprehensive.py +0 -0
  100. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/db/tests/postgres/test_table.py +0 -0
  101. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/db/tests/postgres/test_table_comprehensive.py +0 -0
  102. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/db/tests/postgres/test_transaction.py +0 -0
  103. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/db/tests/sql/__init__.py +0 -0
  104. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/db/tests/sql/common.py +0 -0
  105. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/db/tests/sql/test_postgres_select_advanced.py +0 -0
  106. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/db/tests/sql/test_postgres_select_variances.py +0 -0
  107. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/db/tests/test_cursor_rowcount_fix.py +0 -0
  108. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/db/tests/test_db_utils.py +0 -0
  109. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/db/tests/test_postgres.py +0 -0
  110. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/db/tests/test_postgres_unchanged.py +0 -0
  111. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/db/tests/test_process_error_robustness.py +0 -0
  112. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/db/tests/test_result_caching.py +0 -0
  113. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/db/tests/test_result_sql_aware.py +0 -0
  114. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/db/tests/test_row_get_missing_column.py +0 -0
  115. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/db/tests/test_schema_locking_initializers.py +0 -0
  116. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/db/tests/test_schema_locking_simple.py +0 -0
  117. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/db/tests/test_sql_builder.py +0 -0
  118. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/db/tests/test_tablehelper.py +0 -0
  119. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/db/tests/test_view_helper.py +0 -0
  120. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/db/utils.py +0 -0
  121. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/logging.py +0 -0
  122. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/misc/__init__.py +0 -0
  123. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/misc/conv/__init__.py +0 -0
  124. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/misc/conv/iconv.py +0 -0
  125. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/misc/conv/oconv.py +0 -0
  126. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/misc/db.py +0 -0
  127. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/misc/export.py +0 -0
  128. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/misc/format.py +0 -0
  129. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/misc/mail.py +0 -0
  130. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/misc/merge.py +0 -0
  131. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/misc/pdf.py +0 -0
  132. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/misc/tests/__init__.py +0 -0
  133. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/misc/tests/test_db.py +0 -0
  134. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/misc/tests/test_fix.py +0 -0
  135. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/misc/tests/test_format.py +0 -0
  136. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/misc/tests/test_iconv.py +0 -0
  137. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/misc/tests/test_merge.py +0 -0
  138. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/misc/tests/test_oconv.py +0 -0
  139. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/misc/tests/test_original_error.py +0 -0
  140. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/misc/tests/test_timer.py +0 -0
  141. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/misc/timer.py +0 -0
  142. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/misc/tools.py +0 -0
  143. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/payment/__init__.py +0 -0
  144. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/payment/authorizenet_adapter.py +0 -0
  145. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/payment/authorizenet_mirror.py +0 -0
  146. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/payment/base_adapter.py +0 -0
  147. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/payment/braintree_adapter.py +0 -0
  148. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/payment/braintree_mirror.py +0 -0
  149. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/payment/charge_rules.py +0 -0
  150. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/payment/stripe_adapter.py +0 -0
  151. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity/payment/stripe_mirror.py +0 -0
  152. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity_python.egg-info/SOURCES.txt +0 -0
  153. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity_python.egg-info/dependency_links.txt +0 -0
  154. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity_python.egg-info/entry_points.txt +0 -0
  155. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity_python.egg-info/requires.txt +0 -0
  156. {velocity_python-0.1.81 → velocity_python-0.1.83}/src/velocity_python.egg-info/top_level.txt +0 -0
  157. {velocity_python-0.1.81 → velocity_python-0.1.83}/tests/test_activity_tracking_aborted_tx.py +0 -0
  158. {velocity_python-0.1.81 → velocity_python-0.1.83}/tests/test_asset_indexing.py +0 -0
  159. {velocity_python-0.1.81 → velocity_python-0.1.83}/tests/test_asset_references.py +0 -0
  160. {velocity_python-0.1.81 → velocity_python-0.1.83}/tests/test_assets_service.py +0 -0
  161. {velocity_python-0.1.81 → velocity_python-0.1.83}/tests/test_async_support.py +0 -0
  162. {velocity_python-0.1.81 → velocity_python-0.1.83}/tests/test_batch_operations.py +0 -0
  163. {velocity_python-0.1.81 → velocity_python-0.1.83}/tests/test_column_tx_arg.py +0 -0
  164. {velocity_python-0.1.81 → velocity_python-0.1.83}/tests/test_concurrency_safety.py +0 -0
  165. {velocity_python-0.1.81 → velocity_python-0.1.83}/tests/test_connection_pool.py +0 -0
  166. {velocity_python-0.1.81 → velocity_python-0.1.83}/tests/test_connection_resilience.py +0 -0
  167. {velocity_python-0.1.81 → velocity_python-0.1.83}/tests/test_context_job_descriptions.py +0 -0
  168. {velocity_python-0.1.81 → velocity_python-0.1.83}/tests/test_db_credentials_ssm_cascade.py +0 -0
  169. {velocity_python-0.1.81 → velocity_python-0.1.83}/tests/test_db_maintenance.py +0 -0
  170. {velocity_python-0.1.81 → velocity_python-0.1.83}/tests/test_decorators.py +0 -0
  171. {velocity_python-0.1.81 → velocity_python-0.1.83}/tests/test_dirty_pipeline_fast_path.py +0 -0
  172. {velocity_python-0.1.81 → velocity_python-0.1.83}/tests/test_email_processing.py +0 -0
  173. {velocity_python-0.1.81 → velocity_python-0.1.83}/tests/test_enqueue_send_failures.py +0 -0
  174. {velocity_python-0.1.81 → velocity_python-0.1.83}/tests/test_get_cognito_user_provider.py +0 -0
  175. {velocity_python-0.1.81 → velocity_python-0.1.83}/tests/test_http_handler_rollback.py +0 -0
  176. {velocity_python-0.1.81 → velocity_python-0.1.83}/tests/test_iconv_money_to_cents.py +0 -0
  177. {velocity_python-0.1.81 → velocity_python-0.1.83}/tests/test_identifier_injection_guard.py +0 -0
  178. {velocity_python-0.1.81 → velocity_python-0.1.83}/tests/test_json_columns.py +0 -0
  179. {velocity_python-0.1.81 → velocity_python-0.1.83}/tests/test_jsonb_dict_adapter.py +0 -0
  180. {velocity_python-0.1.81 → velocity_python-0.1.83}/tests/test_lambda_handler.py +0 -0
  181. {velocity_python-0.1.81 → velocity_python-0.1.83}/tests/test_lambda_handler_auth.py +0 -0
  182. {velocity_python-0.1.81 → velocity_python-0.1.83}/tests/test_lambda_handler_masquerade.py +0 -0
  183. {velocity_python-0.1.81 → velocity_python-0.1.83}/tests/test_masquerade_grant.py +0 -0
  184. {velocity_python-0.1.81 → velocity_python-0.1.83}/tests/test_mixins_import.py +0 -0
  185. {velocity_python-0.1.81 → velocity_python-0.1.83}/tests/test_n_plus_one.py +0 -0
  186. {velocity_python-0.1.81 → velocity_python-0.1.83}/tests/test_observability.py +0 -0
  187. {velocity_python-0.1.81 → velocity_python-0.1.83}/tests/test_payment_authorizenet_adapter.py +0 -0
  188. {velocity_python-0.1.81 → velocity_python-0.1.83}/tests/test_payment_braintree_adapter.py +0 -0
  189. {velocity_python-0.1.81 → velocity_python-0.1.83}/tests/test_payment_braintree_mirror.py +0 -0
  190. {velocity_python-0.1.81 → velocity_python-0.1.83}/tests/test_payment_mirror_empty_table.py +0 -0
  191. {velocity_python-0.1.81 → velocity_python-0.1.83}/tests/test_payment_profile_sorting.py +0 -0
  192. {velocity_python-0.1.81 → velocity_python-0.1.83}/tests/test_payment_stripe_adapter.py +0 -0
  193. {velocity_python-0.1.81 → velocity_python-0.1.83}/tests/test_pdf.py +0 -0
  194. {velocity_python-0.1.81 → velocity_python-0.1.83}/tests/test_prepared_statements.py +0 -0
  195. {velocity_python-0.1.81 → velocity_python-0.1.83}/tests/test_psycopg3_upgrade.py +0 -0
  196. {velocity_python-0.1.81 → velocity_python-0.1.83}/tests/test_query_cache.py +0 -0
  197. {velocity_python-0.1.81 → velocity_python-0.1.83}/tests/test_restricted_direct_tables.py +0 -0
  198. {velocity_python-0.1.81 → velocity_python-0.1.83}/tests/test_retry_side_effect_guard.py +0 -0
  199. {velocity_python-0.1.81 → velocity_python-0.1.83}/tests/test_return_default_safety.py +0 -0
  200. {velocity_python-0.1.81 → velocity_python-0.1.83}/tests/test_row_batch_update.py +0 -0
  201. {velocity_python-0.1.81 → velocity_python-0.1.83}/tests/test_row_cache_staleness.py +0 -0
  202. {velocity_python-0.1.81 → velocity_python-0.1.83}/tests/test_schema_migrations.py +0 -0
  203. {velocity_python-0.1.81 → velocity_python-0.1.83}/tests/test_security_hardening.py +0 -0
  204. {velocity_python-0.1.81 → velocity_python-0.1.83}/tests/test_server_cursor.py +0 -0
  205. {velocity_python-0.1.81 → velocity_python-0.1.83}/tests/test_single_autocommit_safety.py +0 -0
  206. {velocity_python-0.1.81 → velocity_python-0.1.83}/tests/test_spreadsheet_functions.py +0 -0
  207. {velocity_python-0.1.81 → velocity_python-0.1.83}/tests/test_sqlite_backend.py +0 -0
  208. {velocity_python-0.1.81 → velocity_python-0.1.83}/tests/test_sqs_per_record_transactions.py +0 -0
  209. {velocity_python-0.1.81 → velocity_python-0.1.83}/tests/test_ssm_config.py +0 -0
  210. {velocity_python-0.1.81 → velocity_python-0.1.83}/tests/test_store_user_data.py +0 -0
  211. {velocity_python-0.1.81 → velocity_python-0.1.83}/tests/test_sys_modified_count_postgres_demo.py +0 -0
  212. {velocity_python-0.1.81 → velocity_python-0.1.83}/tests/test_table_alter.py +0 -0
  213. {velocity_python-0.1.81 → velocity_python-0.1.83}/tests/test_transaction_class_wrapping.py +0 -0
  214. {velocity_python-0.1.81 → velocity_python-0.1.83}/tests/test_transaction_commit_and_ownership.py +0 -0
  215. {velocity_python-0.1.81 → velocity_python-0.1.83}/tests/test_transaction_edge_cases.py +0 -0
  216. {velocity_python-0.1.81 → velocity_python-0.1.83}/tests/test_where_clause_validation.py +0 -0
  217. {velocity_python-0.1.81 → velocity_python-0.1.83}/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.81
3
+ Version: 0.1.83
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.81"
7
+ version = "0.1.83"
8
8
  authors = [
9
9
  { name="Velocity Team", email="info@codeclubs.org" },
10
10
  ]
@@ -1,4 +1,4 @@
1
- __version__ = version = "0.1.81"
1
+ __version__ = version = "0.1.83"
2
2
 
3
3
  import importlib as _importlib
4
4
 
@@ -294,7 +294,54 @@ def _normalize_policy_document(policy_document: Any) -> Any:
294
294
  return json.loads(policy_document)
295
295
 
296
296
 
297
+ def _canonical_statement(statement: Mapping[str, Any]) -> str:
298
+ """Canonical form for statement identity: scalar Action/Resource and their
299
+ list equivalents compare equal, action order is ignored."""
300
+ normalized: Dict[str, Any] = {}
301
+ for key, value in statement.items():
302
+ if key in ("Action", "NotAction", "Resource", "NotResource"):
303
+ items = value if isinstance(value, list) else [value]
304
+ normalized[key] = sorted(str(item) for item in items)
305
+ else:
306
+ normalized[key] = value
307
+ return json.dumps(normalized, sort_keys=True)
308
+
309
+
310
+ def _merge_policy_statements(
311
+ current_document: Mapping[str, Any], desired_document: Mapping[str, Any]
312
+ ) -> Dict[str, Any]:
313
+ """Additive union of policy statements.
314
+
315
+ Every statement already on the policy is kept (manually-added grants and
316
+ other apps' statements survive); desired statements not already present are
317
+ appended. Statements are never removed here — remove manually when needed.
318
+ """
319
+ current_statements = list(current_document.get("Statement", []))
320
+ seen = {_canonical_statement(statement) for statement in current_statements}
321
+ merged = list(current_statements)
322
+ for statement in desired_document.get("Statement", []):
323
+ key = _canonical_statement(statement)
324
+ if key not in seen:
325
+ merged.append(statement)
326
+ seen.add(key)
327
+ merged_document = dict(current_document)
328
+ if "Version" not in merged_document and "Version" in desired_document:
329
+ merged_document["Version"] = desired_document["Version"]
330
+ merged_document["Statement"] = merged
331
+ return merged_document
332
+
333
+
297
334
  def _sync_managed_policy_document(iam_client, policy_arn: str, policy_document: Any) -> None:
335
+ """Ensure the managed policy contains every desired statement (additive).
336
+
337
+ The policy document is the union of what is already on the policy and the
338
+ desired statements; existing statements are never dropped. This keeps a
339
+ shared policy (e.g. lambda-vpc-execution, attached by every app's build)
340
+ stable across builds of apps with differing extra statements, and preserves
341
+ grants added out-of-band. Note: IAM managed policies cap at 6144 chars —
342
+ if the union outgrows that, create_policy_version raises and the surplus
343
+ must be pruned manually.
344
+ """
298
345
  policy = retryable_call(iam_client.get_policy, PolicyArn=policy_arn)["Policy"]
299
346
  current_version = retryable_call(
300
347
  iam_client.get_policy_version,
@@ -303,7 +350,9 @@ def _sync_managed_policy_document(iam_client, policy_arn: str, policy_document:
303
350
  )["PolicyVersion"]
304
351
 
305
352
  current_document = _normalize_policy_document(current_version["Document"])
306
- desired_document = _normalize_policy_document(policy_document)
353
+ desired_document = _merge_policy_statements(
354
+ current_document, _normalize_policy_document(policy_document)
355
+ )
307
356
  if json.dumps(current_document, sort_keys=True) == json.dumps(desired_document, sort_keys=True):
308
357
  return
309
358
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: velocity-python
3
- Version: 0.1.81
3
+ Version: 0.1.83
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
@@ -215,3 +215,106 @@ def test_update_custom_redirect_rules_serves_static_html_and_jpeg():
215
215
  spa_rewrite = call["customRules"][1]["source"]
216
216
  for ext in ("html", "jpeg", "jpg", "css", "js"):
217
217
  assert f"|{ext}|" in f"|{spa_rewrite}|".replace("(", "|").replace(")", "|"), ext
218
+
219
+
220
+ class FakeIamClient:
221
+ """Minimal IAM stub for _sync_managed_policy_document tests."""
222
+
223
+ class exceptions:
224
+ class NoSuchEntityException(Exception):
225
+ pass
226
+
227
+ def __init__(self, current_document):
228
+ self._document = current_document
229
+ self.created_versions = []
230
+
231
+ def get_policy(self, PolicyArn):
232
+ return {
233
+ "Policy": {
234
+ "PolicyName": PolicyArn.rsplit("/", 1)[-1],
235
+ "DefaultVersionId": "v1",
236
+ }
237
+ }
238
+
239
+ def get_policy_version(self, PolicyArn, VersionId):
240
+ return {"PolicyVersion": {"Document": self._document}}
241
+
242
+ def list_policy_versions(self, PolicyArn):
243
+ return {"Versions": [{"IsDefaultVersion": True, "VersionId": "v1", "CreateDate": 0}]}
244
+
245
+ def create_policy_version(self, PolicyArn, PolicyDocument, SetAsDefault):
246
+ import json as _json
247
+
248
+ self.created_versions.append(_json.loads(PolicyDocument))
249
+ return {}
250
+
251
+
252
+ def _stmt(actions, resource, effect="Allow"):
253
+ return {"Effect": effect, "Action": actions, "Resource": resource}
254
+
255
+
256
+ def test_sync_managed_policy_preserves_existing_statements(monkeypatch):
257
+ from velocity.aws import amplify_build
258
+
259
+ monkeypatch.setattr(amplify_build.time, "sleep", lambda *_: None)
260
+ manual_grant = _stmt(["s3:PutObject"], "arn:aws:s3:::client-uploads/*")
261
+ current = {"Version": "2012-10-17", "Statement": [manual_grant]}
262
+ desired = {"Version": "2012-10-17", "Statement": [_stmt(["ssm:GetParameter"], "*")]}
263
+
264
+ iam = FakeIamClient(current)
265
+ amplify_build._sync_managed_policy_document(iam, "arn:aws:iam::1:policy/p", desired)
266
+
267
+ assert len(iam.created_versions) == 1
268
+ written = iam.created_versions[0]["Statement"]
269
+ assert manual_grant in written, "manually-added grant must survive the sync"
270
+ assert _stmt(["ssm:GetParameter"], "*") in written
271
+
272
+
273
+ def test_sync_managed_policy_noop_when_all_desired_present(monkeypatch):
274
+ from velocity.aws import amplify_build
275
+
276
+ monkeypatch.setattr(amplify_build.time, "sleep", lambda *_: None)
277
+ shared = _stmt(["ssm:GetParameter"], "*")
278
+ extra = _stmt(["s3:GetObject"], "arn:aws:s3:::other-apps-bucket/*")
279
+ current = {"Version": "2012-10-17", "Statement": [shared, extra]}
280
+ desired = {"Version": "2012-10-17", "Statement": [shared]}
281
+
282
+ iam = FakeIamClient(current)
283
+ amplify_build._sync_managed_policy_document(iam, "arn:aws:iam::1:policy/p", desired)
284
+
285
+ assert iam.created_versions == [], "no version churn when nothing new to add"
286
+
287
+
288
+ def test_sync_managed_policy_dedupes_scalar_vs_list_forms(monkeypatch):
289
+ from velocity.aws import amplify_build
290
+
291
+ monkeypatch.setattr(amplify_build.time, "sleep", lambda *_: None)
292
+ current = {
293
+ "Version": "2012-10-17",
294
+ "Statement": [{"Effect": "Allow", "Action": "s3:GetObject", "Resource": "arn:aws:s3:::b/*"}],
295
+ }
296
+ desired = {
297
+ "Version": "2012-10-17",
298
+ "Statement": [{"Effect": "Allow", "Action": ["s3:GetObject"], "Resource": ["arn:aws:s3:::b/*"]}],
299
+ }
300
+
301
+ iam = FakeIamClient(current)
302
+ amplify_build._sync_managed_policy_document(iam, "arn:aws:iam::1:policy/p", desired)
303
+
304
+ assert iam.created_versions == [], "scalar and list forms are the same statement"
305
+
306
+
307
+ def test_merge_policy_statements_never_removes():
308
+ from velocity.aws.amplify_build import _merge_policy_statements
309
+
310
+ current = {
311
+ "Version": "2012-10-17",
312
+ "Statement": [_stmt(["a:One"], "*"), _stmt(["b:Two"], "arn:x")],
313
+ }
314
+ desired = {"Version": "2012-10-17", "Statement": [_stmt(["c:Three"], "*")]}
315
+
316
+ merged = _merge_policy_statements(current, desired)
317
+
318
+ assert merged["Statement"][:2] == current["Statement"]
319
+ assert _stmt(["c:Three"], "*") in merged["Statement"]
320
+ assert len(merged["Statement"]) == 3