velocity-python 0.0.1__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.
Potentially problematic release.
This version of velocity-python might be problematic. Click here for more details.
- velocity-python-0.0.1/LICENSE +19 -0
- velocity-python-0.0.1/PKG-INFO +181 -0
- velocity-python-0.0.1/README.md +160 -0
- velocity-python-0.0.1/pyproject.toml +27 -0
- velocity-python-0.0.1/setup.cfg +4 -0
- velocity-python-0.0.1/src/velocity/__init__.py +3 -0
- velocity-python-0.0.1/src/velocity/aws/__init__.py +24 -0
- velocity-python-0.0.1/src/velocity/aws/context.py +0 -0
- velocity-python-0.0.1/src/velocity/aws/handlers/__init__.py +2 -0
- velocity-python-0.0.1/src/velocity/aws/handlers/lambda_handler.py +123 -0
- velocity-python-0.0.1/src/velocity/aws/handlers/sqs_handler.py +48 -0
- velocity-python-0.0.1/src/velocity/db/__init__.py +5 -0
- velocity-python-0.0.1/src/velocity/db/core/__init__.py +0 -0
- velocity-python-0.0.1/src/velocity/db/core/column.py +202 -0
- velocity-python-0.0.1/src/velocity/db/core/database.py +65 -0
- velocity-python-0.0.1/src/velocity/db/core/decorators.py +81 -0
- velocity-python-0.0.1/src/velocity/db/core/engine.py +367 -0
- velocity-python-0.0.1/src/velocity/db/core/exceptions.py +31 -0
- velocity-python-0.0.1/src/velocity/db/core/result.py +137 -0
- velocity-python-0.0.1/src/velocity/db/core/row.py +191 -0
- velocity-python-0.0.1/src/velocity/db/core/sequence.py +33 -0
- velocity-python-0.0.1/src/velocity/db/core/table.py +448 -0
- velocity-python-0.0.1/src/velocity/db/core/transaction.py +178 -0
- velocity-python-0.0.1/src/velocity/db/servers/__init__.py +0 -0
- velocity-python-0.0.1/src/velocity/db/servers/mysql.py +575 -0
- velocity-python-0.0.1/src/velocity/db/servers/postgres.py +1275 -0
- velocity-python-0.0.1/src/velocity/db/servers/sql.py +558 -0
- velocity-python-0.0.1/src/velocity/db/servers/sqlite.py +899 -0
- velocity-python-0.0.1/src/velocity/db/servers/sqlserver.py +821 -0
- velocity-python-0.0.1/src/velocity/misc/__init__.py +0 -0
- velocity-python-0.0.1/src/velocity/misc/conv.py +420 -0
- velocity-python-0.0.1/src/velocity/misc/db.py +85 -0
- velocity-python-0.0.1/src/velocity/misc/export.py +147 -0
- velocity-python-0.0.1/src/velocity/misc/format.py +81 -0
- velocity-python-0.0.1/src/velocity/misc/mail.py +67 -0
- velocity-python-0.0.1/src/velocity/misc/timer.py +27 -0
- velocity-python-0.0.1/src/velocity_python.egg-info/PKG-INFO +181 -0
- velocity-python-0.0.1/src/velocity_python.egg-info/SOURCES.txt +39 -0
- velocity-python-0.0.1/src/velocity_python.egg-info/dependency_links.txt +1 -0
- velocity-python-0.0.1/src/velocity_python.egg-info/requires.txt +8 -0
- velocity-python-0.0.1/src/velocity_python.egg-info/top_level.txt +1 -0
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
Copyright (c) 2000-2023 Paul Perez
|
|
2
|
+
|
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
4
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
5
|
+
in the Software without restriction, including without limitation the rights
|
|
6
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
7
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
8
|
+
furnished to do so, subject to the following conditions:
|
|
9
|
+
|
|
10
|
+
The above copyright notice and this permission notice shall be included in all
|
|
11
|
+
copies or substantial portions of the Software.
|
|
12
|
+
|
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
15
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
16
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
17
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
18
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
19
|
+
SOFTWARE.
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: velocity-python
|
|
3
|
+
Version: 0.0.1
|
|
4
|
+
Summary: A rapid application development library for interfacing with data storage
|
|
5
|
+
Author-email: Paul Perez <pperez@codeclubs.org>
|
|
6
|
+
Project-URL: Homepage, https://codeclubs.org/projects/velocity
|
|
7
|
+
Classifier: Programming Language :: Python :: 3
|
|
8
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
9
|
+
Classifier: Operating System :: OS Independent
|
|
10
|
+
Requires-Python: >=3.7
|
|
11
|
+
Description-Content-Type: text/markdown
|
|
12
|
+
License-File: LICENSE
|
|
13
|
+
Requires-Dist: requests
|
|
14
|
+
Requires-Dist: psycopg2-binary
|
|
15
|
+
Requires-Dist: python-tds
|
|
16
|
+
Requires-Dist: mysql-connector-python
|
|
17
|
+
Requires-Dist: openpyxl
|
|
18
|
+
Requires-Dist: boto3
|
|
19
|
+
Requires-Dist: jinja2
|
|
20
|
+
Requires-Dist: xlrd
|
|
21
|
+
|
|
22
|
+
# Velocity.DB
|
|
23
|
+
|
|
24
|
+
This project's goal is to simplify database management by abstracting complex (and many times database engine specific) functions to Python methods. This project is still in its infancy and is not yet ready for production use. If you would like to contribute to this project, please feel free to fork it and submit a pull request. This documentation is severely out of date and not yet complete, but will be updated as the project progresses.
|
|
25
|
+
|
|
26
|
+
This project currently supports the following database engines:
|
|
27
|
+
|
|
28
|
+
<b>PostgreSQL</b><br/>
|
|
29
|
+
<b>Microsoft SQL Server</b><br/>
|
|
30
|
+
<b>SQLite</b><br/>
|
|
31
|
+
<b>MySQL</b><br/>
|
|
32
|
+
|
|
33
|
+
[The source for this project is available here][src].
|
|
34
|
+
|
|
35
|
+
<b>Prerequisites:</b><br/>
|
|
36
|
+
The following packages must be installed prior to using Velocity.DB:<br/>
|
|
37
|
+
`psycopg2` - For PostgreSQL<br/>
|
|
38
|
+
`pytds` - For Microsoft SQL Server<br/>
|
|
39
|
+
`sqlite3` - For SQLite 3<br/>
|
|
40
|
+
`mysqlclient` - MySQL<br/>
|
|
41
|
+
You will also need the MySQL Connector for your operating system before you install `mysqlclient`. You can download it <a href='https://dev.mysql.com/downloads/connector/c/'>here.</a>
|
|
42
|
+
|
|
43
|
+
<b>For Windows Users:</b><br/>
|
|
44
|
+
If you're using Windows, after you install the MySQL Connector you will need the Visual C++ Compiler for Python 2.7, you can download it <a href='https://www.microsoft.com/en-us/download/details.aspx?id=44266'>here.</a> After both dependencies are installed you can install `mysqlclient` without issue.
|
|
45
|
+
|
|
46
|
+
Optionally if you only want to support a single database engine or do not want to install dependencies for engines you won't be using, download the source code for velocity.db and comment out the engines you wont be using in the `python-db/velocity/db/__init_.py` file on the following lines:
|
|
47
|
+
|
|
48
|
+
<pre>
|
|
49
|
+
# Import for PostgreSQL Support
|
|
50
|
+
import servers.postgres
|
|
51
|
+
postgres = servers.postgres.initialize()
|
|
52
|
+
<br/># Import for Microsoft SQL Server Support
|
|
53
|
+
import servers.sqlserver
|
|
54
|
+
sqlserver = servers.sqlserver.initialize
|
|
55
|
+
<br/># Import for SQLite 3 Support
|
|
56
|
+
import servers.sqlite
|
|
57
|
+
sqlite = servers.sqlite.initialize
|
|
58
|
+
<br/># Import for MySQL Support
|
|
59
|
+
import servers.mysql
|
|
60
|
+
mysql = servers.mysql.initialize</pre>
|
|
61
|
+
|
|
62
|
+
If you setup your project this way, make sure to install velocity.db using: `python setup.py develop` in case you want to revert your changes.
|
|
63
|
+
|
|
64
|
+
----
|
|
65
|
+
|
|
66
|
+
# Using Velocity.DB
|
|
67
|
+
|
|
68
|
+
<b>Warning: Not all database engines are alike, and some datatypes in certain engines will be specific to the engine. This tutorial assumes you have basic knowledge of your database engine and it's specific datatypes.</b>
|
|
69
|
+
|
|
70
|
+
To setup Velocity.DB with your server, define your server variable like so:
|
|
71
|
+
|
|
72
|
+
<b>PostgreSQL:</b>
|
|
73
|
+
<pre>
|
|
74
|
+
import velocity.db
|
|
75
|
+
<br/>server = velocity.db.postgres({
|
|
76
|
+
'database':'db-name',
|
|
77
|
+
'host': 'server',
|
|
78
|
+
'user':'username',
|
|
79
|
+
'password':'password',
|
|
80
|
+
})
|
|
81
|
+
</pre>
|
|
82
|
+
<b>Microsoft SQL Server:</b>
|
|
83
|
+
<pre>
|
|
84
|
+
import velocity.db
|
|
85
|
+
<br/>server = velocity.db.sqlserver({
|
|
86
|
+
'database': 'db-name',
|
|
87
|
+
'server': 'server',
|
|
88
|
+
'user':'username',
|
|
89
|
+
'password':'password',
|
|
90
|
+
'use_mars': True, # To enable Multiple Active Result Sets (disabled by default)
|
|
91
|
+
})
|
|
92
|
+
</pre>
|
|
93
|
+
<b>SQLite:</b>
|
|
94
|
+
<pre>
|
|
95
|
+
import velocity.db
|
|
96
|
+
<br/>server = velocity.db.sqlserver({
|
|
97
|
+
'database': 'db-name' # Use ':memory:' for an in memory database
|
|
98
|
+
})
|
|
99
|
+
</pre>
|
|
100
|
+
<b>MySQL:</b>
|
|
101
|
+
<pre>
|
|
102
|
+
import velocity.db
|
|
103
|
+
<br/>server = velocity.db.mysql({
|
|
104
|
+
'db':'db-name',
|
|
105
|
+
'host':'server',
|
|
106
|
+
'user':'username',
|
|
107
|
+
'passwd':'password',
|
|
108
|
+
})
|
|
109
|
+
</pre>
|
|
110
|
+
<br>
|
|
111
|
+
<b>Basic SQL Functions:</b><br/>
|
|
112
|
+
Since the SQL ANSI standard holds all SQL compliant databases to the CRUD standard (Create, Read, Update, Delete) we will cover how to accomplish all of those functions using Velocity.DB.<br/>
|
|
113
|
+
<br/><b>The <code>@server.transaction</code> Decorator:</b><br/>
|
|
114
|
+
All SQL transactions have to live in their own functions so that in case some part of the function fails, the transaction will not commit. In order to signify a method as a transaction, use the <code>@server.transaction</code> decorator. Any function using this decorator will not commit any changes to the database unless the function successfully completes without error. This also passes the argument <code>tx</code> to your method which allows you to access the transaction object within your method.<br/>
|
|
115
|
+
<br/><b>Creating a Table:</b>
|
|
116
|
+
<pre>
|
|
117
|
+
@server.transaction
|
|
118
|
+
def create_new_table(self, tx):
|
|
119
|
+
t = tx.table('new_table')
|
|
120
|
+
t.create()
|
|
121
|
+
</pre>
|
|
122
|
+
Once the function is complete the transaction will commit and you will have a new table in your database titled 'new_table'.<br>
|
|
123
|
+
If you would like to create a new row and add a column, you could do so using the following syntax:
|
|
124
|
+
<pre>
|
|
125
|
+
@server.transaction
|
|
126
|
+
def add_column(self,tx):
|
|
127
|
+
# We will be using the same table we made in the above method.
|
|
128
|
+
t = tx.table('new_table')
|
|
129
|
+
# Creates a new row with a primary key of 1 (sys_id by default)
|
|
130
|
+
r = t.row(1)
|
|
131
|
+
r['new_column'] = 'Value to be placed in the first row of the new column'
|
|
132
|
+
</pre>
|
|
133
|
+
<br/><b>Reading Data from a Table:</b>
|
|
134
|
+
<br/>Now let's say you already have a table with data named 'people', and you want to read the 'firstname' column of your table on the third row and return that field. You would accomplish this in Velocity.DB like so:
|
|
135
|
+
<pre>
|
|
136
|
+
@server.transaction
|
|
137
|
+
def read_third_firstname(self, tx):
|
|
138
|
+
t = tx.table('people')
|
|
139
|
+
r = t.row(3)
|
|
140
|
+
return r['firstname']
|
|
141
|
+
</pre>
|
|
142
|
+
The above method will return the value of the 'firstname' column in row 3 of the table. The table object is iterable so if you would like to return the values of each field in the 'firstname' column you could do so like this:
|
|
143
|
+
<pre>
|
|
144
|
+
@server.transaction
|
|
145
|
+
def read_all_firstnames(self,tx):
|
|
146
|
+
t = tx.table('people')
|
|
147
|
+
name_list = []
|
|
148
|
+
for r in t:
|
|
149
|
+
name_list.append(r['firstname'])
|
|
150
|
+
return name_list
|
|
151
|
+
</pre>
|
|
152
|
+
<b>Updating a Preexisting Table:</b><br/>
|
|
153
|
+
If you already have a table that you would like to update the data within, you can update data fields using the same syntax that you would use to create the field. This example will be working on a table named 'people' with columns: 'firstname' and 'lastname' with information filled out for 3 rows. Let's assume that the person on row 2 just got married and their last name has changed so we need to update it within the database.
|
|
154
|
+
<pre>
|
|
155
|
+
@server.transaction
|
|
156
|
+
def update_lastname(self, tx):
|
|
157
|
+
t = tx.table('people')
|
|
158
|
+
r = t.row(2)
|
|
159
|
+
r['lastname'] = 'Newname'
|
|
160
|
+
</pre>
|
|
161
|
+
Notice the syntax is the same as if we were creating a new column. This syntax will attempt to insert the data, and if the column doesn't exist then it will create it. It will also see if the data is already populated, and if so it will issue a UPDATE command to the database instead.<br/>
|
|
162
|
+
<br/><b>Deleting Data and Dropping Tables:</b><br/>
|
|
163
|
+
To delete data from an existing table you may want to only delete a specific row. We will use the same 'people' database, let's go ahead and delete the person that was occupying row 3.
|
|
164
|
+
<pre>
|
|
165
|
+
@server.transaction
|
|
166
|
+
def delete_person(self, tx):
|
|
167
|
+
t = tx.table('people')
|
|
168
|
+
r = t.row(3)
|
|
169
|
+
r.delete()
|
|
170
|
+
</pre>
|
|
171
|
+
It's as simple as that! But what if instead you were wanting to drop the whole table? <b>Warning: Executing the following code will drop the table from the database, if you are testing on your own database make sure you have a backup first.</b>
|
|
172
|
+
<pre>
|
|
173
|
+
@server.transaction
|
|
174
|
+
def drop_table(self, tx):
|
|
175
|
+
t = tx.table('people')
|
|
176
|
+
t.drop()
|
|
177
|
+
</pre>
|
|
178
|
+
Keep in mind this will use the "IF EXISTS" SQL statement so if you accidentally misspell a table name, your program will not hang and no tables will be dropped.<br/>
|
|
179
|
+
<br/>Congratulations, you now know how to use basic CRUD functionality with Velocity.DB. Velocity.DB has many advanced features as well, so if you'd like to see how some of those methods are used check out the <code>python-db/velocity/tests/db/unit_tests.py</code> file for examples.
|
|
180
|
+
|
|
181
|
+
[src]: https://github.com/
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
# Velocity.DB
|
|
2
|
+
|
|
3
|
+
This project's goal is to simplify database management by abstracting complex (and many times database engine specific) functions to Python methods. This project is still in its infancy and is not yet ready for production use. If you would like to contribute to this project, please feel free to fork it and submit a pull request. This documentation is severely out of date and not yet complete, but will be updated as the project progresses.
|
|
4
|
+
|
|
5
|
+
This project currently supports the following database engines:
|
|
6
|
+
|
|
7
|
+
<b>PostgreSQL</b><br/>
|
|
8
|
+
<b>Microsoft SQL Server</b><br/>
|
|
9
|
+
<b>SQLite</b><br/>
|
|
10
|
+
<b>MySQL</b><br/>
|
|
11
|
+
|
|
12
|
+
[The source for this project is available here][src].
|
|
13
|
+
|
|
14
|
+
<b>Prerequisites:</b><br/>
|
|
15
|
+
The following packages must be installed prior to using Velocity.DB:<br/>
|
|
16
|
+
`psycopg2` - For PostgreSQL<br/>
|
|
17
|
+
`pytds` - For Microsoft SQL Server<br/>
|
|
18
|
+
`sqlite3` - For SQLite 3<br/>
|
|
19
|
+
`mysqlclient` - MySQL<br/>
|
|
20
|
+
You will also need the MySQL Connector for your operating system before you install `mysqlclient`. You can download it <a href='https://dev.mysql.com/downloads/connector/c/'>here.</a>
|
|
21
|
+
|
|
22
|
+
<b>For Windows Users:</b><br/>
|
|
23
|
+
If you're using Windows, after you install the MySQL Connector you will need the Visual C++ Compiler for Python 2.7, you can download it <a href='https://www.microsoft.com/en-us/download/details.aspx?id=44266'>here.</a> After both dependencies are installed you can install `mysqlclient` without issue.
|
|
24
|
+
|
|
25
|
+
Optionally if you only want to support a single database engine or do not want to install dependencies for engines you won't be using, download the source code for velocity.db and comment out the engines you wont be using in the `python-db/velocity/db/__init_.py` file on the following lines:
|
|
26
|
+
|
|
27
|
+
<pre>
|
|
28
|
+
# Import for PostgreSQL Support
|
|
29
|
+
import servers.postgres
|
|
30
|
+
postgres = servers.postgres.initialize()
|
|
31
|
+
<br/># Import for Microsoft SQL Server Support
|
|
32
|
+
import servers.sqlserver
|
|
33
|
+
sqlserver = servers.sqlserver.initialize
|
|
34
|
+
<br/># Import for SQLite 3 Support
|
|
35
|
+
import servers.sqlite
|
|
36
|
+
sqlite = servers.sqlite.initialize
|
|
37
|
+
<br/># Import for MySQL Support
|
|
38
|
+
import servers.mysql
|
|
39
|
+
mysql = servers.mysql.initialize</pre>
|
|
40
|
+
|
|
41
|
+
If you setup your project this way, make sure to install velocity.db using: `python setup.py develop` in case you want to revert your changes.
|
|
42
|
+
|
|
43
|
+
----
|
|
44
|
+
|
|
45
|
+
# Using Velocity.DB
|
|
46
|
+
|
|
47
|
+
<b>Warning: Not all database engines are alike, and some datatypes in certain engines will be specific to the engine. This tutorial assumes you have basic knowledge of your database engine and it's specific datatypes.</b>
|
|
48
|
+
|
|
49
|
+
To setup Velocity.DB with your server, define your server variable like so:
|
|
50
|
+
|
|
51
|
+
<b>PostgreSQL:</b>
|
|
52
|
+
<pre>
|
|
53
|
+
import velocity.db
|
|
54
|
+
<br/>server = velocity.db.postgres({
|
|
55
|
+
'database':'db-name',
|
|
56
|
+
'host': 'server',
|
|
57
|
+
'user':'username',
|
|
58
|
+
'password':'password',
|
|
59
|
+
})
|
|
60
|
+
</pre>
|
|
61
|
+
<b>Microsoft SQL Server:</b>
|
|
62
|
+
<pre>
|
|
63
|
+
import velocity.db
|
|
64
|
+
<br/>server = velocity.db.sqlserver({
|
|
65
|
+
'database': 'db-name',
|
|
66
|
+
'server': 'server',
|
|
67
|
+
'user':'username',
|
|
68
|
+
'password':'password',
|
|
69
|
+
'use_mars': True, # To enable Multiple Active Result Sets (disabled by default)
|
|
70
|
+
})
|
|
71
|
+
</pre>
|
|
72
|
+
<b>SQLite:</b>
|
|
73
|
+
<pre>
|
|
74
|
+
import velocity.db
|
|
75
|
+
<br/>server = velocity.db.sqlserver({
|
|
76
|
+
'database': 'db-name' # Use ':memory:' for an in memory database
|
|
77
|
+
})
|
|
78
|
+
</pre>
|
|
79
|
+
<b>MySQL:</b>
|
|
80
|
+
<pre>
|
|
81
|
+
import velocity.db
|
|
82
|
+
<br/>server = velocity.db.mysql({
|
|
83
|
+
'db':'db-name',
|
|
84
|
+
'host':'server',
|
|
85
|
+
'user':'username',
|
|
86
|
+
'passwd':'password',
|
|
87
|
+
})
|
|
88
|
+
</pre>
|
|
89
|
+
<br>
|
|
90
|
+
<b>Basic SQL Functions:</b><br/>
|
|
91
|
+
Since the SQL ANSI standard holds all SQL compliant databases to the CRUD standard (Create, Read, Update, Delete) we will cover how to accomplish all of those functions using Velocity.DB.<br/>
|
|
92
|
+
<br/><b>The <code>@server.transaction</code> Decorator:</b><br/>
|
|
93
|
+
All SQL transactions have to live in their own functions so that in case some part of the function fails, the transaction will not commit. In order to signify a method as a transaction, use the <code>@server.transaction</code> decorator. Any function using this decorator will not commit any changes to the database unless the function successfully completes without error. This also passes the argument <code>tx</code> to your method which allows you to access the transaction object within your method.<br/>
|
|
94
|
+
<br/><b>Creating a Table:</b>
|
|
95
|
+
<pre>
|
|
96
|
+
@server.transaction
|
|
97
|
+
def create_new_table(self, tx):
|
|
98
|
+
t = tx.table('new_table')
|
|
99
|
+
t.create()
|
|
100
|
+
</pre>
|
|
101
|
+
Once the function is complete the transaction will commit and you will have a new table in your database titled 'new_table'.<br>
|
|
102
|
+
If you would like to create a new row and add a column, you could do so using the following syntax:
|
|
103
|
+
<pre>
|
|
104
|
+
@server.transaction
|
|
105
|
+
def add_column(self,tx):
|
|
106
|
+
# We will be using the same table we made in the above method.
|
|
107
|
+
t = tx.table('new_table')
|
|
108
|
+
# Creates a new row with a primary key of 1 (sys_id by default)
|
|
109
|
+
r = t.row(1)
|
|
110
|
+
r['new_column'] = 'Value to be placed in the first row of the new column'
|
|
111
|
+
</pre>
|
|
112
|
+
<br/><b>Reading Data from a Table:</b>
|
|
113
|
+
<br/>Now let's say you already have a table with data named 'people', and you want to read the 'firstname' column of your table on the third row and return that field. You would accomplish this in Velocity.DB like so:
|
|
114
|
+
<pre>
|
|
115
|
+
@server.transaction
|
|
116
|
+
def read_third_firstname(self, tx):
|
|
117
|
+
t = tx.table('people')
|
|
118
|
+
r = t.row(3)
|
|
119
|
+
return r['firstname']
|
|
120
|
+
</pre>
|
|
121
|
+
The above method will return the value of the 'firstname' column in row 3 of the table. The table object is iterable so if you would like to return the values of each field in the 'firstname' column you could do so like this:
|
|
122
|
+
<pre>
|
|
123
|
+
@server.transaction
|
|
124
|
+
def read_all_firstnames(self,tx):
|
|
125
|
+
t = tx.table('people')
|
|
126
|
+
name_list = []
|
|
127
|
+
for r in t:
|
|
128
|
+
name_list.append(r['firstname'])
|
|
129
|
+
return name_list
|
|
130
|
+
</pre>
|
|
131
|
+
<b>Updating a Preexisting Table:</b><br/>
|
|
132
|
+
If you already have a table that you would like to update the data within, you can update data fields using the same syntax that you would use to create the field. This example will be working on a table named 'people' with columns: 'firstname' and 'lastname' with information filled out for 3 rows. Let's assume that the person on row 2 just got married and their last name has changed so we need to update it within the database.
|
|
133
|
+
<pre>
|
|
134
|
+
@server.transaction
|
|
135
|
+
def update_lastname(self, tx):
|
|
136
|
+
t = tx.table('people')
|
|
137
|
+
r = t.row(2)
|
|
138
|
+
r['lastname'] = 'Newname'
|
|
139
|
+
</pre>
|
|
140
|
+
Notice the syntax is the same as if we were creating a new column. This syntax will attempt to insert the data, and if the column doesn't exist then it will create it. It will also see if the data is already populated, and if so it will issue a UPDATE command to the database instead.<br/>
|
|
141
|
+
<br/><b>Deleting Data and Dropping Tables:</b><br/>
|
|
142
|
+
To delete data from an existing table you may want to only delete a specific row. We will use the same 'people' database, let's go ahead and delete the person that was occupying row 3.
|
|
143
|
+
<pre>
|
|
144
|
+
@server.transaction
|
|
145
|
+
def delete_person(self, tx):
|
|
146
|
+
t = tx.table('people')
|
|
147
|
+
r = t.row(3)
|
|
148
|
+
r.delete()
|
|
149
|
+
</pre>
|
|
150
|
+
It's as simple as that! But what if instead you were wanting to drop the whole table? <b>Warning: Executing the following code will drop the table from the database, if you are testing on your own database make sure you have a backup first.</b>
|
|
151
|
+
<pre>
|
|
152
|
+
@server.transaction
|
|
153
|
+
def drop_table(self, tx):
|
|
154
|
+
t = tx.table('people')
|
|
155
|
+
t.drop()
|
|
156
|
+
</pre>
|
|
157
|
+
Keep in mind this will use the "IF EXISTS" SQL statement so if you accidentally misspell a table name, your program will not hang and no tables will be dropped.<br/>
|
|
158
|
+
<br/>Congratulations, you now know how to use basic CRUD functionality with Velocity.DB. Velocity.DB has many advanced features as well, so if you'd like to see how some of those methods are used check out the <code>python-db/velocity/tests/db/unit_tests.py</code> file for examples.
|
|
159
|
+
|
|
160
|
+
[src]: https://github.com/
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "velocity-python"
|
|
3
|
+
version = "0.0.1"
|
|
4
|
+
authors = [
|
|
5
|
+
{ name="Paul Perez", email="pperez@codeclubs.org" },
|
|
6
|
+
]
|
|
7
|
+
description = "A rapid application development library for interfacing with data storage"
|
|
8
|
+
readme = "README.md"
|
|
9
|
+
requires-python = ">=3.7"
|
|
10
|
+
classifiers = [
|
|
11
|
+
"Programming Language :: Python :: 3",
|
|
12
|
+
"License :: OSI Approved :: MIT License",
|
|
13
|
+
"Operating System :: OS Independent",
|
|
14
|
+
]
|
|
15
|
+
dependencies = [
|
|
16
|
+
'requests',
|
|
17
|
+
'psycopg2-binary',
|
|
18
|
+
'python-tds',
|
|
19
|
+
'mysql-connector-python',
|
|
20
|
+
'openpyxl',
|
|
21
|
+
'boto3',
|
|
22
|
+
'jinja2',
|
|
23
|
+
'xlrd',
|
|
24
|
+
|
|
25
|
+
]
|
|
26
|
+
[project.urls]
|
|
27
|
+
Homepage = "https://codeclubs.org/projects/velocity"
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import requests
|
|
3
|
+
|
|
4
|
+
from velocity.aws.handlers import LambdaHandler
|
|
5
|
+
from velocity.aws.handlers import SqsHandler
|
|
6
|
+
|
|
7
|
+
DEBUG = (os.environ.get('ENV') != 'production') \
|
|
8
|
+
or (os.environ.get('DEBUG') == 'Y')
|
|
9
|
+
|
|
10
|
+
# This is helpful for running HTTPS clients on lambda.
|
|
11
|
+
if os.path.exists('/opt/python/ca-certificates.crt'):
|
|
12
|
+
os.environ["REQUESTS_CA_BUNDLE"] = '/opt/python/ca-certificates.crt'
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class AWS(object):
|
|
16
|
+
# Get AWS EC2 Instance ID. Must run this from the EC2 instance itself to get the ID
|
|
17
|
+
@staticmethod
|
|
18
|
+
def instance_id(cls):
|
|
19
|
+
response = requests.get(
|
|
20
|
+
'http://169.254.169.254/latest/meta-data/instance-id')
|
|
21
|
+
instance_id = response.text
|
|
22
|
+
return instance_id
|
|
23
|
+
|
|
24
|
+
|
|
File without changes
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
from velocity.misc.format import to_json
|
|
2
|
+
import json
|
|
3
|
+
import pprint
|
|
4
|
+
import traceback
|
|
5
|
+
|
|
6
|
+
class LambdaHandler:
|
|
7
|
+
def __init__(self, event, context):
|
|
8
|
+
self.event = event
|
|
9
|
+
self.context = context
|
|
10
|
+
self.serve_action_default = True
|
|
11
|
+
|
|
12
|
+
requestContext = event.get('requestContext', {})
|
|
13
|
+
identity = requestContext.get('identity', {})
|
|
14
|
+
headers = event.get('headers', {})
|
|
15
|
+
self.session = {
|
|
16
|
+
'authentication_provider':
|
|
17
|
+
identity.get('cognitoAuthenticationProvider'),
|
|
18
|
+
'authentication_type':
|
|
19
|
+
identity.get('cognitoAuthenticationType'),
|
|
20
|
+
'cognito_user':
|
|
21
|
+
identity.get('user'),
|
|
22
|
+
'is_desktop':
|
|
23
|
+
headers.get('CloudFront-Is-Desktop-Viewer') == 'true',
|
|
24
|
+
'is_mobile':
|
|
25
|
+
headers.get('CloudFront-Is-Mobile-Viewer') == 'true',
|
|
26
|
+
'is_smart_tv':
|
|
27
|
+
headers.get('CloudFront-Is-SmartTV-Viewer') == 'true',
|
|
28
|
+
'is_tablet':
|
|
29
|
+
headers.get('CloudFront-Is-Tablet-Viewer') == 'true',
|
|
30
|
+
'origin':
|
|
31
|
+
headers.get('origin'),
|
|
32
|
+
'path':
|
|
33
|
+
event.get('path'),
|
|
34
|
+
'referer':
|
|
35
|
+
headers.get('Referer'),
|
|
36
|
+
'source_ip':
|
|
37
|
+
identity.get('sourceIp'),
|
|
38
|
+
'user_agent':
|
|
39
|
+
identity.get('userAgent'),
|
|
40
|
+
}
|
|
41
|
+
if self.session.get('is_mobile'):
|
|
42
|
+
self.session['device_type'] = 'mobile'
|
|
43
|
+
elif self.session.get('is_desktop'):
|
|
44
|
+
self.session['device_type'] = 'desktop'
|
|
45
|
+
elif self.session.get('is_tablet'):
|
|
46
|
+
self.session['device_type'] = 'tablet'
|
|
47
|
+
elif self.session.get('is_smart_tv'):
|
|
48
|
+
self.session['device_type'] = 'smart_tv'
|
|
49
|
+
else:
|
|
50
|
+
self.session['device_type'] = 'unknown'
|
|
51
|
+
|
|
52
|
+
def serve(self, tx):
|
|
53
|
+
response = {
|
|
54
|
+
'statusCode': 200,
|
|
55
|
+
'body': '{}',
|
|
56
|
+
'headers': {
|
|
57
|
+
'Content-Type': 'application/json',
|
|
58
|
+
"Access-Control-Allow-Origin": "*",
|
|
59
|
+
},
|
|
60
|
+
}
|
|
61
|
+
try:
|
|
62
|
+
postdata = {}
|
|
63
|
+
if self.event.get('body'):
|
|
64
|
+
postdata = json.loads(self.event.get('body'))
|
|
65
|
+
req_params = self.event.get('queryStringParameters') or {}
|
|
66
|
+
if hasattr(self, 'beforeAction'):
|
|
67
|
+
self.beforeAction(args=req_params,
|
|
68
|
+
postdata=postdata,
|
|
69
|
+
response=response)
|
|
70
|
+
actions = []
|
|
71
|
+
action = postdata.get('action', req_params.get('action'))
|
|
72
|
+
if action:
|
|
73
|
+
actions.append(
|
|
74
|
+
f"on action {action.replace('-', ' ').replace('_', ' ')}".
|
|
75
|
+
title().replace(' ', ''))
|
|
76
|
+
if self.serve_action_default:
|
|
77
|
+
actions.append('OnActionDefault')
|
|
78
|
+
for action in actions:
|
|
79
|
+
if hasattr(self, action):
|
|
80
|
+
getattr(self, action)(args=req_params,
|
|
81
|
+
postdata=postdata,
|
|
82
|
+
response=response)
|
|
83
|
+
break
|
|
84
|
+
if hasattr(self, 'afterAction'):
|
|
85
|
+
self.afterAction(args=req_params,
|
|
86
|
+
postdata=postdata,
|
|
87
|
+
response=response)
|
|
88
|
+
|
|
89
|
+
except Exception as e:
|
|
90
|
+
response = {
|
|
91
|
+
'statusCode':
|
|
92
|
+
500,
|
|
93
|
+
'body':
|
|
94
|
+
to_json({
|
|
95
|
+
'type': 'Unhandled Exception',
|
|
96
|
+
'error_message': str(e),
|
|
97
|
+
'user_message': 'Oops! An unhandled error occurred.',
|
|
98
|
+
'traceback': traceback.format_exc() if DEBUG else None
|
|
99
|
+
}),
|
|
100
|
+
'headers': {
|
|
101
|
+
'Content-Type': 'application/json',
|
|
102
|
+
'Access-Control-Allow-Origin': '*'
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
if hasattr(self, 'onError'):
|
|
106
|
+
self.onError(args=req_params,
|
|
107
|
+
postdata=postdata,
|
|
108
|
+
response=response,
|
|
109
|
+
exc=e,
|
|
110
|
+
tb=traceback.format_exc())
|
|
111
|
+
|
|
112
|
+
return response
|
|
113
|
+
|
|
114
|
+
def OnActionDefault(self, tx, args, postdata, response):
|
|
115
|
+
response['body'] = to_json({'event': self.event, 'postdata': postdata})
|
|
116
|
+
|
|
117
|
+
def onError(self, tx, args, postdata, response, exc, tb):
|
|
118
|
+
pprint.pprint({
|
|
119
|
+
'message': 'Unhandled Exception',
|
|
120
|
+
'exception': str(exc),
|
|
121
|
+
'traceback': traceback.format_exc()
|
|
122
|
+
})
|
|
123
|
+
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
from velocity.misc.format import to_json
|
|
2
|
+
import json
|
|
3
|
+
import traceback
|
|
4
|
+
|
|
5
|
+
class SqsHandler:
|
|
6
|
+
def __init__(self, event, context):
|
|
7
|
+
self.event = event
|
|
8
|
+
self.context = context
|
|
9
|
+
self.serve_action_default = True
|
|
10
|
+
|
|
11
|
+
def serve(self, tx):
|
|
12
|
+
records = self.event.get('Records', [])
|
|
13
|
+
print(f"Handling batch of {len(records)} records from SQS")
|
|
14
|
+
for record in records:
|
|
15
|
+
print(f"Start MessageId {record.get('messageId')}")
|
|
16
|
+
attrs = record.get('attributes')
|
|
17
|
+
try:
|
|
18
|
+
postdata = {}
|
|
19
|
+
if record.get('body'):
|
|
20
|
+
postdata = json.loads(record.get('body'))
|
|
21
|
+
if hasattr(self, 'beforeAction'):
|
|
22
|
+
self.beforeAction(attrs=attrs, postdata=postdata)
|
|
23
|
+
actions = []
|
|
24
|
+
action = postdata.get('action')
|
|
25
|
+
if action:
|
|
26
|
+
actions.append(
|
|
27
|
+
f"on action {action.replace('-', ' ').replace('_', ' ')}"
|
|
28
|
+
.title().replace(' ', ''))
|
|
29
|
+
if self.serve_action_default:
|
|
30
|
+
actions.append('OnActionDefault')
|
|
31
|
+
for action in actions:
|
|
32
|
+
if hasattr(self, action):
|
|
33
|
+
getattr(self, action)(attrs=attrs, postdata=postdata)
|
|
34
|
+
break
|
|
35
|
+
if hasattr(self, 'afterAction'):
|
|
36
|
+
self.afterAction(attrs=attrs, postdata=postdata)
|
|
37
|
+
except Exception as e:
|
|
38
|
+
if hasattr(self, 'onError'):
|
|
39
|
+
self.onError(attrs=attrs,
|
|
40
|
+
postdata=postdata,
|
|
41
|
+
exc=e,
|
|
42
|
+
tb=traceback.format_exc())
|
|
43
|
+
|
|
44
|
+
def OnActionDefault(self, tx, attrs, postdata):
|
|
45
|
+
print(
|
|
46
|
+
"Action handler not found. Calling default action `SqsHandler.OnActionDefault` with the following parameters for tx, attrs, and postdata:"
|
|
47
|
+
)
|
|
48
|
+
print({'tx': tx, 'attrs': attrs, 'postdata': postdata})
|
|
File without changes
|