velocity-python 0.0.30__tar.gz → 0.0.32__tar.gz
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.
- {velocity-python-0.0.30 → velocity_python-0.0.32}/PKG-INFO +1 -1
- {velocity-python-0.0.30 → velocity_python-0.0.32}/pyproject.toml +1 -1
- {velocity-python-0.0.30 → velocity_python-0.0.32}/src/velocity/__init__.py +1 -1
- velocity_python-0.0.32/src/velocity/aws/__init__.py +18 -0
- velocity_python-0.0.32/src/velocity/aws/handlers/response.py +290 -0
- {velocity-python-0.0.30 → velocity_python-0.0.32}/src/velocity/db/core/column.py +31 -20
- {velocity-python-0.0.30 → velocity_python-0.0.32}/src/velocity/db/core/database.py +9 -9
- {velocity-python-0.0.30 → velocity_python-0.0.32}/src/velocity/db/core/engine.py +101 -99
- {velocity-python-0.0.30 → velocity_python-0.0.32}/src/velocity/db/core/exceptions.py +23 -0
- {velocity-python-0.0.30 → velocity_python-0.0.32}/src/velocity/db/core/sequence.py +11 -3
- velocity_python-0.0.32/src/velocity/db/servers/mysql.py +873 -0
- velocity_python-0.0.32/src/velocity/db/servers/sqlite.py +1177 -0
- velocity_python-0.0.32/src/velocity/db/servers/sqlserver.py +1236 -0
- {velocity-python-0.0.30 → velocity_python-0.0.32}/src/velocity/misc/conv/__init__.py +1 -1
- velocity_python-0.0.32/src/velocity/misc/conv/iconv.py +185 -0
- velocity_python-0.0.32/src/velocity/misc/conv/oconv.py +170 -0
- {velocity-python-0.0.30 → velocity_python-0.0.32}/src/velocity/misc/db.py +25 -19
- velocity_python-0.0.32/src/velocity/misc/export.py +157 -0
- velocity_python-0.0.32/src/velocity/misc/format.py +79 -0
- velocity_python-0.0.32/src/velocity/misc/mail.py +78 -0
- velocity_python-0.0.32/src/velocity/misc/merge.py +52 -0
- velocity_python-0.0.32/src/velocity/misc/timer.py +50 -0
- {velocity-python-0.0.30 → velocity_python-0.0.32}/src/velocity_python.egg-info/PKG-INFO +1 -1
- {velocity-python-0.0.30 → velocity_python-0.0.32}/src/velocity_python.egg-info/SOURCES.txt +11 -1
- velocity_python-0.0.32/tests/test_db.py +90 -0
- velocity_python-0.0.32/tests/test_email_processing.py +112 -0
- velocity_python-0.0.32/tests/test_format.py +64 -0
- velocity_python-0.0.32/tests/test_iconv.py +141 -0
- velocity_python-0.0.32/tests/test_merge.py +82 -0
- velocity_python-0.0.32/tests/test_oconv.py +140 -0
- velocity_python-0.0.32/tests/test_postgres.py +205 -0
- velocity_python-0.0.32/tests/test_response.py +156 -0
- velocity_python-0.0.32/tests/test_spreadsheet_functions.py +124 -0
- velocity_python-0.0.32/tests/test_timer.py +74 -0
- velocity-python-0.0.30/src/velocity/aws/__init__.py +0 -22
- velocity-python-0.0.30/src/velocity/aws/handlers/response.py +0 -139
- velocity-python-0.0.30/src/velocity/db/servers/mysql.py +0 -575
- velocity-python-0.0.30/src/velocity/db/servers/sqlite.py +0 -899
- velocity-python-0.0.30/src/velocity/db/servers/sqlserver.py +0 -821
- velocity-python-0.0.30/src/velocity/misc/conv/iconv.py +0 -222
- velocity-python-0.0.30/src/velocity/misc/conv/oconv.py +0 -204
- velocity-python-0.0.30/src/velocity/misc/export.py +0 -147
- velocity-python-0.0.30/src/velocity/misc/format.py +0 -81
- velocity-python-0.0.30/src/velocity/misc/mail.py +0 -67
- velocity-python-0.0.30/src/velocity/misc/merge.py +0 -35
- velocity-python-0.0.30/src/velocity/misc/timer.py +0 -27
- {velocity-python-0.0.30 → velocity_python-0.0.32}/LICENSE +0 -0
- {velocity-python-0.0.30 → velocity_python-0.0.32}/README.md +0 -0
- {velocity-python-0.0.30 → velocity_python-0.0.32}/setup.cfg +0 -0
- {velocity-python-0.0.30 → velocity_python-0.0.32}/src/velocity/aws/handlers/__init__.py +0 -0
- {velocity-python-0.0.30 → velocity_python-0.0.32}/src/velocity/aws/handlers/context.py +0 -0
- {velocity-python-0.0.30 → velocity_python-0.0.32}/src/velocity/aws/handlers/lambda_handler.py +0 -0
- {velocity-python-0.0.30 → velocity_python-0.0.32}/src/velocity/aws/handlers/sqs_handler.py +0 -0
- {velocity-python-0.0.30 → velocity_python-0.0.32}/src/velocity/db/__init__.py +0 -0
- {velocity-python-0.0.30 → velocity_python-0.0.32}/src/velocity/db/core/__init__.py +0 -0
- {velocity-python-0.0.30 → velocity_python-0.0.32}/src/velocity/db/core/decorators.py +0 -0
- {velocity-python-0.0.30 → velocity_python-0.0.32}/src/velocity/db/core/result.py +0 -0
- {velocity-python-0.0.30 → velocity_python-0.0.32}/src/velocity/db/core/row.py +0 -0
- {velocity-python-0.0.30 → velocity_python-0.0.32}/src/velocity/db/core/table.py +0 -0
- {velocity-python-0.0.30 → velocity_python-0.0.32}/src/velocity/db/core/transaction.py +0 -0
- {velocity-python-0.0.30 → velocity_python-0.0.32}/src/velocity/db/servers/__init__.py +0 -0
- {velocity-python-0.0.30 → velocity_python-0.0.32}/src/velocity/db/servers/postgres.py +0 -0
- {velocity-python-0.0.30 → velocity_python-0.0.32}/src/velocity/misc/__init__.py +0 -0
- {velocity-python-0.0.30 → velocity_python-0.0.32}/src/velocity_python.egg-info/dependency_links.txt +0 -0
- {velocity-python-0.0.30 → velocity_python-0.0.32}/src/velocity_python.egg-info/requires.txt +0 -0
- {velocity-python-0.0.30 → velocity_python-0.0.32}/src/velocity_python.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: velocity-python
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.32
|
|
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
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import requests
|
|
3
|
+
|
|
4
|
+
DEBUG = (os.environ.get("ENV") != "production") or (os.environ.get("DEBUG") == "Y")
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
# This is helpful for running HTTPS clients on lambda.
|
|
8
|
+
if os.path.exists("/opt/python/ca-certificates.crt"):
|
|
9
|
+
os.environ["REQUESTS_CA_BUNDLE"] = "/opt/python/ca-certificates.crt"
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class AWS(object):
|
|
13
|
+
# Get AWS EC2 Instance ID. Must run this from the EC2 instance itself to get the ID
|
|
14
|
+
@staticmethod
|
|
15
|
+
def instance_id(cls):
|
|
16
|
+
response = requests.get("http://169.254.169.254/latest/meta-data/instance-id")
|
|
17
|
+
instance_id = response.text
|
|
18
|
+
return instance_id
|
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
import sys
|
|
2
|
+
import traceback
|
|
3
|
+
from typing import Any, Dict, List, Optional, Union
|
|
4
|
+
from velocity.misc.format import to_json
|
|
5
|
+
from support.app import DEBUG
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class Response:
|
|
9
|
+
"""Class to manage and structure HTTP responses with various actions and custom headers."""
|
|
10
|
+
|
|
11
|
+
VALID_VARIANTS = {"success", "error", "warning", "info"}
|
|
12
|
+
|
|
13
|
+
def __init__(self):
|
|
14
|
+
"""Initialize the Response object with default status, headers, and an empty actions list."""
|
|
15
|
+
self.actions: List[Dict[str, Any]] = []
|
|
16
|
+
self.body: Dict[str, Any] = {"actions": self.actions}
|
|
17
|
+
self.raw: Dict[str, Any] = {
|
|
18
|
+
"statusCode": 200,
|
|
19
|
+
"body": "{}",
|
|
20
|
+
"headers": {
|
|
21
|
+
"Content-Type": "application/json",
|
|
22
|
+
"Access-Control-Allow-Headers": "*",
|
|
23
|
+
"Access-Control-Allow-Origin": "*",
|
|
24
|
+
"Access-Control-Allow-Methods": "OPTIONS,POST,GET",
|
|
25
|
+
},
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
def render(self) -> Dict[str, Any]:
|
|
29
|
+
"""
|
|
30
|
+
Finalize the response body as JSON and return the complete response dictionary.
|
|
31
|
+
|
|
32
|
+
Returns:
|
|
33
|
+
Dict[str, Any]: The complete HTTP response with headers, status code, and JSON body.
|
|
34
|
+
"""
|
|
35
|
+
self.raw["body"] = to_json(self.body)
|
|
36
|
+
return self.raw
|
|
37
|
+
|
|
38
|
+
def alert(self, message: str, title: str = "Notification") -> "Response":
|
|
39
|
+
"""
|
|
40
|
+
Add an alert action to the response.
|
|
41
|
+
|
|
42
|
+
Args:
|
|
43
|
+
message (str): The alert message.
|
|
44
|
+
title (str): Title for the alert. Defaults to "Notification".
|
|
45
|
+
|
|
46
|
+
Returns:
|
|
47
|
+
Response: The current Response object, allowing method chaining.
|
|
48
|
+
"""
|
|
49
|
+
self.actions.append(
|
|
50
|
+
{
|
|
51
|
+
"action": "alert",
|
|
52
|
+
"payload": {"title": title, "message": message},
|
|
53
|
+
}
|
|
54
|
+
)
|
|
55
|
+
return self
|
|
56
|
+
|
|
57
|
+
def toast(self, message: str, variant: str = "success") -> "Response":
|
|
58
|
+
"""
|
|
59
|
+
Add a toast notification action to the response with a specified variant.
|
|
60
|
+
|
|
61
|
+
Args:
|
|
62
|
+
message (str): The message to display in the toast.
|
|
63
|
+
variant (str): The style variant of the toast (e.g., "success", "error"). Must be one of VALID_VARIANTS.
|
|
64
|
+
|
|
65
|
+
Raises:
|
|
66
|
+
ValueError: If the variant is not one of VALID_VARIANTS.
|
|
67
|
+
|
|
68
|
+
Returns:
|
|
69
|
+
Response: The current Response object, allowing method chaining.
|
|
70
|
+
"""
|
|
71
|
+
variant = variant.lower()
|
|
72
|
+
if variant not in self.VALID_VARIANTS:
|
|
73
|
+
raise ValueError(
|
|
74
|
+
f"Notistack variant '{variant}' not in {self.VALID_VARIANTS}"
|
|
75
|
+
)
|
|
76
|
+
self.actions.append(
|
|
77
|
+
{
|
|
78
|
+
"action": "toast",
|
|
79
|
+
"payload": {"options": {"variant": variant}, "message": message},
|
|
80
|
+
}
|
|
81
|
+
)
|
|
82
|
+
return self
|
|
83
|
+
|
|
84
|
+
def load_object(self, payload: Dict[str, Any]) -> "Response":
|
|
85
|
+
"""
|
|
86
|
+
Add a load-object action to the response with a specified payload.
|
|
87
|
+
|
|
88
|
+
Args:
|
|
89
|
+
payload (Dict[str, Any]): The data to load into the response.
|
|
90
|
+
|
|
91
|
+
Returns:
|
|
92
|
+
Response: The current Response object, allowing method chaining.
|
|
93
|
+
"""
|
|
94
|
+
self.actions.append({"action": "load-object", "payload": payload})
|
|
95
|
+
return self
|
|
96
|
+
|
|
97
|
+
def update_store(self, payload: Dict[str, Any]) -> "Response":
|
|
98
|
+
"""
|
|
99
|
+
Add an update-store action to the response with a specified payload.
|
|
100
|
+
|
|
101
|
+
Args:
|
|
102
|
+
payload (Dict[str, Any]): The data to update the store with.
|
|
103
|
+
|
|
104
|
+
Returns:
|
|
105
|
+
Response: The current Response object, allowing method chaining.
|
|
106
|
+
"""
|
|
107
|
+
self.actions.append({"action": "update-store", "payload": payload})
|
|
108
|
+
return self
|
|
109
|
+
|
|
110
|
+
def file_download(self, payload: Dict[str, Any]) -> "Response":
|
|
111
|
+
"""
|
|
112
|
+
Add a file-download action to the response with a specified payload.
|
|
113
|
+
|
|
114
|
+
Args:
|
|
115
|
+
payload (Dict[str, Any]): The data for file download details.
|
|
116
|
+
|
|
117
|
+
Returns:
|
|
118
|
+
Response: The current Response object, allowing method chaining.
|
|
119
|
+
"""
|
|
120
|
+
self.actions.append({"action": "file-download", "payload": payload})
|
|
121
|
+
return self
|
|
122
|
+
|
|
123
|
+
def status(self, code: Optional[int] = None) -> int:
|
|
124
|
+
"""
|
|
125
|
+
Get or set the status code of the response.
|
|
126
|
+
|
|
127
|
+
Args:
|
|
128
|
+
code (Optional[int]): The HTTP status code to set. If None, returns the current status code.
|
|
129
|
+
|
|
130
|
+
Returns:
|
|
131
|
+
int: The current status code.
|
|
132
|
+
"""
|
|
133
|
+
if code is not None:
|
|
134
|
+
self.raw["statusCode"] = int(code)
|
|
135
|
+
return self.raw["statusCode"]
|
|
136
|
+
|
|
137
|
+
def headers(self, headers: Optional[Dict[str, str]] = None) -> Dict[str, str]:
|
|
138
|
+
"""
|
|
139
|
+
Get or update the headers of the response.
|
|
140
|
+
|
|
141
|
+
Args:
|
|
142
|
+
headers (Optional[Dict[str, str]]): A dictionary of headers to add or update.
|
|
143
|
+
|
|
144
|
+
Returns:
|
|
145
|
+
Dict[str, str]: The current headers after updates.
|
|
146
|
+
"""
|
|
147
|
+
if headers:
|
|
148
|
+
formatted_headers = {
|
|
149
|
+
self._format_header_key(k): v for k, v in headers.items()
|
|
150
|
+
}
|
|
151
|
+
self.raw["headers"].update(formatted_headers)
|
|
152
|
+
return self.raw["headers"]
|
|
153
|
+
|
|
154
|
+
def set_status(self, code: int) -> "Response":
|
|
155
|
+
"""
|
|
156
|
+
Set the HTTP status code of the response.
|
|
157
|
+
|
|
158
|
+
Args:
|
|
159
|
+
code (int): The status code to set.
|
|
160
|
+
|
|
161
|
+
Returns:
|
|
162
|
+
Response: The current Response object, allowing method chaining.
|
|
163
|
+
"""
|
|
164
|
+
self.status(code)
|
|
165
|
+
return self
|
|
166
|
+
|
|
167
|
+
def set_headers(self, headers: Dict[str, str]) -> "Response":
|
|
168
|
+
"""
|
|
169
|
+
Set custom headers for the response.
|
|
170
|
+
|
|
171
|
+
Args:
|
|
172
|
+
headers (Dict[str, str]): The headers to add or update.
|
|
173
|
+
|
|
174
|
+
Returns:
|
|
175
|
+
Response: The current Response object, allowing method chaining.
|
|
176
|
+
"""
|
|
177
|
+
self.headers(headers)
|
|
178
|
+
return self
|
|
179
|
+
|
|
180
|
+
def set_body(self, body: Dict[str, Any]) -> "Response":
|
|
181
|
+
"""
|
|
182
|
+
Update the body of the response with new data.
|
|
183
|
+
|
|
184
|
+
Args:
|
|
185
|
+
body (Dict[str, Any]): The body data to update.
|
|
186
|
+
|
|
187
|
+
Returns:
|
|
188
|
+
Response: The current Response object, allowing method chaining.
|
|
189
|
+
"""
|
|
190
|
+
self.body.update(body)
|
|
191
|
+
return self
|
|
192
|
+
|
|
193
|
+
def exception(self) -> None:
|
|
194
|
+
"""
|
|
195
|
+
Capture and format the current exception details and set a 500 status code.
|
|
196
|
+
Includes traceback information if DEBUG mode is enabled.
|
|
197
|
+
"""
|
|
198
|
+
exc_type, exc_value, tb = sys.exc_info()
|
|
199
|
+
self.set_status(500)
|
|
200
|
+
self.set_body(
|
|
201
|
+
{
|
|
202
|
+
"python_exception": {
|
|
203
|
+
"type": str(exc_type),
|
|
204
|
+
"value": str(exc_value),
|
|
205
|
+
"traceback": traceback.format_exc() if DEBUG else None,
|
|
206
|
+
"tb": traceback.format_tb(tb) if DEBUG else None,
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
)
|
|
210
|
+
|
|
211
|
+
def console(self, message: str, title: str = "Notification") -> "Response":
|
|
212
|
+
"""
|
|
213
|
+
Add a console log action to the response.
|
|
214
|
+
|
|
215
|
+
Args:
|
|
216
|
+
message (str): The console message.
|
|
217
|
+
title (str): Title for the console message. Defaults to "Notification".
|
|
218
|
+
|
|
219
|
+
Returns:
|
|
220
|
+
Response: The current Response object, allowing method chaining.
|
|
221
|
+
"""
|
|
222
|
+
self.actions.append(
|
|
223
|
+
{
|
|
224
|
+
"action": "console",
|
|
225
|
+
"payload": {"title": title, "message": message},
|
|
226
|
+
}
|
|
227
|
+
)
|
|
228
|
+
return self
|
|
229
|
+
|
|
230
|
+
def redirect(self, location: str) -> "Response":
|
|
231
|
+
"""
|
|
232
|
+
Add a redirect action to the response with the target location.
|
|
233
|
+
|
|
234
|
+
Args:
|
|
235
|
+
location (str): The URL to redirect to.
|
|
236
|
+
|
|
237
|
+
Returns:
|
|
238
|
+
Response: The current Response object, allowing method chaining.
|
|
239
|
+
"""
|
|
240
|
+
self.actions.append({"action": "redirect", "payload": {"location": location}})
|
|
241
|
+
return self
|
|
242
|
+
|
|
243
|
+
def signout(self) -> "Response":
|
|
244
|
+
"""
|
|
245
|
+
Add a signout action to the response.
|
|
246
|
+
|
|
247
|
+
Returns:
|
|
248
|
+
Response: The current Response object, allowing method chaining.
|
|
249
|
+
"""
|
|
250
|
+
self.actions.append({"action": "signout"})
|
|
251
|
+
return self
|
|
252
|
+
|
|
253
|
+
def set_table(self, payload: Dict[str, Any]) -> "Response":
|
|
254
|
+
"""
|
|
255
|
+
Add a set-table action to the response with the specified payload.
|
|
256
|
+
|
|
257
|
+
Args:
|
|
258
|
+
payload (Dict[str, Any]): The table data to set.
|
|
259
|
+
|
|
260
|
+
Returns:
|
|
261
|
+
Response: The current Response object, allowing method chaining.
|
|
262
|
+
"""
|
|
263
|
+
self.actions.append({"action": "set-table", "payload": payload})
|
|
264
|
+
return self
|
|
265
|
+
|
|
266
|
+
def set_repo(self, payload: Dict[str, Any]) -> "Response":
|
|
267
|
+
"""
|
|
268
|
+
Add a set-repo action to the response with the specified payload.
|
|
269
|
+
|
|
270
|
+
Args:
|
|
271
|
+
payload (Dict[str, Any]): The repository data to set.
|
|
272
|
+
|
|
273
|
+
Returns:
|
|
274
|
+
Response: The current Response object, allowing method chaining.
|
|
275
|
+
"""
|
|
276
|
+
self.actions.append({"action": "set-repo", "payload": payload})
|
|
277
|
+
return self
|
|
278
|
+
|
|
279
|
+
@staticmethod
|
|
280
|
+
def _format_header_key(key: str) -> str:
|
|
281
|
+
"""
|
|
282
|
+
Format HTTP headers to be in a title-cased format.
|
|
283
|
+
|
|
284
|
+
Args:
|
|
285
|
+
key (str): The header key to format.
|
|
286
|
+
|
|
287
|
+
Returns:
|
|
288
|
+
str: The formatted header key.
|
|
289
|
+
"""
|
|
290
|
+
return "-".join(word.capitalize() for word in key.split("-"))
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
from velocity.db import exceptions
|
|
2
2
|
from velocity.db.core.decorators import return_default
|
|
3
3
|
|
|
4
|
+
|
|
4
5
|
class Column(object):
|
|
5
6
|
"""
|
|
6
7
|
Represents a column in a database table.
|
|
7
8
|
"""
|
|
9
|
+
|
|
8
10
|
def __init__(self, table, name):
|
|
9
11
|
"""
|
|
10
12
|
Initializes a column object with the specified table and name.
|
|
@@ -12,11 +14,11 @@ class Column(object):
|
|
|
12
14
|
Args:
|
|
13
15
|
table (table): The table object that the column belongs to.
|
|
14
16
|
name (str): The name of the column.
|
|
15
|
-
|
|
17
|
+
|
|
16
18
|
Raises:
|
|
17
19
|
Exception: If the table parameter is not of type 'table'.
|
|
18
20
|
"""
|
|
19
|
-
if isinstance(table,str):
|
|
21
|
+
if isinstance(table, str):
|
|
20
22
|
raise Exception("column table parameter must be a `table` class.")
|
|
21
23
|
self.tx = table.tx
|
|
22
24
|
self.sql = table.tx.engine.sql
|
|
@@ -39,13 +41,13 @@ class Column(object):
|
|
|
39
41
|
NULL OK: %s
|
|
40
42
|
Foreign Key: %s
|
|
41
43
|
""" % (
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
44
|
+
self.table.name,
|
|
45
|
+
self.name,
|
|
46
|
+
self.exists(),
|
|
47
|
+
self.py_type,
|
|
48
|
+
self.sql_type,
|
|
49
|
+
self.is_nullok,
|
|
50
|
+
self.foreign_key_to,
|
|
49
51
|
)
|
|
50
52
|
|
|
51
53
|
@property
|
|
@@ -55,7 +57,7 @@ class Column(object):
|
|
|
55
57
|
|
|
56
58
|
Returns:
|
|
57
59
|
dict: A dictionary containing information about the column.
|
|
58
|
-
|
|
60
|
+
|
|
59
61
|
Raises:
|
|
60
62
|
DbColumnMissingError: If the column does not exist in the database.
|
|
61
63
|
"""
|
|
@@ -72,7 +74,7 @@ class Column(object):
|
|
|
72
74
|
|
|
73
75
|
Returns:
|
|
74
76
|
dict: A dictionary containing information about the foreign key constraint.
|
|
75
|
-
|
|
77
|
+
|
|
76
78
|
Raises:
|
|
77
79
|
DbColumnMissingError: If the column does not exist in the database.
|
|
78
80
|
"""
|
|
@@ -89,12 +91,14 @@ class Column(object):
|
|
|
89
91
|
|
|
90
92
|
Returns:
|
|
91
93
|
str: The name of the referenced table and column in the format 'referenced_table_name.referenced_column_name'.
|
|
92
|
-
|
|
94
|
+
|
|
93
95
|
Raises:
|
|
94
96
|
DbColumnMissingError: If the column does not exist in the database.
|
|
95
97
|
"""
|
|
96
98
|
try:
|
|
97
|
-
return "{referenced_table_name}.{referenced_column_name}".format(
|
|
99
|
+
return "{referenced_table_name}.{referenced_column_name}".format(
|
|
100
|
+
**self.foreign_key_info
|
|
101
|
+
)
|
|
98
102
|
except exceptions.DbColumnMissingError:
|
|
99
103
|
return None
|
|
100
104
|
|
|
@@ -105,12 +109,12 @@ class Column(object):
|
|
|
105
109
|
|
|
106
110
|
Returns:
|
|
107
111
|
str: The name of the referenced table.
|
|
108
|
-
|
|
112
|
+
|
|
109
113
|
Raises:
|
|
110
114
|
DbColumnMissingError: If the column does not exist in the database.
|
|
111
115
|
"""
|
|
112
116
|
try:
|
|
113
|
-
return self.foreign_key_info[
|
|
117
|
+
return self.foreign_key_info["referenced_table_name"]
|
|
114
118
|
except exceptions.DbColumnMissingError:
|
|
115
119
|
return None
|
|
116
120
|
|
|
@@ -167,7 +171,7 @@ class Column(object):
|
|
|
167
171
|
self.name = name
|
|
168
172
|
|
|
169
173
|
@return_default([])
|
|
170
|
-
def distinct(self, order=
|
|
174
|
+
def distinct(self, order="asc", qty=None):
|
|
171
175
|
"""
|
|
172
176
|
Retrieves distinct values from the column.
|
|
173
177
|
|
|
@@ -178,7 +182,12 @@ class Column(object):
|
|
|
178
182
|
Returns:
|
|
179
183
|
list: A list of distinct values from the column.
|
|
180
184
|
"""
|
|
181
|
-
sql, vals = self.sql.select(
|
|
185
|
+
sql, vals = self.sql.select(
|
|
186
|
+
columns="distinct {}".format(self.name),
|
|
187
|
+
table=self.table.name,
|
|
188
|
+
orderby="{} {}".format(self.name, order),
|
|
189
|
+
qty=qty,
|
|
190
|
+
)
|
|
182
191
|
return self.tx.execute(sql, vals).as_simple_list().all()
|
|
183
192
|
|
|
184
193
|
def max(self, where=None):
|
|
@@ -190,13 +199,15 @@ class Column(object):
|
|
|
190
199
|
|
|
191
200
|
Returns:
|
|
192
201
|
int: The maximum value from the column.
|
|
193
|
-
|
|
202
|
+
|
|
194
203
|
Raises:
|
|
195
204
|
DbTableMissingError: If the table does not exist in the database.
|
|
196
205
|
DbColumnMissingError: If the column does not exist in the database.
|
|
197
206
|
"""
|
|
198
207
|
try:
|
|
199
|
-
sql, vals = self.sql.select(
|
|
208
|
+
sql, vals = self.sql.select(
|
|
209
|
+
columns="max({})".format(self.name), table=self.table.name, where=where
|
|
210
|
+
)
|
|
200
211
|
return self.tx.execute(sql, vals).scalar()
|
|
201
|
-
except (exceptions.DbTableMissingError,exceptions.DbColumnMissingError):
|
|
212
|
+
except (exceptions.DbTableMissingError, exceptions.DbColumnMissingError):
|
|
202
213
|
return 0
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
class Database(object):
|
|
2
|
-
|
|
2
|
+
|
|
3
3
|
def __init__(self, tx, name=None):
|
|
4
4
|
self.tx = tx
|
|
5
|
-
self.name = name or self.tx.engine.config[
|
|
5
|
+
self.name = name or self.tx.engine.config["database"]
|
|
6
6
|
self.sql = tx.engine.sql
|
|
7
7
|
|
|
8
8
|
def __str__(self):
|
|
@@ -12,10 +12,10 @@ class Database(object):
|
|
|
12
12
|
(db exists) %s
|
|
13
13
|
Tables: %s
|
|
14
14
|
""" % (
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
15
|
+
self.tx.engine.sql.server,
|
|
16
|
+
self.name,
|
|
17
|
+
self.exists(),
|
|
18
|
+
len(self.tables),
|
|
19
19
|
)
|
|
20
20
|
|
|
21
21
|
def __enter__(self):
|
|
@@ -28,7 +28,7 @@ class Database(object):
|
|
|
28
28
|
def close(self):
|
|
29
29
|
try:
|
|
30
30
|
self._cursor.close()
|
|
31
|
-
#print("*** database('{}').cursor.close()".format(self.name))
|
|
31
|
+
# print("*** database('{}').cursor.close()".format(self.name))
|
|
32
32
|
except AttributeError:
|
|
33
33
|
pass
|
|
34
34
|
|
|
@@ -37,7 +37,7 @@ class Database(object):
|
|
|
37
37
|
try:
|
|
38
38
|
return self._cursor
|
|
39
39
|
except AttributeError:
|
|
40
|
-
#print("*** database('{}').cursor.open()".format(self.name))
|
|
40
|
+
# print("*** database('{}').cursor.open()".format(self.name))
|
|
41
41
|
self._cursor = self.tx.cursor()
|
|
42
42
|
return self._cursor
|
|
43
43
|
|
|
@@ -57,7 +57,7 @@ class Database(object):
|
|
|
57
57
|
@property
|
|
58
58
|
def tables(self):
|
|
59
59
|
sql, vals = self.sql.tables()
|
|
60
|
-
result = self.tx.execute(sql
|
|
60
|
+
result = self.tx.execute(sql, vals, cursor=self.cursor)
|
|
61
61
|
return ["%s.%s" % x for x in result.as_tuple()]
|
|
62
62
|
|
|
63
63
|
def reindex(self):
|