velocity-python 0.0.206__tar.gz → 0.0.208__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.206 → velocity_python-0.0.208}/PKG-INFO +1 -1
- {velocity_python-0.0.206 → velocity_python-0.0.208}/pyproject.toml +1 -1
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/__init__.py +1 -1
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/aws/handlers/base_handler.py +25 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/aws/handlers/mixins/data_service.py +137 -3
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/db/core/decorators.py +14 -1
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity_python.egg-info/PKG-INFO +1 -1
- {velocity_python-0.0.206 → velocity_python-0.0.208}/LICENSE +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/README.md +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/setup.cfg +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/app/__init__.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/app/invoices.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/app/orders.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/app/payments.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/app/purchase_orders.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/app/tests/__init__.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/app/tests/test_email_processing.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/app/tests/test_payment_profile_sorting.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/app/tests/test_spreadsheet_functions.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/aws/__init__.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/aws/amplify.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/aws/handlers/__init__.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/aws/handlers/context.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/aws/handlers/context_factory.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/aws/handlers/exceptions.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/aws/handlers/lambda_handler.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/aws/handlers/mixins/__init__.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/aws/handlers/mixins/web_handler.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/aws/handlers/perf.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/aws/handlers/response.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/aws/handlers/sqs_handler.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/aws/tests/__init__.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/aws/tests/test_lambda_handler_json_serialization.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/aws/tests/test_response.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/db/__init__.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/db/core/__init__.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/db/core/column.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/db/core/database.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/db/core/engine.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/db/core/result.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/db/core/row.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/db/core/sequence.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/db/core/table.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/db/core/transaction.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/db/core/view.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/db/exceptions.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/db/servers/__init__.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/db/servers/base/__init__.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/db/servers/base/initializer.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/db/servers/base/operators.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/db/servers/base/sql.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/db/servers/base/types.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/db/servers/mysql/__init__.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/db/servers/mysql/operators.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/db/servers/mysql/reserved.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/db/servers/mysql/sql.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/db/servers/mysql/types.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/db/servers/postgres/__init__.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/db/servers/postgres/operators.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/db/servers/postgres/reserved.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/db/servers/postgres/sql.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/db/servers/postgres/types.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/db/servers/sqlite/__init__.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/db/servers/sqlite/operators.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/db/servers/sqlite/reserved.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/db/servers/sqlite/sql.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/db/servers/sqlite/types.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/db/servers/sqlserver/__init__.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/db/servers/sqlserver/operators.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/db/servers/sqlserver/reserved.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/db/servers/sqlserver/sql.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/db/servers/sqlserver/types.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/db/servers/tablehelper.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/db/tests/__init__.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/db/tests/common_db_test.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/db/tests/postgres/__init__.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/db/tests/postgres/common.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/db/tests/postgres/test_column.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/db/tests/postgres/test_connections.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/db/tests/postgres/test_database.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/db/tests/postgres/test_engine.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/db/tests/postgres/test_general_usage.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/db/tests/postgres/test_imports.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/db/tests/postgres/test_result.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/db/tests/postgres/test_row.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/db/tests/postgres/test_row_comprehensive.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/db/tests/postgres/test_schema_locking.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/db/tests/postgres/test_schema_locking_unit.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/db/tests/postgres/test_sequence.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/db/tests/postgres/test_sql_comprehensive.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/db/tests/postgres/test_table.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/db/tests/postgres/test_table_comprehensive.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/db/tests/postgres/test_transaction.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/db/tests/sql/__init__.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/db/tests/sql/common.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/db/tests/sql/test_postgres_select_advanced.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/db/tests/sql/test_postgres_select_variances.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/db/tests/test_cursor_rowcount_fix.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/db/tests/test_db_utils.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/db/tests/test_postgres.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/db/tests/test_postgres_unchanged.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/db/tests/test_process_error_robustness.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/db/tests/test_result_caching.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/db/tests/test_result_sql_aware.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/db/tests/test_row_get_missing_column.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/db/tests/test_schema_locking_initializers.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/db/tests/test_schema_locking_simple.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/db/tests/test_sql_builder.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/db/tests/test_tablehelper.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/db/tests/test_view_helper.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/db/utils.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/logging.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/misc/__init__.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/misc/conv/__init__.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/misc/conv/iconv.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/misc/conv/oconv.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/misc/db.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/misc/export.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/misc/format.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/misc/mail.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/misc/merge.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/misc/tests/__init__.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/misc/tests/test_db.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/misc/tests/test_fix.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/misc/tests/test_format.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/misc/tests/test_iconv.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/misc/tests/test_merge.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/misc/tests/test_oconv.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/misc/tests/test_original_error.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/misc/tests/test_timer.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/misc/timer.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/misc/tools.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/payment/__init__.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/payment/base_adapter.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/payment/braintree_adapter.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/payment/router.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/payment/stripe_adapter.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity_python.egg-info/SOURCES.txt +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity_python.egg-info/dependency_links.txt +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity_python.egg-info/requires.txt +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity_python.egg-info/top_level.txt +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/tests/test_decorators.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/tests/test_iconv_money_to_cents.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/tests/test_lambda_handler.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/tests/test_lambda_handler_auth.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/tests/test_mixins_import.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/tests/test_sys_modified_count_postgres_demo.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/tests/test_table_alter.py +0 -0
- {velocity_python-0.0.206 → velocity_python-0.0.208}/tests/test_where_clause_validation.py +0 -0
{velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/aws/handlers/base_handler.py
RENAMED
|
@@ -13,6 +13,7 @@ from typing import Any, Dict, List, Optional
|
|
|
13
13
|
|
|
14
14
|
from velocity.aws.handlers import context as VelocityContext
|
|
15
15
|
from velocity.aws.handlers.context_factory import ContextFactory
|
|
16
|
+
from velocity.aws.handlers.exceptions import AlertError
|
|
16
17
|
|
|
17
18
|
logger = logging.getLogger(__name__)
|
|
18
19
|
|
|
@@ -221,6 +222,30 @@ class BaseHandler:
|
|
|
221
222
|
local_context: The context object
|
|
222
223
|
exception: The exception that occurred
|
|
223
224
|
"""
|
|
225
|
+
if isinstance(exception, AlertError):
|
|
226
|
+
payload = {}
|
|
227
|
+
try:
|
|
228
|
+
payload = exception.get_payload() or {}
|
|
229
|
+
except Exception:
|
|
230
|
+
payload = {"message": str(exception)}
|
|
231
|
+
|
|
232
|
+
title = payload.get("title") or "Notification"
|
|
233
|
+
message = payload.get("message") or str(exception)
|
|
234
|
+
|
|
235
|
+
logger.warning(
|
|
236
|
+
"AlertError during action execution",
|
|
237
|
+
exc_info=True,
|
|
238
|
+
extra={
|
|
239
|
+
"handler": self.__class__.__name__,
|
|
240
|
+
"action": getattr(local_context, "action", lambda: None)(),
|
|
241
|
+
"tx_present": tx is not None,
|
|
242
|
+
},
|
|
243
|
+
)
|
|
244
|
+
|
|
245
|
+
# Historical behavior: raising AlertError should surface a UI alert.
|
|
246
|
+
local_context.response().alert(message=message, title=title)
|
|
247
|
+
return
|
|
248
|
+
|
|
224
249
|
# Always log the original exception so it isn't lost if the error-path
|
|
225
250
|
# (e.g. job-status updates) fails due to a transient DB disconnect.
|
|
226
251
|
logger.exception(
|
{velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/aws/handlers/mixins/data_service.py
RENAMED
|
@@ -9,6 +9,7 @@ import base64
|
|
|
9
9
|
import datetime
|
|
10
10
|
import importlib
|
|
11
11
|
import logging
|
|
12
|
+
import re
|
|
12
13
|
from io import BytesIO
|
|
13
14
|
|
|
14
15
|
from velocity.misc import export
|
|
@@ -152,8 +153,116 @@ class DataServiceMixin:
|
|
|
152
153
|
self._call_rwx_hook("before_query", "common", tx, table, payload, context)
|
|
153
154
|
self._call_rwx_hook("before_query", table, tx, table, payload, context)
|
|
154
155
|
params = payload.get("params", {})
|
|
155
|
-
|
|
156
|
-
|
|
156
|
+
result_format = payload.get("result_format")
|
|
157
|
+
|
|
158
|
+
# Clear any previous swallowed-error details so we only report errors
|
|
159
|
+
# related to this query.
|
|
160
|
+
if hasattr(tx, "_last_return_default_error"):
|
|
161
|
+
tx._last_return_default_error = None
|
|
162
|
+
|
|
163
|
+
obj = payload["obj"]
|
|
164
|
+
|
|
165
|
+
def _normalize_identifier(identifier: str):
|
|
166
|
+
if identifier is None:
|
|
167
|
+
return None
|
|
168
|
+
identifier = str(identifier).strip()
|
|
169
|
+
if not identifier:
|
|
170
|
+
return None
|
|
171
|
+
if identifier[0] == identifier[-1] and identifier[0] in {'"', "'"}:
|
|
172
|
+
identifier = identifier[1:-1]
|
|
173
|
+
return identifier
|
|
174
|
+
|
|
175
|
+
def _extract_requested_column_names(columns_spec):
|
|
176
|
+
if not columns_spec:
|
|
177
|
+
return []
|
|
178
|
+
if isinstance(columns_spec, str):
|
|
179
|
+
columns_spec = [columns_spec]
|
|
180
|
+
if not isinstance(columns_spec, (list, tuple)):
|
|
181
|
+
return []
|
|
182
|
+
|
|
183
|
+
requested = []
|
|
184
|
+
simple_identifier = re.compile(
|
|
185
|
+
r"^([A-Za-z_][A-Za-z0-9_]*)(\\.([A-Za-z_][A-Za-z0-9_]*))?$"
|
|
186
|
+
)
|
|
187
|
+
|
|
188
|
+
for col in columns_spec:
|
|
189
|
+
if not isinstance(col, str):
|
|
190
|
+
continue
|
|
191
|
+
|
|
192
|
+
raw = col.strip()
|
|
193
|
+
if not raw or raw == "*":
|
|
194
|
+
continue
|
|
195
|
+
|
|
196
|
+
# If this looks like an expression (functions, casts, aliases, etc.),
|
|
197
|
+
# skip strict validation and let the DB error (which we will surface).
|
|
198
|
+
lowered = raw.lower()
|
|
199
|
+
if (
|
|
200
|
+
"(" in raw
|
|
201
|
+
or ")" in raw
|
|
202
|
+
or " over " in lowered
|
|
203
|
+
or "::" in raw
|
|
204
|
+
or " as " in lowered
|
|
205
|
+
or "+" in raw
|
|
206
|
+
or "-" in raw
|
|
207
|
+
or "/" in raw
|
|
208
|
+
or "*" in raw
|
|
209
|
+
or "||" in raw
|
|
210
|
+
):
|
|
211
|
+
continue
|
|
212
|
+
|
|
213
|
+
# Allow simple identifiers, optionally qualified (table.column).
|
|
214
|
+
match = simple_identifier.match(raw)
|
|
215
|
+
if not match:
|
|
216
|
+
continue
|
|
217
|
+
|
|
218
|
+
colname = match.group(3) or match.group(1)
|
|
219
|
+
colname = _normalize_identifier(colname)
|
|
220
|
+
if colname:
|
|
221
|
+
requested.append(colname)
|
|
222
|
+
|
|
223
|
+
return requested
|
|
224
|
+
|
|
225
|
+
# Optional: detect missing columns before running the query.
|
|
226
|
+
requested_cols = _extract_requested_column_names(params.get("columns"))
|
|
227
|
+
if requested_cols:
|
|
228
|
+
available_cols = {c.lower() for c in tx.table(obj).sys_columns()}
|
|
229
|
+
missing = sorted(
|
|
230
|
+
{c for c in requested_cols if c.lower() not in available_cols},
|
|
231
|
+
key=lambda v: v.lower(),
|
|
232
|
+
)
|
|
233
|
+
if missing:
|
|
234
|
+
message = (
|
|
235
|
+
f"Query failed for '{obj}': requested columns not present in the database: "
|
|
236
|
+
+ ", ".join(missing)
|
|
237
|
+
)
|
|
238
|
+
context.response().toast(message, "error")
|
|
239
|
+
error_payload = {
|
|
240
|
+
"type": "missing-columns",
|
|
241
|
+
"message": message,
|
|
242
|
+
"missing": missing,
|
|
243
|
+
}
|
|
244
|
+
if result_format == "excel":
|
|
245
|
+
return {
|
|
246
|
+
"headers": payload.get("headers", []),
|
|
247
|
+
"rows": [],
|
|
248
|
+
"error": error_payload,
|
|
249
|
+
}
|
|
250
|
+
return {
|
|
251
|
+
"rows": [],
|
|
252
|
+
"config": {
|
|
253
|
+
"lastFetch": datetime.datetime.now(),
|
|
254
|
+
"query": None,
|
|
255
|
+
"format": result_format,
|
|
256
|
+
"error": error_payload,
|
|
257
|
+
},
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
result = tx.table(obj).select(**params)
|
|
261
|
+
|
|
262
|
+
swallowed_error = getattr(tx, "_last_return_default_error", None)
|
|
263
|
+
if swallowed_error:
|
|
264
|
+
tx._last_return_default_error = None
|
|
265
|
+
if result_format == "excel":
|
|
157
266
|
data = {
|
|
158
267
|
"headers": payload.get(
|
|
159
268
|
"headers", [x.replace("_", " ").title() for x in result.headers]
|
|
@@ -166,9 +275,34 @@ class DataServiceMixin:
|
|
|
166
275
|
"config": {
|
|
167
276
|
"lastFetch": datetime.datetime.now(),
|
|
168
277
|
"query": result.sql,
|
|
169
|
-
"format":
|
|
278
|
+
"format": result_format,
|
|
170
279
|
},
|
|
171
280
|
}
|
|
281
|
+
|
|
282
|
+
# If the DB call failed but was swallowed (return_default), surface a reason.
|
|
283
|
+
# Common symptoms are empty rows + null SQL.
|
|
284
|
+
if swallowed_error and result_format == "excel":
|
|
285
|
+
error_message = swallowed_error.get("message") or "Unknown database error"
|
|
286
|
+
context.response().toast(
|
|
287
|
+
f"Query failed for '{obj}': {error_message.splitlines()[0]}",
|
|
288
|
+
"error",
|
|
289
|
+
)
|
|
290
|
+
data["error"] = {"type": "db-error", **swallowed_error}
|
|
291
|
+
elif swallowed_error and isinstance(data, dict) and data.get("config") is not None:
|
|
292
|
+
error_message = swallowed_error.get("message") or "Unknown database error"
|
|
293
|
+
context.response().toast(
|
|
294
|
+
f"Query failed for '{obj}': {error_message.splitlines()[0]}",
|
|
295
|
+
"error",
|
|
296
|
+
)
|
|
297
|
+
data["config"].update(
|
|
298
|
+
{
|
|
299
|
+
"query": data["config"].get("query") or None,
|
|
300
|
+
"error": {
|
|
301
|
+
"type": "db-error",
|
|
302
|
+
**swallowed_error,
|
|
303
|
+
},
|
|
304
|
+
}
|
|
305
|
+
)
|
|
172
306
|
if payload.get("count"):
|
|
173
307
|
data["count"] = tx.table(payload["obj"]).count(
|
|
174
308
|
where=params.get("where", None)
|
|
@@ -105,8 +105,21 @@ def return_default(
|
|
|
105
105
|
result = func(self, *args, **kwds)
|
|
106
106
|
if result is None:
|
|
107
107
|
result = default
|
|
108
|
-
except func.exceptions:
|
|
108
|
+
except func.exceptions as e:
|
|
109
109
|
self.tx.rollback_savepoint(sp, cursor=self.cursor())
|
|
110
|
+
|
|
111
|
+
# Capture swallowed exceptions for upstream diagnostics.
|
|
112
|
+
# This decorator intentionally returns a default value instead of
|
|
113
|
+
# raising, but consumers (e.g. API handlers) may still want to
|
|
114
|
+
# surface a reason to the caller.
|
|
115
|
+
try:
|
|
116
|
+
self.tx._last_return_default_error = {
|
|
117
|
+
"type": e.__class__.__name__,
|
|
118
|
+
"message": str(e),
|
|
119
|
+
"function": f"{func.__module__}.{getattr(func, '__qualname__', func.__name__)}",
|
|
120
|
+
}
|
|
121
|
+
except Exception:
|
|
122
|
+
pass
|
|
110
123
|
return default
|
|
111
124
|
self.tx.release_savepoint(sp, cursor=self.cursor())
|
|
112
125
|
return result
|
|
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.206 → velocity_python-0.0.208}/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.206 → velocity_python-0.0.208}/src/velocity/aws/handlers/context_factory.py
RENAMED
|
File without changes
|
|
File without changes
|
{velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/aws/handlers/lambda_handler.py
RENAMED
|
File without changes
|
{velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/aws/handlers/mixins/__init__.py
RENAMED
|
File without changes
|
{velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/aws/handlers/mixins/web_handler.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{velocity_python-0.0.206 → velocity_python-0.0.208}/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
|
{velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/db/servers/base/__init__.py
RENAMED
|
File without changes
|
{velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/db/servers/base/initializer.py
RENAMED
|
File without changes
|
{velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/db/servers/base/operators.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/db/servers/mysql/__init__.py
RENAMED
|
File without changes
|
{velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/db/servers/mysql/operators.py
RENAMED
|
File without changes
|
{velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/db/servers/mysql/reserved.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/db/servers/postgres/__init__.py
RENAMED
|
File without changes
|
{velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/db/servers/postgres/operators.py
RENAMED
|
File without changes
|
{velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/db/servers/postgres/reserved.py
RENAMED
|
File without changes
|
|
File without changes
|
{velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/db/servers/postgres/types.py
RENAMED
|
File without changes
|
{velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/db/servers/sqlite/__init__.py
RENAMED
|
File without changes
|
{velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/db/servers/sqlite/operators.py
RENAMED
|
File without changes
|
{velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/db/servers/sqlite/reserved.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/db/servers/sqlserver/__init__.py
RENAMED
|
File without changes
|
{velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/db/servers/sqlserver/operators.py
RENAMED
|
File without changes
|
{velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/db/servers/sqlserver/reserved.py
RENAMED
|
File without changes
|
{velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/db/servers/sqlserver/sql.py
RENAMED
|
File without changes
|
{velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/db/servers/sqlserver/types.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/db/tests/postgres/__init__.py
RENAMED
|
File without changes
|
{velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/db/tests/postgres/common.py
RENAMED
|
File without changes
|
{velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/db/tests/postgres/test_column.py
RENAMED
|
File without changes
|
|
File without changes
|
{velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/db/tests/postgres/test_database.py
RENAMED
|
File without changes
|
{velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/db/tests/postgres/test_engine.py
RENAMED
|
File without changes
|
|
File without changes
|
{velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/db/tests/postgres/test_imports.py
RENAMED
|
File without changes
|
{velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/db/tests/postgres/test_result.py
RENAMED
|
File without changes
|
{velocity_python-0.0.206 → velocity_python-0.0.208}/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.206 → velocity_python-0.0.208}/src/velocity/db/tests/postgres/test_sequence.py
RENAMED
|
File without changes
|
|
File without changes
|
{velocity_python-0.0.206 → velocity_python-0.0.208}/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.206 → velocity_python-0.0.208}/src/velocity/db/tests/test_postgres_unchanged.py
RENAMED
|
File without changes
|
|
File without changes
|
{velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/db/tests/test_result_caching.py
RENAMED
|
File without changes
|
{velocity_python-0.0.206 → velocity_python-0.0.208}/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.206 → velocity_python-0.0.208}/src/velocity/db/tests/test_sql_builder.py
RENAMED
|
File without changes
|
{velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/db/tests/test_tablehelper.py
RENAMED
|
File without changes
|
{velocity_python-0.0.206 → velocity_python-0.0.208}/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.206 → velocity_python-0.0.208}/src/velocity/misc/tests/test_original_error.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity/payment/braintree_adapter.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity_python.egg-info/SOURCES.txt
RENAMED
|
File without changes
|
|
File without changes
|
{velocity_python-0.0.206 → velocity_python-0.0.208}/src/velocity_python.egg-info/requires.txt
RENAMED
|
File without changes
|
{velocity_python-0.0.206 → velocity_python-0.0.208}/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
|
{velocity_python-0.0.206 → velocity_python-0.0.208}/tests/test_sys_modified_count_postgres_demo.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|