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/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(field_name: str, default_value: Any = "") -> Callable[[dict], Any]:
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(rows: List[dict], field_name: str,
83
- none_handling: str = "last",
84
- default_value: Any = "",
85
- reverse: bool = False) -> List[dict]:
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(f"Invalid none_handling option: {none_handling}. "
127
- "Must be 'first', 'last', or 'default'")
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(grouped_rows: dict, field_name: str,
176
- none_handling: str = "last",
177
- default_value: Any = "",
178
- reverse: bool = False) -> dict:
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(rows, field_name, none_handling, default_value, reverse)
208
-
220
+ result[key] = safe_sort_rows(
221
+ rows, field_name, none_handling, default_value, reverse
222
+ )
223
+
209
224
  return result
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: velocity-python
3
- Version: 0.0.115
3
+ Version: 0.0.117
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,29 +1,31 @@
1
- velocity/__init__.py,sha256=89oRDLFlR3tlSTcYrvhfokSBF3tLPmP4nt_p9ayIScY,107
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=n6ttzHmbF8tc0ZDN8LIA6s_fnkZ3ylu3AAUAYyD9MzE,15048
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/context.py,sha256=saeK-2hpfbuOZvA76C1_2ZJSblPO_tDuKeaeDVfli1w,8052
11
- velocity/aws/handlers/lambda_handler.py,sha256=k8ZTj4vhuDbB9xinQ1-s7hKgx5JznldTNT3-udfMw04,6391
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=nqt8NMOc5yO-L6CZo7NjgR8Q4KPKTDFBO-0eHu6oxkY,7149
14
- velocity/db/__init__.py,sha256=t7YJT42U19Vkd4MMz5MhU8IFryKfblNPLJcPqzpb4HQ,566
15
- velocity/db/exceptions.py,sha256=oTXzdxP0GrraGrqRD1JgIVP5urO5yNN7A3IzTiAtNJ0,2173
16
- velocity/db/utils.py,sha256=3uUTLjMUC6g18bn7jRGBajYlXNFlBDZkGxIwQSBK_Y8,7298
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=Yy6uwxT44a4oEHrFF312ChzFO01cR2W79BTryFgTe-s,18635
22
- velocity/db/core/exceptions.py,sha256=tuDniRqTX8Opc2d033LPJOI3Ux4NSwUcHqW729n-HXA,1027
23
- velocity/db/core/result.py,sha256=dgiOXH-iJXuDH4PbSTWVkn-heAkJQcXCC-gs0ZuqF94,12814
24
- velocity/db/core/row.py,sha256=zZ3zZbWjZkZfYAYuZJLHFJ8jdXc7dYv8Iyv9Ut8W8tE,7261
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=oQFam6DwLnGiqa6v8Wys_yD_N4iWwfxGBwgLB5VUQSQ,34682
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=qOHHKgQgUC0t_AUcY5oaPfjkRJS9wnMI4YJCDIb9Rew,22583
36
- velocity/db/servers/postgres/__init__.py,sha256=FUvXO3R5CtKCTGRim1geisIxXbiG_aQ_VFSQX9HGsjw,529
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=vcdzj5PtlF3Qnt4Lh3y2OtaSuq4iLIUKyGP5F9vULE8,41576
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.115.dist-info/licenses/LICENSE,sha256=aoN245GG8s9oRUU89KNiGTU4_4OtnNmVi4hQeChg6rM,1076
53
- velocity_python-0.0.115.dist-info/METADATA,sha256=mH47xoUtbkjBSArI6QU7Mtx9qLjyPguYdAcVbPwtSLw,34262
54
- velocity_python-0.0.115.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
55
- velocity_python-0.0.115.dist-info/top_level.txt,sha256=JW2vJPmodgdgSz7H6yoZvnxF8S3fTMIv-YJWCT1sNW0,9
56
- velocity_python-0.0.115.dist-info/RECORD,,
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,,