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

@@ -1,32 +1,33 @@
1
+ # iconv.py
1
2
  import re
2
3
  import codecs
3
- import decimal as _decimal
4
+ from decimal import Decimal, ROUND_HALF_UP
4
5
  from email.utils import parseaddr
5
6
  from datetime import datetime
7
+ from typing import Optional, Union, Callable
6
8
 
9
+ # Convert data to SQL format for storage
7
10
 
8
- def none(data):
9
- if data == "":
10
- return None
11
- if data == "null":
12
- return None
13
- if data == "@NULL":
14
- return None
15
- return data
11
+
12
+ def none(data: str) -> Optional[str]:
13
+ """Converts various 'null' representations to None."""
14
+ return None if data in ("", "null", "None", "@NULL") else data
16
15
 
17
16
 
18
- def phone(data):
19
- if data == "None":
17
+ def phone(data: str) -> Optional[str]:
18
+ """Extracts a 10-digit phone number or returns None if invalid."""
19
+ if data in ("None", None):
20
20
  return None
21
- if not data:
22
- return data
23
- return re.search(r"\d{10}$", re.sub("[^0-9]", "", data)).group()
21
+ cleaned_data = re.sub(r"[^0-9]", "", data)
22
+ match = re.search(r"\d{10}$", cleaned_data)
23
+ return match.group() if match else None
24
24
 
25
25
 
26
- def day_of_week(data):
26
+ def day_of_week(data: str) -> Optional[int]:
27
+ """Converts day of the week to an integer representation."""
27
28
  if not data:
28
- return data
29
- return {
29
+ return None
30
+ days = {
30
31
  "monday": 1,
31
32
  "tuesday": 2,
32
33
  "wednesday": 3,
@@ -41,174 +42,141 @@ def day_of_week(data):
41
42
  "fri": 5,
42
43
  "sat": 6,
43
44
  "sun": 7,
44
- }[data.lower()]
45
-
45
+ }
46
+ return days.get(data.lower())
46
47
 
47
- def date(*args, **kwds):
48
- kwds.setdefault("fmt", "%Y-%m-%d")
49
48
 
50
- def _(param):
51
- if isinstance(param, str):
52
- return datetime.strptime(param, kwds["fmt"]).date()
53
- else:
54
- return param
55
-
56
- if args and args[0]:
57
- return _(args[0])
58
- return _
49
+ def date(data: str, fmt: str = "%Y-%m-%d") -> Optional[datetime.date]:
50
+ """Parses a date string into a date object using the specified format."""
51
+ try:
52
+ return datetime.strptime(data, fmt).date()
53
+ except (ValueError, TypeError):
54
+ return None
59
55
 
60
56
 
61
- def time(*args, **kwds):
62
- kwds.setdefault("fmt", "%X")
57
+ def time(data: str, fmt: str = "%X") -> Optional[datetime.time]:
58
+ """Parses a time string into a time object using the specified format."""
59
+ try:
60
+ return datetime.strptime(data, fmt).time()
61
+ except (ValueError, TypeError):
62
+ return None
63
63
 
64
- def _(param):
65
- if isinstance(param, str):
66
- return datetime.strptime(param, kwds["fmt"]).time()
67
- else:
68
- return param
69
64
 
70
- if args and args[0]:
71
- return _(args[0])
72
- return _
65
+ def timestamp(data: str, fmt: str = "%c") -> Optional[datetime]:
66
+ """Parses a timestamp string into a datetime object using the specified format."""
67
+ try:
68
+ return datetime.strptime(data, fmt)
69
+ except (ValueError, TypeError):
70
+ return None
73
71
 
74
72
 
75
- def timestamp(*args, **kwds):
76
- kwds.setdefault("fmt", "%c")
73
+ def email(data: str) -> Optional[str]:
74
+ """Validates and returns an email address if properly formatted."""
75
+ if not data or data.lower() == "none":
76
+ return None
77
+ data = data.strip().lower()
78
+ email_address = parseaddr(data)[1]
79
+ if "@" in email_address and "." in email_address.split("@")[1]:
80
+ return email_address
81
+ raise ValueError("Invalid email format")
77
82
 
78
- def _(param):
79
- if isinstance(param, str):
80
- return datetime.strptime(param, kwds["fmt"])
81
- else:
82
- return param
83
83
 
84
- if args and args[0]:
85
- return _(args[0])
86
- return _
84
+ def integer(data: str) -> int:
85
+ """Converts a string to an integer, removing non-numeric characters."""
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
- def email(data):
90
- if not data:
91
- return None
92
- if data == "None":
93
- return None
94
- data = data.strip().lower()
95
- if "@" not in data:
96
- raise Exception()
97
- email = parseaddr(data)[1]
98
- mailbox, domain = email.split("@")
99
- if "." in domain:
100
- if len(domain.split(".")[1]) < 1:
101
- raise Exception()
102
- else:
103
- raise Exception()
104
- return data
105
-
106
-
107
- def integer(data):
108
- return int(re.sub("[^0-9\.-]", "", str(data)))
109
-
110
-
111
- def boolean(data):
112
- if isinstance(data, str):
113
- if data.lower() in ["false", "", "f", "off", "no"]:
114
- return False
93
+ def boolean(data: Union[str, bool]) -> bool:
94
+ """Converts various string representations to a boolean."""
95
+ if isinstance(data, str) and data.lower() in ["false", "", "f", "off", "no"]:
96
+ return False
115
97
  return bool(data)
116
98
 
117
99
 
118
- def rot13(data):
100
+ def rot13(data: str) -> str:
101
+ """Encodes a string using ROT13."""
119
102
  return codecs.encode(data, "rot13")
120
103
 
121
104
 
122
- def pointer(data):
123
- if data == "@new":
124
- return data
125
- if data == "":
126
- return None
127
- if data == None:
128
- return None
129
- if data == "@NULL":
105
+ def pointer(data: Union[str, None]) -> Optional[int]:
106
+ """Converts a pointer to an integer, or returns None for null values."""
107
+ if data in ("@new", "", "@NULL", None):
130
108
  return None
131
109
  return int(data)
132
110
 
133
111
 
134
- def money(data):
135
- if data == "None":
112
+ def money(data: str) -> Optional[Decimal]:
113
+ """Converts a monetary string to a Decimal, removing non-numeric characters."""
114
+ if data in ("None", None):
136
115
  return None
137
- if not data:
138
- return data
139
- return _decimal.Decimal(re.sub("[^0-9\.-]", "", str(data)))
116
+ return Decimal(re.sub(r"[^0-9\.-]", "", data))
117
+
140
118
 
119
+ def round_to(
120
+ precision: int, data: Optional[Union[str, float, Decimal]] = None
121
+ ) -> Union[Decimal, Callable[[Union[str, float, Decimal]], Decimal]]:
122
+ """Rounds a number to a specified precision."""
141
123
 
142
- def round(precision, data=None):
143
- def function(data):
144
- if data == "None":
124
+ def function(value):
125
+ if value in ("None", None):
145
126
  return None
146
- if not data:
147
- return data
148
- if isinstance(data, str):
149
- data = re.sub("[^0-9\.-]", "", data)
150
- return _decimal.Decimal(data).quantize(
151
- _decimal.Decimal(10) ** -precision, rounding=_decimal.ROUND_HALF_UP
127
+ if isinstance(value, str):
128
+ value = re.sub(r"[^0-9\.-]", "", value)
129
+ return Decimal(value).quantize(
130
+ Decimal(10) ** -precision, rounding=ROUND_HALF_UP
152
131
  )
153
132
 
154
- if data == None:
155
- return function
156
- return function(data)
133
+ return function(data) if data is not None else function
157
134
 
158
135
 
159
- def decimal(data):
160
- if data == "None":
136
+ def decimal(data: str) -> Optional[Decimal]:
137
+ """Converts a numeric string to a Decimal, removing non-numeric characters."""
138
+ if data in ("None", None):
161
139
  return None
162
- if not data:
163
- return data
164
- return _decimal.Decimal(re.sub("[^0-9\.-]", "", str(data)))
140
+ return Decimal(re.sub(r"[^0-9\.-]", "", data))
165
141
 
166
142
 
167
- def ein(data):
168
- if data == "None":
143
+ def ein(data: str) -> Optional[str]:
144
+ """Validates and returns a 9-digit EIN, or None if invalid."""
145
+ if data in ("None", None):
169
146
  return None
170
- if not data:
171
- return data
172
- return re.search(r"^\d{9}$", re.sub("[^0-9]", "", data)).group()
147
+ cleaned_data = re.sub(r"[^0-9]", "", data)
148
+ match = re.fullmatch(r"\d{9}", cleaned_data)
149
+ return match.group() if match else None
173
150
 
174
151
 
175
- def list(data):
152
+ def to_list(data: Union[str, list]) -> Optional[list]:
153
+ """Converts a string or single element into a list representation."""
176
154
  if data in (None, "None"):
177
155
  return None
178
- if isinstance(data, str):
179
- if data[0] == "[":
180
- return data
181
- if not isinstance(data, list):
182
- data = [data]
183
- return repr(data)
156
+ if isinstance(data, str) and data.startswith("["):
157
+ return eval(data) # Assuming the input string is a list string
158
+ return [data] if not isinstance(data, list) else data
159
+
184
160
 
161
+ def title(data: str) -> str:
162
+ """Converts a string to title case."""
163
+ return "" if data in (None, "None") else str(data).title()
185
164
 
186
- def title(data):
187
- if data == None:
188
- return ""
189
- if data == "None":
190
- return ""
191
- return str(data).title()
192
165
 
166
+ def lower(data: str) -> str:
167
+ """Converts a string to lowercase."""
168
+ return "" if data in (None, "None") else str(data).lower()
193
169
 
194
- def lower(data):
195
- if data == None:
196
- return ""
197
- if data == "None":
198
- return ""
199
- return str(data).lower()
200
170
 
171
+ def upper(data: str) -> str:
172
+ """Converts a string to uppercase."""
173
+ return "" if data in (None, "None") else str(data).upper()
201
174
 
202
- def upper(data):
203
- if data == None:
204
- return ""
205
- if data == "None":
206
- return ""
207
- return str(data).upper()
208
175
 
176
+ def padding(length: int, char: str = " ") -> Callable[[str], Optional[str]]:
177
+ """Pads a string to the specified length with a given character."""
209
178
 
210
- def padding(length, char):
211
- def inner(data):
179
+ def inner(data: str) -> Optional[str]:
212
180
  if data in [None, "None", ""]:
213
181
  return None
214
182
  return str(data).rjust(length, char)
@@ -216,7 +184,6 @@ def padding(length, char):
216
184
  return inner
217
185
 
218
186
 
219
- def string(data):
220
- if data == "":
221
- return None
222
- return str(data)
187
+ def string(data: str) -> Optional[str]:
188
+ """Converts an empty string to None, otherwise returns the string itself."""
189
+ return None if data == "" else str(data)
@@ -1,48 +1,35 @@
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
7
+ from typing import Optional, Union, List, Callable
8
+ import ast
6
9
 
10
+ # Convert SQL data to JS format for display
7
11
 
8
- def none(data):
9
- if data == None:
10
- return ""
11
- if data == "None":
12
- return ""
13
- if data == "null":
14
- return ""
15
- return data
16
12
 
13
+ def none(data: Optional[str]) -> str:
14
+ """Converts various 'null' representations to an empty string."""
15
+ return "" if data in (None, "None", "null", "@NULL") else data
17
16
 
18
- def phone(data):
19
- if data == None:
20
- return ""
21
- if data == "None":
17
+
18
+ def phone(data: Optional[str]) -> str:
19
+ """Formats a 10-digit phone number as (XXX) XXX-XXXX or returns an empty string if invalid."""
20
+ if data in (None, "None", ""):
22
21
  return ""
23
- if not data:
24
- return data
25
- data = re.search(r"\d{10}$", re.sub("[^0-9]", "", data)).group()
26
- return "({}) {}-{}".format(data[:3], data[3:6], data[6:])
22
+ digits = re.sub(r"[^0-9]", "", data)
23
+ match = re.search(r"\d{10}$", digits)
24
+ if match:
25
+ num = match.group()
26
+ return f"({num[:3]}) {num[3:6]}-{num[6:]}"
27
+ return ""
27
28
 
28
29
 
29
- def day_of_week(data, abbrev=False):
30
- if isinstance(data, list):
31
- new = []
32
- for day in data:
33
- new.append(day_of_week(day, abbrev=abbrev))
34
- return ",".join(new)
35
- if data == None:
36
- return ""
37
- if data == "None":
38
- return ""
39
- if not data:
40
- return data
41
- if abbrev:
42
- return {1: "Mon", 2: "Tue", 3: "Wed", 4: "Thu", 5: "Fri", 6: "Sat", 7: "Sun"}[
43
- int(data)
44
- ]
45
- return {
30
+ def day_of_week(data: Union[int, str, List], abbrev: bool = False) -> str:
31
+ """Converts a day number (1-7) to a day name, abbreviated if specified. Supports lists."""
32
+ days_full = {
46
33
  1: "Monday",
47
34
  2: "Tuesday",
48
35
  3: "Wednesday",
@@ -50,159 +37,164 @@ def day_of_week(data, abbrev=False):
50
37
  5: "Friday",
51
38
  6: "Saturday",
52
39
  7: "Sunday",
53
- }[int(data)]
40
+ }
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
+ }
50
+ days = days_abbrev if abbrev else days_full
54
51
 
52
+ if isinstance(data, list):
53
+ return ",".join(day_of_week(day, abbrev) for day in data if day in days)
55
54
 
56
- def date(*args, **kwds):
57
- kwds.setdefault("fmt", "%Y-%m-%d")
58
-
59
- def _(param):
60
- if isinstance(param, (datetime, date)):
61
- return param.strftime(kwds["fmt"])
62
- else:
63
- return param
64
-
65
- if args and args[0]:
66
- return _(args[0])
67
- return _
55
+ try:
56
+ return days[int(data)]
57
+ except (ValueError, KeyError, TypeError):
58
+ return ""
68
59
 
69
60
 
70
- def time(*args, **kwds):
71
- kwds.setdefault("fmt", "%X")
61
+ def date(
62
+ data: Union[datetime.datetime, datetime.date, str], fmt: str = "%Y-%m-%d"
63
+ ) -> str:
64
+ """Formats a date object as a string according to the specified format."""
65
+ return (
66
+ data.strftime(fmt)
67
+ if isinstance(data, (datetime.datetime, datetime.date))
68
+ else str(data)
69
+ )
72
70
 
73
- def _(param):
74
- if isinstance(param, (datetime, time)):
75
- return param.strftime(kwds["fmt"])
76
- else:
77
- return param
78
71
 
79
- if args and args[0]:
80
- return _(args[0])
81
- return _
72
+ def time(data: Union[datetime.datetime, datetime.time, str], fmt: str = "%X") -> str:
73
+ """Formats a time object as a string according to the specified format."""
74
+ return (
75
+ data.strftime(fmt)
76
+ if isinstance(data, (datetime.datetime, datetime.time))
77
+ else str(data)
78
+ )
82
79
 
83
80
 
84
- def timestamp(*args, **kwds):
85
- kwds.setdefault("fmt", "%c")
81
+ def timestamp(data: Union[datetime.datetime, str], fmt: str = "%c") -> str:
82
+ """Formats a datetime object as a string according to the specified format."""
83
+ return data.strftime(fmt) if isinstance(data, datetime.datetime) else str(data)
86
84
 
87
- def _(param):
88
- if isinstance(param, (datetime)):
89
- return param.strftime(kwds["fmt"])
90
- else:
91
- return param
92
85
 
93
- if args:
94
- return _(args[0])
95
- return _
86
+ def email(data: Optional[str]) -> str:
87
+ """Returns a lowercase email address or an empty string if invalid."""
88
+ return "" if data in (None, "None") else data.lower()
96
89
 
97
90
 
98
- def email(data):
99
- if data == None:
100
- return ""
101
- if data == "None":
102
- return ""
103
- return data.lower()
104
-
105
-
106
- def pointer(data):
91
+ def pointer(data: Union[str, int]) -> Union[int, str]:
92
+ """Converts a string to an integer, or returns an empty string if conversion fails."""
107
93
  try:
108
94
  return int(data)
109
- except:
95
+ except (ValueError, TypeError):
110
96
  return ""
111
97
 
112
98
 
113
- def rot13(data):
99
+ def rot13(data: str) -> str:
100
+ """Encodes a string using ROT13."""
114
101
  return codecs.decode(data, "rot13")
115
102
 
116
103
 
117
- def boolean(data):
118
- if isinstance(data, str):
119
- if data.lower() in ["false", "", "f", "off", "no"]:
120
- return False
104
+ def boolean(data: Union[str, bool]) -> bool:
105
+ """Converts various representations to a boolean."""
106
+ if isinstance(data, str) and data.lower() in ["false", "", "f", "off", "no"]:
107
+ return False
121
108
  return bool(data)
122
109
 
123
110
 
124
- def money(data):
111
+ def money(data: Union[str, float, int, decimal.Decimal]) -> str:
112
+ """Formats a numeric value as currency."""
125
113
  if data in [None, ""]:
126
114
  return ""
127
- data = re.sub("[^0-9\.-]", "", str(data))
128
- return "${:,.2f}".format(decimal.Decimal(data))
115
+ try:
116
+ amount = decimal.Decimal(str(data))
117
+ return f"${amount:,.2f}"
118
+ except (decimal.InvalidOperation, ValueError):
119
+ return ""
120
+
129
121
 
122
+ def round_to(
123
+ precision: int, data: Optional[Union[str, float, decimal.Decimal]] = None
124
+ ) -> Union[Callable[[Union[str, float, decimal.Decimal]], str], str]:
125
+ """Rounds a number to the specified precision."""
130
126
 
131
- def round(precision, data=None):
132
- def function(data):
133
- data = re.sub("[^0-9\.]", "", str(data))
134
- if data == "":
127
+ def function(value):
128
+ try:
129
+ amount = decimal.Decimal(str(value))
130
+ rounded = round(amount, precision)
131
+ return f"{rounded:.{precision}f}"
132
+ except (decimal.InvalidOperation, ValueError):
135
133
  return "0"
136
- return "{:.{prec}f}".format(decimal.Decimal(data), prec=precision)
137
134
 
138
- if data == None:
139
- return function
140
- return function(data)
135
+ return function if data is None else function(data)
141
136
 
142
137
 
143
- def ein(data):
144
- if data == None:
138
+ def ein(data: str) -> str:
139
+ """Formats a 9-digit EIN as XX-XXXXXXX or returns an empty string if invalid."""
140
+ if data in (None, "None", ""):
145
141
  return ""
146
- if data == "None":
147
- return ""
148
- if not data:
149
- return data
150
- data = re.search(r"\d{9}$", re.sub("[^0-9]", "", data)).group()
151
- return "{}-{}".format(data[:2], data[2:])
142
+ cleaned_data = re.sub(r"[^0-9]", "", data)
143
+ match = re.fullmatch(r"\d{9}", cleaned_data)
144
+ return f"{cleaned_data[:2]}-{cleaned_data[2:]}" if match else ""
152
145
 
153
146
 
154
- def list(data):
147
+ def to_list(data: Union[str, List]) -> Optional[List]:
148
+ """Converts a single element or JSON-like list string to a list."""
155
149
  if data in (None, "None"):
156
150
  return None
157
151
  if isinstance(data, list):
158
152
  return data
159
153
  if isinstance(data, str):
160
- if data[0] == "[":
161
- return eval(data)
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]
162
162
  return [data]
163
163
 
164
164
 
165
- def title(data):
166
- if data == None:
167
- return ""
168
- if data == "None":
169
- return ""
170
- return str(data).title()
165
+ def title(data: Optional[str]) -> str:
166
+ """Converts a string to title case."""
167
+ return "" if data in (None, "None") else str(data).title()
171
168
 
172
169
 
173
- def lower(data):
174
- if data == None:
175
- return ""
176
- if data == "None":
177
- return ""
178
- return str(data).lower()
170
+ def lower(data: Optional[str]) -> str:
171
+ """Converts a string to lowercase."""
172
+ return "" if data in (None, "None") else str(data).lower()
179
173
 
180
174
 
181
- def upper(data):
182
- if data == None:
183
- return ""
184
- if data == "None":
185
- return ""
186
- return str(data).upper()
175
+ def upper(data: Optional[str]) -> str:
176
+ """Converts a string to uppercase."""
177
+ return "" if data in (None, "None") else str(data).upper()
187
178
 
188
179
 
189
- def padding(length, char):
190
- def inner(data):
191
- if data is None:
192
- return ""
193
- return str(data).rjust(length, char)
180
+ def padding(length: int, char: str) -> Callable[[str], str]:
181
+ """Returns a function that pads a string to the specified length with the given character."""
182
+
183
+ def inner(data: str) -> str:
184
+ return str(data).rjust(length, char) if data not in (None, "None", "") else ""
194
185
 
195
186
  return inner
196
187
 
197
188
 
198
- def pprint(data):
189
+ def pprint(data: str) -> str:
190
+ """Pretty-prints a JSON-like string representation of data."""
199
191
  try:
200
- return pformat(eval(data))
201
- except:
192
+ parsed_data = ast.literal_eval(data)
193
+ return pformat(parsed_data)
194
+ except (SyntaxError, ValueError):
202
195
  return data
203
196
 
204
197
 
205
- def string(data):
206
- if data == None:
207
- return ""
208
- return str(data)
198
+ def string(data: Optional[str]) -> str:
199
+ """Converts a None value to an empty string; otherwise returns the string itself."""
200
+ return "" if data is None else str(data)