velocity-python 0.0.32__py3-none-any.whl → 0.0.34__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.32"
1
+ __version__ = version = "0.0.34"
2
2
 
3
3
  from . import aws
4
4
  from . import db
@@ -1,5 +1,6 @@
1
1
  from functools import wraps
2
2
  from velocity.db import exceptions
3
+ import traceback
3
4
 
4
5
 
5
6
  def retry_on_dup_key(function):
@@ -55,6 +56,7 @@ def return_default(
55
56
  if result is None:
56
57
  result = default
57
58
  except f.exceptions as e:
59
+ traceback.print_exc()
58
60
  self.tx.rollback_savepoint(sp, cursor=self.cursor)
59
61
  return f.default
60
62
  self.tx.release_savepoint(sp, cursor=self.cursor)
@@ -169,6 +169,8 @@ class Engine(object):
169
169
  return function(*args, **kwds)
170
170
  except exceptions.DbRetryTransaction as e:
171
171
  if e.args and e.args[0]:
172
+ print(e)
173
+ print("**Retry Transaction. Rollback and start over")
172
174
  _tx.rollback()
173
175
  continue
174
176
  retry_count += 1
@@ -249,6 +251,7 @@ class Engine(object):
249
251
  conf["database"] = database
250
252
  if "dbname" in conf:
251
253
  conf["dbname"] = database
254
+
252
255
  return self
253
256
 
254
257
  def set_config(self, config):
velocity/db/core/table.py CHANGED
@@ -1,3 +1,4 @@
1
+ # table.py
1
2
  from velocity.db import exceptions
2
3
  from velocity.db.core.row import Row
3
4
  from velocity.db.core.result import Result
@@ -9,8 +10,13 @@ from velocity.db.core.decorators import (
9
10
  )
10
11
 
11
12
 
12
- class Query(str):
13
- pass
13
+ class Query:
14
+ def __init__(self, sql, params=()):
15
+ self.sql = sql
16
+ self.params = params
17
+
18
+ def __str__(self):
19
+ return self.sql
14
20
 
15
21
 
16
22
  class Table(object):
@@ -6,6 +6,7 @@ from velocity.db.core.column import Column
6
6
  from velocity.db.core.database import Database
7
7
  from velocity.db.core.sequence import Sequence
8
8
  from velocity.misc.db import randomword
9
+ import traceback
9
10
 
10
11
 
11
12
  debug = False
@@ -29,6 +30,11 @@ class Transaction(object):
29
30
 
30
31
  def __exit__(self, exc_type, exc_val, exc_tb):
31
32
  if exc_type:
33
+ if debug:
34
+ print("Transaction.__exit__")
35
+ tb_str = "".join(traceback.format_exception(exc_type, exc_val, exc_tb))
36
+ if debug:
37
+ print(tb_str)
32
38
  self.rollback()
33
39
  self.close()
34
40
 
@@ -206,3 +212,10 @@ class Transaction(object):
206
212
  result = self.execute(sql, vals)
207
213
  self.__pg_types = dict(result.as_tuple())
208
214
  return self.__pg_types
215
+
216
+ def switch_to_database(self, name):
217
+ if self.connection:
218
+ self.connection.close()
219
+ self.connection = None
220
+ self.engine.switch_to_database(name)
221
+ return self
@@ -445,7 +445,7 @@ class SQL(object):
445
445
  trigger = "".format(name)
446
446
  sql = []
447
447
  if drop:
448
- sql.append(cls.drop_table(fqtn))
448
+ sql.append(cls.drop_table(fqtn)[0])
449
449
  sql.append(
450
450
  """
451
451
  CREATE TABLE {0} (
@@ -83,7 +83,11 @@ def email(data: str) -> Optional[str]:
83
83
 
84
84
  def integer(data: str) -> int:
85
85
  """Converts a string to an integer, removing non-numeric characters."""
86
- return int(re.sub(r"[^0-9\.-]", "", data))
86
+ cleaned_data = re.sub(r"[^0-9\.-]", "", data)
87
+ try:
88
+ return int(float(cleaned_data))
89
+ except ValueError:
90
+ raise ValueError(f"Cannot convert {data} to integer.")
87
91
 
88
92
 
89
93
  def boolean(data: Union[str, bool]) -> bool:
@@ -1,9 +1,11 @@
1
+ # oconv.py
1
2
  import re
2
3
  import codecs
3
4
  import decimal
4
- from datetime import datetime, date, time
5
+ import datetime
5
6
  from pprint import pformat
6
7
  from typing import Optional, Union, List, Callable
8
+ import ast
7
9
 
8
10
  # Convert SQL data to JS format for display
9
11
 
@@ -36,7 +38,15 @@ def day_of_week(data: Union[int, str, List], abbrev: bool = False) -> str:
36
38
  6: "Saturday",
37
39
  7: "Sunday",
38
40
  }
39
- days_abbrev = {1: "Mon", 2: "Tue", 3: "Wed", 4: "Thu", 5: "Fri", 6: "Sat", 7: "Sun"}
41
+ days_abbrev = {
42
+ 1: "Mon",
43
+ 2: "Tue",
44
+ 3: "Wed",
45
+ 4: "Thu",
46
+ 5: "Fri",
47
+ 6: "Sat",
48
+ 7: "Sun",
49
+ }
40
50
  days = days_abbrev if abbrev else days_full
41
51
 
42
52
  if isinstance(data, list):
@@ -48,19 +58,29 @@ def day_of_week(data: Union[int, str, List], abbrev: bool = False) -> str:
48
58
  return ""
49
59
 
50
60
 
51
- def date(data: Union[datetime, date, str], fmt: str = "%Y-%m-%d") -> str:
61
+ def date(
62
+ data: Union[datetime.datetime, datetime.date, str], fmt: str = "%Y-%m-%d"
63
+ ) -> str:
52
64
  """Formats a date object as a string according to the specified format."""
53
- return data.strftime(fmt) if isinstance(data, (datetime, date)) else str(data)
65
+ return (
66
+ data.strftime(fmt)
67
+ if isinstance(data, (datetime.datetime, datetime.date))
68
+ else str(data)
69
+ )
54
70
 
55
71
 
56
- def time(data: Union[datetime, time, str], fmt: str = "%X") -> str:
72
+ def time(data: Union[datetime.datetime, datetime.time, str], fmt: str = "%X") -> str:
57
73
  """Formats a time object as a string according to the specified format."""
58
- return data.strftime(fmt) if isinstance(data, (datetime, time)) else str(data)
74
+ return (
75
+ data.strftime(fmt)
76
+ if isinstance(data, (datetime.datetime, datetime.time))
77
+ else str(data)
78
+ )
59
79
 
60
80
 
61
- def timestamp(data: Union[datetime, str], fmt: str = "%c") -> str:
81
+ def timestamp(data: Union[datetime.datetime, str], fmt: str = "%c") -> str:
62
82
  """Formats a datetime object as a string according to the specified format."""
63
- return data.strftime(fmt) if isinstance(data, datetime) else str(data)
83
+ return data.strftime(fmt) if isinstance(data, datetime.datetime) else str(data)
64
84
 
65
85
 
66
86
  def email(data: Optional[str]) -> str:
@@ -88,24 +108,29 @@ def boolean(data: Union[str, bool]) -> bool:
88
108
  return bool(data)
89
109
 
90
110
 
91
- def money(data: str) -> str:
92
- """Formats a numeric string as currency."""
111
+ def money(data: Union[str, float, int, decimal.Decimal]) -> str:
112
+ """Formats a numeric value as currency."""
93
113
  if data in [None, ""]:
94
114
  return ""
95
- cleaned_data = re.sub(r"[^0-9\.-]", "", str(data))
96
- return f"${decimal.Decimal(cleaned_data):,.2f}"
115
+ try:
116
+ amount = decimal.Decimal(str(data))
117
+ return f"${amount:,.2f}"
118
+ except (decimal.InvalidOperation, ValueError):
119
+ return ""
97
120
 
98
121
 
99
122
  def round_to(
100
123
  precision: int, data: Optional[Union[str, float, decimal.Decimal]] = None
101
- ) -> Union[Callable, str]:
124
+ ) -> Union[Callable[[Union[str, float, decimal.Decimal]], str], str]:
102
125
  """Rounds a number to the specified precision."""
103
126
 
104
127
  def function(value):
105
- cleaned_value = re.sub(r"[^0-9\.-]", "", str(value))
106
- return (
107
- f"{decimal.Decimal(cleaned_value):.{precision}f}" if cleaned_value else "0"
108
- )
128
+ try:
129
+ amount = decimal.Decimal(str(value))
130
+ rounded = round(amount, precision)
131
+ return f"{rounded:.{precision}f}"
132
+ except (decimal.InvalidOperation, ValueError):
133
+ return "0"
109
134
 
110
135
  return function if data is None else function(data)
111
136
 
@@ -125,11 +150,15 @@ def to_list(data: Union[str, List]) -> Optional[List]:
125
150
  return None
126
151
  if isinstance(data, list):
127
152
  return data
128
- if isinstance(data, str) and data.startswith("["):
129
- try:
130
- return eval(data) # Be cautious with eval; only use if data is trusted
131
- except (SyntaxError, NameError):
132
- return None
153
+ if isinstance(data, str):
154
+ data = data.strip()
155
+ if data.startswith("[") and data.endswith("]"):
156
+ try:
157
+ return ast.literal_eval(data)
158
+ except (SyntaxError, ValueError):
159
+ return None
160
+ else:
161
+ return [data]
133
162
  return [data]
134
163
 
135
164
 
@@ -160,8 +189,9 @@ def padding(length: int, char: str) -> Callable[[str], str]:
160
189
  def pprint(data: str) -> str:
161
190
  """Pretty-prints a JSON-like string representation of data."""
162
191
  try:
163
- return pformat(eval(data))
164
- except (SyntaxError, NameError):
192
+ parsed_data = ast.literal_eval(data)
193
+ return pformat(parsed_data)
194
+ except (SyntaxError, ValueError):
165
195
  return data
166
196
 
167
197
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: velocity-python
3
- Version: 0.0.32
3
+ Version: 0.0.34
4
4
  Summary: A rapid application development library for interfacing with data storage
5
5
  Author-email: Paul Perez <pperez@codeclubs.org>
6
6
  Project-URL: Homepage, https://codeclubs.org/projects/velocity
@@ -1,4 +1,4 @@
1
- velocity/__init__.py,sha256=8Xcz_RUYvy6ibGGQeUrwa-fEVzDMhSKe2ZnYgytCeTw,88
1
+ velocity/__init__.py,sha256=hlMhCqzGev3NaHpaO6Uf0N-bpmP_fv3PUHIpqrGgInY,88
2
2
  velocity/aws/__init__.py,sha256=GBTEr02whnCH3TG-BWCpUC3KfHY3uNxD21g0OvsVJnc,598
3
3
  velocity/aws/handlers/__init__.py,sha256=xnpFZJVlC2uoeeFW4zuPST8wA8ajaQDky5Y6iXZzi3A,172
4
4
  velocity/aws/handlers/context.py,sha256=UIjNR83y2NSIyK8HMPX8t5tpJHFNabiZvNgmmdQL3HA,1822
@@ -9,17 +9,17 @@ velocity/db/__init__.py,sha256=vrn2AFNAKaqTdnPwLFS0OcREcCtzUCOodlmH54U7ADg,200
9
9
  velocity/db/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10
10
  velocity/db/core/column.py,sha256=nibAue9zBY3ln7S81tgMvCDzpAmrHlBqAjvvzatzB5A,6258
11
11
  velocity/db/core/database.py,sha256=r4S_x9ntkdXkwqdPqSgVQ7YB2r68SbKssHyXfSfCJYo,1875
12
- velocity/db/core/decorators.py,sha256=q3_0j06vZF9J-pPcLjsR2wftp4iXjlGgJ2l70WdtbUo,3271
13
- velocity/db/core/engine.py,sha256=qubySirnGymBYfQb5hF6EdYUhNr-GSjOmvRNswG9RFI,14535
12
+ velocity/db/core/decorators.py,sha256=HxlelX8BPuGz1T2owhZwHnLxHg5aywUgr1tXvg1zghQ,3326
13
+ velocity/db/core/engine.py,sha256=yleohNqeqLfsTapOamKW-aiGxMooQPcR61p7vN9cCVo,14647
14
14
  velocity/db/core/exceptions.py,sha256=MOWyA1mlMe8eWbFkEHK0Lp9czdplpRyqbAn2JfGmMrM,707
15
15
  velocity/db/core/result.py,sha256=keE-SKn4Uw08uoiA_8FdaMzBfiaAIxidQEEsl3TM86U,4945
16
16
  velocity/db/core/row.py,sha256=AHopXrrQUp5dCXEMLEDm0iAhswKDtMUdBxjTtPQ7Udk,5659
17
17
  velocity/db/core/sequence.py,sha256=4WkXJUE1tea4bo3y8JzJq6KgtU_1yAV6rp3HHrOVAoI,1177
18
- velocity/db/core/table.py,sha256=d7KyIXAinBBzIqvxIZClJ8d-DGskPucruFiFFT4PtCM,19805
19
- velocity/db/core/transaction.py,sha256=XeqGkgrleIqC8krrDcqVXWiBAjXx9z67ZecJNjELgiw,6641
18
+ velocity/db/core/table.py,sha256=0CvuhHWEMOC6I3_ycXGU35zzIxIipfj1XRpnzIiCPt8,19942
19
+ velocity/db/core/transaction.py,sha256=S0ojO40u4Ads_QhofUYAXvHcvhs1W3ir2kyhe5d-btM,7067
20
20
  velocity/db/servers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
21
21
  velocity/db/servers/mysql.py,sha256=O3-lP1Y4VmdeAL5PcYcj_mulJBeK7vcoei_v23oo8qc,24272
22
- velocity/db/servers/postgres.py,sha256=aA4Fkz-PTo-Vi9kpDvWWMt2snv4r93PtQYDzgCg1XIs,42723
22
+ velocity/db/servers/postgres.py,sha256=E8JRRVW3_YrpbmcYM-ZbVgk-BoVZajlWUr4Ni3KtQvg,42726
23
23
  velocity/db/servers/sqlite.py,sha256=_PGg6ECHdOyOMn4tTWX4WlectAukW3Dov7cZxHbVtBM,36198
24
24
  velocity/db/servers/sqlserver.py,sha256=ACdkTyJzdFzN-RpmOabKgmMPtCdHzT-FwYH00UpSNyM,34465
25
25
  velocity/misc/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -30,10 +30,10 @@ velocity/misc/mail.py,sha256=BrxDqeVsOd0epyJKwrHA-owzs6di2oLA_qJskoTux-c,2553
30
30
  velocity/misc/merge.py,sha256=EYtqwnckBllPO60tRALxFRuzmUQ7Wl0qZC6sCgyiZDA,1885
31
31
  velocity/misc/timer.py,sha256=cN3aS0t6HLlhYfF2Ir6ihJehxNrWf9ebaLzXUaWRKEA,1637
32
32
  velocity/misc/conv/__init__.py,sha256=MLYF58QHjzfDSxb1rdnmLnuEQCa3gnhzzZ30CwZVvQo,40
33
- velocity/misc/conv/iconv.py,sha256=ThTT3_t0Us5P7UuBa58ko-GKVm30FFUrSmPBd6Gfh90,5660
34
- velocity/misc/conv/oconv.py,sha256=XdRTQnywWNwVc0FH-8hPHjlTpZNFg80ivIfyTV3mMak,5495
35
- velocity_python-0.0.32.dist-info/LICENSE,sha256=aoN245GG8s9oRUU89KNiGTU4_4OtnNmVi4hQeChg6rM,1076
36
- velocity_python-0.0.32.dist-info/METADATA,sha256=teq0KrZ_b16Wx7QWDWpXIChNmAxJMiKbyjBMDt_9uf4,8522
37
- velocity_python-0.0.32.dist-info/WHEEL,sha256=R06PA3UVYHThwHvxuRWMqaGcr-PuniXahwjmQRFMEkY,91
38
- velocity_python-0.0.32.dist-info/top_level.txt,sha256=JW2vJPmodgdgSz7H6yoZvnxF8S3fTMIv-YJWCT1sNW0,9
39
- velocity_python-0.0.32.dist-info/RECORD,,
33
+ velocity/misc/conv/iconv.py,sha256=d3Vafl0xaMjWD3aeWDnfraOrLinAFjGRPqiozoRunio,5798
34
+ velocity/misc/conv/oconv.py,sha256=WdyGhifokFkta6Q0jBc9z9dk34rU0htMR_e0eUY-Vyg,6018
35
+ velocity_python-0.0.34.dist-info/LICENSE,sha256=aoN245GG8s9oRUU89KNiGTU4_4OtnNmVi4hQeChg6rM,1076
36
+ velocity_python-0.0.34.dist-info/METADATA,sha256=HxyHJU7LxOIbkqWqp903MgxLEQgGtpJzk-BH-eH8d1Y,8522
37
+ velocity_python-0.0.34.dist-info/WHEEL,sha256=R06PA3UVYHThwHvxuRWMqaGcr-PuniXahwjmQRFMEkY,91
38
+ velocity_python-0.0.34.dist-info/top_level.txt,sha256=JW2vJPmodgdgSz7H6yoZvnxF8S3fTMIv-YJWCT1sNW0,9
39
+ velocity_python-0.0.34.dist-info/RECORD,,