velocity-python 0.0.234__tar.gz → 0.0.236__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {velocity_python-0.0.234/src/velocity_python.egg-info → velocity_python-0.0.236}/PKG-INFO +1 -1
- {velocity_python-0.0.234 → velocity_python-0.0.236}/pyproject.toml +1 -1
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/__init__.py +1 -1
- velocity_python-0.0.236/src/velocity/app/validators/__init__.py +1 -0
- velocity_python-0.0.236/src/velocity/app/validators/formbuilder_template.py +204 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236/src/velocity_python.egg-info}/PKG-INFO +1 -1
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity_python.egg-info/SOURCES.txt +3 -0
- velocity_python-0.0.236/tests/test_formbuilder_template_validator.py +240 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/LICENSE +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/README.md +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/setup.cfg +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/app/__init__.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/app/invoices.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/app/orders.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/app/payments.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/app/purchase_orders.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/app/tests/__init__.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/app/tests/test_email_processing.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/app/tests/test_payment_profile_sorting.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/app/tests/test_spreadsheet_functions.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/aws/__init__.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/aws/amplify.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/aws/amplify_build.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/aws/handlers/__init__.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/aws/handlers/base_handler.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/aws/handlers/context.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/aws/handlers/context_factory.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/aws/handlers/exceptions.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/aws/handlers/lambda_handler.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/aws/handlers/mixins/__init__.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/aws/handlers/mixins/data_service.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/aws/handlers/mixins/web_handler.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/aws/handlers/perf.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/aws/handlers/response.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/aws/handlers/sqs_handler.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/aws/tests/__init__.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/aws/tests/test_base_handler_error_response.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/aws/tests/test_lambda_handler_json_serialization.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/aws/tests/test_response.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/db/__init__.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/db/core/__init__.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/db/core/column.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/db/core/database.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/db/core/decorators.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/db/core/engine.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/db/core/result.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/db/core/row.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/db/core/sequence.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/db/core/table.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/db/core/transaction.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/db/core/view.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/db/exceptions.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/db/servers/__init__.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/db/servers/base/__init__.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/db/servers/base/initializer.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/db/servers/base/operators.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/db/servers/base/sql.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/db/servers/base/types.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/db/servers/mysql/__init__.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/db/servers/mysql/operators.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/db/servers/mysql/reserved.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/db/servers/mysql/sql.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/db/servers/mysql/types.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/db/servers/postgres/__init__.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/db/servers/postgres/operators.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/db/servers/postgres/reserved.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/db/servers/postgres/sql.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/db/servers/postgres/types.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/db/servers/sqlite/__init__.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/db/servers/sqlite/operators.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/db/servers/sqlite/reserved.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/db/servers/sqlite/sql.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/db/servers/sqlite/types.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/db/servers/sqlserver/__init__.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/db/servers/sqlserver/operators.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/db/servers/sqlserver/reserved.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/db/servers/sqlserver/sql.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/db/servers/sqlserver/types.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/db/servers/tablehelper.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/db/tests/__init__.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/db/tests/common_db_test.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/db/tests/postgres/__init__.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/db/tests/postgres/common.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/db/tests/postgres/test_column.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/db/tests/postgres/test_connections.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/db/tests/postgres/test_database.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/db/tests/postgres/test_engine.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/db/tests/postgres/test_general_usage.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/db/tests/postgres/test_imports.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/db/tests/postgres/test_result.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/db/tests/postgres/test_row.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/db/tests/postgres/test_row_comprehensive.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/db/tests/postgres/test_schema_locking.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/db/tests/postgres/test_schema_locking_unit.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/db/tests/postgres/test_sequence.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/db/tests/postgres/test_sql_comprehensive.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/db/tests/postgres/test_table.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/db/tests/postgres/test_table_comprehensive.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/db/tests/postgres/test_transaction.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/db/tests/sql/__init__.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/db/tests/sql/common.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/db/tests/sql/test_postgres_select_advanced.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/db/tests/sql/test_postgres_select_variances.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/db/tests/test_cursor_rowcount_fix.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/db/tests/test_db_utils.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/db/tests/test_postgres.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/db/tests/test_postgres_unchanged.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/db/tests/test_process_error_robustness.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/db/tests/test_result_caching.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/db/tests/test_result_sql_aware.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/db/tests/test_row_get_missing_column.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/db/tests/test_schema_locking_initializers.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/db/tests/test_schema_locking_simple.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/db/tests/test_sql_builder.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/db/tests/test_tablehelper.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/db/tests/test_view_helper.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/db/utils.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/logging.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/misc/__init__.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/misc/conv/__init__.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/misc/conv/iconv.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/misc/conv/oconv.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/misc/db.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/misc/export.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/misc/format.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/misc/mail.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/misc/merge.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/misc/tests/__init__.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/misc/tests/test_db.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/misc/tests/test_fix.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/misc/tests/test_format.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/misc/tests/test_iconv.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/misc/tests/test_merge.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/misc/tests/test_oconv.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/misc/tests/test_original_error.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/misc/tests/test_timer.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/misc/timer.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/misc/tools.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/payment/__init__.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/payment/authorizenet_adapter.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/payment/base_adapter.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/payment/braintree_adapter.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/payment/charge_rules.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/payment/demo_profiles.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/payment/profiles.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/payment/router.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/payment/stripe_adapter.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity_python.egg-info/dependency_links.txt +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity_python.egg-info/requires.txt +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity_python.egg-info/top_level.txt +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/tests/test_amplify_build.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/tests/test_decorators.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/tests/test_iconv_money_to_cents.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/tests/test_lambda_handler.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/tests/test_lambda_handler_auth.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/tests/test_mixins_import.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/tests/test_payment_braintree_adapter.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/tests/test_payment_demo_profiles.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/tests/test_payment_profiles.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/tests/test_payment_router.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/tests/test_payment_stripe_adapter.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/tests/test_sys_modified_count_postgres_demo.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/tests/test_table_alter.py +0 -0
- {velocity_python-0.0.234 → velocity_python-0.0.236}/tests/test_where_clause_validation.py +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""velocity.app.validators — domain validators for shared application entities."""
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
"""Pure-Python validator for form_builder_template dicts.
|
|
2
|
+
|
|
3
|
+
Authoritative location: velocity.app.validators.formbuilder_template
|
|
4
|
+
|
|
5
|
+
Called by:
|
|
6
|
+
- BackOffice before_write hook (rwx/form_builder_template.py)
|
|
7
|
+
- BackOffice CLI: scripts/validate_formbuilder_templates.py
|
|
8
|
+
- DonateMain CLI: scripts/formbuilder_validator.py (shim — imports from here)
|
|
9
|
+
- Tests: velocity-python/tests/app/validators/test_formbuilder_template.py
|
|
10
|
+
BackOffice.demo/tests/backend/test_form_builder_template_hook.py
|
|
11
|
+
DonateMain.demo/tests/backend/test_formbuilder_validators.py
|
|
12
|
+
|
|
13
|
+
No external dependencies — only the stdlib so it runs everywhere the test suite runs.
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
from __future__ import annotations
|
|
17
|
+
|
|
18
|
+
import re
|
|
19
|
+
from typing import Any, Dict, List
|
|
20
|
+
|
|
21
|
+
# --------------------------------------------------------------------------- #
|
|
22
|
+
# Helpers
|
|
23
|
+
# --------------------------------------------------------------------------- #
|
|
24
|
+
|
|
25
|
+
_EMAIL_RE = re.compile(r"^[^@\s]+@[^@\s]+\.[^@\s]+$")
|
|
26
|
+
# Also accept RFC 5322 display-name format: "Label <user@example.com>"
|
|
27
|
+
_EMAIL_DISPLAY_RE = re.compile(r"<[^@\s>]+@[^@\s>]+\.[^@\s>]+>$")
|
|
28
|
+
_URL_RE = re.compile(r"^https?://", re.IGNORECASE)
|
|
29
|
+
|
|
30
|
+
# Braintree: descriptor must be <= 22 characters, NAME*TEXT format.
|
|
31
|
+
_BT_DESCRIPTOR_MAX_LEN = 22
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def _str_val(fb: Dict[str, Any], key: str) -> str:
|
|
35
|
+
"""Return the stripped string value for a key, or '' when None/missing."""
|
|
36
|
+
v = fb.get(key)
|
|
37
|
+
return v.strip() if isinstance(v, str) else ""
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
# --------------------------------------------------------------------------- #
|
|
41
|
+
# Public API
|
|
42
|
+
# --------------------------------------------------------------------------- #
|
|
43
|
+
|
|
44
|
+
Issue = Dict[str, str] # {field, severity, message}
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def validate_formbuilder_template(fb: Dict[str, Any]) -> List[Issue]:
|
|
48
|
+
"""Validate a form_builder_template dict for known configuration problems.
|
|
49
|
+
|
|
50
|
+
Returns a list of issue dicts::
|
|
51
|
+
|
|
52
|
+
[{"field": "...", "severity": "error"|"warning", "message": "..."}]
|
|
53
|
+
|
|
54
|
+
An empty list means no issues were found.
|
|
55
|
+
|
|
56
|
+
Severities:
|
|
57
|
+
error – will cause a runtime crash or silent payment failure.
|
|
58
|
+
warning – likely produces a broken/confusing user experience.
|
|
59
|
+
"""
|
|
60
|
+
issues: List[Issue] = []
|
|
61
|
+
|
|
62
|
+
def error(field: str, message: str) -> None:
|
|
63
|
+
issues.append({"field": field, "severity": "error", "message": message})
|
|
64
|
+
|
|
65
|
+
def warning(field: str, message: str) -> None:
|
|
66
|
+
issues.append({"field": field, "severity": "warning", "message": message})
|
|
67
|
+
|
|
68
|
+
# ---------------------------------------------------------------------- #
|
|
69
|
+
# Identity
|
|
70
|
+
# ---------------------------------------------------------------------- #
|
|
71
|
+
if not _str_val(fb, "client"):
|
|
72
|
+
error("client", "client is required; KeyError will crash the handler")
|
|
73
|
+
|
|
74
|
+
if not _str_val(fb, "campaign"):
|
|
75
|
+
error("campaign", "campaign is required; KeyError will crash the handler")
|
|
76
|
+
|
|
77
|
+
if not _str_val(fb, "url_slug"):
|
|
78
|
+
error("url_slug", "url_slug is required; template will not be routable")
|
|
79
|
+
|
|
80
|
+
# ---------------------------------------------------------------------- #
|
|
81
|
+
# Receipt email fields
|
|
82
|
+
# (used with direct key access: fb["receipt_from_address"] etc.)
|
|
83
|
+
# ---------------------------------------------------------------------- #
|
|
84
|
+
from_addr = _str_val(fb, "receipt_from_address")
|
|
85
|
+
if not from_addr:
|
|
86
|
+
error(
|
|
87
|
+
"receipt_from_address",
|
|
88
|
+
"receipt_from_address is empty; donation receipt emails will fail to send",
|
|
89
|
+
)
|
|
90
|
+
elif not _EMAIL_RE.match(from_addr) and not _EMAIL_DISPLAY_RE.search(from_addr):
|
|
91
|
+
error(
|
|
92
|
+
"receipt_from_address",
|
|
93
|
+
f"receipt_from_address '{from_addr}' is not a valid email address",
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
if not _str_val(fb, "receipt_subject"):
|
|
97
|
+
warning(
|
|
98
|
+
"receipt_subject",
|
|
99
|
+
"receipt_subject is empty; donation receipt email subject will be blank",
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
if not _str_val(fb, "receipt_body_text"):
|
|
103
|
+
error(
|
|
104
|
+
"receipt_body_text",
|
|
105
|
+
"receipt_body_text is empty; donation receipt emails will have no content",
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
# ---------------------------------------------------------------------- #
|
|
109
|
+
# Braintree transaction descriptor
|
|
110
|
+
# Rules: <= 22 chars, should contain '*', ASCII printable only.
|
|
111
|
+
# ---------------------------------------------------------------------- #
|
|
112
|
+
descriptor = _str_val(fb, "descriptor")
|
|
113
|
+
if descriptor:
|
|
114
|
+
if len(descriptor) > _BT_DESCRIPTOR_MAX_LEN:
|
|
115
|
+
error(
|
|
116
|
+
"descriptor",
|
|
117
|
+
f"descriptor is {len(descriptor)} chars (max {_BT_DESCRIPTOR_MAX_LEN}); "
|
|
118
|
+
"Braintree will reject the transaction",
|
|
119
|
+
)
|
|
120
|
+
if "*" not in descriptor:
|
|
121
|
+
warning(
|
|
122
|
+
"descriptor",
|
|
123
|
+
f"descriptor '{descriptor}' should follow 'NAME*TEXT' format for Braintree",
|
|
124
|
+
)
|
|
125
|
+
bad_chars = [c for c in descriptor if not (32 <= ord(c) <= 126)]
|
|
126
|
+
if bad_chars:
|
|
127
|
+
error(
|
|
128
|
+
"descriptor",
|
|
129
|
+
f"descriptor contains non-ASCII/non-printable characters: {bad_chars!r}",
|
|
130
|
+
)
|
|
131
|
+
|
|
132
|
+
# ---------------------------------------------------------------------- #
|
|
133
|
+
# Content — at least one active donation or metric must be configured
|
|
134
|
+
# ---------------------------------------------------------------------- #
|
|
135
|
+
has_content = _has_donation_content(fb) or _has_metric_content(fb)
|
|
136
|
+
if not has_content:
|
|
137
|
+
warning(
|
|
138
|
+
"donations/metrics",
|
|
139
|
+
"template has no donation amounts or metrics configured; the form will be empty",
|
|
140
|
+
)
|
|
141
|
+
|
|
142
|
+
# ---------------------------------------------------------------------- #
|
|
143
|
+
# Share URL (used in confirmation email)
|
|
144
|
+
# ---------------------------------------------------------------------- #
|
|
145
|
+
share_url = _str_val(fb, "share_url")
|
|
146
|
+
if share_url and not _URL_RE.match(share_url):
|
|
147
|
+
warning(
|
|
148
|
+
"share_url",
|
|
149
|
+
f"share_url '{share_url}' does not look like a valid URL (expected https://...)",
|
|
150
|
+
)
|
|
151
|
+
|
|
152
|
+
# ---------------------------------------------------------------------- #
|
|
153
|
+
# Confirmation page text
|
|
154
|
+
# ---------------------------------------------------------------------- #
|
|
155
|
+
if not _str_val(fb, "confirmation_header_text"):
|
|
156
|
+
warning(
|
|
157
|
+
"confirmation_header_text",
|
|
158
|
+
"confirmation_header_text is empty; the thank-you page header will be blank",
|
|
159
|
+
)
|
|
160
|
+
|
|
161
|
+
return issues
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
# --------------------------------------------------------------------------- #
|
|
165
|
+
# Internal helpers
|
|
166
|
+
# --------------------------------------------------------------------------- #
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
def _has_donation_content(fb: Dict[str, Any]) -> bool:
|
|
170
|
+
"""Return True if at least one visible donation is configured."""
|
|
171
|
+
donations = fb.get("donations")
|
|
172
|
+
if isinstance(donations, dict):
|
|
173
|
+
for key, item in donations.items():
|
|
174
|
+
hide_key = f"donation_{key}_hide_donation_from_ui"
|
|
175
|
+
if fb.get(hide_key):
|
|
176
|
+
continue
|
|
177
|
+
if isinstance(item, dict) and item.get("label"):
|
|
178
|
+
return True
|
|
179
|
+
# Legacy numbered fields
|
|
180
|
+
for i in range(1, 10):
|
|
181
|
+
if fb.get(f"donation_{i}_hide_donation_from_ui"):
|
|
182
|
+
continue
|
|
183
|
+
if _str_val(fb, f"donation_{i}_label") or fb.get(f"donation_{i}_values"):
|
|
184
|
+
return True
|
|
185
|
+
return False
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
def _has_metric_content(fb: Dict[str, Any]) -> bool:
|
|
189
|
+
"""Return True if at least one visible metric is configured."""
|
|
190
|
+
metrics = fb.get("metrics")
|
|
191
|
+
if isinstance(metrics, dict):
|
|
192
|
+
for key, item in metrics.items():
|
|
193
|
+
hide_key = f"{key}_hide_donation_from_ui"
|
|
194
|
+
if fb.get(hide_key):
|
|
195
|
+
continue
|
|
196
|
+
if isinstance(item, dict) and item.get("label"):
|
|
197
|
+
return True
|
|
198
|
+
# Legacy numbered fields
|
|
199
|
+
for i in range(1, 10):
|
|
200
|
+
if fb.get(f"metric_{i}_hide_donation_from_ui"):
|
|
201
|
+
continue
|
|
202
|
+
if _str_val(fb, f"metric_{i}_label") or fb.get(f"metric_{i}_values"):
|
|
203
|
+
return True
|
|
204
|
+
return False
|
{velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity_python.egg-info/SOURCES.txt
RENAMED
|
@@ -12,6 +12,8 @@ src/velocity/app/tests/__init__.py
|
|
|
12
12
|
src/velocity/app/tests/test_email_processing.py
|
|
13
13
|
src/velocity/app/tests/test_payment_profile_sorting.py
|
|
14
14
|
src/velocity/app/tests/test_spreadsheet_functions.py
|
|
15
|
+
src/velocity/app/validators/__init__.py
|
|
16
|
+
src/velocity/app/validators/formbuilder_template.py
|
|
15
17
|
src/velocity/aws/__init__.py
|
|
16
18
|
src/velocity/aws/amplify.py
|
|
17
19
|
src/velocity/aws/amplify_build.py
|
|
@@ -145,6 +147,7 @@ src/velocity_python.egg-info/requires.txt
|
|
|
145
147
|
src/velocity_python.egg-info/top_level.txt
|
|
146
148
|
tests/test_amplify_build.py
|
|
147
149
|
tests/test_decorators.py
|
|
150
|
+
tests/test_formbuilder_template_validator.py
|
|
148
151
|
tests/test_iconv_money_to_cents.py
|
|
149
152
|
tests/test_lambda_handler.py
|
|
150
153
|
tests/test_lambda_handler_auth.py
|
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
"""Unit tests for velocity.app.validators.formbuilder_template.
|
|
2
|
+
|
|
3
|
+
These tests are the canonical regression suite for the shared validator.
|
|
4
|
+
Consumer-project tests (DonateMain, BackOffice) import from this module via
|
|
5
|
+
velocity so their suites should stay in sync.
|
|
6
|
+
|
|
7
|
+
Runs entirely offline — no database or network access required.
|
|
8
|
+
|
|
9
|
+
python -m pytest tests/test_formbuilder_template_validator.py -v
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
from __future__ import annotations
|
|
13
|
+
|
|
14
|
+
import unittest
|
|
15
|
+
|
|
16
|
+
from velocity.app.validators.formbuilder_template import validate_formbuilder_template
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
# --------------------------------------------------------------------------- #
|
|
20
|
+
# Helpers
|
|
21
|
+
# --------------------------------------------------------------------------- #
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def _make_valid_fb(**overrides) -> dict:
|
|
25
|
+
"""Return the minimal template dict that passes all validations."""
|
|
26
|
+
base = {
|
|
27
|
+
"client": "TestClient",
|
|
28
|
+
"campaign": "test_campaign",
|
|
29
|
+
"url_slug": "/test/campaign",
|
|
30
|
+
"receipt_from_address": "noreply@example.com",
|
|
31
|
+
"receipt_subject": "Thank you for your donation",
|
|
32
|
+
"receipt_body_text": "<p>Dear {first_name}, thank you for donating!</p>",
|
|
33
|
+
"descriptor": "CaringCent*TEST",
|
|
34
|
+
"confirmation_header_text": "Thank you!",
|
|
35
|
+
"share_url": "https://donate.example.org/campaign",
|
|
36
|
+
"donations": {
|
|
37
|
+
"d1": {"label": "Give $25", "values": {"$25": "25"}},
|
|
38
|
+
},
|
|
39
|
+
}
|
|
40
|
+
base.update(overrides)
|
|
41
|
+
return base
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def _errors(issues, field=None):
|
|
45
|
+
return [
|
|
46
|
+
i
|
|
47
|
+
for i in issues
|
|
48
|
+
if i["severity"] == "error" and (field is None or i["field"] == field)
|
|
49
|
+
]
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def _warnings(issues, field=None):
|
|
53
|
+
return [
|
|
54
|
+
i
|
|
55
|
+
for i in issues
|
|
56
|
+
if i["severity"] == "warning" and (field is None or i["field"] == field)
|
|
57
|
+
]
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
# --------------------------------------------------------------------------- #
|
|
61
|
+
# Baseline
|
|
62
|
+
# --------------------------------------------------------------------------- #
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
class ValidTemplatePassesTests(unittest.TestCase):
|
|
66
|
+
|
|
67
|
+
def test_valid_template_has_no_issues(self):
|
|
68
|
+
issues = validate_formbuilder_template(_make_valid_fb())
|
|
69
|
+
self.assertEqual(issues, [], f"Unexpected issues: {issues}")
|
|
70
|
+
|
|
71
|
+
def test_returns_a_list(self):
|
|
72
|
+
result = validate_formbuilder_template(_make_valid_fb())
|
|
73
|
+
self.assertIsInstance(result, list)
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
# --------------------------------------------------------------------------- #
|
|
77
|
+
# Identity fields
|
|
78
|
+
# --------------------------------------------------------------------------- #
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
class IdentityFieldTests(unittest.TestCase):
|
|
82
|
+
|
|
83
|
+
def test_missing_client_is_error(self):
|
|
84
|
+
self.assertTrue(_errors(validate_formbuilder_template(_make_valid_fb(client="")), "client"))
|
|
85
|
+
|
|
86
|
+
def test_none_client_is_error(self):
|
|
87
|
+
self.assertTrue(_errors(validate_formbuilder_template(_make_valid_fb(client=None)), "client"))
|
|
88
|
+
|
|
89
|
+
def test_missing_campaign_is_error(self):
|
|
90
|
+
self.assertTrue(_errors(validate_formbuilder_template(_make_valid_fb(campaign="")), "campaign"))
|
|
91
|
+
|
|
92
|
+
def test_missing_url_slug_is_error(self):
|
|
93
|
+
fb = _make_valid_fb()
|
|
94
|
+
del fb["url_slug"]
|
|
95
|
+
self.assertTrue(_errors(validate_formbuilder_template(fb), "url_slug"))
|
|
96
|
+
|
|
97
|
+
def test_none_url_slug_is_error(self):
|
|
98
|
+
self.assertTrue(_errors(validate_formbuilder_template(_make_valid_fb(url_slug=None)), "url_slug"))
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
# --------------------------------------------------------------------------- #
|
|
102
|
+
# Receipt email fields
|
|
103
|
+
# --------------------------------------------------------------------------- #
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
class ReceiptEmailFieldTests(unittest.TestCase):
|
|
107
|
+
|
|
108
|
+
def test_empty_from_address_is_error(self):
|
|
109
|
+
self.assertTrue(_errors(validate_formbuilder_template(
|
|
110
|
+
_make_valid_fb(receipt_from_address="")), "receipt_from_address"))
|
|
111
|
+
|
|
112
|
+
def test_none_from_address_is_error(self):
|
|
113
|
+
self.assertTrue(_errors(validate_formbuilder_template(
|
|
114
|
+
_make_valid_fb(receipt_from_address=None)), "receipt_from_address"))
|
|
115
|
+
|
|
116
|
+
def test_invalid_from_address_is_error(self):
|
|
117
|
+
self.assertTrue(_errors(validate_formbuilder_template(
|
|
118
|
+
_make_valid_fb(receipt_from_address="not-an-email")), "receipt_from_address"))
|
|
119
|
+
|
|
120
|
+
def test_display_name_format_passes(self):
|
|
121
|
+
"""'Display Name <user@example.com>' is RFC 5322 valid and used in practice."""
|
|
122
|
+
issues = validate_formbuilder_template(
|
|
123
|
+
_make_valid_fb(receipt_from_address="Tigers Athletics <noreply@example.com>"))
|
|
124
|
+
self.assertFalse(_errors(issues, "receipt_from_address"))
|
|
125
|
+
|
|
126
|
+
def test_empty_subject_is_warning(self):
|
|
127
|
+
self.assertTrue(_warnings(validate_formbuilder_template(
|
|
128
|
+
_make_valid_fb(receipt_subject="")), "receipt_subject"))
|
|
129
|
+
|
|
130
|
+
def test_empty_body_is_error(self):
|
|
131
|
+
self.assertTrue(_errors(validate_formbuilder_template(
|
|
132
|
+
_make_valid_fb(receipt_body_text="")), "receipt_body_text"))
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
# --------------------------------------------------------------------------- #
|
|
136
|
+
# Braintree descriptor
|
|
137
|
+
# --------------------------------------------------------------------------- #
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
class DescriptorTests(unittest.TestCase):
|
|
141
|
+
|
|
142
|
+
def test_valid_descriptor_passes(self):
|
|
143
|
+
issues = validate_formbuilder_template(_make_valid_fb())
|
|
144
|
+
self.assertFalse(_errors(issues, "descriptor"))
|
|
145
|
+
self.assertFalse(_warnings(issues, "descriptor"))
|
|
146
|
+
|
|
147
|
+
def test_omitted_descriptor_passes(self):
|
|
148
|
+
fb = _make_valid_fb()
|
|
149
|
+
del fb["descriptor"]
|
|
150
|
+
issues = validate_formbuilder_template(fb)
|
|
151
|
+
self.assertFalse(_errors(issues, "descriptor"))
|
|
152
|
+
|
|
153
|
+
def test_descriptor_too_long_is_error(self):
|
|
154
|
+
self.assertTrue(_errors(validate_formbuilder_template(
|
|
155
|
+
_make_valid_fb(descriptor="A" * 23)), "descriptor"))
|
|
156
|
+
|
|
157
|
+
def test_descriptor_exactly_22_chars_passes(self):
|
|
158
|
+
issues = validate_formbuilder_template(_make_valid_fb(descriptor="CaringCent*EXACTLY22CH"))
|
|
159
|
+
self.assertFalse(_errors(issues, "descriptor"))
|
|
160
|
+
|
|
161
|
+
def test_descriptor_without_asterisk_is_warning(self):
|
|
162
|
+
fb = _make_valid_fb(descriptor="CaringCentNOASTERISK")
|
|
163
|
+
issues = validate_formbuilder_template(fb)
|
|
164
|
+
self.assertTrue(_warnings(issues, "descriptor"))
|
|
165
|
+
|
|
166
|
+
def test_descriptor_with_non_ascii_is_error(self):
|
|
167
|
+
self.assertTrue(_errors(validate_formbuilder_template(
|
|
168
|
+
_make_valid_fb(descriptor="CaringCent*\x80TEST")), "descriptor"))
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
# --------------------------------------------------------------------------- #
|
|
172
|
+
# Content — donations / metrics
|
|
173
|
+
# --------------------------------------------------------------------------- #
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
class ContentConfigurationTests(unittest.TestCase):
|
|
177
|
+
|
|
178
|
+
def test_no_donations_no_metrics_is_warning(self):
|
|
179
|
+
fb = _make_valid_fb()
|
|
180
|
+
del fb["donations"]
|
|
181
|
+
self.assertTrue(_warnings(validate_formbuilder_template(fb), "donations/metrics"))
|
|
182
|
+
|
|
183
|
+
def test_modern_donations_dict_counts_as_content(self):
|
|
184
|
+
issues = validate_formbuilder_template(_make_valid_fb())
|
|
185
|
+
self.assertFalse(_warnings(issues, "donations/metrics"))
|
|
186
|
+
|
|
187
|
+
def test_hidden_donation_does_not_count_as_content(self):
|
|
188
|
+
fb = _make_valid_fb()
|
|
189
|
+
fb["donations"] = {"d1": {"label": "Hidden", "values": {}}}
|
|
190
|
+
fb["donation_d1_hide_donation_from_ui"] = True
|
|
191
|
+
issues = validate_formbuilder_template(fb)
|
|
192
|
+
self.assertTrue(_warnings(issues, "donations/metrics"))
|
|
193
|
+
|
|
194
|
+
def test_legacy_numbered_donation_fields_count_as_content(self):
|
|
195
|
+
fb = _make_valid_fb()
|
|
196
|
+
del fb["donations"]
|
|
197
|
+
fb["donation_1_label"] = "Give $25"
|
|
198
|
+
issues = validate_formbuilder_template(fb)
|
|
199
|
+
self.assertFalse(_warnings(issues, "donations/metrics"))
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
# --------------------------------------------------------------------------- #
|
|
203
|
+
# Share URL
|
|
204
|
+
# --------------------------------------------------------------------------- #
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
class ShareUrlTests(unittest.TestCase):
|
|
208
|
+
|
|
209
|
+
def test_missing_share_url_is_ok(self):
|
|
210
|
+
fb = _make_valid_fb()
|
|
211
|
+
del fb["share_url"]
|
|
212
|
+
self.assertFalse(_warnings(validate_formbuilder_template(fb), "share_url"))
|
|
213
|
+
|
|
214
|
+
def test_valid_https_url_passes(self):
|
|
215
|
+
issues = validate_formbuilder_template(_make_valid_fb())
|
|
216
|
+
self.assertFalse(_warnings(issues, "share_url"))
|
|
217
|
+
|
|
218
|
+
def test_non_url_share_url_is_warning(self):
|
|
219
|
+
self.assertTrue(_warnings(validate_formbuilder_template(
|
|
220
|
+
_make_valid_fb(share_url="not-a-url")), "share_url"))
|
|
221
|
+
|
|
222
|
+
|
|
223
|
+
# --------------------------------------------------------------------------- #
|
|
224
|
+
# Confirmation page text
|
|
225
|
+
# --------------------------------------------------------------------------- #
|
|
226
|
+
|
|
227
|
+
|
|
228
|
+
class ConfirmationTextTests(unittest.TestCase):
|
|
229
|
+
|
|
230
|
+
def test_empty_confirmation_header_is_warning(self):
|
|
231
|
+
self.assertTrue(_warnings(validate_formbuilder_template(
|
|
232
|
+
_make_valid_fb(confirmation_header_text="")), "confirmation_header_text"))
|
|
233
|
+
|
|
234
|
+
def test_valid_confirmation_header_passes(self):
|
|
235
|
+
issues = validate_formbuilder_template(_make_valid_fb())
|
|
236
|
+
self.assertFalse(_warnings(issues, "confirmation_header_text"))
|
|
237
|
+
|
|
238
|
+
|
|
239
|
+
if __name__ == "__main__":
|
|
240
|
+
unittest.main()
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/app/tests/test_email_processing.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/aws/handlers/base_handler.py
RENAMED
|
File without changes
|
|
File without changes
|
{velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/aws/handlers/context_factory.py
RENAMED
|
File without changes
|
|
File without changes
|
{velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/aws/handlers/lambda_handler.py
RENAMED
|
File without changes
|
{velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/aws/handlers/mixins/__init__.py
RENAMED
|
File without changes
|
{velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/aws/handlers/mixins/data_service.py
RENAMED
|
File without changes
|
{velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/aws/handlers/mixins/web_handler.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/aws/handlers/sqs_handler.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/db/servers/base/__init__.py
RENAMED
|
File without changes
|
{velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/db/servers/base/initializer.py
RENAMED
|
File without changes
|
{velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/db/servers/base/operators.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/db/servers/mysql/__init__.py
RENAMED
|
File without changes
|
{velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/db/servers/mysql/operators.py
RENAMED
|
File without changes
|
{velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/db/servers/mysql/reserved.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/db/servers/postgres/__init__.py
RENAMED
|
File without changes
|
{velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/db/servers/postgres/operators.py
RENAMED
|
File without changes
|
{velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/db/servers/postgres/reserved.py
RENAMED
|
File without changes
|
|
File without changes
|
{velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/db/servers/postgres/types.py
RENAMED
|
File without changes
|
{velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/db/servers/sqlite/__init__.py
RENAMED
|
File without changes
|
{velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/db/servers/sqlite/operators.py
RENAMED
|
File without changes
|
{velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/db/servers/sqlite/reserved.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/db/servers/sqlserver/__init__.py
RENAMED
|
File without changes
|
{velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/db/servers/sqlserver/operators.py
RENAMED
|
File without changes
|
{velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/db/servers/sqlserver/reserved.py
RENAMED
|
File without changes
|
{velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/db/servers/sqlserver/sql.py
RENAMED
|
File without changes
|
{velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/db/servers/sqlserver/types.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/db/tests/postgres/__init__.py
RENAMED
|
File without changes
|
{velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/db/tests/postgres/common.py
RENAMED
|
File without changes
|
{velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/db/tests/postgres/test_column.py
RENAMED
|
File without changes
|
|
File without changes
|
{velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/db/tests/postgres/test_database.py
RENAMED
|
File without changes
|
{velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/db/tests/postgres/test_engine.py
RENAMED
|
File without changes
|
|
File without changes
|
{velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/db/tests/postgres/test_imports.py
RENAMED
|
File without changes
|
{velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/db/tests/postgres/test_result.py
RENAMED
|
File without changes
|
{velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/db/tests/postgres/test_row.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/db/tests/postgres/test_sequence.py
RENAMED
|
File without changes
|
|
File without changes
|
{velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/db/tests/postgres/test_table.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/db/tests/test_postgres_unchanged.py
RENAMED
|
File without changes
|
|
File without changes
|
{velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/db/tests/test_result_caching.py
RENAMED
|
File without changes
|
{velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/db/tests/test_result_sql_aware.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/db/tests/test_sql_builder.py
RENAMED
|
File without changes
|
{velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/db/tests/test_tablehelper.py
RENAMED
|
File without changes
|
{velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/db/tests/test_view_helper.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/misc/tests/test_original_error.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/payment/authorizenet_adapter.py
RENAMED
|
File without changes
|
|
File without changes
|
{velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity/payment/braintree_adapter.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity_python.egg-info/requires.txt
RENAMED
|
File without changes
|
{velocity_python-0.0.234 → velocity_python-0.0.236}/src/velocity_python.egg-info/top_level.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{velocity_python-0.0.234 → velocity_python-0.0.236}/tests/test_sys_modified_count_postgres_demo.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|