velocity-python 0.0.116__py3-none-any.whl → 0.0.118__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.

Files changed (36) hide show
  1. velocity/__init__.py +3 -1
  2. velocity/aws/__init__.py +3 -0
  3. velocity/aws/amplify.py +10 -6
  4. velocity/aws/handlers/__init__.py +2 -0
  5. velocity/aws/handlers/base_handler.py +245 -0
  6. velocity/aws/handlers/context.py +58 -41
  7. velocity/aws/handlers/exceptions.py +16 -0
  8. velocity/aws/handlers/lambda_handler.py +15 -84
  9. velocity/aws/handlers/response.py +1 -1
  10. velocity/aws/handlers/sqs_handler.py +23 -144
  11. velocity/db/__init__.py +16 -1
  12. velocity/db/core/decorators.py +0 -1
  13. velocity/db/core/engine.py +33 -31
  14. velocity/db/core/exceptions.py +3 -0
  15. velocity/db/core/result.py +30 -24
  16. velocity/db/core/row.py +3 -1
  17. velocity/db/core/table.py +6 -5
  18. velocity/db/exceptions.py +35 -18
  19. velocity/db/servers/mysql.py +2 -3
  20. velocity/db/servers/postgres/__init__.py +10 -12
  21. velocity/db/servers/postgres/sql.py +36 -17
  22. velocity/db/servers/sqlite.py +2 -2
  23. velocity/db/servers/sqlserver.py +3 -3
  24. velocity/db/servers/tablehelper.py +117 -91
  25. velocity/db/utils.py +62 -47
  26. velocity/misc/conv/__init__.py +2 -0
  27. velocity/misc/conv/iconv.py +5 -4
  28. velocity/misc/export.py +1 -4
  29. velocity/misc/merge.py +1 -1
  30. velocity/misc/tools.py +0 -1
  31. {velocity_python-0.0.116.dist-info → velocity_python-0.0.118.dist-info}/METADATA +1 -1
  32. velocity_python-0.0.118.dist-info/RECORD +58 -0
  33. velocity_python-0.0.116.dist-info/RECORD +0 -56
  34. {velocity_python-0.0.116.dist-info → velocity_python-0.0.118.dist-info}/WHEEL +0 -0
  35. {velocity_python-0.0.116.dist-info → velocity_python-0.0.118.dist-info}/licenses/LICENSE +0 -0
  36. {velocity_python-0.0.116.dist-info → velocity_python-0.0.118.dist-info}/top_level.txt +0 -0
velocity/db/exceptions.py CHANGED
@@ -5,108 +5,125 @@ Database exceptions for the velocity library.
5
5
 
6
6
  class DbException(Exception):
7
7
  """Base class for all database exceptions."""
8
+
8
9
  pass
9
10
 
10
11
 
11
12
  class DbApplicationError(DbException):
12
13
  """Application-level database error."""
14
+
13
15
  pass
14
16
 
15
17
 
16
18
  class DbForeignKeyMissingError(DbException):
17
19
  """Foreign key constraint violation."""
20
+
18
21
  pass
19
22
 
20
23
 
21
24
  class DbDatabaseMissingError(DbException):
22
25
  """Database does not exist."""
26
+
23
27
  pass
24
28
 
25
29
 
26
30
  class DbTableMissingError(DbException):
27
31
  """Table does not exist."""
32
+
28
33
  pass
29
34
 
30
35
 
31
36
  class DbColumnMissingError(DbException):
32
37
  """Column does not exist."""
38
+
33
39
  pass
34
40
 
35
41
 
36
42
  class DbTruncationError(DbException):
37
43
  """Data truncation error."""
44
+
38
45
  pass
39
46
 
40
47
 
41
48
  class DbConnectionError(DbException):
42
49
  """Database connection error."""
50
+
43
51
  pass
44
52
 
45
53
 
46
54
  class DbDuplicateKeyError(DbException):
47
55
  """Duplicate key constraint violation."""
56
+
48
57
  pass
49
58
 
50
59
 
51
60
  class DbObjectExistsError(DbException):
52
61
  """Database object already exists."""
62
+
53
63
  pass
54
64
 
55
65
 
56
66
  class DbLockTimeoutError(DbException):
57
67
  """Lock timeout error."""
68
+
58
69
  pass
59
70
 
60
71
 
61
72
  class DbRetryTransaction(DbException):
62
73
  """Transaction should be retried."""
74
+
63
75
  pass
64
76
 
65
77
 
66
78
  class DbDataIntegrityError(DbException):
67
79
  """Data integrity constraint violation."""
80
+
68
81
  pass
69
82
 
70
83
 
71
84
  class DbQueryError(DbException):
72
85
  """Database query error."""
86
+
73
87
  pass
74
88
 
75
89
 
76
90
  class DbTransactionError(DbException):
77
91
  """Database transaction error."""
92
+
78
93
  pass
79
94
 
80
95
 
81
96
  class DuplicateRowsFoundError(Exception):
82
97
  """Multiple rows found when expecting single result."""
98
+
83
99
  pass
84
100
 
85
101
 
86
102
  # Add aliases for backward compatibility with engine.py
87
103
  class DatabaseError(DbException):
88
104
  """Generic database error - alias for DbException."""
105
+
89
106
  pass
90
107
 
108
+
91
109
  __all__ = [
92
110
  # Base exceptions
93
- 'DbException',
94
- 'DatabaseError',
95
-
111
+ "DbException",
112
+ "DatabaseError",
96
113
  # Specific exceptions
97
- 'DbApplicationError',
98
- 'DbForeignKeyMissingError',
99
- 'DbDatabaseMissingError',
100
- 'DbTableMissingError',
101
- 'DbColumnMissingError',
102
- 'DbTruncationError',
103
- 'DbConnectionError',
104
- 'DbDuplicateKeyError',
105
- 'DbObjectExistsError',
106
- 'DbLockTimeoutError',
107
- 'DbRetryTransaction',
108
- 'DbDataIntegrityError',
109
- 'DbQueryError',
110
- 'DbTransactionError',
111
- 'DuplicateRowsFoundError',
114
+ "DbApplicationError",
115
+ "DbForeignKeyMissingError",
116
+ "DbDatabaseMissingError",
117
+ "DbTableMissingError",
118
+ "DbColumnMissingError",
119
+ "DbTruncationError",
120
+ "DbConnectionError",
121
+ "DbDuplicateKeyError",
122
+ "DbObjectExistsError",
123
+ "DbLockTimeoutError",
124
+ "DbRetryTransaction",
125
+ "DbDataIntegrityError",
126
+ "DbQueryError",
127
+ "DbTransactionError",
128
+ "DuplicateRowsFoundError",
112
129
  ]
@@ -30,7 +30,7 @@ def make_where(where, sql, vals, is_join=False):
30
30
  if is_join:
31
31
  if "." not in key:
32
32
  key = "A." + key
33
- if val == None:
33
+ if val is None:
34
34
  if "!" in key:
35
35
  key = key.replace("!", "")
36
36
  sql.append("{} is not NULL".format(quote(key.lower())))
@@ -198,7 +198,7 @@ class SQL:
198
198
  cls, table, columns, key_to_table, key_to_columns, name=None, schema=None
199
199
  ):
200
200
  if "." not in table and schema:
201
- if schema == None:
201
+ if schema is None:
202
202
  schema = cls.default_schema
203
203
  table = "{}.{}".format(schema, table)
204
204
  if isinstance(key_to_columns, str):
@@ -254,7 +254,6 @@ class SQL:
254
254
 
255
255
  @classmethod
256
256
  def create_table(cls, name, columns={}, drop=False):
257
- trigger = "".format(name)
258
257
  sql = []
259
258
  if drop:
260
259
  sql.append(cls.drop_table(name))
@@ -4,16 +4,14 @@ from .sql import SQL
4
4
  from velocity.db.core import engine
5
5
 
6
6
 
7
-
8
7
  def initialize(config=None, **kwargs):
9
- if not config:
10
- # Keep the default config inside this function.
11
- config = {
12
- "database": os.environ["DBDatabase"],
13
- "host": os.environ["DBHost"],
14
- "port": os.environ["DBPort"],
15
- "user": os.environ["DBUser"],
16
- "password": os.environ["DBPassword"],
17
- }
18
- config.update(kwargs)
19
- return engine.Engine(psycopg2, config, SQL)
8
+ konfig = {
9
+ "database": os.environ["DBDatabase"],
10
+ "host": os.environ["DBHost"],
11
+ "port": os.environ["DBPort"],
12
+ "user": os.environ["DBUser"],
13
+ "password": os.environ["DBPassword"],
14
+ }
15
+ konfig.update(config or {})
16
+ konfig.update(kwargs)
17
+ return engine.Engine(psycopg2, konfig, SQL)
@@ -1,7 +1,7 @@
1
1
  import re
2
2
  import hashlib
3
3
  import sqlparse
4
- from psycopg2 import sql
4
+ from psycopg2 import sql as psycopg2_sql
5
5
 
6
6
  from velocity.db import exceptions
7
7
 
@@ -37,7 +37,7 @@ def _handle_predicate_errors(predicates, operation="WHERE"):
37
37
  """Process a list of predicates with error handling."""
38
38
  sql_parts = []
39
39
  vals = []
40
-
40
+
41
41
  for pred, val in predicates:
42
42
  sql_parts.append(pred)
43
43
  if val is None:
@@ -46,7 +46,7 @@ def _handle_predicate_errors(predicates, operation="WHERE"):
46
46
  vals.extend(val)
47
47
  else:
48
48
  vals.append(val)
49
-
49
+
50
50
  return sql_parts, vals
51
51
 
52
52
 
@@ -75,8 +75,19 @@ class SQL:
75
75
  ColumnMissingErrorCodes = ["42703"]
76
76
  ForeignKeyMissingErrorCodes = ["42704"]
77
77
 
78
- ConnectionErrorCodes = ["08001", "08S01", "57P03", "08006", "53300", "08003", "08004", "08P01"]
79
- DuplicateKeyErrorCodes = ["23505"] # unique_violation - no longer relying only on regex
78
+ ConnectionErrorCodes = [
79
+ "08001",
80
+ "08S01",
81
+ "57P03",
82
+ "08006",
83
+ "53300",
84
+ "08003",
85
+ "08004",
86
+ "08P01",
87
+ ]
88
+ DuplicateKeyErrorCodes = [
89
+ "23505"
90
+ ] # unique_violation - no longer relying only on regex
80
91
  RetryTransactionCodes = ["40001", "40P01", "40002"]
81
92
  TruncationErrorCodes = ["22001"]
82
93
  LockTimeoutErrorCodes = ["55P03"]
@@ -111,7 +122,7 @@ class SQL:
111
122
  """
112
123
  if not table:
113
124
  raise ValueError("Table name is required.")
114
-
125
+
115
126
  # Validate pagination parameters
116
127
  if start is not None and not isinstance(start, int):
117
128
  raise ValueError("Start (OFFSET) must be an integer.")
@@ -148,7 +159,7 @@ class SQL:
148
159
  columns = [c.strip() for c in columns if c.strip()] # Remove empty columns
149
160
  if not columns:
150
161
  raise ValueError("No valid columns specified")
151
-
162
+
152
163
  distinct = False
153
164
 
154
165
  # Check for DISTINCT keyword in any column
@@ -188,7 +199,7 @@ class SQL:
188
199
  new_orderby = []
189
200
  if isinstance(orderby, str):
190
201
  orderby = th.split_columns(orderby)
191
-
202
+
192
203
  # Handle orderby references
193
204
  if isinstance(orderby, Sequence):
194
205
  for column in orderby:
@@ -200,7 +211,9 @@ class SQL:
200
211
  # Validate direction
201
212
  direction = direction.upper()
202
213
  if direction not in ("ASC", "DESC"):
203
- raise ValueError(f"Invalid ORDER BY direction: {direction}")
214
+ raise ValueError(
215
+ f"Invalid ORDER BY direction: {direction}"
216
+ )
204
217
  col_name = th.resolve_references(
205
218
  col_name.strip(), options={"alias_only": True}
206
219
  )
@@ -213,7 +226,9 @@ class SQL:
213
226
  )
214
227
  new_orderby.append(resolved_col)
215
228
  except Exception as e:
216
- raise ValueError(f"Error processing ORDER BY column '{column}': {e}")
229
+ raise ValueError(
230
+ f"Error processing ORDER BY column '{column}': {e}"
231
+ )
217
232
 
218
233
  elif isinstance(orderby, Mapping):
219
234
  for key, val in orderby.items():
@@ -222,11 +237,13 @@ class SQL:
222
237
  direction = str(val).upper()
223
238
  if direction not in ("ASC", "DESC"):
224
239
  raise ValueError(f"Invalid ORDER BY direction: {direction}")
225
- parsed_key = th.resolve_references(key, options={"alias_only": True})
240
+ parsed_key = th.resolve_references(
241
+ key, options={"alias_only": True}
242
+ )
226
243
  new_orderby.append(f"{parsed_key} {direction}")
227
244
  except Exception as e:
228
245
  raise ValueError(f"Error processing ORDER BY key '{key}': {e}")
229
-
246
+
230
247
  orderby = new_orderby
231
248
 
232
249
  # Handle groupby
@@ -256,7 +273,9 @@ class SQL:
256
273
 
257
274
  # FROM clause
258
275
  if th.foreign_keys:
259
- sql_parts["FROM"].append(f"{TableHelper.quote(table)} AS {TableHelper.quote(alias)}")
276
+ sql_parts["FROM"].append(
277
+ f"{TableHelper.quote(table)} AS {TableHelper.quote(alias)}"
278
+ )
260
279
  # Handle joins
261
280
  done = []
262
281
  for key, ref_info in th.foreign_keys.items():
@@ -463,7 +482,7 @@ class SQL:
463
482
  # Create a temporary TableHelper instance for quoting
464
483
  # Note: We pass None for tx since we only need quoting functionality
465
484
  temp_helper = TableHelper(None, table)
466
-
485
+
467
486
  keys = []
468
487
  vals_placeholders = []
469
488
  args = []
@@ -966,7 +985,7 @@ class SQL:
966
985
  columns = TableHelper.quote(columns)
967
986
  sql = ["DROP"]
968
987
  sql.append("INDEX IF EXISTS")
969
- tablename = TableHelper.quote(table)
988
+ _tablename = TableHelper.quote(table)
970
989
  if not name:
971
990
  name = re.sub(
972
991
  r"\([^)]*\)",
@@ -1136,9 +1155,9 @@ class SQL:
1136
1155
  @classmethod
1137
1156
  def missing(cls, tx, table, list, column="SYS_ID", where=None):
1138
1157
  sql = [
1139
- f"SELECT * FROM",
1158
+ "SELECT * FROM",
1140
1159
  f"UNNEST('{{{','.join([str(x) for x in list])}}}'::int[]) id",
1141
- f"EXCEPT ALL",
1160
+ "EXCEPT ALL",
1142
1161
  f"SELECT {column} FROM {table}",
1143
1162
  ]
1144
1163
  vals = []
@@ -216,7 +216,7 @@ class SQL(object):
216
216
  if is_join:
217
217
  if "." not in key:
218
218
  key = "A." + key
219
- if val == None:
219
+ if val is None:
220
220
  if "!" in key:
221
221
  key = key.replace("!", "")
222
222
  sql.append("{} is not NULL".format(quote(key.lower())))
@@ -919,7 +919,7 @@ class SQL(object):
919
919
  for key in sorted(where.keys()):
920
920
  if join:
921
921
  sql.append(join)
922
- if where[key] == None:
922
+ if where[key] is None:
923
923
  sql.append("{} is NULL".format(quote(key.lower())))
924
924
  else:
925
925
  sql.append("{} = ?".format(quote(key.lower())))
@@ -30,7 +30,7 @@ def make_where(where, sql, vals, is_join=False):
30
30
  if is_join:
31
31
  if "." not in key:
32
32
  key = "A." + key
33
- if val == None:
33
+ if val is None:
34
34
  if "!" in key:
35
35
  key = key.replace("!", "")
36
36
  sql.append("{} is not NULL".format(quote(key.lower())))
@@ -394,7 +394,7 @@ class SQL:
394
394
  cls, table, columns, key_to_table, key_to_columns, name=None, schema=None
395
395
  ):
396
396
  if "." not in table and schema:
397
- if schema == None:
397
+ if schema is None:
398
398
  schema = cls.default_schema
399
399
  table = "{}.{}".format(schema, table)
400
400
  if isinstance(key_to_columns, str):
@@ -873,7 +873,7 @@ class SQL:
873
873
  for key in sorted(where.keys()):
874
874
  if join:
875
875
  sql.append(join)
876
- if where[key] == None:
876
+ if where[key] is None:
877
877
  sql.append("{} is NULL".format(quote(key.lower())))
878
878
  else:
879
879
  sql.append("{} = %s".format(quote(key.lower())))