velocity-python 0.0.113__py3-none-any.whl → 0.0.116__py3-none-any.whl

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.

velocity/__init__.py CHANGED
@@ -1,4 +1,4 @@
1
- __version__ = version = "0.0.113"
1
+ __version__ = version = "0.0.116"
2
2
 
3
3
  from . import aws
4
4
  from . import db
@@ -1,4 +1,10 @@
1
+ import os
2
+ import boto3
3
+ import uuid
1
4
  import support.app
5
+ from velocity.misc.format import to_json
6
+ from velocity.misc.merge import deep_merge
7
+ from datetime import datetime
2
8
 
3
9
  engine = support.app.postgres()
4
10
 
@@ -68,3 +74,143 @@ class Context:
68
74
  print(f"{function}: {message}")
69
75
  else:
70
76
  print(f"{message}")
77
+
78
+ def update_job(self, tx, data=None):
79
+ """Update job status and message in aws_job_activity table.
80
+
81
+ This method only UPDATES existing jobs. For creating new jobs, use create_job.
82
+ """
83
+ if not data:
84
+ return
85
+ if self.postdata("job_id"):
86
+ # Sanitize data before storing in database
87
+ sanitized_data = self._sanitize_job_data(data)
88
+ tx.table("aws_job_activity").update(sanitized_data, {"job_id": self.postdata("job_id")})
89
+ tx.commit()
90
+
91
+ def create_job(self, job_data):
92
+ """Create a new job record in aws_job_activity table using independent transaction."""
93
+ sanitized_data = self._sanitize_job_data(job_data)
94
+ tx.table("aws_job_activity").insert(sanitized_data)
95
+ tx.commit()
96
+
97
+ def _sanitize_job_data(self, data):
98
+ """Sanitize sensitive data before storing in aws_job_activity table."""
99
+ if not isinstance(data, dict):
100
+ return data
101
+
102
+ sanitized = {}
103
+
104
+ # List of sensitive field patterns to sanitize
105
+ sensitive_patterns = [
106
+ 'password', 'token', 'secret', 'key', 'credential', 'auth',
107
+ 'cognito_user', 'session', 'cookie', 'authorization'
108
+ ]
109
+
110
+ for key, value in data.items():
111
+ # Check if key contains sensitive patterns
112
+ if any(pattern in key.lower() for pattern in sensitive_patterns):
113
+ sanitized[key] = "[REDACTED]" if value else value
114
+ elif key == 'error' and value:
115
+ # Sanitize error messages - keep first 500 chars and remove potential sensitive info
116
+ error_str = str(value)[:500]
117
+ for pattern in sensitive_patterns:
118
+ if pattern in error_str.lower():
119
+ # Replace potential sensitive values with placeholder
120
+ import re
121
+ # Remove patterns like password=value, token=value, etc.
122
+ error_str = re.sub(
123
+ rf'{pattern}[=:]\s*[^\s,\]}}]+',
124
+ f'{pattern}=[REDACTED]',
125
+ error_str,
126
+ flags=re.IGNORECASE
127
+ )
128
+ sanitized[key] = error_str
129
+ elif key == 'traceback' and value:
130
+ # Sanitize traceback - keep structure but remove sensitive values
131
+ tb_str = str(value)
132
+ for pattern in sensitive_patterns:
133
+ if pattern in tb_str.lower():
134
+ import re
135
+ # Remove patterns like password=value, token=value, etc.
136
+ tb_str = re.sub(
137
+ rf'{pattern}[=:]\s*[^\s,\]}}]+',
138
+ f'{pattern}=[REDACTED]',
139
+ tb_str,
140
+ flags=re.IGNORECASE
141
+ )
142
+ # Limit traceback size to prevent DB bloat
143
+ sanitized[key] = tb_str[:2000]
144
+ elif key == 'message' and value:
145
+ # Sanitize message field
146
+ message_str = str(value)
147
+ for pattern in sensitive_patterns:
148
+ if pattern in message_str.lower():
149
+ import re
150
+ message_str = re.sub(
151
+ rf'{pattern}[=:]\s*[^\s,\]}}]+',
152
+ f'{pattern}=[REDACTED]',
153
+ message_str,
154
+ flags=re.IGNORECASE
155
+ )
156
+ sanitized[key] = message_str[:1000] # Limit message size
157
+ else:
158
+ # For other fields, copy as-is but check for nested dicts
159
+ if isinstance(value, dict):
160
+ sanitized[key] = self._sanitize_job_data(value)
161
+ elif isinstance(value, str) and len(value) > 5000:
162
+ # Limit very large string fields
163
+ sanitized[key] = value[:5000] + "...[TRUNCATED]"
164
+ else:
165
+ sanitized[key] = value
166
+
167
+ return sanitized
168
+
169
+ def enqueue(self, action, payload={}, user=None, suppress_job_activity=False):
170
+ """
171
+ Enqueue jobs to SQS with independent job activity tracking.
172
+
173
+ This method uses its own transaction for aws_job_activity updates to ensure
174
+ job tracking is never rolled back with other operations.
175
+ """
176
+ batch_id = str(uuid.uuid4())
177
+ results = {"batch_id": batch_id}
178
+ queue = boto3.resource("sqs").get_queue_by_name(
179
+ QueueName=os.environ["SqsWorkQueue"]
180
+ )
181
+ if isinstance(payload, dict):
182
+ payload = [payload]
183
+ messages = []
184
+ if user==None:
185
+ user = self.session.get("email_address") or "EnqueueTasks"
186
+ for item in payload:
187
+ message = {"action": action, "payload": item}
188
+ id = str(uuid.uuid4()).split("-")[0]
189
+ if suppress_job_activity:
190
+ messages.append({"Id": id, "MessageBody": to_json(message)})
191
+ else:
192
+ message["job_id"] = id
193
+ # Use separate transaction for job activity - this should never be rolled back
194
+ self.create_job({
195
+ "action": action,
196
+ "initial_timestamp": datetime.now(),
197
+ "created_by": user,
198
+ "sys_modified_by": user,
199
+ "payload": to_json(message),
200
+ "batch_id": str(batch_id),
201
+ "job_id": id,
202
+ "status": "Initialized",
203
+ "message": f"Job Initialized"
204
+ })
205
+ messages.append({"Id": id, "MessageBody": to_json(message)})
206
+
207
+ if len(messages) == 10:
208
+ result = queue.send_messages(Entries=messages)
209
+ results = deep_merge(results, result)
210
+ messages.clear()
211
+
212
+ if messages:
213
+ result = queue.send_messages(Entries=messages)
214
+ results = deep_merge(results, result)
215
+
216
+ return results
@@ -4,7 +4,7 @@ import sys
4
4
  import os
5
5
  import traceback
6
6
  from support.app import DEBUG
7
- from support.app import helpers, AlertError, enqueue
7
+ from support.app import helpers, AlertError
8
8
 
9
9
  from velocity.aws.handlers import Response
10
10
 
@@ -164,6 +164,3 @@ class LambdaHandler:
164
164
 
165
165
  def OnActionTracking(self, tx, context):
166
166
  self.track(tx, context.payload().get("data", {}))
167
-
168
- def enqueue(self, tx, action, payload={}):
169
- return enqueue(tx, action, payload, self.session["email_address"])
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: velocity-python
3
- Version: 0.0.113
3
+ Version: 0.0.116
4
4
  Summary: A rapid application development library for interfacing with data storage
5
5
  Author-email: Velocity Team <info@codeclubs.org>
6
6
  License-Expression: MIT
@@ -1,4 +1,4 @@
1
- velocity/__init__.py,sha256=ZEotqpoCB8M4poSHlj5a2d_jp7VL9Wr7Y1TEe7LhfRE,107
1
+ velocity/__init__.py,sha256=9HZOcPjfok_APV3xMWucAvFzJMi0ieQU4-E1pepEZZs,107
2
2
  velocity/app/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
3
  velocity/app/invoices.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
4
  velocity/app/orders.py,sha256=W-HAXEwY8-IFXbKh82HnMeRVZM7P-TWGEQOWtkLIzI4,6298
@@ -7,8 +7,8 @@ velocity/app/purchase_orders.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSu
7
7
  velocity/aws/__init__.py,sha256=tj9-NliYxRVPYLnnDuA4FMwBHbbH4ed8gtHgwRskNgY,647
8
8
  velocity/aws/amplify.py,sha256=n6ttzHmbF8tc0ZDN8LIA6s_fnkZ3ylu3AAUAYyD9MzE,15048
9
9
  velocity/aws/handlers/__init__.py,sha256=xnpFZJVlC2uoeeFW4zuPST8wA8ajaQDky5Y6iXZzi3A,172
10
- velocity/aws/handlers/context.py,sha256=UIjNR83y2NSIyK8HMPX8t5tpJHFNabiZvNgmmdQL3HA,1822
11
- velocity/aws/handlers/lambda_handler.py,sha256=xfjjKhV2dv4Qsl36UwYBAfYJZJYfzLUB_MQ-Wd-1dio,6523
10
+ velocity/aws/handlers/context.py,sha256=tLGpMJ0i1KQZAiOPHO1GGn9KKZ_Z8gzZmc0bWp97VG8,8200
11
+ velocity/aws/handlers/lambda_handler.py,sha256=k8ZTj4vhuDbB9xinQ1-s7hKgx5JznldTNT3-udfMw04,6391
12
12
  velocity/aws/handlers/response.py,sha256=LXhtizLKnVBWjtHyE0h0bk-NYDrRpj7CHa7tRz9KkC4,9324
13
13
  velocity/aws/handlers/sqs_handler.py,sha256=nqt8NMOc5yO-L6CZo7NjgR8Q4KPKTDFBO-0eHu6oxkY,7149
14
14
  velocity/db/__init__.py,sha256=t7YJT42U19Vkd4MMz5MhU8IFryKfblNPLJcPqzpb4HQ,566
@@ -49,8 +49,8 @@ velocity/misc/tools.py,sha256=_bGneHHA_BV-kUonzw5H3hdJ5AOJRCKfzhgpkFbGqIo,1502
49
49
  velocity/misc/conv/__init__.py,sha256=MLYF58QHjzfDSxb1rdnmLnuEQCa3gnhzzZ30CwZVvQo,40
50
50
  velocity/misc/conv/iconv.py,sha256=d4_BucW8HTIkGNurJ7GWrtuptqUf-9t79ObzjJ5N76U,10603
51
51
  velocity/misc/conv/oconv.py,sha256=h5Lo05DqOQnxoD3y6Px_MQP_V-pBbWf8Hkgkb9Xp1jk,6032
52
- velocity_python-0.0.113.dist-info/licenses/LICENSE,sha256=aoN245GG8s9oRUU89KNiGTU4_4OtnNmVi4hQeChg6rM,1076
53
- velocity_python-0.0.113.dist-info/METADATA,sha256=YX1doLZ1xu-ELOzIK8UCRF_BVHyEUUIYN5h8rtd9Fs8,34262
54
- velocity_python-0.0.113.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
55
- velocity_python-0.0.113.dist-info/top_level.txt,sha256=JW2vJPmodgdgSz7H6yoZvnxF8S3fTMIv-YJWCT1sNW0,9
56
- velocity_python-0.0.113.dist-info/RECORD,,
52
+ velocity_python-0.0.116.dist-info/licenses/LICENSE,sha256=aoN245GG8s9oRUU89KNiGTU4_4OtnNmVi4hQeChg6rM,1076
53
+ velocity_python-0.0.116.dist-info/METADATA,sha256=781PKVf_fl9PmnetFsRQ7ZbdyhPVhqeFZ5i-gIsMqn8,34262
54
+ velocity_python-0.0.116.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
55
+ velocity_python-0.0.116.dist-info/top_level.txt,sha256=JW2vJPmodgdgSz7H6yoZvnxF8S3fTMIv-YJWCT1sNW0,9
56
+ velocity_python-0.0.116.dist-info/RECORD,,