velocity-python 0.0.129__py3-none-any.whl → 0.0.132__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 (40) hide show
  1. velocity/__init__.py +1 -1
  2. velocity/aws/handlers/mixins/__init__.py +16 -0
  3. velocity/aws/handlers/mixins/activity_tracker.py +142 -0
  4. velocity/aws/handlers/mixins/error_handler.py +192 -0
  5. velocity/aws/handlers/mixins/legacy_mixin.py +53 -0
  6. velocity/aws/handlers/mixins/standard_mixin.py +73 -0
  7. velocity/db/servers/base/__init__.py +9 -0
  8. velocity/db/servers/base/initializer.py +69 -0
  9. velocity/db/servers/base/operators.py +98 -0
  10. velocity/db/servers/base/sql.py +503 -0
  11. velocity/db/servers/base/types.py +135 -0
  12. velocity/db/servers/mysql/__init__.py +64 -0
  13. velocity/db/servers/mysql/operators.py +54 -0
  14. velocity/db/servers/{mysql_reserved.py → mysql/reserved.py} +2 -14
  15. velocity/db/servers/mysql/sql.py +569 -0
  16. velocity/db/servers/mysql/types.py +107 -0
  17. velocity/db/servers/postgres/__init__.py +40 -0
  18. velocity/db/servers/postgres/operators.py +34 -0
  19. velocity/db/servers/postgres/sql.py +4 -3
  20. velocity/db/servers/postgres/types.py +88 -2
  21. velocity/db/servers/sqlite/__init__.py +52 -0
  22. velocity/db/servers/sqlite/operators.py +52 -0
  23. velocity/db/servers/sqlite/reserved.py +20 -0
  24. velocity/db/servers/sqlite/sql.py +530 -0
  25. velocity/db/servers/sqlite/types.py +92 -0
  26. velocity/db/servers/sqlserver/__init__.py +64 -0
  27. velocity/db/servers/sqlserver/operators.py +47 -0
  28. velocity/db/servers/sqlserver/reserved.py +32 -0
  29. velocity/db/servers/sqlserver/sql.py +625 -0
  30. velocity/db/servers/sqlserver/types.py +114 -0
  31. {velocity_python-0.0.129.dist-info → velocity_python-0.0.132.dist-info}/METADATA +1 -1
  32. {velocity_python-0.0.129.dist-info → velocity_python-0.0.132.dist-info}/RECORD +35 -16
  33. velocity/db/servers/mysql.py +0 -640
  34. velocity/db/servers/sqlite.py +0 -968
  35. velocity/db/servers/sqlite_reserved.py +0 -208
  36. velocity/db/servers/sqlserver.py +0 -921
  37. velocity/db/servers/sqlserver_reserved.py +0 -314
  38. {velocity_python-0.0.129.dist-info → velocity_python-0.0.132.dist-info}/WHEEL +0 -0
  39. {velocity_python-0.0.129.dist-info → velocity_python-0.0.132.dist-info}/licenses/LICENSE +0 -0
  40. {velocity_python-0.0.129.dist-info → velocity_python-0.0.132.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,107 @@
1
+ import decimal
2
+ import datetime
3
+ from ..base.types import BaseTypes
4
+
5
+
6
+ class TYPES(BaseTypes):
7
+ """
8
+ MySQL-specific type mapping implementation.
9
+ """
10
+
11
+ TEXT = "TEXT"
12
+ INTEGER = "INTEGER"
13
+ NUMERIC = "DECIMAL"
14
+ DATETIME = "DATETIME"
15
+ TIMESTAMP = "TIMESTAMP"
16
+ DATE = "DATE"
17
+ TIME = "TIME"
18
+ BIGINT = "BIGINT"
19
+ SMALLINT = "SMALLINT"
20
+ TINYINT = "TINYINT"
21
+ BOOLEAN = "BOOLEAN"
22
+ BINARY = "BLOB"
23
+ LONGTEXT = "LONGTEXT"
24
+ MEDIUMTEXT = "MEDIUMTEXT"
25
+ VARCHAR = "VARCHAR"
26
+
27
+ @classmethod
28
+ def get_type(cls, v):
29
+ """
30
+ Returns a suitable SQL type string for a Python value/object (MySQL).
31
+ """
32
+ is_special, special_val = cls._handle_special_values(v)
33
+ if is_special:
34
+ return special_val
35
+
36
+ if isinstance(v, str) or v is str:
37
+ return cls.TEXT
38
+ if isinstance(v, bool) or v is bool:
39
+ return cls.BOOLEAN
40
+ if isinstance(v, int) or v is int:
41
+ return cls.BIGINT
42
+ if isinstance(v, float) or v is float:
43
+ return f"{cls.NUMERIC}(19, 6)"
44
+ if isinstance(v, decimal.Decimal) or v is decimal.Decimal:
45
+ return f"{cls.NUMERIC}(19, 6)"
46
+ if isinstance(v, datetime.datetime) or v is datetime.datetime:
47
+ return cls.DATETIME
48
+ if isinstance(v, datetime.date) or v is datetime.date:
49
+ return cls.DATE
50
+ if isinstance(v, datetime.time) or v is datetime.time:
51
+ return cls.TIME
52
+ if isinstance(v, bytes) or v is bytes:
53
+ return cls.BINARY
54
+ return cls.TEXT
55
+
56
+ @classmethod
57
+ def get_conv(cls, v):
58
+ """
59
+ Returns a base SQL type for expression usage (MySQL).
60
+ """
61
+ is_special, special_val = cls._handle_special_values(v)
62
+ if is_special:
63
+ return special_val
64
+
65
+ if isinstance(v, str) or v is str:
66
+ return cls.TEXT
67
+ if isinstance(v, bool) or v is bool:
68
+ return cls.BOOLEAN
69
+ if isinstance(v, int) or v is int:
70
+ return cls.BIGINT
71
+ if isinstance(v, float) or v is float:
72
+ return cls.NUMERIC
73
+ if isinstance(v, decimal.Decimal) or v is decimal.Decimal:
74
+ return cls.NUMERIC
75
+ if isinstance(v, datetime.datetime) or v is datetime.datetime:
76
+ return cls.DATETIME
77
+ if isinstance(v, datetime.date) or v is datetime.date:
78
+ return cls.DATE
79
+ if isinstance(v, datetime.time) or v is datetime.time:
80
+ return cls.TIME
81
+ if isinstance(v, bytes) or v is bytes:
82
+ return cls.BINARY
83
+ return cls.TEXT
84
+
85
+ @classmethod
86
+ def py_type(cls, v):
87
+ """
88
+ Returns the Python type that corresponds to an SQL type string (MySQL).
89
+ """
90
+ v = str(v).upper()
91
+ if v in (cls.INTEGER, cls.SMALLINT, cls.BIGINT, cls.TINYINT):
92
+ return int
93
+ if v == cls.NUMERIC or "DECIMAL" in v:
94
+ return decimal.Decimal
95
+ if v in (cls.TEXT, cls.LONGTEXT, cls.MEDIUMTEXT, cls.VARCHAR) or "VARCHAR" in v or "CHAR" in v:
96
+ return str
97
+ if v == cls.BOOLEAN:
98
+ return bool
99
+ if v == cls.DATE:
100
+ return datetime.date
101
+ if v == cls.TIME:
102
+ return datetime.time
103
+ if v in (cls.DATETIME, cls.TIMESTAMP):
104
+ return datetime.datetime
105
+ if v == cls.BINARY or "BLOB" in v:
106
+ return bytes
107
+ raise Exception(f"Unmapped MySQL type {v}")
@@ -1,10 +1,50 @@
1
1
  import os
2
2
  import psycopg2
3
3
  from .sql import SQL
4
+ from ..base.initializer import BaseInitializer
4
5
  from velocity.db.core import engine
5
6
 
6
7
 
8
+ class PostgreSQLInitializer(BaseInitializer):
9
+ """PostgreSQL database initializer."""
10
+
11
+ @staticmethod
12
+ def initialize(config=None, **kwargs):
13
+ """
14
+ Initialize PostgreSQL engine with psycopg2 driver.
15
+
16
+ Args:
17
+ config: Configuration dictionary
18
+ **kwargs: Additional configuration parameters
19
+
20
+ Returns:
21
+ Configured Engine instance
22
+ """
23
+ # Base configuration from environment
24
+ base_config = {
25
+ "database": os.environ.get("DBDatabase"),
26
+ "host": os.environ.get("DBHost"),
27
+ "port": os.environ.get("DBPort"),
28
+ "user": os.environ.get("DBUser"),
29
+ "password": os.environ.get("DBPassword"),
30
+ }
31
+
32
+ # Remove None values
33
+ base_config = {k: v for k, v in base_config.items() if v is not None}
34
+
35
+ # Merge configurations
36
+ final_config = PostgreSQLInitializer._merge_config(base_config, config, **kwargs)
37
+
38
+ # Validate required configuration
39
+ required_keys = ["database", "host", "user", "password"]
40
+ PostgreSQLInitializer._validate_required_config(final_config, required_keys)
41
+
42
+ return engine.Engine(psycopg2, final_config, SQL)
43
+
44
+
45
+ # Maintain backward compatibility
7
46
  def initialize(config=None, **kwargs):
47
+ """Backward compatible initialization function - matches original behavior exactly."""
8
48
  konfig = {
9
49
  "database": os.environ["DBDatabase"],
10
50
  "host": os.environ["DBHost"],
@@ -1,3 +1,37 @@
1
+ from ..base.operators import BaseOperators
2
+
3
+
4
+ class PostgreSQLOperators(BaseOperators):
5
+ """
6
+ PostgreSQL-specific operator mappings.
7
+ """
8
+
9
+ @classmethod
10
+ def get_operators(cls):
11
+ """Returns PostgreSQL-specific operator mappings."""
12
+ return OPERATORS
13
+
14
+ @classmethod
15
+ def supports_case_insensitive_like(cls):
16
+ """PostgreSQL supports ILIKE for case-insensitive matching."""
17
+ return True
18
+
19
+ @classmethod
20
+ def supports_regex(cls):
21
+ """PostgreSQL supports regex operators."""
22
+ return True
23
+
24
+ @classmethod
25
+ def get_regex_operators(cls):
26
+ """Returns PostgreSQL regex operators."""
27
+ return {
28
+ "~": "~",
29
+ "!~": "!~",
30
+ "~*": "~*",
31
+ "!~*": "!~*",
32
+ }
33
+
34
+
1
35
  OPERATORS = {
2
36
  "<>": "<>",
3
37
  "!=": "<>",
@@ -4,10 +4,11 @@ import sqlparse
4
4
  from psycopg2 import sql as psycopg2_sql
5
5
 
6
6
  from velocity.db import exceptions
7
+ from ..base.sql import BaseSQLDialect
7
8
 
8
9
  from .reserved import reserved_words
9
10
  from .types import TYPES
10
- from .operators import OPERATORS
11
+ from .operators import OPERATORS, PostgreSQLOperators
11
12
  from ..tablehelper import TableHelper
12
13
  from collections.abc import Mapping, Sequence
13
14
 
@@ -61,7 +62,7 @@ system_fields = [
61
62
  ]
62
63
 
63
64
 
64
- class SQL:
65
+ class SQL(BaseSQLDialect):
65
66
  server = "PostGreSQL"
66
67
  type_column_identifier = "data_type"
67
68
  is_nullable = "is_nullable"
@@ -95,7 +96,7 @@ class SQL:
95
96
  DataIntegrityErrorCodes = ["23503", "23502", "23514", "23P01", "22003"]
96
97
 
97
98
  @classmethod
98
- def get_error(self, e):
99
+ def get_error(cls, e):
99
100
  error_code = getattr(e, "pgcode", None)
100
101
  error_mesg = getattr(e, "pgerror", None)
101
102
  return error_code, error_mesg
@@ -1,10 +1,11 @@
1
1
  import decimal
2
2
  import datetime
3
+ from ..base.types import BaseTypes
3
4
 
4
5
 
5
- class TYPES:
6
+ class TYPES(BaseTypes):
6
7
  """
7
- A simple mapping of Python types <-> SQL types (for PostgreSQL).
8
+ PostgreSQL-specific type mapping implementation.
8
9
  """
9
10
 
10
11
  TEXT = "TEXT"
@@ -107,3 +108,88 @@ class TYPES:
107
108
  if v == cls.DATETIME_TZ or v == cls.TIMESTAMP_TZ:
108
109
  return datetime.datetime
109
110
  raise Exception(f"Unmapped type {v}")
111
+
112
+ @classmethod
113
+ def get_type(cls, v):
114
+ """
115
+ Returns a suitable SQL type string for a Python value/object.
116
+ """
117
+ if isinstance(v, str) and v.startswith("@@"):
118
+ # e.g. @@CURRENT_TIMESTAMP => special usage
119
+ return v[2:] or cls.TEXT
120
+ if isinstance(v, str) or v is str:
121
+ return cls.TEXT
122
+ if isinstance(v, bool) or v is bool:
123
+ return cls.BOOLEAN
124
+ if isinstance(v, int) or v is int:
125
+ return cls.BIGINT
126
+ if isinstance(v, float) or v is float:
127
+ return f"{cls.NUMERIC}(19, 6)"
128
+ if isinstance(v, decimal.Decimal) or v is decimal.Decimal:
129
+ return f"{cls.NUMERIC}(19, 6)"
130
+ if isinstance(v, datetime.datetime) or v is datetime.datetime:
131
+ return cls.DATETIME
132
+ if isinstance(v, datetime.date) or v is datetime.date:
133
+ return cls.DATE
134
+ if isinstance(v, datetime.time) or v is datetime.time:
135
+ return cls.TIME
136
+ if isinstance(v, datetime.timedelta) or v is datetime.timedelta:
137
+ return cls.INTERVAL
138
+ if isinstance(v, bytes) or v is bytes:
139
+ return cls.BINARY
140
+ return cls.TEXT
141
+
142
+ @classmethod
143
+ def get_conv(cls, v):
144
+ """
145
+ Returns a base SQL type for expression usage (e.g. CAST).
146
+ """
147
+ if isinstance(v, str) and v.startswith("@@"):
148
+ return v[2:] or cls.TEXT
149
+ if isinstance(v, str) or v is str:
150
+ return cls.TEXT
151
+ if isinstance(v, bool) or v is bool:
152
+ return cls.BOOLEAN
153
+ if isinstance(v, int) or v is int:
154
+ return cls.BIGINT
155
+ if isinstance(v, float) or v is float:
156
+ return cls.NUMERIC
157
+ if isinstance(v, decimal.Decimal) or v is decimal.Decimal:
158
+ return cls.NUMERIC
159
+ if isinstance(v, datetime.datetime) or v is datetime.datetime:
160
+ return cls.DATETIME
161
+ if isinstance(v, datetime.date) or v is datetime.date:
162
+ return cls.DATE
163
+ if isinstance(v, datetime.time) or v is datetime.time:
164
+ return cls.TIME
165
+ if isinstance(v, datetime.timedelta) or v is datetime.timedelta:
166
+ return cls.INTERVAL
167
+ if isinstance(v, bytes) or v is bytes:
168
+ return cls.BINARY
169
+ return cls.TEXT
170
+
171
+ @classmethod
172
+ def py_type(cls, v):
173
+ """
174
+ Returns the Python type that corresponds to an SQL type string.
175
+ """
176
+ v = str(v).upper()
177
+ if v == cls.INTEGER or v == cls.SMALLINT or v == cls.BIGINT:
178
+ return int
179
+ if v == cls.NUMERIC:
180
+ return decimal.Decimal
181
+ if v == cls.TEXT:
182
+ return str
183
+ if v == cls.BOOLEAN:
184
+ return bool
185
+ if v == cls.DATE:
186
+ return datetime.date
187
+ if v == cls.TIME or v == cls.TIME_TZ:
188
+ return datetime.time
189
+ if v == cls.DATETIME or v == cls.TIMESTAMP:
190
+ return datetime.datetime
191
+ if v == cls.INTERVAL:
192
+ return datetime.timedelta
193
+ if v == cls.DATETIME_TZ or v == cls.TIMESTAMP_TZ:
194
+ return datetime.datetime
195
+ raise Exception(f"Unmapped type {v}")
@@ -0,0 +1,52 @@
1
+ import os
2
+ import sqlite3
3
+ from ..base.initializer import BaseInitializer
4
+ from velocity.db.core import engine
5
+ from .sql import SQL
6
+
7
+
8
+ class SQLiteInitializer(BaseInitializer):
9
+ """SQLite database initializer."""
10
+
11
+ @staticmethod
12
+ def initialize(config=None, **kwargs):
13
+ """
14
+ Initialize SQLite engine with sqlite3 driver.
15
+
16
+ Args:
17
+ config: Configuration dictionary
18
+ **kwargs: Additional configuration parameters
19
+
20
+ Returns:
21
+ Configured Engine instance
22
+ """
23
+ # Base configuration - SQLite is simpler
24
+ base_config = {
25
+ "database": os.environ.get("DBDatabase", ":memory:"), # Default to in-memory
26
+ }
27
+
28
+ # Remove None values
29
+ base_config = {k: v for k, v in base_config.items() if v is not None}
30
+
31
+ # Set SQLite-specific defaults
32
+ sqlite_defaults = {
33
+ "check_same_thread": False, # Allow usage from different threads
34
+ "timeout": 30.0, # Connection timeout
35
+ }
36
+
37
+ # Merge configurations: defaults < env < config < kwargs
38
+ final_config = sqlite_defaults.copy()
39
+ final_config.update(base_config)
40
+ final_config = SQLiteInitializer._merge_config(final_config, config, **kwargs)
41
+
42
+ # Validate required configuration - only database path is required
43
+ required_keys = ["database"]
44
+ SQLiteInitializer._validate_required_config(final_config, required_keys)
45
+
46
+ return engine.Engine(sqlite3, final_config, SQL)
47
+
48
+
49
+ # Maintain backward compatibility
50
+ def initialize(config=None, **kwargs):
51
+ """Backward compatible initialization function."""
52
+ return SQLiteInitializer.initialize(config, **kwargs)
@@ -0,0 +1,52 @@
1
+ from ..base.operators import BaseOperators
2
+
3
+
4
+ class SQLiteOperators(BaseOperators):
5
+ """
6
+ SQLite-specific operator mappings.
7
+ """
8
+
9
+ @classmethod
10
+ def get_operators(cls):
11
+ """Returns SQLite-specific operator mappings."""
12
+ return OPERATORS
13
+
14
+ @classmethod
15
+ def supports_case_insensitive_like(cls):
16
+ """SQLite LIKE is case-insensitive by default."""
17
+ return True # Sort of - depends on the text encoding
18
+
19
+ @classmethod
20
+ def supports_regex(cls):
21
+ """SQLite supports REGEXP if the REGEXP function is defined."""
22
+ return True # But requires the REGEXP function to be defined
23
+
24
+ @classmethod
25
+ def get_regex_operators(cls):
26
+ """Returns SQLite regex operators."""
27
+ return {
28
+ "REGEXP": "REGEXP",
29
+ "GLOB": "GLOB",
30
+ }
31
+
32
+
33
+ OPERATORS = {
34
+ "<>": "<>",
35
+ "!=": "<>",
36
+ "!><": "NOT BETWEEN",
37
+ ">!<": "NOT BETWEEN",
38
+ "><": "BETWEEN",
39
+ "%%": "LIKE", # SQLite LIKE is case-insensitive by default
40
+ "!%%": "NOT LIKE",
41
+ "==": "=",
42
+ "<=": "<=",
43
+ ">=": ">=",
44
+ "<": "<",
45
+ ">": ">",
46
+ "%": "LIKE",
47
+ "!%": "NOT LIKE",
48
+ "=": "=",
49
+ "!": "<>",
50
+ "REGEXP": "REGEXP",
51
+ "GLOB": "GLOB",
52
+ }
@@ -0,0 +1,20 @@
1
+ reserved_words = [
2
+ "ABORT", "ACTION", "ADD", "AFTER", "ALL", "ALTER", "ANALYZE", "AND",
3
+ "AS", "ASC", "ATTACH", "AUTOINCREMENT", "BEFORE", "BEGIN", "BETWEEN",
4
+ "BY", "CASCADE", "CASE", "CAST", "CHECK", "COLLATE", "COLUMN",
5
+ "COMMIT", "CONFLICT", "CONSTRAINT", "CREATE", "CROSS", "CURRENT_DATE",
6
+ "CURRENT_TIME", "CURRENT_TIMESTAMP", "DATABASE", "DEFAULT", "DEFERRABLE",
7
+ "DEFERRED", "DELETE", "DESC", "DETACH", "DISTINCT", "DROP", "EACH",
8
+ "ELSE", "END", "ESCAPE", "EXCEPT", "EXCLUSIVE", "EXISTS", "EXPLAIN",
9
+ "FAIL", "FOR", "FOREIGN", "FROM", "FULL", "GLOB", "GROUP", "HAVING",
10
+ "IF", "IGNORE", "IMMEDIATE", "IN", "INDEX", "INDEXED", "INITIALLY",
11
+ "INNER", "INSERT", "INSTEAD", "INTERSECT", "INTO", "IS", "ISNULL",
12
+ "JOIN", "KEY", "LEFT", "LIKE", "LIMIT", "MATCH", "NATURAL", "NO",
13
+ "NOT", "NOTNULL", "NULL", "OF", "OFFSET", "ON", "OR", "ORDER",
14
+ "OUTER", "PLAN", "PRAGMA", "PRIMARY", "QUERY", "RAISE", "RECURSIVE",
15
+ "REFERENCES", "REGEXP", "REINDEX", "RELEASE", "RENAME", "REPLACE",
16
+ "RESTRICT", "RIGHT", "ROLLBACK", "ROW", "SAVEPOINT", "SELECT", "SET",
17
+ "TABLE", "TEMP", "TEMPORARY", "THEN", "TO", "TRANSACTION", "TRIGGER",
18
+ "UNION", "UNIQUE", "UPDATE", "USING", "VACUUM", "VALUES", "VIEW",
19
+ "VIRTUAL", "WHEN", "WHERE", "WITH", "WITHOUT"
20
+ ]