velocity-python 0.0.95__tar.gz → 0.0.96__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.

Potentially problematic release.


This version of velocity-python might be problematic. Click here for more details.

Files changed (71) hide show
  1. {velocity_python-0.0.95 → velocity_python-0.0.96}/PKG-INFO +1 -1
  2. {velocity_python-0.0.95 → velocity_python-0.0.96}/pyproject.toml +1 -1
  3. {velocity_python-0.0.95 → velocity_python-0.0.96}/src/velocity/__init__.py +1 -1
  4. velocity_python-0.0.96/src/velocity/aws/handlers/sqs_handler.py +230 -0
  5. {velocity_python-0.0.95 → velocity_python-0.0.96}/src/velocity_python.egg-info/PKG-INFO +1 -1
  6. velocity_python-0.0.95/src/velocity/aws/handlers/sqs_handler.py +0 -97
  7. {velocity_python-0.0.95 → velocity_python-0.0.96}/LICENSE +0 -0
  8. {velocity_python-0.0.95 → velocity_python-0.0.96}/README.md +0 -0
  9. {velocity_python-0.0.95 → velocity_python-0.0.96}/setup.cfg +0 -0
  10. {velocity_python-0.0.95 → velocity_python-0.0.96}/src/velocity/app/__init__.py +0 -0
  11. {velocity_python-0.0.95 → velocity_python-0.0.96}/src/velocity/app/invoices.py +0 -0
  12. {velocity_python-0.0.95 → velocity_python-0.0.96}/src/velocity/app/orders.py +0 -0
  13. {velocity_python-0.0.95 → velocity_python-0.0.96}/src/velocity/app/payments.py +0 -0
  14. {velocity_python-0.0.95 → velocity_python-0.0.96}/src/velocity/app/purchase_orders.py +0 -0
  15. {velocity_python-0.0.95 → velocity_python-0.0.96}/src/velocity/aws/__init__.py +0 -0
  16. {velocity_python-0.0.95 → velocity_python-0.0.96}/src/velocity/aws/amplify.py +0 -0
  17. {velocity_python-0.0.95 → velocity_python-0.0.96}/src/velocity/aws/handlers/__init__.py +0 -0
  18. {velocity_python-0.0.95 → velocity_python-0.0.96}/src/velocity/aws/handlers/context.py +0 -0
  19. {velocity_python-0.0.95 → velocity_python-0.0.96}/src/velocity/aws/handlers/lambda_handler.py +0 -0
  20. {velocity_python-0.0.95 → velocity_python-0.0.96}/src/velocity/aws/handlers/response.py +0 -0
  21. {velocity_python-0.0.95 → velocity_python-0.0.96}/src/velocity/db/__init__.py +0 -0
  22. {velocity_python-0.0.95 → velocity_python-0.0.96}/src/velocity/db/core/__init__.py +0 -0
  23. {velocity_python-0.0.95 → velocity_python-0.0.96}/src/velocity/db/core/column.py +0 -0
  24. {velocity_python-0.0.95 → velocity_python-0.0.96}/src/velocity/db/core/database.py +0 -0
  25. {velocity_python-0.0.95 → velocity_python-0.0.96}/src/velocity/db/core/decorators.py +0 -0
  26. {velocity_python-0.0.95 → velocity_python-0.0.96}/src/velocity/db/core/engine.py +0 -0
  27. {velocity_python-0.0.95 → velocity_python-0.0.96}/src/velocity/db/core/exceptions.py +0 -0
  28. {velocity_python-0.0.95 → velocity_python-0.0.96}/src/velocity/db/core/result.py +0 -0
  29. {velocity_python-0.0.95 → velocity_python-0.0.96}/src/velocity/db/core/row.py +0 -0
  30. {velocity_python-0.0.95 → velocity_python-0.0.96}/src/velocity/db/core/sequence.py +0 -0
  31. {velocity_python-0.0.95 → velocity_python-0.0.96}/src/velocity/db/core/table.py +0 -0
  32. {velocity_python-0.0.95 → velocity_python-0.0.96}/src/velocity/db/core/transaction.py +0 -0
  33. {velocity_python-0.0.95 → velocity_python-0.0.96}/src/velocity/db/servers/__init__.py +0 -0
  34. {velocity_python-0.0.95 → velocity_python-0.0.96}/src/velocity/db/servers/mysql.py +0 -0
  35. {velocity_python-0.0.95 → velocity_python-0.0.96}/src/velocity/db/servers/mysql_reserved.py +0 -0
  36. {velocity_python-0.0.95 → velocity_python-0.0.96}/src/velocity/db/servers/postgres/__init__.py +0 -0
  37. {velocity_python-0.0.95 → velocity_python-0.0.96}/src/velocity/db/servers/postgres/operators.py +0 -0
  38. {velocity_python-0.0.95 → velocity_python-0.0.96}/src/velocity/db/servers/postgres/reserved.py +0 -0
  39. {velocity_python-0.0.95 → velocity_python-0.0.96}/src/velocity/db/servers/postgres/sql.py +0 -0
  40. {velocity_python-0.0.95 → velocity_python-0.0.96}/src/velocity/db/servers/postgres/types.py +0 -0
  41. {velocity_python-0.0.95 → velocity_python-0.0.96}/src/velocity/db/servers/sqlite.py +0 -0
  42. {velocity_python-0.0.95 → velocity_python-0.0.96}/src/velocity/db/servers/sqlite_reserved.py +0 -0
  43. {velocity_python-0.0.95 → velocity_python-0.0.96}/src/velocity/db/servers/sqlserver.py +0 -0
  44. {velocity_python-0.0.95 → velocity_python-0.0.96}/src/velocity/db/servers/sqlserver_reserved.py +0 -0
  45. {velocity_python-0.0.95 → velocity_python-0.0.96}/src/velocity/db/servers/tablehelper.py +0 -0
  46. {velocity_python-0.0.95 → velocity_python-0.0.96}/src/velocity/misc/__init__.py +0 -0
  47. {velocity_python-0.0.95 → velocity_python-0.0.96}/src/velocity/misc/conv/__init__.py +0 -0
  48. {velocity_python-0.0.95 → velocity_python-0.0.96}/src/velocity/misc/conv/iconv.py +0 -0
  49. {velocity_python-0.0.95 → velocity_python-0.0.96}/src/velocity/misc/conv/oconv.py +0 -0
  50. {velocity_python-0.0.95 → velocity_python-0.0.96}/src/velocity/misc/db.py +0 -0
  51. {velocity_python-0.0.95 → velocity_python-0.0.96}/src/velocity/misc/export.py +0 -0
  52. {velocity_python-0.0.95 → velocity_python-0.0.96}/src/velocity/misc/format.py +0 -0
  53. {velocity_python-0.0.95 → velocity_python-0.0.96}/src/velocity/misc/mail.py +0 -0
  54. {velocity_python-0.0.95 → velocity_python-0.0.96}/src/velocity/misc/merge.py +0 -0
  55. {velocity_python-0.0.95 → velocity_python-0.0.96}/src/velocity/misc/timer.py +0 -0
  56. {velocity_python-0.0.95 → velocity_python-0.0.96}/src/velocity/misc/tools.py +0 -0
  57. {velocity_python-0.0.95 → velocity_python-0.0.96}/src/velocity_python.egg-info/SOURCES.txt +0 -0
  58. {velocity_python-0.0.95 → velocity_python-0.0.96}/src/velocity_python.egg-info/dependency_links.txt +0 -0
  59. {velocity_python-0.0.95 → velocity_python-0.0.96}/src/velocity_python.egg-info/requires.txt +0 -0
  60. {velocity_python-0.0.95 → velocity_python-0.0.96}/src/velocity_python.egg-info/top_level.txt +0 -0
  61. {velocity_python-0.0.95 → velocity_python-0.0.96}/tests/test_db.py +0 -0
  62. {velocity_python-0.0.95 → velocity_python-0.0.96}/tests/test_email_processing.py +0 -0
  63. {velocity_python-0.0.95 → velocity_python-0.0.96}/tests/test_format.py +0 -0
  64. {velocity_python-0.0.95 → velocity_python-0.0.96}/tests/test_iconv.py +0 -0
  65. {velocity_python-0.0.95 → velocity_python-0.0.96}/tests/test_merge.py +0 -0
  66. {velocity_python-0.0.95 → velocity_python-0.0.96}/tests/test_oconv.py +0 -0
  67. {velocity_python-0.0.95 → velocity_python-0.0.96}/tests/test_postgres.py +0 -0
  68. {velocity_python-0.0.95 → velocity_python-0.0.96}/tests/test_response.py +0 -0
  69. {velocity_python-0.0.95 → velocity_python-0.0.96}/tests/test_spreadsheet_functions.py +0 -0
  70. {velocity_python-0.0.95 → velocity_python-0.0.96}/tests/test_sql_builder.py +0 -0
  71. {velocity_python-0.0.95 → velocity_python-0.0.96}/tests/test_timer.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: velocity-python
3
- Version: 0.0.95
3
+ Version: 0.0.96
4
4
  Summary: A rapid application development library for interfacing with data storage
5
5
  Author-email: Velocity Team <contact@example.com>
6
6
  License: MIT
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "velocity-python"
7
- version = "0.0.95"
7
+ version = "0.0.96"
8
8
  authors = [
9
9
  { name="Velocity Team", email="contact@example.com" },
10
10
  ]
@@ -1,4 +1,4 @@
1
- __version__ = version = "0.0.95"
1
+ __version__ = version = "0.0.96"
2
2
 
3
3
  from . import aws
4
4
  from . import db
@@ -0,0 +1,230 @@
1
+ """
2
+ SQS Handler Module
3
+
4
+ This module provides a base class for handling AWS SQS events in Lambda functions.
5
+ It includes logging capabilities, action routing, and error handling.
6
+ """
7
+
8
+ import json
9
+ import os
10
+ import sys
11
+ import traceback
12
+ from typing import Any, Dict, Optional
13
+
14
+ from velocity.aws import DEBUG
15
+ from velocity.aws.handlers import context as VelocityContext
16
+ from velocity.misc.format import to_json
17
+
18
+
19
+ class SqsHandler:
20
+ """
21
+ Base class for handling SQS events in AWS Lambda functions.
22
+
23
+ Provides structured processing of SQS records with automatic action routing,
24
+ logging capabilities, and error handling hooks.
25
+ """
26
+
27
+ def __init__(self, aws_event: Dict[str, Any], aws_context: Any,
28
+ context_class=VelocityContext.Context):
29
+ """
30
+ Initialize the SQS handler.
31
+
32
+ Args:
33
+ aws_event: The AWS Lambda event containing SQS records
34
+ aws_context: The AWS Lambda context object
35
+ context_class: The context class to use for processing
36
+ """
37
+ self.aws_event = aws_event
38
+ self.aws_context = aws_context
39
+ self.serve_action_default = True
40
+ self.skip_action = False
41
+ self.ContextClass = context_class
42
+
43
+ self.aws_event = aws_event
44
+ self.aws_context = aws_context
45
+ self.serve_action_default = True
46
+ self.skip_action = False
47
+ self.ContextClass = context_class
48
+
49
+ def log(self, tx, message: str, function: Optional[str] = None):
50
+ """
51
+ Log a message to the system log table.
52
+
53
+ Args:
54
+ tx: Database transaction object
55
+ message: The message to log
56
+ function: Optional function name, auto-detected if not provided
57
+ """
58
+ if not function:
59
+ function = self._get_calling_function()
60
+
61
+ data = {
62
+ "app_name": os.environ.get("ProjectName", "Unknown"),
63
+ "referer": "SQS",
64
+ "user_agent": "QueueHandler",
65
+ "device_type": "Lambda",
66
+ "function": function,
67
+ "message": message,
68
+ "sys_modified_by": "Lambda:BackOfficeQueueHandler",
69
+ }
70
+ tx.table("sys_log").insert(data)
71
+
72
+ def _get_calling_function(self) -> str:
73
+ """
74
+ Get the name of the calling function by inspecting the call stack.
75
+
76
+ Returns:
77
+ The name of the calling function or "<Unknown>" if not found
78
+ """
79
+ skip_functions = {"x", "log", "_transaction", "_get_calling_function"}
80
+
81
+ for idx in range(10): # Limit search to prevent infinite loops
82
+ try:
83
+ frame = sys._getframe(idx)
84
+ function_name = frame.f_code.co_name
85
+
86
+ if function_name not in skip_functions:
87
+ return function_name
88
+
89
+ except ValueError:
90
+ # No more frames in the stack
91
+ break
92
+
93
+ return "<Unknown>"
94
+
95
+ def serve(self, tx):
96
+ """
97
+ Process all SQS records in the event.
98
+
99
+ Args:
100
+ tx: Database transaction object
101
+ """
102
+ records = self.aws_event.get("Records", [])
103
+
104
+ for record in records:
105
+ self._process_record(tx, record)
106
+
107
+ def _process_record(self, tx, record: Dict[str, Any]):
108
+ """
109
+ Process a single SQS record.
110
+
111
+ Args:
112
+ tx: Database transaction object
113
+ record: Individual SQS record to process
114
+ """
115
+ attrs = record.get("attributes", {})
116
+ postdata = {}
117
+
118
+ # Parse message body if present
119
+ body = record.get("body")
120
+ if body:
121
+ try:
122
+ postdata = json.loads(body)
123
+ except json.JSONDecodeError as e:
124
+ print(f"Failed to parse SQS message body as JSON: {e}")
125
+ postdata = {"raw_body": body}
126
+
127
+ # Create local context for this record
128
+ local_context = self.ContextClass(
129
+ aws_event=self.aws_event,
130
+ aws_context=self.aws_context,
131
+ args=attrs,
132
+ postdata=postdata,
133
+ response=None,
134
+ session=None,
135
+ )
136
+
137
+ try:
138
+ self._execute_actions(local_context)
139
+ except Exception as e:
140
+ if hasattr(self, "onError"):
141
+ self.onError(
142
+ local_context,
143
+ exc=e.__class__.__name__,
144
+ tb=traceback.format_exc(),
145
+ )
146
+ else:
147
+ # Re-raise if no error handler is defined
148
+ raise
149
+
150
+ def _execute_actions(self, local_context):
151
+ """
152
+ Execute the appropriate actions for the given context.
153
+
154
+ Args:
155
+ local_context: The context object for this record
156
+ """
157
+ # Execute beforeAction hook if available
158
+ if hasattr(self, "beforeAction"):
159
+ self.beforeAction(local_context)
160
+
161
+ # Determine which actions to execute
162
+ actions = self._get_actions_to_execute(local_context)
163
+
164
+ # Execute the first matching action
165
+ for action in actions:
166
+ if self.skip_action:
167
+ return
168
+
169
+ if hasattr(self, action):
170
+ getattr(self, action)(local_context)
171
+ break
172
+
173
+ # Execute afterAction hook if available
174
+ if hasattr(self, "afterAction"):
175
+ self.afterAction(local_context)
176
+
177
+ def _get_actions_to_execute(self, local_context) -> list:
178
+ """
179
+ Get the list of actions to execute for the given context.
180
+
181
+ Args:
182
+ local_context: The context object for this record
183
+
184
+ Returns:
185
+ List of action method names to try executing
186
+ """
187
+ actions = []
188
+
189
+ # Add specific action if available
190
+ action = local_context.action()
191
+ if action:
192
+ action_method = self._format_action_name(action)
193
+ actions.append(action_method)
194
+
195
+ # Add default action if enabled
196
+ if self.serve_action_default:
197
+ actions.append("OnActionDefault")
198
+
199
+ return actions
200
+
201
+ def _format_action_name(self, action: str) -> str:
202
+ """
203
+ Format an action string into a method name.
204
+
205
+ Args:
206
+ action: The raw action string
207
+
208
+ Returns:
209
+ Formatted method name
210
+ """
211
+ formatted = action.replace('-', ' ').replace('_', ' ')
212
+ return f"on action {formatted}".title().replace(" ", "")
213
+
214
+ def OnActionDefault(self, tx, context):
215
+ """
216
+ Default action handler when no specific action is found.
217
+
218
+ Args:
219
+ tx: Database transaction object
220
+ context: The context object for this record
221
+ """
222
+ action = context.action() if hasattr(context, 'action') else 'unknown'
223
+ warning_message = (
224
+ f"[Warn] Action handler not found. Calling default action "
225
+ f"`SqsHandler.OnActionDefault` with the following parameters:\n"
226
+ f" - action: {action}\n"
227
+ f" - attrs: {context.args()}\n"
228
+ f" - postdata: {context.postdata()}"
229
+ )
230
+ print(warning_message)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: velocity-python
3
- Version: 0.0.95
3
+ Version: 0.0.96
4
4
  Summary: A rapid application development library for interfacing with data storage
5
5
  Author-email: Velocity Team <contact@example.com>
6
6
  License: MIT
@@ -1,97 +0,0 @@
1
- from velocity.misc.format import to_json
2
- import json
3
- import sys
4
- import os
5
- import traceback
6
- from velocity.aws import DEBUG
7
- from velocity.aws.handlers import context as VelocityContext
8
-
9
-
10
- class SqsHandler:
11
-
12
- def __init__(self, aws_event, aws_context, context_class=VelocityContext.Context):
13
- self.aws_event = aws_event
14
- self.aws_context = aws_context
15
- self.serve_action_default = True
16
- self.skip_action = False
17
- self.ContextClass = context_class
18
-
19
- def log(self, tx, message, function=None):
20
- if not function:
21
- function = "<Unknown>"
22
- idx = 0
23
- while True:
24
- try:
25
- temp = sys._getframe(idx).f_code.co_name
26
- except ValueError as e:
27
- break
28
- if temp in ["x", "log", "_transaction"]:
29
- idx += 1
30
- continue
31
- function = temp
32
- break
33
-
34
- data = {
35
- "app_name": os.environ["ProjectName"],
36
- "referer": "SQS",
37
- "user_agent": "QueueHandler",
38
- "device_type": "Lambda",
39
- "function": function,
40
- "message": message,
41
- "sys_modified_by": "lambda:BackOfficeQueueHandler",
42
- }
43
- tx.table("sys_log").insert(data)
44
-
45
- def serve(self, tx):
46
- records = self.aws_event.get("Records", [])
47
- for record in records:
48
- attrs = record.get("attributes")
49
- postdata = {}
50
- if record.get("body"):
51
- postdata = json.loads(record.get("body"))
52
-
53
- local_context = self.ContextClass(
54
- aws_event=self.aws_event,
55
- aws_context=self.aws_context,
56
- args=attrs,
57
- postdata=postdata,
58
- response=None,
59
- session=None,
60
- )
61
- try:
62
- if hasattr(self, "beforeAction"):
63
- self.beforeAction(local_context)
64
- actions = []
65
- action = local_context.action()
66
- if action:
67
- actions.append(
68
- f"on action {action.replace('-', ' ').replace('_', ' ')}".title().replace(
69
- " ", ""
70
- )
71
- )
72
- if self.serve_action_default:
73
- actions.append("OnActionDefault")
74
- for action in actions:
75
- if self.skip_action:
76
- return
77
- if hasattr(self, action):
78
- getattr(self, action)(local_context)
79
- break
80
- if hasattr(self, "afterAction"):
81
- self.afterAction(local_context)
82
- except Exception as e:
83
- if hasattr(self, "onError"):
84
- self.onError(
85
- local_context,
86
- exc=e.__class__.__name__,
87
- tb=traceback.format_exc(),
88
- )
89
-
90
- def OnActionDefault(self, tx, context):
91
- print(
92
- f"""
93
- [Warn] Action handler not found. Calling default action `SqsHandler.OnActionDefault` with the following parameters for attrs, and postdata:
94
- attrs: {str(context.args())}
95
- postdata: {str(context.postdata())}
96
- """
97
- )