velocity-python 0.0.115__py3-none-any.whl → 0.0.117__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 +1 -1
- velocity/aws/amplify.py +8 -3
- velocity/aws/handlers/base_handler.py +245 -0
- velocity/aws/handlers/context.py +66 -44
- velocity/aws/handlers/exceptions.py +16 -0
- velocity/aws/handlers/lambda_handler.py +12 -77
- velocity/aws/handlers/sqs_handler.py +22 -138
- velocity/db/__init__.py +1 -1
- velocity/db/core/engine.py +30 -26
- velocity/db/core/exceptions.py +3 -0
- velocity/db/core/result.py +30 -22
- velocity/db/core/row.py +3 -1
- velocity/db/core/table.py +2 -1
- velocity/db/exceptions.py +35 -18
- velocity/db/servers/postgres/__init__.py +10 -12
- velocity/db/servers/postgres/sql.py +32 -13
- velocity/db/servers/tablehelper.py +117 -91
- velocity/db/utils.py +61 -46
- {velocity_python-0.0.115.dist-info → velocity_python-0.0.117.dist-info}/METADATA +1 -1
- {velocity_python-0.0.115.dist-info → velocity_python-0.0.117.dist-info}/RECORD +23 -21
- {velocity_python-0.0.115.dist-info → velocity_python-0.0.117.dist-info}/WHEEL +0 -0
- {velocity_python-0.0.115.dist-info → velocity_python-0.0.117.dist-info}/licenses/LICENSE +0 -0
- {velocity_python-0.0.115.dist-info → velocity_python-0.0.117.dist-info}/top_level.txt +0 -0
velocity/db/utils.py
CHANGED
|
@@ -11,109 +11,117 @@ from typing import Any, Callable, List, Optional, Union
|
|
|
11
11
|
def safe_sort_key_none_last(field_name: str) -> Callable[[dict], tuple]:
|
|
12
12
|
"""
|
|
13
13
|
Create a sort key function that places None values at the end.
|
|
14
|
-
|
|
14
|
+
|
|
15
15
|
Args:
|
|
16
16
|
field_name: Name of the field to sort by
|
|
17
|
-
|
|
17
|
+
|
|
18
18
|
Returns:
|
|
19
19
|
A function suitable for use as a sort key that handles None values
|
|
20
|
-
|
|
20
|
+
|
|
21
21
|
Example:
|
|
22
22
|
rows = [{"date": "2024-01"}, {"date": None}, {"date": "2023-12"}]
|
|
23
23
|
sorted_rows = sorted(rows, key=safe_sort_key_none_last("date"))
|
|
24
24
|
# Result: [{"date": "2023-12"}, {"date": "2024-01"}, {"date": None}]
|
|
25
25
|
"""
|
|
26
|
+
|
|
26
27
|
def sort_key(row: dict) -> tuple:
|
|
27
28
|
value = row.get(field_name)
|
|
28
29
|
if value is None:
|
|
29
30
|
return (1, "") # None values sort last
|
|
30
31
|
return (0, value)
|
|
31
|
-
|
|
32
|
+
|
|
32
33
|
return sort_key
|
|
33
34
|
|
|
34
35
|
|
|
35
36
|
def safe_sort_key_none_first(field_name: str) -> Callable[[dict], tuple]:
|
|
36
37
|
"""
|
|
37
38
|
Create a sort key function that places None values at the beginning.
|
|
38
|
-
|
|
39
|
+
|
|
39
40
|
Args:
|
|
40
41
|
field_name: Name of the field to sort by
|
|
41
|
-
|
|
42
|
+
|
|
42
43
|
Returns:
|
|
43
44
|
A function suitable for use as a sort key that handles None values
|
|
44
|
-
|
|
45
|
+
|
|
45
46
|
Example:
|
|
46
47
|
rows = [{"date": "2024-01"}, {"date": None}, {"date": "2023-12"}]
|
|
47
48
|
sorted_rows = sorted(rows, key=safe_sort_key_none_first("date"))
|
|
48
49
|
# Result: [{"date": None}, {"date": "2023-12"}, {"date": "2024-01"}]
|
|
49
50
|
"""
|
|
51
|
+
|
|
50
52
|
def sort_key(row: dict) -> tuple:
|
|
51
53
|
value = row.get(field_name)
|
|
52
54
|
if value is None:
|
|
53
55
|
return (0, "") # None values sort first
|
|
54
56
|
return (1, value)
|
|
55
|
-
|
|
57
|
+
|
|
56
58
|
return sort_key
|
|
57
59
|
|
|
58
60
|
|
|
59
|
-
def safe_sort_key_with_default(
|
|
61
|
+
def safe_sort_key_with_default(
|
|
62
|
+
field_name: str, default_value: Any = ""
|
|
63
|
+
) -> Callable[[dict], Any]:
|
|
60
64
|
"""
|
|
61
65
|
Create a sort key function that replaces None values with a default.
|
|
62
|
-
|
|
66
|
+
|
|
63
67
|
Args:
|
|
64
68
|
field_name: Name of the field to sort by
|
|
65
69
|
default_value: Value to use for None entries
|
|
66
|
-
|
|
70
|
+
|
|
67
71
|
Returns:
|
|
68
72
|
A function suitable for use as a sort key that handles None values
|
|
69
|
-
|
|
73
|
+
|
|
70
74
|
Example:
|
|
71
75
|
rows = [{"date": "2024-01"}, {"date": None}, {"date": "2023-12"}]
|
|
72
76
|
sorted_rows = sorted(rows, key=safe_sort_key_with_default("date", "1900-01"))
|
|
73
77
|
# Result: [{"date": None}, {"date": "2023-12"}, {"date": "2024-01"}]
|
|
74
78
|
"""
|
|
79
|
+
|
|
75
80
|
def sort_key(row: dict) -> Any:
|
|
76
81
|
value = row.get(field_name)
|
|
77
82
|
return default_value if value is None else value
|
|
78
|
-
|
|
83
|
+
|
|
79
84
|
return sort_key
|
|
80
85
|
|
|
81
86
|
|
|
82
|
-
def safe_sort_rows(
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
87
|
+
def safe_sort_rows(
|
|
88
|
+
rows: List[dict],
|
|
89
|
+
field_name: str,
|
|
90
|
+
none_handling: str = "last",
|
|
91
|
+
default_value: Any = "",
|
|
92
|
+
reverse: bool = False,
|
|
93
|
+
) -> List[dict]:
|
|
86
94
|
"""
|
|
87
95
|
Safely sort a list of dictionaries by a field that may contain None values.
|
|
88
|
-
|
|
96
|
+
|
|
89
97
|
Args:
|
|
90
98
|
rows: List of dictionaries to sort
|
|
91
99
|
field_name: Name of the field to sort by
|
|
92
100
|
none_handling: How to handle None values - "first", "last", or "default"
|
|
93
101
|
default_value: Default value to use when none_handling is "default"
|
|
94
102
|
reverse: Whether to reverse the sort order
|
|
95
|
-
|
|
103
|
+
|
|
96
104
|
Returns:
|
|
97
105
|
New list of dictionaries sorted by the specified field
|
|
98
|
-
|
|
106
|
+
|
|
99
107
|
Raises:
|
|
100
108
|
ValueError: If none_handling is not a valid option
|
|
101
|
-
|
|
109
|
+
|
|
102
110
|
Example:
|
|
103
111
|
rows = [
|
|
104
112
|
{"name": "Alice", "date": "2024-01"},
|
|
105
113
|
{"name": "Bob", "date": None},
|
|
106
114
|
{"name": "Charlie", "date": "2023-12"}
|
|
107
115
|
]
|
|
108
|
-
|
|
116
|
+
|
|
109
117
|
# None values last
|
|
110
118
|
sorted_rows = safe_sort_rows(rows, "date")
|
|
111
|
-
|
|
112
|
-
# None values first
|
|
119
|
+
|
|
120
|
+
# None values first
|
|
113
121
|
sorted_rows = safe_sort_rows(rows, "date", none_handling="first")
|
|
114
|
-
|
|
122
|
+
|
|
115
123
|
# Replace None with default
|
|
116
|
-
sorted_rows = safe_sort_rows(rows, "date", none_handling="default",
|
|
124
|
+
sorted_rows = safe_sort_rows(rows, "date", none_handling="default",
|
|
117
125
|
default_value="1900-01")
|
|
118
126
|
"""
|
|
119
127
|
if none_handling == "last":
|
|
@@ -123,37 +131,39 @@ def safe_sort_rows(rows: List[dict], field_name: str,
|
|
|
123
131
|
elif none_handling == "default":
|
|
124
132
|
key_func = safe_sort_key_with_default(field_name, default_value)
|
|
125
133
|
else:
|
|
126
|
-
raise ValueError(
|
|
127
|
-
|
|
128
|
-
|
|
134
|
+
raise ValueError(
|
|
135
|
+
f"Invalid none_handling option: {none_handling}. "
|
|
136
|
+
"Must be 'first', 'last', or 'default'"
|
|
137
|
+
)
|
|
138
|
+
|
|
129
139
|
return sorted(rows, key=key_func, reverse=reverse)
|
|
130
140
|
|
|
131
141
|
|
|
132
142
|
def group_by_fields(rows: List[dict], *field_names: str) -> dict:
|
|
133
143
|
"""
|
|
134
144
|
Group rows by one or more field values.
|
|
135
|
-
|
|
145
|
+
|
|
136
146
|
Args:
|
|
137
147
|
rows: List of dictionaries to group
|
|
138
148
|
*field_names: Names of fields to group by
|
|
139
|
-
|
|
149
|
+
|
|
140
150
|
Returns:
|
|
141
151
|
Dictionary where keys are tuples of field values and values are lists of rows
|
|
142
|
-
|
|
152
|
+
|
|
143
153
|
Example:
|
|
144
154
|
rows = [
|
|
145
155
|
{"email": "alice@example.com", "type": "premium", "amount": 100},
|
|
146
156
|
{"email": "alice@example.com", "type": "basic", "amount": 50},
|
|
147
157
|
{"email": "bob@example.com", "type": "premium", "amount": 100},
|
|
148
158
|
]
|
|
149
|
-
|
|
159
|
+
|
|
150
160
|
# Group by email only
|
|
151
161
|
groups = group_by_fields(rows, "email")
|
|
152
162
|
# Result: {
|
|
153
163
|
# ("alice@example.com",): [row1, row2],
|
|
154
164
|
# ("bob@example.com",): [row3]
|
|
155
165
|
# }
|
|
156
|
-
|
|
166
|
+
|
|
157
167
|
# Group by email and type
|
|
158
168
|
groups = group_by_fields(rows, "email", "type")
|
|
159
169
|
# Result: {
|
|
@@ -168,34 +178,37 @@ def group_by_fields(rows: List[dict], *field_names: str) -> dict:
|
|
|
168
178
|
if key not in groups:
|
|
169
179
|
groups[key] = []
|
|
170
180
|
groups[key].append(row)
|
|
171
|
-
|
|
181
|
+
|
|
172
182
|
return groups
|
|
173
183
|
|
|
174
184
|
|
|
175
|
-
def safe_sort_grouped_rows(
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
185
|
+
def safe_sort_grouped_rows(
|
|
186
|
+
grouped_rows: dict,
|
|
187
|
+
field_name: str,
|
|
188
|
+
none_handling: str = "last",
|
|
189
|
+
default_value: Any = "",
|
|
190
|
+
reverse: bool = False,
|
|
191
|
+
) -> dict:
|
|
179
192
|
"""
|
|
180
193
|
Safely sort rows within each group of a grouped result.
|
|
181
|
-
|
|
194
|
+
|
|
182
195
|
Args:
|
|
183
196
|
grouped_rows: Dictionary of grouped rows (from group_by_fields)
|
|
184
197
|
field_name: Name of the field to sort by within each group
|
|
185
198
|
none_handling: How to handle None values - "first", "last", or "default"
|
|
186
199
|
default_value: Default value to use when none_handling is "default"
|
|
187
200
|
reverse: Whether to reverse the sort order
|
|
188
|
-
|
|
201
|
+
|
|
189
202
|
Returns:
|
|
190
203
|
Dictionary with the same keys but sorted lists as values
|
|
191
|
-
|
|
204
|
+
|
|
192
205
|
Example:
|
|
193
206
|
# After grouping payment profiles by email and card number
|
|
194
207
|
groups = group_by_fields(payment_profiles, "email_address", "card_number")
|
|
195
|
-
|
|
208
|
+
|
|
196
209
|
# Sort each group by expiration date, with None values last
|
|
197
210
|
sorted_groups = safe_sort_grouped_rows(groups, "expiration_date")
|
|
198
|
-
|
|
211
|
+
|
|
199
212
|
# Now process each sorted group
|
|
200
213
|
for group_key, sorted_group in sorted_groups.items():
|
|
201
214
|
for idx, row in enumerate(sorted_group):
|
|
@@ -204,6 +217,8 @@ def safe_sort_grouped_rows(grouped_rows: dict, field_name: str,
|
|
|
204
217
|
"""
|
|
205
218
|
result = {}
|
|
206
219
|
for key, rows in grouped_rows.items():
|
|
207
|
-
result[key] = safe_sort_rows(
|
|
208
|
-
|
|
220
|
+
result[key] = safe_sort_rows(
|
|
221
|
+
rows, field_name, none_handling, default_value, reverse
|
|
222
|
+
)
|
|
223
|
+
|
|
209
224
|
return result
|
|
@@ -1,29 +1,31 @@
|
|
|
1
|
-
velocity/__init__.py,sha256=
|
|
1
|
+
velocity/__init__.py,sha256=vYepl_-j4oCRAfwn61jSaTKIXufh522rvwO4XYqn_es,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
|
|
5
5
|
velocity/app/payments.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
6
6
|
velocity/app/purchase_orders.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
7
7
|
velocity/aws/__init__.py,sha256=tj9-NliYxRVPYLnnDuA4FMwBHbbH4ed8gtHgwRskNgY,647
|
|
8
|
-
velocity/aws/amplify.py,sha256=
|
|
8
|
+
velocity/aws/amplify.py,sha256=ygu_QrZUMahOYIJfnri-AW-2r-3Xpn6zJr8vyTtSz9w,15284
|
|
9
9
|
velocity/aws/handlers/__init__.py,sha256=xnpFZJVlC2uoeeFW4zuPST8wA8ajaQDky5Y6iXZzi3A,172
|
|
10
|
-
velocity/aws/handlers/
|
|
11
|
-
velocity/aws/handlers/
|
|
10
|
+
velocity/aws/handlers/base_handler.py,sha256=rnEX5X4a5P-FO9Va0-9ZJYCqfqtjvuf101UTz1Vfqyg,7822
|
|
11
|
+
velocity/aws/handlers/context.py,sha256=Mf6Cnu4_dmYB870l51cVI9Mkd3IoE2-WdSty2qCwC0E,8354
|
|
12
|
+
velocity/aws/handlers/exceptions.py,sha256=i4wcB8ZSWUHglX2xnesDlWLsU9AMYU72cHCWRBDmjQ8,361
|
|
13
|
+
velocity/aws/handlers/lambda_handler.py,sha256=fKbTOYpN_scXFGGWMhB8tlsPYVGiX9RZyuq5rXQsOhU,4060
|
|
12
14
|
velocity/aws/handlers/response.py,sha256=LXhtizLKnVBWjtHyE0h0bk-NYDrRpj7CHa7tRz9KkC4,9324
|
|
13
|
-
velocity/aws/handlers/sqs_handler.py,sha256=
|
|
14
|
-
velocity/db/__init__.py,sha256=
|
|
15
|
-
velocity/db/exceptions.py,sha256=
|
|
16
|
-
velocity/db/utils.py,sha256=
|
|
15
|
+
velocity/aws/handlers/sqs_handler.py,sha256=rVOuLrrays1dO69S0snYnK9ImXYQ35l8ZzJTeXcEOfc,3269
|
|
16
|
+
velocity/db/__init__.py,sha256=buxlhBZNQd2UjryPXJGiAzcgcIoBCucEXXhWJF1cMYI,567
|
|
17
|
+
velocity/db/exceptions.py,sha256=XHREJvzNctrtYE-ScBRLnbk7thxTswkfWojKhMmBmd8,2185
|
|
18
|
+
velocity/db/utils.py,sha256=JUGr7G-kRk4LPjDkZrmI8DHPHw9lZHukBVZNjCGMWZ4,7037
|
|
17
19
|
velocity/db/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
18
20
|
velocity/db/core/column.py,sha256=tAr8tL3a2nyaYpNHhGl508FrY_pGZTzyYgjAV5CEBv4,4092
|
|
19
21
|
velocity/db/core/database.py,sha256=3zNGItklu9tZCKsbx2T2vCcU1so8AL9PPL0DLjvaz6s,3554
|
|
20
22
|
velocity/db/core/decorators.py,sha256=76Jkr9XptXt8cvcgp1zbHfuL8uHzWy8lwfR29u-DVu4,4574
|
|
21
|
-
velocity/db/core/engine.py,sha256=
|
|
22
|
-
velocity/db/core/exceptions.py,sha256=
|
|
23
|
-
velocity/db/core/result.py,sha256=
|
|
24
|
-
velocity/db/core/row.py,sha256=
|
|
23
|
+
velocity/db/core/engine.py,sha256=cgiDWSAiMlkuJqzWtw7GaxejvSMtxlerRFb78aKS2ek,18491
|
|
24
|
+
velocity/db/core/exceptions.py,sha256=9jhPtxagHZtGdMcSwa2uRe82Gqydla5fWCqs4v-Ah8U,1030
|
|
25
|
+
velocity/db/core/result.py,sha256=FvI7dtXM-8vFeN5DWu0oc4O_smGJBqRvQ1V6SsEPog8,12844
|
|
26
|
+
velocity/db/core/row.py,sha256=yqxm03uEDy3oSbnkCtKyiqFdSqG3zXTq2HIHYKOvPY4,7291
|
|
25
27
|
velocity/db/core/sequence.py,sha256=VMBc0ZjGnOaWTwKW6xMNTdP8rZ2umQ8ml4fHTTwuGq4,3904
|
|
26
|
-
velocity/db/core/table.py,sha256=
|
|
28
|
+
velocity/db/core/table.py,sha256=yyv7Glds194Zp-ooA_iaqcmrVpWyoVFni1bLegLDays,34685
|
|
27
29
|
velocity/db/core/transaction.py,sha256=unjmVkkfb7D8Wow6V8V8aLaxUZo316i--ksZxc4-I1Q,6613
|
|
28
30
|
velocity/db/servers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
29
31
|
velocity/db/servers/mysql.py,sha256=qHwlB_Mg02R7QFjD5QvJCorYYiP50CqEiQyZVl3uYns,20914
|
|
@@ -32,11 +34,11 @@ velocity/db/servers/sqlite.py,sha256=X210a5pENT9PiVK7f16fxXzFwEsq8fSe58Vouv2xqlk
|
|
|
32
34
|
velocity/db/servers/sqlite_reserved.py,sha256=-xmjl-Hgu6lKqkCAXq_6U8_aJX6gvaMgLMLdCt-Ej7o,3006
|
|
33
35
|
velocity/db/servers/sqlserver.py,sha256=0uGLEWRXiUhrOVTpEA1zvaKq1mcfiaCDp9r7gX-N71g,29914
|
|
34
36
|
velocity/db/servers/sqlserver_reserved.py,sha256=3LGQYU0qfvk6AbKety96gbzzfLbZ0dNHDPLxKGvvi4Q,4596
|
|
35
|
-
velocity/db/servers/tablehelper.py,sha256=
|
|
36
|
-
velocity/db/servers/postgres/__init__.py,sha256=
|
|
37
|
+
velocity/db/servers/tablehelper.py,sha256=Q48ObN5KD_U2sBP0GUcjaQjKeE4Hr351sPQirwQ0_1s,22163
|
|
38
|
+
velocity/db/servers/postgres/__init__.py,sha256=saeE5iySVYMHCwlKMsHFYdPJmuLy33I9BpPUE0czUas,457
|
|
37
39
|
velocity/db/servers/postgres/operators.py,sha256=A2T1qFwhzPl0fdXVhLZJhh5Qfx-qF8oZsDnxnq2n_V8,389
|
|
38
40
|
velocity/db/servers/postgres/reserved.py,sha256=5tKLaqFV-HrWRj-nsrxl5KGbmeM3ukn_bPZK36XEu8M,3648
|
|
39
|
-
velocity/db/servers/postgres/sql.py,sha256=
|
|
41
|
+
velocity/db/servers/postgres/sql.py,sha256=okWDm8Bj_vzSLTAIFQS5rHuIZz4WvAGNSHMZQtL5inI,41781
|
|
40
42
|
velocity/db/servers/postgres/types.py,sha256=Wa45ppVf_pdWul-jYWFRGMl6IdSq8dAp10SKnhL7osQ,3757
|
|
41
43
|
velocity/misc/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
42
44
|
velocity/misc/db.py,sha256=MPgt-kkukKR_Wh_S_5W-MyDgaeoZ4YLoDJ54wU2ppm4,2830
|
|
@@ -49,8 +51,8 @@ velocity/misc/tools.py,sha256=_bGneHHA_BV-kUonzw5H3hdJ5AOJRCKfzhgpkFbGqIo,1502
|
|
|
49
51
|
velocity/misc/conv/__init__.py,sha256=MLYF58QHjzfDSxb1rdnmLnuEQCa3gnhzzZ30CwZVvQo,40
|
|
50
52
|
velocity/misc/conv/iconv.py,sha256=d4_BucW8HTIkGNurJ7GWrtuptqUf-9t79ObzjJ5N76U,10603
|
|
51
53
|
velocity/misc/conv/oconv.py,sha256=h5Lo05DqOQnxoD3y6Px_MQP_V-pBbWf8Hkgkb9Xp1jk,6032
|
|
52
|
-
velocity_python-0.0.
|
|
53
|
-
velocity_python-0.0.
|
|
54
|
-
velocity_python-0.0.
|
|
55
|
-
velocity_python-0.0.
|
|
56
|
-
velocity_python-0.0.
|
|
54
|
+
velocity_python-0.0.117.dist-info/licenses/LICENSE,sha256=aoN245GG8s9oRUU89KNiGTU4_4OtnNmVi4hQeChg6rM,1076
|
|
55
|
+
velocity_python-0.0.117.dist-info/METADATA,sha256=YYvat0naHNdq7pBtNCBxBJ7SBKdhsFy0rOIbhKj4RNY,34262
|
|
56
|
+
velocity_python-0.0.117.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
57
|
+
velocity_python-0.0.117.dist-info/top_level.txt,sha256=JW2vJPmodgdgSz7H6yoZvnxF8S3fTMIv-YJWCT1sNW0,9
|
|
58
|
+
velocity_python-0.0.117.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|