velocity-python 0.1.14__tar.gz → 0.1.16__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 (188) hide show
  1. {velocity_python-0.1.14/src/velocity_python.egg-info → velocity_python-0.1.16}/PKG-INFO +1 -1
  2. {velocity_python-0.1.14 → velocity_python-0.1.16}/pyproject.toml +1 -1
  3. {velocity_python-0.1.14 → velocity_python-0.1.16}/src/velocity/__init__.py +2 -3
  4. {velocity_python-0.1.14 → velocity_python-0.1.16}/src/velocity/misc/pdf.py +3 -1
  5. {velocity_python-0.1.14 → velocity_python-0.1.16/src/velocity_python.egg-info}/PKG-INFO +1 -1
  6. {velocity_python-0.1.14 → velocity_python-0.1.16}/src/velocity_python.egg-info/SOURCES.txt +3 -15
  7. velocity_python-0.1.14/src/velocity/app/formbuilder/__init__.py +0 -1
  8. velocity_python-0.1.14/src/velocity/app/formbuilder/reshaper.py +0 -201
  9. velocity_python-0.1.14/src/velocity/app/invoices.py +0 -0
  10. velocity_python-0.1.14/src/velocity/app/orders.py +0 -179
  11. velocity_python-0.1.14/src/velocity/app/payments.py +0 -0
  12. velocity_python-0.1.14/src/velocity/app/purchase_orders.py +0 -0
  13. velocity_python-0.1.14/src/velocity/app/tests/__init__.py +0 -1
  14. velocity_python-0.1.14/src/velocity/app/validators/__init__.py +0 -1
  15. velocity_python-0.1.14/src/velocity/app/validators/formbuilder_template.py +0 -204
  16. velocity_python-0.1.14/src/velocity/misc/__init__.py +0 -0
  17. velocity_python-0.1.14/tests/test_formbuilder_reshaper.py +0 -315
  18. velocity_python-0.1.14/tests/test_formbuilder_template_validator.py +0 -240
  19. {velocity_python-0.1.14 → velocity_python-0.1.16}/LICENSE +0 -0
  20. {velocity_python-0.1.14 → velocity_python-0.1.16}/README.md +0 -0
  21. {velocity_python-0.1.14 → velocity_python-0.1.16}/setup.cfg +0 -0
  22. {velocity_python-0.1.14 → velocity_python-0.1.16}/src/velocity/aws/__init__.py +0 -0
  23. {velocity_python-0.1.14 → velocity_python-0.1.16}/src/velocity/aws/amplify.py +0 -0
  24. {velocity_python-0.1.14 → velocity_python-0.1.16}/src/velocity/aws/amplify_build.py +0 -0
  25. {velocity_python-0.1.14 → velocity_python-0.1.16}/src/velocity/aws/handlers/__init__.py +0 -0
  26. {velocity_python-0.1.14 → velocity_python-0.1.16}/src/velocity/aws/handlers/base_handler.py +0 -0
  27. {velocity_python-0.1.14 → velocity_python-0.1.16}/src/velocity/aws/handlers/context.py +0 -0
  28. {velocity_python-0.1.14 → velocity_python-0.1.16}/src/velocity/aws/handlers/context_factory.py +0 -0
  29. {velocity_python-0.1.14 → velocity_python-0.1.16}/src/velocity/aws/handlers/exceptions.py +0 -0
  30. {velocity_python-0.1.14 → velocity_python-0.1.16}/src/velocity/aws/handlers/lambda_handler.py +0 -0
  31. {velocity_python-0.1.14 → velocity_python-0.1.16}/src/velocity/aws/handlers/mixins/__init__.py +0 -0
  32. {velocity_python-0.1.14 → velocity_python-0.1.16}/src/velocity/aws/handlers/mixins/data_service.py +0 -0
  33. {velocity_python-0.1.14 → velocity_python-0.1.16}/src/velocity/aws/handlers/mixins/web_handler.py +0 -0
  34. {velocity_python-0.1.14 → velocity_python-0.1.16}/src/velocity/aws/handlers/perf.py +0 -0
  35. {velocity_python-0.1.14 → velocity_python-0.1.16}/src/velocity/aws/handlers/response.py +0 -0
  36. {velocity_python-0.1.14 → velocity_python-0.1.16}/src/velocity/aws/handlers/sqs_handler.py +0 -0
  37. {velocity_python-0.1.14 → velocity_python-0.1.16}/src/velocity/aws/tests/__init__.py +0 -0
  38. {velocity_python-0.1.14 → velocity_python-0.1.16}/src/velocity/aws/tests/test_base_handler_error_response.py +0 -0
  39. {velocity_python-0.1.14 → velocity_python-0.1.16}/src/velocity/aws/tests/test_lambda_handler_json_serialization.py +0 -0
  40. {velocity_python-0.1.14 → velocity_python-0.1.16}/src/velocity/aws/tests/test_response.py +0 -0
  41. {velocity_python-0.1.14 → velocity_python-0.1.16}/src/velocity/db/__init__.py +0 -0
  42. {velocity_python-0.1.14/src/velocity/app → velocity_python-0.1.16/src/velocity/db/core}/__init__.py +0 -0
  43. {velocity_python-0.1.14 → velocity_python-0.1.16}/src/velocity/db/core/async_support.py +0 -0
  44. {velocity_python-0.1.14 → velocity_python-0.1.16}/src/velocity/db/core/column.py +0 -0
  45. {velocity_python-0.1.14 → velocity_python-0.1.16}/src/velocity/db/core/database.py +0 -0
  46. {velocity_python-0.1.14 → velocity_python-0.1.16}/src/velocity/db/core/decorators.py +0 -0
  47. {velocity_python-0.1.14 → velocity_python-0.1.16}/src/velocity/db/core/engine.py +0 -0
  48. {velocity_python-0.1.14 → velocity_python-0.1.16}/src/velocity/db/core/result.py +0 -0
  49. {velocity_python-0.1.14 → velocity_python-0.1.16}/src/velocity/db/core/row.py +0 -0
  50. {velocity_python-0.1.14 → velocity_python-0.1.16}/src/velocity/db/core/sequence.py +0 -0
  51. {velocity_python-0.1.14 → velocity_python-0.1.16}/src/velocity/db/core/table.py +0 -0
  52. {velocity_python-0.1.14 → velocity_python-0.1.16}/src/velocity/db/core/transaction.py +0 -0
  53. {velocity_python-0.1.14 → velocity_python-0.1.16}/src/velocity/db/core/view.py +0 -0
  54. {velocity_python-0.1.14 → velocity_python-0.1.16}/src/velocity/db/exceptions.py +0 -0
  55. {velocity_python-0.1.14 → velocity_python-0.1.16}/src/velocity/db/migrations.py +0 -0
  56. {velocity_python-0.1.14/src/velocity/db/core → velocity_python-0.1.16/src/velocity/db/servers}/__init__.py +0 -0
  57. {velocity_python-0.1.14 → velocity_python-0.1.16}/src/velocity/db/servers/base/__init__.py +0 -0
  58. {velocity_python-0.1.14 → velocity_python-0.1.16}/src/velocity/db/servers/base/initializer.py +0 -0
  59. {velocity_python-0.1.14 → velocity_python-0.1.16}/src/velocity/db/servers/base/operators.py +0 -0
  60. {velocity_python-0.1.14 → velocity_python-0.1.16}/src/velocity/db/servers/base/sql.py +0 -0
  61. {velocity_python-0.1.14 → velocity_python-0.1.16}/src/velocity/db/servers/base/types.py +0 -0
  62. {velocity_python-0.1.14 → velocity_python-0.1.16}/src/velocity/db/servers/mysql/__init__.py +0 -0
  63. {velocity_python-0.1.14 → velocity_python-0.1.16}/src/velocity/db/servers/mysql/operators.py +0 -0
  64. {velocity_python-0.1.14 → velocity_python-0.1.16}/src/velocity/db/servers/mysql/reserved.py +0 -0
  65. {velocity_python-0.1.14 → velocity_python-0.1.16}/src/velocity/db/servers/mysql/sql.py +0 -0
  66. {velocity_python-0.1.14 → velocity_python-0.1.16}/src/velocity/db/servers/mysql/types.py +0 -0
  67. {velocity_python-0.1.14 → velocity_python-0.1.16}/src/velocity/db/servers/postgres/__init__.py +0 -0
  68. {velocity_python-0.1.14 → velocity_python-0.1.16}/src/velocity/db/servers/postgres/operators.py +0 -0
  69. {velocity_python-0.1.14 → velocity_python-0.1.16}/src/velocity/db/servers/postgres/reserved.py +0 -0
  70. {velocity_python-0.1.14 → velocity_python-0.1.16}/src/velocity/db/servers/postgres/sql.py +0 -0
  71. {velocity_python-0.1.14 → velocity_python-0.1.16}/src/velocity/db/servers/postgres/types.py +0 -0
  72. {velocity_python-0.1.14 → velocity_python-0.1.16}/src/velocity/db/servers/sqlite/__init__.py +0 -0
  73. {velocity_python-0.1.14 → velocity_python-0.1.16}/src/velocity/db/servers/sqlite/operators.py +0 -0
  74. {velocity_python-0.1.14 → velocity_python-0.1.16}/src/velocity/db/servers/sqlite/reserved.py +0 -0
  75. {velocity_python-0.1.14 → velocity_python-0.1.16}/src/velocity/db/servers/sqlite/sql.py +0 -0
  76. {velocity_python-0.1.14 → velocity_python-0.1.16}/src/velocity/db/servers/sqlite/types.py +0 -0
  77. {velocity_python-0.1.14 → velocity_python-0.1.16}/src/velocity/db/servers/sqlserver/__init__.py +0 -0
  78. {velocity_python-0.1.14 → velocity_python-0.1.16}/src/velocity/db/servers/sqlserver/operators.py +0 -0
  79. {velocity_python-0.1.14 → velocity_python-0.1.16}/src/velocity/db/servers/sqlserver/reserved.py +0 -0
  80. {velocity_python-0.1.14 → velocity_python-0.1.16}/src/velocity/db/servers/sqlserver/sql.py +0 -0
  81. {velocity_python-0.1.14 → velocity_python-0.1.16}/src/velocity/db/servers/sqlserver/types.py +0 -0
  82. {velocity_python-0.1.14 → velocity_python-0.1.16}/src/velocity/db/servers/tablehelper.py +0 -0
  83. {velocity_python-0.1.14 → velocity_python-0.1.16}/src/velocity/db/tests/__init__.py +0 -0
  84. {velocity_python-0.1.14 → velocity_python-0.1.16}/src/velocity/db/tests/common_db_test.py +0 -0
  85. {velocity_python-0.1.14 → velocity_python-0.1.16}/src/velocity/db/tests/postgres/__init__.py +0 -0
  86. {velocity_python-0.1.14 → velocity_python-0.1.16}/src/velocity/db/tests/postgres/common.py +0 -0
  87. {velocity_python-0.1.14 → velocity_python-0.1.16}/src/velocity/db/tests/postgres/test_column.py +0 -0
  88. {velocity_python-0.1.14 → velocity_python-0.1.16}/src/velocity/db/tests/postgres/test_connections.py +0 -0
  89. {velocity_python-0.1.14 → velocity_python-0.1.16}/src/velocity/db/tests/postgres/test_database.py +0 -0
  90. {velocity_python-0.1.14 → velocity_python-0.1.16}/src/velocity/db/tests/postgres/test_engine.py +0 -0
  91. {velocity_python-0.1.14 → velocity_python-0.1.16}/src/velocity/db/tests/postgres/test_general_usage.py +0 -0
  92. {velocity_python-0.1.14 → velocity_python-0.1.16}/src/velocity/db/tests/postgres/test_imports.py +0 -0
  93. {velocity_python-0.1.14 → velocity_python-0.1.16}/src/velocity/db/tests/postgres/test_result.py +0 -0
  94. {velocity_python-0.1.14 → velocity_python-0.1.16}/src/velocity/db/tests/postgres/test_row.py +0 -0
  95. {velocity_python-0.1.14 → velocity_python-0.1.16}/src/velocity/db/tests/postgres/test_row_comprehensive.py +0 -0
  96. {velocity_python-0.1.14 → velocity_python-0.1.16}/src/velocity/db/tests/postgres/test_schema_locking.py +0 -0
  97. {velocity_python-0.1.14 → velocity_python-0.1.16}/src/velocity/db/tests/postgres/test_schema_locking_unit.py +0 -0
  98. {velocity_python-0.1.14 → velocity_python-0.1.16}/src/velocity/db/tests/postgres/test_sequence.py +0 -0
  99. {velocity_python-0.1.14 → velocity_python-0.1.16}/src/velocity/db/tests/postgres/test_sql_comprehensive.py +0 -0
  100. {velocity_python-0.1.14 → velocity_python-0.1.16}/src/velocity/db/tests/postgres/test_table.py +0 -0
  101. {velocity_python-0.1.14 → velocity_python-0.1.16}/src/velocity/db/tests/postgres/test_table_comprehensive.py +0 -0
  102. {velocity_python-0.1.14 → velocity_python-0.1.16}/src/velocity/db/tests/postgres/test_transaction.py +0 -0
  103. {velocity_python-0.1.14 → velocity_python-0.1.16}/src/velocity/db/tests/sql/__init__.py +0 -0
  104. {velocity_python-0.1.14 → velocity_python-0.1.16}/src/velocity/db/tests/sql/common.py +0 -0
  105. {velocity_python-0.1.14 → velocity_python-0.1.16}/src/velocity/db/tests/sql/test_postgres_select_advanced.py +0 -0
  106. {velocity_python-0.1.14 → velocity_python-0.1.16}/src/velocity/db/tests/sql/test_postgres_select_variances.py +0 -0
  107. {velocity_python-0.1.14 → velocity_python-0.1.16}/src/velocity/db/tests/test_cursor_rowcount_fix.py +0 -0
  108. {velocity_python-0.1.14 → velocity_python-0.1.16}/src/velocity/db/tests/test_db_utils.py +0 -0
  109. {velocity_python-0.1.14 → velocity_python-0.1.16}/src/velocity/db/tests/test_postgres.py +0 -0
  110. {velocity_python-0.1.14 → velocity_python-0.1.16}/src/velocity/db/tests/test_postgres_unchanged.py +0 -0
  111. {velocity_python-0.1.14 → velocity_python-0.1.16}/src/velocity/db/tests/test_process_error_robustness.py +0 -0
  112. {velocity_python-0.1.14 → velocity_python-0.1.16}/src/velocity/db/tests/test_result_caching.py +0 -0
  113. {velocity_python-0.1.14 → velocity_python-0.1.16}/src/velocity/db/tests/test_result_sql_aware.py +0 -0
  114. {velocity_python-0.1.14 → velocity_python-0.1.16}/src/velocity/db/tests/test_row_get_missing_column.py +0 -0
  115. {velocity_python-0.1.14 → velocity_python-0.1.16}/src/velocity/db/tests/test_schema_locking_initializers.py +0 -0
  116. {velocity_python-0.1.14 → velocity_python-0.1.16}/src/velocity/db/tests/test_schema_locking_simple.py +0 -0
  117. {velocity_python-0.1.14 → velocity_python-0.1.16}/src/velocity/db/tests/test_sql_builder.py +0 -0
  118. {velocity_python-0.1.14 → velocity_python-0.1.16}/src/velocity/db/tests/test_tablehelper.py +0 -0
  119. {velocity_python-0.1.14 → velocity_python-0.1.16}/src/velocity/db/tests/test_view_helper.py +0 -0
  120. {velocity_python-0.1.14 → velocity_python-0.1.16}/src/velocity/db/utils.py +0 -0
  121. {velocity_python-0.1.14 → velocity_python-0.1.16}/src/velocity/logging.py +0 -0
  122. {velocity_python-0.1.14/src/velocity/db/servers → velocity_python-0.1.16/src/velocity/misc}/__init__.py +0 -0
  123. {velocity_python-0.1.14 → velocity_python-0.1.16}/src/velocity/misc/conv/__init__.py +0 -0
  124. {velocity_python-0.1.14 → velocity_python-0.1.16}/src/velocity/misc/conv/iconv.py +0 -0
  125. {velocity_python-0.1.14 → velocity_python-0.1.16}/src/velocity/misc/conv/oconv.py +0 -0
  126. {velocity_python-0.1.14 → velocity_python-0.1.16}/src/velocity/misc/db.py +0 -0
  127. {velocity_python-0.1.14 → velocity_python-0.1.16}/src/velocity/misc/export.py +0 -0
  128. {velocity_python-0.1.14 → velocity_python-0.1.16}/src/velocity/misc/format.py +0 -0
  129. {velocity_python-0.1.14 → velocity_python-0.1.16}/src/velocity/misc/mail.py +0 -0
  130. {velocity_python-0.1.14 → velocity_python-0.1.16}/src/velocity/misc/merge.py +0 -0
  131. {velocity_python-0.1.14 → velocity_python-0.1.16}/src/velocity/misc/tests/__init__.py +0 -0
  132. {velocity_python-0.1.14 → velocity_python-0.1.16}/src/velocity/misc/tests/test_db.py +0 -0
  133. {velocity_python-0.1.14 → velocity_python-0.1.16}/src/velocity/misc/tests/test_fix.py +0 -0
  134. {velocity_python-0.1.14 → velocity_python-0.1.16}/src/velocity/misc/tests/test_format.py +0 -0
  135. {velocity_python-0.1.14 → velocity_python-0.1.16}/src/velocity/misc/tests/test_iconv.py +0 -0
  136. {velocity_python-0.1.14 → velocity_python-0.1.16}/src/velocity/misc/tests/test_merge.py +0 -0
  137. {velocity_python-0.1.14 → velocity_python-0.1.16}/src/velocity/misc/tests/test_oconv.py +0 -0
  138. {velocity_python-0.1.14 → velocity_python-0.1.16}/src/velocity/misc/tests/test_original_error.py +0 -0
  139. {velocity_python-0.1.14 → velocity_python-0.1.16}/src/velocity/misc/tests/test_timer.py +0 -0
  140. {velocity_python-0.1.14 → velocity_python-0.1.16}/src/velocity/misc/timer.py +0 -0
  141. {velocity_python-0.1.14 → velocity_python-0.1.16}/src/velocity/misc/tools.py +0 -0
  142. {velocity_python-0.1.14 → velocity_python-0.1.16}/src/velocity/payment/__init__.py +0 -0
  143. {velocity_python-0.1.14 → velocity_python-0.1.16}/src/velocity/payment/authorizenet_adapter.py +0 -0
  144. {velocity_python-0.1.14 → velocity_python-0.1.16}/src/velocity/payment/base_adapter.py +0 -0
  145. {velocity_python-0.1.14 → velocity_python-0.1.16}/src/velocity/payment/braintree_adapter.py +0 -0
  146. {velocity_python-0.1.14 → velocity_python-0.1.16}/src/velocity/payment/charge_rules.py +0 -0
  147. {velocity_python-0.1.14 → velocity_python-0.1.16}/src/velocity/payment/demo_profiles.py +0 -0
  148. {velocity_python-0.1.14 → velocity_python-0.1.16}/src/velocity/payment/profiles.py +0 -0
  149. {velocity_python-0.1.14 → velocity_python-0.1.16}/src/velocity/payment/router.py +0 -0
  150. {velocity_python-0.1.14 → velocity_python-0.1.16}/src/velocity/payment/stripe_adapter.py +0 -0
  151. {velocity_python-0.1.14 → velocity_python-0.1.16}/src/velocity_python.egg-info/dependency_links.txt +0 -0
  152. {velocity_python-0.1.14 → velocity_python-0.1.16}/src/velocity_python.egg-info/entry_points.txt +0 -0
  153. {velocity_python-0.1.14 → velocity_python-0.1.16}/src/velocity_python.egg-info/requires.txt +0 -0
  154. {velocity_python-0.1.14 → velocity_python-0.1.16}/src/velocity_python.egg-info/top_level.txt +0 -0
  155. {velocity_python-0.1.14 → velocity_python-0.1.16}/tests/test_amplify_build.py +0 -0
  156. {velocity_python-0.1.14 → velocity_python-0.1.16}/tests/test_async_support.py +0 -0
  157. {velocity_python-0.1.14 → velocity_python-0.1.16}/tests/test_batch_operations.py +0 -0
  158. {velocity_python-0.1.14 → velocity_python-0.1.16}/tests/test_concurrency_safety.py +0 -0
  159. {velocity_python-0.1.14 → velocity_python-0.1.16}/tests/test_connection_pool.py +0 -0
  160. {velocity_python-0.1.14 → velocity_python-0.1.16}/tests/test_connection_resilience.py +0 -0
  161. {velocity_python-0.1.14 → velocity_python-0.1.16}/tests/test_decorators.py +0 -0
  162. {velocity_python-0.1.14/src/velocity/app → velocity_python-0.1.16}/tests/test_email_processing.py +0 -0
  163. {velocity_python-0.1.14 → velocity_python-0.1.16}/tests/test_iconv_money_to_cents.py +0 -0
  164. {velocity_python-0.1.14 → velocity_python-0.1.16}/tests/test_lambda_handler.py +0 -0
  165. {velocity_python-0.1.14 → velocity_python-0.1.16}/tests/test_lambda_handler_auth.py +0 -0
  166. {velocity_python-0.1.14 → velocity_python-0.1.16}/tests/test_mixins_import.py +0 -0
  167. {velocity_python-0.1.14 → velocity_python-0.1.16}/tests/test_n_plus_one.py +0 -0
  168. {velocity_python-0.1.14 → velocity_python-0.1.16}/tests/test_observability.py +0 -0
  169. {velocity_python-0.1.14 → velocity_python-0.1.16}/tests/test_payment_braintree_adapter.py +0 -0
  170. {velocity_python-0.1.14 → velocity_python-0.1.16}/tests/test_payment_demo_profiles.py +0 -0
  171. {velocity_python-0.1.14/src/velocity/app → velocity_python-0.1.16}/tests/test_payment_profile_sorting.py +0 -0
  172. {velocity_python-0.1.14 → velocity_python-0.1.16}/tests/test_payment_profiles.py +0 -0
  173. {velocity_python-0.1.14 → velocity_python-0.1.16}/tests/test_payment_router.py +0 -0
  174. {velocity_python-0.1.14 → velocity_python-0.1.16}/tests/test_payment_stripe_adapter.py +0 -0
  175. {velocity_python-0.1.14 → velocity_python-0.1.16}/tests/test_pdf.py +0 -0
  176. {velocity_python-0.1.14 → velocity_python-0.1.16}/tests/test_prepared_statements.py +0 -0
  177. {velocity_python-0.1.14 → velocity_python-0.1.16}/tests/test_psycopg3_upgrade.py +0 -0
  178. {velocity_python-0.1.14 → velocity_python-0.1.16}/tests/test_query_cache.py +0 -0
  179. {velocity_python-0.1.14 → velocity_python-0.1.16}/tests/test_row_batch_update.py +0 -0
  180. {velocity_python-0.1.14 → velocity_python-0.1.16}/tests/test_row_cache_staleness.py +0 -0
  181. {velocity_python-0.1.14 → velocity_python-0.1.16}/tests/test_row_dirty_tracking.py +0 -0
  182. {velocity_python-0.1.14 → velocity_python-0.1.16}/tests/test_schema_migrations.py +0 -0
  183. {velocity_python-0.1.14 → velocity_python-0.1.16}/tests/test_security_hardening.py +0 -0
  184. {velocity_python-0.1.14/src/velocity/app → velocity_python-0.1.16}/tests/test_spreadsheet_functions.py +0 -0
  185. {velocity_python-0.1.14 → velocity_python-0.1.16}/tests/test_sqs_per_record_transactions.py +0 -0
  186. {velocity_python-0.1.14 → velocity_python-0.1.16}/tests/test_sys_modified_count_postgres_demo.py +0 -0
  187. {velocity_python-0.1.14 → velocity_python-0.1.16}/tests/test_table_alter.py +0 -0
  188. {velocity_python-0.1.14 → velocity_python-0.1.16}/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.14
3
+ Version: 0.1.16
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.14"
7
+ version = "0.1.16"
8
8
  authors = [
9
9
  { name="Velocity Team", email="info@codeclubs.org" },
10
10
  ]
@@ -1,12 +1,11 @@
1
- __version__ = version = "0.1.14"
1
+ __version__ = version = "0.1.16"
2
2
 
3
3
  import importlib as _importlib
4
4
 
5
5
  from . import db
6
6
  from . import misc
7
- from . import app
8
7
 
9
- __all__ = ["aws", "db", "misc", "app"]
8
+ __all__ = ["aws", "db", "misc"]
10
9
 
11
10
  _LAZY_SUBMODULES = {"aws"}
12
11
 
@@ -46,7 +46,9 @@ if "AWS_LAMBDA_FUNCTION_NAME" in os.environ:
46
46
 
47
47
  try:
48
48
  import weasyprint
49
- except ImportError:
49
+ except (ImportError, OSError):
50
+ # OSError: WeasyPrint's ffi.py raises OSError when native libs
51
+ # (libgobject, libpango, etc.) cannot be loaded via cffi.dlopen().
50
52
  weasyprint = None # type: ignore[assignment]
51
53
 
52
54
  _DEFAULT_BODY_CSS = """\
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: velocity-python
3
- Version: 0.1.14
3
+ Version: 0.1.16
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
@@ -3,19 +3,6 @@ README.md
3
3
  pyproject.toml
4
4
  src/velocity/__init__.py
5
5
  src/velocity/logging.py
6
- src/velocity/app/__init__.py
7
- src/velocity/app/invoices.py
8
- src/velocity/app/orders.py
9
- src/velocity/app/payments.py
10
- src/velocity/app/purchase_orders.py
11
- src/velocity/app/formbuilder/__init__.py
12
- src/velocity/app/formbuilder/reshaper.py
13
- src/velocity/app/tests/__init__.py
14
- src/velocity/app/tests/test_email_processing.py
15
- src/velocity/app/tests/test_payment_profile_sorting.py
16
- src/velocity/app/tests/test_spreadsheet_functions.py
17
- src/velocity/app/validators/__init__.py
18
- src/velocity/app/validators/formbuilder_template.py
19
6
  src/velocity/aws/__init__.py
20
7
  src/velocity/aws/amplify.py
21
8
  src/velocity/aws/amplify_build.py
@@ -158,8 +145,7 @@ tests/test_concurrency_safety.py
158
145
  tests/test_connection_pool.py
159
146
  tests/test_connection_resilience.py
160
147
  tests/test_decorators.py
161
- tests/test_formbuilder_reshaper.py
162
- tests/test_formbuilder_template_validator.py
148
+ tests/test_email_processing.py
163
149
  tests/test_iconv_money_to_cents.py
164
150
  tests/test_lambda_handler.py
165
151
  tests/test_lambda_handler_auth.py
@@ -168,6 +154,7 @@ tests/test_n_plus_one.py
168
154
  tests/test_observability.py
169
155
  tests/test_payment_braintree_adapter.py
170
156
  tests/test_payment_demo_profiles.py
157
+ tests/test_payment_profile_sorting.py
171
158
  tests/test_payment_profiles.py
172
159
  tests/test_payment_router.py
173
160
  tests/test_payment_stripe_adapter.py
@@ -180,6 +167,7 @@ tests/test_row_cache_staleness.py
180
167
  tests/test_row_dirty_tracking.py
181
168
  tests/test_schema_migrations.py
182
169
  tests/test_security_hardening.py
170
+ tests/test_spreadsheet_functions.py
183
171
  tests/test_sqs_per_record_transactions.py
184
172
  tests/test_sys_modified_count_postgres_demo.py
185
173
  tests/test_table_alter.py
@@ -1 +0,0 @@
1
- """velocity.app.formbuilder — shared logic for form_builder_template records."""
@@ -1,201 +0,0 @@
1
- """velocity.app.formbuilder.reshaper
2
-
3
- Reshape a raw ``form_builder_template`` database row into the public ``fb``
4
- payload structure as produced by ``DonateMainEvents.OnActionGetFormBuilder``.
5
-
6
- The single public entry-point is :func:`reshape_formbuilder_template`. It is
7
- a **pure function** — the input is deep-copied and never mutated.
8
-
9
- Payment tokens, reCAPTCHA keys, and live thermometer totals are **not**
10
- included; those are runtime secrets and database query results that the caller
11
- must add separately (as DonateMain does in
12
- ``OnActionGetFormBuilder``). The returned dict is safe to serialise and
13
- return as a preview payload.
14
-
15
- Usage::
16
-
17
- from velocity.app.formbuilder.reshaper import reshape_formbuilder_template
18
-
19
- fb = reshape_formbuilder_template(template_row.to_dict())
20
- """
21
-
22
- import ast
23
- import copy
24
- from typing import Any, Dict, Optional
25
-
26
-
27
- # ---------------------------------------------------------------------------
28
- # Internal per-metric / per-donation helpers
29
- # ---------------------------------------------------------------------------
30
-
31
- def _parse_key_value_string(raw: Optional[str]) -> Dict[str, Any]:
32
- """Parse a ``"key1: val1, key2: val2"`` string into a dict.
33
-
34
- Wraps the string in braces and calls ``ast.literal_eval``, exactly as the
35
- original DonateMain ``getMetric`` / ``getDonation`` functions do.
36
- Returns an empty dict on failure so a bad value never crashes the reshaper.
37
- """
38
- if not raw:
39
- return {}
40
- try:
41
- return ast.literal_eval("{" + raw + "}")
42
- except Exception:
43
- return {}
44
-
45
-
46
- def _extract_metric(count: int, data: Dict[str, Any]) -> Dict[str, Any]:
47
- """Extract metric_{count}_* fields from *data* (mutates *data*).
48
-
49
- Returns the nested metric dict when the metric has a label and is not
50
- hidden, otherwise returns ``{}``. Either way all flat metric_N_* keys
51
- are removed from *data*.
52
- """
53
- prefix = f"metric_{count}_"
54
- flat_keys = [
55
- "header", "image", "label", "secondarytext", "helpertext",
56
- "values", "defaultvalue", "show_other", "other_minimum_value",
57
- "orientation",
58
- ]
59
-
60
- is_hidden = data.get(f"{prefix}hide_donation_from_ui")
61
- has_label = data.get(f"{prefix}label")
62
-
63
- if not is_hidden and has_label:
64
- result = {
65
- "header": data.pop(f"{prefix}header", None),
66
- "image": data.pop(f"{prefix}image", None),
67
- "label": data.pop(f"{prefix}label", None),
68
- "secondarytext": data.pop(f"{prefix}secondarytext", None),
69
- "helpertext": data.pop(f"{prefix}helpertext", None),
70
- "values": _parse_key_value_string(data.pop(f"{prefix}values", None)),
71
- "defaultvalue": data.pop(f"{prefix}defaultvalue", None),
72
- "show_other": data.pop(f"{prefix}show_other", ""),
73
- "other_minimum_value": data.pop(f"{prefix}other_minimum_value", ""),
74
- "orientation": data.pop(f"{prefix}orientation", ""),
75
- }
76
- data.pop(f"{prefix}hide_donation_from_ui", None)
77
- return result
78
-
79
- # Strip all flat keys even when hidden / empty
80
- for key in flat_keys:
81
- data.pop(f"{prefix}{key}", None)
82
- data.pop(f"{prefix}hide_donation_from_ui", None)
83
- return {}
84
-
85
-
86
- def _extract_donation(count: int, data: Dict[str, Any]) -> Dict[str, Any]:
87
- """Extract donation_{count}_* fields from *data* (mutates *data*).
88
-
89
- Returns the nested donation dict when the donation has a label and is not
90
- hidden, otherwise returns ``{}``. Either way all flat donation_N_* keys
91
- are removed from *data*.
92
- """
93
- prefix = f"donation_{count}_"
94
- flat_keys = [
95
- "header", "image", "html", "label", "secondarytext", "helpertext",
96
- "values", "defaultvalue", "show_other", "other_minimum_value",
97
- "orientation", "dropdown", "dropdown_label",
98
- ]
99
-
100
- is_hidden = data.get(f"{prefix}hide_donation_from_ui")
101
- has_label = data.get(f"{prefix}label")
102
-
103
- if not is_hidden and has_label:
104
- result = {
105
- "header": data.pop(f"{prefix}header", None),
106
- "image": data.pop(f"{prefix}image", None),
107
- "html": data.pop(f"{prefix}html", None),
108
- "label": data.pop(f"{prefix}label", None),
109
- "secondarytext": data.pop(f"{prefix}secondarytext", None),
110
- "helpertext": data.pop(f"{prefix}helpertext", None),
111
- "values": _parse_key_value_string(data.pop(f"{prefix}values", None)),
112
- "defaultvalue": data.pop(f"{prefix}defaultvalue", None),
113
- "show_other": data.pop(f"{prefix}show_other", ""),
114
- "other_minimum_value": data.pop(f"{prefix}other_minimum_value", ""),
115
- "orientation": data.pop(f"{prefix}orientation", ""),
116
- "dropdown": data.pop(f"{prefix}dropdown", None),
117
- "dropdown_label": data.pop(f"{prefix}dropdown_label", None),
118
- }
119
- data.pop(f"{prefix}hide_donation_from_ui", None)
120
- return result
121
-
122
- for key in flat_keys:
123
- data.pop(f"{prefix}{key}", None)
124
- data.pop(f"{prefix}hide_donation_from_ui", None)
125
- return {}
126
-
127
-
128
- # ---------------------------------------------------------------------------
129
- # Public API
130
- # ---------------------------------------------------------------------------
131
-
132
- def reshape_formbuilder_template(raw_row: Dict[str, Any]) -> Dict[str, Any]:
133
- """Reshape a raw ``form_builder_template`` DB row into the public ``fb`` dict.
134
-
135
- This replicates exactly what ``DonateMainEvents.OnActionGetFormBuilder``
136
- does to reshape the flat database row before returning it to the browser,
137
- without the live DB queries (thermometer totals) or runtime secrets
138
- (payment tokens, reCAPTCHA keys).
139
-
140
- The caller is responsible for:
141
-
142
- - Passing in a plain Python dict (call ``.to_dict()`` on a velocity DB
143
- row first so that Decimal and datetime values are already serialisable).
144
- - Optionally adding ``fb["thermometer"]`` / ``fb["rival_thermometer"]``
145
- after the call if live totals are desired.
146
-
147
- Returns a new dict; the input is never mutated.
148
-
149
- Example::
150
-
151
- row = tx.table("form_builder_template").one({"sys_id": sys_id})
152
- fb = reshape_formbuilder_template(row.to_dict())
153
- """
154
- fb = copy.deepcopy(raw_row)
155
-
156
- fb["metrics"] = {
157
- f"metric_{i}": _extract_metric(i, fb) for i in range(1, 10)
158
- }
159
- fb["donations"] = {
160
- f"donation_{i}": _extract_donation(i, fb) for i in range(1, 10)
161
- }
162
-
163
- # Expose the primary key under the public name used by DonateMain
164
- fb["_num_entries"] = fb.get("sys_id")
165
-
166
- # Strip internal / private fields
167
- for key in list(fb.keys()):
168
- if key.startswith("sys_"):
169
- del fb[key]
170
-
171
- for key in (
172
- # UI-only computed column (row counter) — never a real DB column
173
- "row_number",
174
- "url_slug",
175
- "url_slug_alternate",
176
- # Administrative / validation metadata — not read by DonateMain frontend
177
- "is_published",
178
- "datetime_last_validated",
179
- "last_validation_result",
180
- "last_validation_reason",
181
- # Backend-only: security / fraud prevention
182
- "whitelist_end_date",
183
- "recaptcha_version",
184
- "recaptcha_v3_score_threshold",
185
- # Backend-only: routing / campaign metadata
186
- "campaign",
187
- "sub_campaign",
188
- # Backend-only: email receipts (server-side sending only)
189
- "receipt_from_address",
190
- "receipt_subject",
191
- "receipt_body_text",
192
- "mail_bcc",
193
- # Backend-only: rally out-of-band receipts
194
- "rally_receipt_from_address",
195
- "rally_receipt_subject",
196
- "rally_receipt_body_text",
197
- "rally_mail_bcc",
198
- ):
199
- fb.pop(key, None)
200
-
201
- return fb
File without changes
@@ -1,179 +0,0 @@
1
- import datetime
2
- import pprint
3
- import velocity.db
4
-
5
- engine = velocity.db.postgres.initialize()
6
- REQUIRED = object()
7
-
8
-
9
- @engine.transaction
10
- class Order:
11
- SCHEMA = {
12
- "headers": {
13
- "customer_email": REQUIRED,
14
- "order_date": REQUIRED,
15
- "order_type": REQUIRED,
16
- },
17
- "lineitems": {
18
- "sku": REQUIRED,
19
- "qty": REQUIRED,
20
- "price": REQUIRED,
21
- },
22
- "lineitems_supp": {
23
- "note": str,
24
- },
25
- }
26
-
27
- DEFAULTS = {
28
- "headers": {
29
- "order_date": lambda: datetime.date.today(),
30
- "effective_date": lambda: datetime.date.today(),
31
- }
32
- }
33
-
34
- def __init__(self, order_id=None):
35
- self.order_id = order_id
36
- self.headers = {}
37
- self.lineitems = {}
38
- self.lineitems_supp = {}
39
-
40
- def __repr__(self):
41
- return f"Order(order_id={self.order_id}, headers={pprint.pformat(self.headers)}, lineitems={pprint.pformat(self.lineitems)}, lineitems_supp={pprint.pformat(self.lineitems_supp)})"
42
-
43
- def exists(self, tx):
44
- if not self.order_id:
45
- raise ValueError("order_id must be set to check existence")
46
- return tx.table("orders").find(self.order_id)
47
-
48
- def __bool__(self):
49
- return bool(self.order_id) and self.exists(engine.transaction())
50
-
51
- def load(self, tx):
52
- if not self.order_id:
53
- raise ValueError("order_id must be set to load an order")
54
-
55
- order = tx.table("orders").one(self.order_id)
56
- if not order:
57
- raise ValueError(f"Order {self.order_id} not found")
58
-
59
- self.headers = dict(order)
60
-
61
- items = (
62
- tx.table("order_lineitems")
63
- .select(where={"order_id": self.order_id}, orderby="line_number")
64
- .all()
65
- )
66
- for idx, row in enumerate(items):
67
- self.lineitems[idx] = dict(row)
68
-
69
- supps = (
70
- tx.table("order_lineitems_supp")
71
- .select(where={"order_id": self.order_id}, orderby="line_number")
72
- .all()
73
- )
74
- for idx, row in enumerate(supps):
75
- self.lineitems_supp[idx] = dict(row)
76
-
77
- def update_header(self, key, value):
78
- self.headers[key] = value
79
-
80
- def add_lineitem(self, data: dict, supp_data: dict = None):
81
- index = len(self.lineitems)
82
- self.lineitems[index] = data
83
- self.lineitems_supp[index] = supp_data or {}
84
-
85
- def update_lineitem(self, index: int, data: dict = None, supp_data: dict = None):
86
- if index not in self.lineitems:
87
- raise IndexError(f"No line item at index {index}")
88
- if data:
89
- self.lineitems[index].update(data)
90
- if supp_data is not None:
91
- self.lineitems_supp[index].update(supp_data)
92
-
93
- def delete_lineitem(self, index: int):
94
- if index not in self.lineitems:
95
- raise IndexError(f"No line item at index {index}")
96
- del self.lineitems[index]
97
- if index in self.lineitems_supp:
98
- del self.lineitems_supp[index]
99
- self._reindex_lineitems()
100
-
101
- def _reindex_lineitems(self):
102
- """Re-index lineitems and supplemental data after deletion."""
103
- new_items = {}
104
- new_supps = {}
105
- for i, key in enumerate(sorted(self.lineitems)):
106
- new_items[i] = self.lineitems[key]
107
- new_supps[i] = self.lineitems_supp.get(key, {})
108
- self.lineitems = new_items
109
- self.lineitems_supp = new_supps
110
-
111
- def _apply_defaults(self):
112
- for section, defaults in self.DEFAULTS.items():
113
- target = getattr(self, section)
114
- for key, default in defaults.items():
115
- if key not in target:
116
- target[key] = default() if callable(default) else default
117
-
118
- def _validate(self):
119
- self._apply_defaults()
120
-
121
- for key, requirement in self.SCHEMA["headers"].items():
122
- if requirement is REQUIRED and key not in self.headers:
123
- raise ValueError(f"Missing required header field: {key}")
124
- if (
125
- key in self.headers
126
- and requirement is not REQUIRED
127
- and not isinstance(self.headers[key], requirement)
128
- ):
129
- raise TypeError(
130
- f"Header field '{key}' must be of type {requirement.__name__}"
131
- )
132
-
133
- for idx, item in self.lineitems.items():
134
- for key, requirement in self.SCHEMA["lineitems"].items():
135
- if requirement is REQUIRED and key not in item:
136
- raise ValueError(f"Line item {idx} missing required field: {key}")
137
-
138
- for idx, supp in self.lineitems_supp.items():
139
- for key, expected in self.SCHEMA["lineitems_supp"].items():
140
- if key in supp and not isinstance(supp[key], expected):
141
- raise TypeError(
142
- f"Supplemental field '{key}' in item {idx} must be of type {expected.__name__}"
143
- )
144
-
145
- def persist(self, tx):
146
- self._validate()
147
-
148
- if self.order_id:
149
- tx.table("orders").update(self.headers, self.order_id)
150
- else:
151
- record = tx.table("orders").new(self.headers)
152
- self.order_id = record["sys_id"]
153
-
154
- tx.table("order_lineitems").delete(where={"order_id": self.order_id})
155
- tx.table("order_lineitems_supp").delete(where={"order_id": self.order_id})
156
-
157
- for index in sorted(self.lineitems):
158
- tx.table("order_lineitems").insert(
159
- {
160
- "order_id": self.order_id,
161
- "line_number": index,
162
- **self.lineitems[index],
163
- }
164
- )
165
- tx.table("order_lineitems_supp").insert(
166
- {
167
- "order_id": self.order_id,
168
- "line_number": index,
169
- **self.lineitems_supp.get(index, {}),
170
- }
171
- )
172
-
173
- def to_dict(self):
174
- return {
175
- "order_id": self.order_id,
176
- "headers": self.headers,
177
- "lineitems": self.lineitems,
178
- "lineitems_supp": self.lineitems_supp,
179
- }
File without changes
@@ -1 +0,0 @@
1
- # App module tests
@@ -1 +0,0 @@
1
- """velocity.app.validators — domain validators for shared application entities."""