tina4-python 0.2.122__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.
- tina4_python/Auth.py +222 -0
- tina4_python/Constant.py +43 -0
- tina4_python/Database.py +591 -0
- tina4_python/DatabaseResult.py +107 -0
- tina4_python/DatabaseTypes.py +15 -0
- tina4_python/Debug.py +126 -0
- tina4_python/Env.py +37 -0
- tina4_python/Localization.py +42 -0
- tina4_python/Messages.py +30 -0
- tina4_python/MiddleWare.py +90 -0
- tina4_python/Migration.py +107 -0
- tina4_python/ORM.py +639 -0
- tina4_python/Queue.py +615 -0
- tina4_python/Request.py +19 -0
- tina4_python/Response.py +121 -0
- tina4_python/Router.py +423 -0
- tina4_python/Session.py +342 -0
- tina4_python/ShellColors.py +20 -0
- tina4_python/Swagger.py +228 -0
- tina4_python/Template.py +107 -0
- tina4_python/Webserver.py +429 -0
- tina4_python/Websocket.py +49 -0
- tina4_python/__init__.py +392 -0
- tina4_python/messages.pot +83 -0
- tina4_python/public/css/readme.md +0 -0
- tina4_python/public/favicon.ico +0 -0
- tina4_python/public/images/403.png +0 -0
- tina4_python/public/images/404.png +0 -0
- tina4_python/public/images/500.png +0 -0
- tina4_python/public/images/logo.png +0 -0
- tina4_python/public/images/readme.md +0 -0
- tina4_python/public/js/readme.md +0 -0
- tina4_python/public/js/reconnecting-websocket.js +365 -0
- tina4_python/public/js/tina4helper.js +397 -0
- tina4_python/public/swagger/index.html +90 -0
- tina4_python/public/swagger/oauth2-redirect.html +63 -0
- tina4_python/templates/errors/403.twig +10 -0
- tina4_python/templates/errors/404.twig +10 -0
- tina4_python/templates/errors/500.twig +11 -0
- tina4_python/templates/readme.md +1 -0
- tina4_python/translations/en/LC_MESSAGES/messages.mo +0 -0
- tina4_python/translations/en/LC_MESSAGES/messages.po +80 -0
- tina4_python/translations/fr/LC_MESSAGES/messages.mo +0 -0
- tina4_python/translations/fr/LC_MESSAGES/messages.po +84 -0
- tina4_python-0.2.122.dist-info/METADATA +465 -0
- tina4_python-0.2.122.dist-info/RECORD +47 -0
- tina4_python-0.2.122.dist-info/WHEEL +4 -0
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# French translations for PROJECT.
|
|
2
|
+
# Copyright (C) 2024 ORGANIZATION
|
|
3
|
+
# This file is distributed under the same license as the PROJECT project.
|
|
4
|
+
# FIRST AUTHOR <EMAIL@ADDRESS>, 2024.
|
|
5
|
+
#
|
|
6
|
+
msgid ""
|
|
7
|
+
msgstr ""
|
|
8
|
+
"Project-Id-Version: PROJECT VERSION\n"
|
|
9
|
+
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
|
|
10
|
+
"POT-Creation-Date: 2024-02-14 18:17+0200\n"
|
|
11
|
+
"PO-Revision-Date: 2024-02-14 18:17+0200\n"
|
|
12
|
+
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
|
13
|
+
"Language: fr\n"
|
|
14
|
+
"Language-Team: fr <LL@li.org>\n"
|
|
15
|
+
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
|
|
16
|
+
"MIME-Version: 1.0\n"
|
|
17
|
+
"Content-Type: text/plain; charset=utf-8\n"
|
|
18
|
+
"Content-Transfer-Encoding: 8bit\n"
|
|
19
|
+
"Generated-By: Babel 2.13.1\n"
|
|
20
|
+
|
|
21
|
+
#: Messages.py:5
|
|
22
|
+
msgid "Debug: {message}"
|
|
23
|
+
msgstr "Débogage : {message}"
|
|
24
|
+
|
|
25
|
+
#: Messages.py:6
|
|
26
|
+
msgid "Warning: {message}"
|
|
27
|
+
msgstr "Avertissement : {message}"
|
|
28
|
+
|
|
29
|
+
#: Messages.py:7
|
|
30
|
+
msgid "Error: {message}"
|
|
31
|
+
msgstr "Erreur : {message}"
|
|
32
|
+
|
|
33
|
+
#: Messages.py:8
|
|
34
|
+
msgid "Info: {message}"
|
|
35
|
+
msgstr "Info : {message}"
|
|
36
|
+
|
|
37
|
+
#: Messages.py:12
|
|
38
|
+
msgid "Matching: {matching}"
|
|
39
|
+
msgstr "Correspondance : {matching}"
|
|
40
|
+
|
|
41
|
+
#: Messages.py:13
|
|
42
|
+
msgid "Variables: {variables}"
|
|
43
|
+
msgstr "Variables : {variables}"
|
|
44
|
+
|
|
45
|
+
#: Messages.py:14
|
|
46
|
+
msgid "Root Path {root_path} {url}"
|
|
47
|
+
msgstr "Chemin racine : {root_path} {url}"
|
|
48
|
+
|
|
49
|
+
#: Messages.py:15
|
|
50
|
+
msgid "Attempting to serve static file: {static_file}"
|
|
51
|
+
msgstr "Tentative de servir le fichier statique : {static_file}"
|
|
52
|
+
|
|
53
|
+
#: Messages.py:16
|
|
54
|
+
msgid "Attempting to serve CSS file: {css_file}"
|
|
55
|
+
msgstr "Tentative de servir le fichier CSS : {css_file}"
|
|
56
|
+
|
|
57
|
+
#: Messages.py:17
|
|
58
|
+
msgid "Attempting to serve image file: {image_file}"
|
|
59
|
+
msgstr "Tentative de servir le fichier image : {image_file}"
|
|
60
|
+
|
|
61
|
+
#: __init__.py:15
|
|
62
|
+
msgid "Assuming root path: {root_path}, library path: {library_path}"
|
|
63
|
+
msgstr "Hypothèse chemin racine : {root_path}, chemin bibliothèque : {library_path}"
|
|
64
|
+
|
|
65
|
+
#: __init__.py:16
|
|
66
|
+
msgid "Load all things"
|
|
67
|
+
msgstr "Charger tout"
|
|
68
|
+
|
|
69
|
+
#: __init__.py:17
|
|
70
|
+
msgid "Server started http://{host_name}:{port}"
|
|
71
|
+
msgstr "Serveur démarré http://{host_name}:{port}"
|
|
72
|
+
|
|
73
|
+
#: __init__.py:18
|
|
74
|
+
msgid "Server stopped."
|
|
75
|
+
msgstr "Serveur arrêté."
|
|
76
|
+
|
|
77
|
+
#: __init__.py:19
|
|
78
|
+
msgid "Starting webserver on {port}"
|
|
79
|
+
msgstr "Démarrage du serveur web sur {port}"
|
|
80
|
+
|
|
81
|
+
#: __init__.py:20
|
|
82
|
+
msgid "Entry point name ... {name}"
|
|
83
|
+
msgstr "Nom du point d'entrée... {name}"
|
|
84
|
+
|
|
@@ -0,0 +1,465 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: tina4-python
|
|
3
|
+
Version: 0.2.122
|
|
4
|
+
Summary: Tina4Python - This is not another framework for Python
|
|
5
|
+
Author-email: Andre van Zuydam <andrevanzuydam@gmail.com>
|
|
6
|
+
Requires-Python: <4.0,>=3.12
|
|
7
|
+
Requires-Dist: asyncer>=0.0.8
|
|
8
|
+
Requires-Dist: bcrypt<5.0.0,>=4.2.1
|
|
9
|
+
Requires-Dist: cryptography<45.0.0,>=44.0.0
|
|
10
|
+
Requires-Dist: hypercorn<0.18.0,>=0.17.3
|
|
11
|
+
Requires-Dist: jinja2<4.0.0,>=3.1.5
|
|
12
|
+
Requires-Dist: libsass<0.24.0,>=0.23.0
|
|
13
|
+
Requires-Dist: litequeue<0.10,>=0.9
|
|
14
|
+
Requires-Dist: pyjwt<3.0.0,>=2.10.1
|
|
15
|
+
Requires-Dist: python-dotenv<2.0.0,>=1.0.1
|
|
16
|
+
Requires-Dist: simple-websocket<2.0.0,>=1.1.0
|
|
17
|
+
Requires-Dist: watchdog<7.0.0,>=6.0.0
|
|
18
|
+
Description-Content-Type: text/markdown
|
|
19
|
+
|
|
20
|
+
### Tina4Python - This is not a framework for Python
|
|
21
|
+
|
|
22
|
+
Tina4Python is a light-weight routing and twig based templating system based on the [Tina4](https://github.com/tina4stack/tina4-php) stack which allows you to write websites and API applications very quickly.
|
|
23
|
+
.
|
|
24
|
+
### System Requirements
|
|
25
|
+
|
|
26
|
+
- Install UV
|
|
27
|
+
|
|
28
|
+
Linux
|
|
29
|
+
```bash
|
|
30
|
+
curl -LsSf https://astral.sh/uv/install.sh | sh
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Windows
|
|
34
|
+
```bash
|
|
35
|
+
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Lock down a specific Python version
|
|
39
|
+
```bash
|
|
40
|
+
uv python pin 3.13
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
- Install Jurigged (Enables Hot Reloading):
|
|
44
|
+
```bash
|
|
45
|
+
uv pip install jurigged
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### Quick Start
|
|
49
|
+
|
|
50
|
+
Our package management is moving to UV, the following is enough to get started once uv has been installed.
|
|
51
|
+
See here https://docs.astral.sh/uv/getting-started/installation/
|
|
52
|
+
```bash
|
|
53
|
+
uv add tina4_python
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Poetry should still work as follows
|
|
57
|
+
```bash
|
|
58
|
+
poetry new project-name
|
|
59
|
+
cd project-name
|
|
60
|
+
poetry add tina4_python
|
|
61
|
+
poetry add jurigged
|
|
62
|
+
```
|
|
63
|
+
Create an entry point for Tina4 called ```app.py``` and add the following to the file
|
|
64
|
+
```python
|
|
65
|
+
from tina4_python import *
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### Overview
|
|
69
|
+
The basic tina4 project uses an autoloader methodology from the src folder
|
|
70
|
+
All the source folders you should need are created there and they are run from __init__.py
|
|
71
|
+
|
|
72
|
+
If you are developing on Tina4, make sure you copy the public folder from tina4_python into src
|
|
73
|
+
|
|
74
|
+
### Installation
|
|
75
|
+
|
|
76
|
+
Virtual environment
|
|
77
|
+
|
|
78
|
+
Linux / Mac
|
|
79
|
+
```bash
|
|
80
|
+
python3 -m venv venv
|
|
81
|
+
source ./venv/bin/activate
|
|
82
|
+
pip install poetry
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
Windows
|
|
86
|
+
```bash
|
|
87
|
+
python -m venv venv
|
|
88
|
+
.\venv\Scripts\activate
|
|
89
|
+
pip install poetry
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
#### Windows
|
|
93
|
+
|
|
94
|
+
1.) Install Poetry:
|
|
95
|
+
```powershell
|
|
96
|
+
(Invoke-WebRequest -Uri https://install.python-poetry.org -UseBasicParsing).Content | py -
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
2.) Add the following path to the system PATH:
|
|
100
|
+
```
|
|
101
|
+
%APPDATA%\pypoetry\venv\Scripts
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
3.) Install Tina4Python and Jurigged:
|
|
105
|
+
```bash
|
|
106
|
+
poetry add tina4_python
|
|
107
|
+
poetry add jurigged
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
**or**
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
pip install tina4_python
|
|
114
|
+
pip install jurigged
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
### Usage
|
|
118
|
+
|
|
119
|
+
After defining templates and routes, run the Tina4Python server:
|
|
120
|
+
|
|
121
|
+
- **Normal Server**:
|
|
122
|
+
```bash
|
|
123
|
+
poetry run python app.py
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
- **Server with Hot Reloading**:
|
|
127
|
+
```bash
|
|
128
|
+
poetry run jurigged app.py
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
- **Server on a Specific Port**:
|
|
132
|
+
```bash
|
|
133
|
+
poetry run python app.py 7777
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
- **Server to not autostart **:
|
|
137
|
+
```bash
|
|
138
|
+
poetry run python app.py manual
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
- **Server with alternate language** (for example fr = French):
|
|
142
|
+
```bash
|
|
143
|
+
poetry run python app.py fr
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
Add more translations by going [here](TRANSLATIONS.md)
|
|
147
|
+
|
|
148
|
+
### Templating
|
|
149
|
+
Tina4 uses Jinja2 (Twig) templating to provide a simple and efficient way to create web pages.
|
|
150
|
+
|
|
151
|
+
1.) **Twig Files**: Add your Twig files within the `src/templates` folder. For instance, you might create files like `index.twig`, `base.twig`, etc., containing your HTML structure with Twig templating syntax for dynamic content.
|
|
152
|
+
|
|
153
|
+
2.) **Using Twig**: In these Twig files, you can use Twig syntax to embed dynamic content, control structures, variables, and more. For example:
|
|
154
|
+
|
|
155
|
+
```twig
|
|
156
|
+
<!-- index.twig -->
|
|
157
|
+
<!DOCTYPE html>
|
|
158
|
+
<html>
|
|
159
|
+
<head>
|
|
160
|
+
<title>Welcome</title>
|
|
161
|
+
</head>
|
|
162
|
+
<body>
|
|
163
|
+
<h1>Hello, {{ name }}!</h1>
|
|
164
|
+
</body>
|
|
165
|
+
</html>
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
### Defining Routes
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
The routing in Tina4Python can be defined in the `__init__.py` file or any file used as an entry point to your application. Tina4Python provides decorators to define routes easily.
|
|
172
|
+
|
|
173
|
+
1.) **Creating Routes**: Define routes using decorators from Tina4Python to handle HTTP requests.
|
|
174
|
+
|
|
175
|
+
Example:
|
|
176
|
+
```python
|
|
177
|
+
from tina4_python.Router import get
|
|
178
|
+
from tina4_python.Response import Response
|
|
179
|
+
@get("/hello")
|
|
180
|
+
async def hello(request, response):
|
|
181
|
+
return response("Hello, World!")
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
This code creates a route for a GET request to `/hello`, responding with "Hello, World!".
|
|
185
|
+
|
|
186
|
+
2.) **Route Parameters**: You can define route parameters by enclosing variables with curly braces { }. The parameters are passed to the function as arguments.
|
|
187
|
+
|
|
188
|
+
Example:
|
|
189
|
+
```python
|
|
190
|
+
from tina4_python.Router import get
|
|
191
|
+
from tina4_python.Response import Response
|
|
192
|
+
|
|
193
|
+
@get("/hello/{name}")
|
|
194
|
+
async def greet(**params): #(request, response)
|
|
195
|
+
name = params['request'].params['name']
|
|
196
|
+
return params['response'](f"Hello, {name}!") # return response()
|
|
197
|
+
````
|
|
198
|
+
|
|
199
|
+
This code creates a route for a GET request to `/hello/{name}`, where `name` is a parameter in the URL. The function `greet` accepts this parameter and responds with a personalized greeting.
|
|
200
|
+
|
|
201
|
+
Example:
|
|
202
|
+
- Visiting `/hello/John` will respond with "Hello, John!"
|
|
203
|
+
- Visiting `/hello/Alice` will respond with "Hello, Alice!"
|
|
204
|
+
|
|
205
|
+
3.) POST routes now require jwt token or API key to validate requests with an Authorization header
|
|
206
|
+
```
|
|
207
|
+
Authorization: Bearer <token>
|
|
208
|
+
```
|
|
209
|
+
You can generate tokens using tina4_python.tina4_auth which takes in a payload parameter which is a dictionary:
|
|
210
|
+
#### Example of a post with a form, assume the route is ```/capture```
|
|
211
|
+
|
|
212
|
+
You need the following twig file in the ```src/templates``` folder called ```something.twig```
|
|
213
|
+
|
|
214
|
+
```twig something.twig
|
|
215
|
+
<form method="post">
|
|
216
|
+
<input name="email" type="text" placeholder="Email">
|
|
217
|
+
<button type="submit">Send</button>
|
|
218
|
+
<input type="hidden" name="formToken" value="{{ token }}" >
|
|
219
|
+
</form>
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
You can add the following code to ```src/routes/example.py```
|
|
223
|
+
|
|
224
|
+
```python
|
|
225
|
+
# get router which renders the twig form html
|
|
226
|
+
@get("/capture")
|
|
227
|
+
async def capture_get(request, response):
|
|
228
|
+
# get a token to add to the form
|
|
229
|
+
token = tina4_python.tina4_auth.get_token({"data": {"formName": "capture"}})
|
|
230
|
+
html = Template.render_twig_template("somefile.twig", {"token": token})
|
|
231
|
+
return response(html)
|
|
232
|
+
|
|
233
|
+
# returns back to the user the form data that has been posted
|
|
234
|
+
@post("/capture")
|
|
235
|
+
async def capture_post(request, response):
|
|
236
|
+
return response(request.body)
|
|
237
|
+
|
|
238
|
+
@get("/simple")
|
|
239
|
+
async def simple_get(request, response):
|
|
240
|
+
print("<h1>Hello World!</h1>")
|
|
241
|
+
|
|
242
|
+
@get("/redirect")
|
|
243
|
+
async def simple_get(request, response):
|
|
244
|
+
|
|
245
|
+
return response.redirect("/test")
|
|
246
|
+
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
In your ```src/__init__.py``` add the following code
|
|
250
|
+
|
|
251
|
+
```python
|
|
252
|
+
from .routes.example import *
|
|
253
|
+
```
|
|
254
|
+
Generate tokens with the following code as per the example above, tokens carry a payload and we add an additional ```expires``` value to the token based on the env variable ```TINA4_TOKEN_LIMIT```
|
|
255
|
+
|
|
256
|
+
```python
|
|
257
|
+
import tina4_python
|
|
258
|
+
|
|
259
|
+
tina4_python.tina4_auth.get_token({"data": {"something":"more"}})
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
OR
|
|
263
|
+
|
|
264
|
+
For ease of use you can supply an `API_KEY` param to your .env with a secret of your choice to use:
|
|
265
|
+
|
|
266
|
+
```dotenv
|
|
267
|
+
API_KEY=somehash
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
### Suppressing the default webservice
|
|
271
|
+
|
|
272
|
+
You may want to use your Tina4 project as a library in another project so suppressing the default webservice is probably needed.
|
|
273
|
+
|
|
274
|
+
```.env
|
|
275
|
+
TINA4_DEFAULT_WEBSERVER="False"
|
|
276
|
+
```
|
|
277
|
+
or in your `__init__.py` file
|
|
278
|
+
```python
|
|
279
|
+
import os
|
|
280
|
+
os.environ["TINA4_DEFAULT_WEBSERVER"] = "False"
|
|
281
|
+
```
|
|
282
|
+
Additionally, it will require you to rename `src` to the name of your package
|
|
283
|
+
|
|
284
|
+
### Features
|
|
285
|
+
| Completed | To Do |
|
|
286
|
+
|----------------------------|-------|
|
|
287
|
+
| Python pip package | |
|
|
288
|
+
| Basic environment handling | |
|
|
289
|
+
| Routing with Swagger | |
|
|
290
|
+
| Enhanced Routing | |
|
|
291
|
+
| CSS Support | |
|
|
292
|
+
| Image Support | |
|
|
293
|
+
| Localization | |
|
|
294
|
+
| Error Pages | |
|
|
295
|
+
| Template handling | |
|
|
296
|
+
| Form posting | |
|
|
297
|
+
| Migrations | |
|
|
298
|
+
| Colored Debugging | |
|
|
299
|
+
| Database Abstraction | |
|
|
300
|
+
|
|
301
|
+
### Database
|
|
302
|
+
|
|
303
|
+
```bash
|
|
304
|
+
|
|
305
|
+
Various databases initialised:
|
|
306
|
+
|
|
307
|
+
dba = Database("sqlite3:test.db", "username", "password")
|
|
308
|
+
dba = Database("mysql:localhost/3306:myschema", "username", "password")
|
|
309
|
+
dba = Database("postgres:localhost/5432:myschema", "username", "password")
|
|
310
|
+
dba = Database("firebird:localhost/3050:/home/database/FIREBIRD.FDB", "username", "password")
|
|
311
|
+
# mssql
|
|
312
|
+
brew install FreeTDS
|
|
313
|
+
export LDFLAGS="-L/opt/homebrew/lib -L/opt/homebrew/opt/openssl/lib"
|
|
314
|
+
export CFLAGS="-I/opt/homebrew/include"
|
|
315
|
+
export CPPFLAGS="-I/opt/homebrew/opt/openssl@3/include"
|
|
316
|
+
poetry run pip uninstall pymssql -y
|
|
317
|
+
poetry run pip install pymssql==2.3.2 --no-binary :all:
|
|
318
|
+
NoSQL support (Still to be developed):
|
|
319
|
+
|
|
320
|
+
dba = Database("mongodb:localhost/27017:mycollection", "username", "password")
|
|
321
|
+
dba = Database("firebase:https://your_storage.firebaseio.com", "username", "password")
|
|
322
|
+
|
|
323
|
+
Fetching records and passing data as parameters, limit and skip specified:
|
|
324
|
+
|
|
325
|
+
records = dba.fetch("select * from table where something = ? and something2 = ?", params=["something", "something2"], limit=10, skip=5)
|
|
326
|
+
|
|
327
|
+
print (records)
|
|
328
|
+
print (records.to_json())
|
|
329
|
+
{
|
|
330
|
+
id : 1
|
|
331
|
+
something: "something",
|
|
332
|
+
something2: "something2"
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
print(records[0].id)
|
|
336
|
+
1
|
|
337
|
+
|
|
338
|
+
record = dba.fetch_one("select * from table where something = ? and something2 = ?", params=["something", "something2"])
|
|
339
|
+
|
|
340
|
+
print(record.id)
|
|
341
|
+
|
|
342
|
+
print (records.to_json())
|
|
343
|
+
1
|
|
344
|
+
|
|
345
|
+
|
|
346
|
+
Executing sql queries:
|
|
347
|
+
|
|
348
|
+
dba.execute ("update table set something = ? and something2 = ? where id = ?", params=["something", "something2", 1])
|
|
349
|
+
dba.execute ("delete from table where id = ?", params=[1])
|
|
350
|
+
|
|
351
|
+
|
|
352
|
+
Starting a transaction:
|
|
353
|
+
|
|
354
|
+
dba.start_transaction()
|
|
355
|
+
|
|
356
|
+
|
|
357
|
+
Rollback a transaction:
|
|
358
|
+
|
|
359
|
+
dba.roll_back()
|
|
360
|
+
|
|
361
|
+
|
|
362
|
+
Commit a transaction:
|
|
363
|
+
|
|
364
|
+
dba.commit()
|
|
365
|
+
|
|
366
|
+
|
|
367
|
+
Select method (Still in development):
|
|
368
|
+
|
|
369
|
+
dba.select(["id", "something", "something2"], "table_name", filter={"id": 1}, limit=10, skip=0)
|
|
370
|
+
dba.select(["id", "something", "something2"], "table_name", filter=[{"id": 1}, {"id": 2}], limit=10, skip=0)
|
|
371
|
+
dba.select(["id", "something", "sum(id)"])
|
|
372
|
+
.from(["table"])
|
|
373
|
+
.join(["tabel2"])
|
|
374
|
+
.on([""])
|
|
375
|
+
.and([{"id": 1}])
|
|
376
|
+
.where({"id" : 2}, "id = ?", [{"id": 2}])
|
|
377
|
+
.having()
|
|
378
|
+
.group_by()
|
|
379
|
+
.order_by(["id"])
|
|
380
|
+
|
|
381
|
+
|
|
382
|
+
Updating records - records will be found by primary key specified and then updated:
|
|
383
|
+
|
|
384
|
+
dba.update(table_name="table_name", records.fromJSON(json_string))
|
|
385
|
+
dba.update(table_name="table_name", records, primary_key="id")
|
|
386
|
+
dba.update(table_name="table_name", record, primary_key="id") # primary key implied by first key value pair
|
|
387
|
+
|
|
388
|
+
|
|
389
|
+
Inserting records - pass a dictionary for a single record and a list of dictionaries for multiple records:
|
|
390
|
+
|
|
391
|
+
dba.insert(table_name="table_name", dba.from_json(json_string))
|
|
392
|
+
dba.insert(table_name="table_name", {"id": 1, "something": "hello", "something2": "world"})
|
|
393
|
+
dba.insert(table_name="table_name", [{"id": 1, "something": "hello", "something2": "world"},
|
|
394
|
+
{"id": 2, "something": "hello2", "something2": "world2"}])
|
|
395
|
+
|
|
396
|
+
|
|
397
|
+
Deleting records - specify table name. Records can either be found by primary key or filter:
|
|
398
|
+
|
|
399
|
+
dba.delete("table_name", record, primary_key="id")
|
|
400
|
+
dba.delete("table_name", filter={"id": 1})
|
|
401
|
+
dba.delete("table_name", filter=[{"id": 1}, {"id": 2}])
|
|
402
|
+
|
|
403
|
+
Migration updates:
|
|
404
|
+
|
|
405
|
+
- record count added
|
|
406
|
+
- Database result object updated
|
|
407
|
+
```
|
|
408
|
+
|
|
409
|
+
### Building and Deployment
|
|
410
|
+
|
|
411
|
+
#### Using Python
|
|
412
|
+
|
|
413
|
+
Building the package without poetry - you will need to request an API key:
|
|
414
|
+
```bash
|
|
415
|
+
python3 -m pip install --upgrade build
|
|
416
|
+
python3 -m build
|
|
417
|
+
python3 -m pip install --upgrade twine
|
|
418
|
+
python3 -m twine upload dist/*
|
|
419
|
+
```
|
|
420
|
+
|
|
421
|
+
#### Using Poetry
|
|
422
|
+
|
|
423
|
+
Building the package:
|
|
424
|
+
```bash
|
|
425
|
+
poetry build
|
|
426
|
+
```
|
|
427
|
+
|
|
428
|
+
Publishing the package:
|
|
429
|
+
```bash
|
|
430
|
+
poetry publish
|
|
431
|
+
```
|
|
432
|
+
|
|
433
|
+
#### Running tests & checks
|
|
434
|
+
|
|
435
|
+
PyTests
|
|
436
|
+
```
|
|
437
|
+
uv run pytest ./tests --verbose
|
|
438
|
+
```
|
|
439
|
+
|
|
440
|
+
Flake8 Code tests
|
|
441
|
+
```
|
|
442
|
+
uv run flake8 ./tina4_python
|
|
443
|
+
```
|
|
444
|
+
|
|
445
|
+
### Using queues
|
|
446
|
+
|
|
447
|
+
```bash
|
|
448
|
+
docker run -d --hostname=my-kafka --name=some-kafka -p 9092:9092 apache/kafka
|
|
449
|
+
```
|
|
450
|
+
|
|
451
|
+
```bash
|
|
452
|
+
docker run -d --hostname=my-rabbit --name=some-rabbit -p 15672:15672 -p 5672:5672 rabbitmq:3
|
|
453
|
+
```
|
|
454
|
+
|
|
455
|
+
## Websocket Testing
|
|
456
|
+
|
|
457
|
+
```bash
|
|
458
|
+
brew install websocat
|
|
459
|
+
```
|
|
460
|
+
|
|
461
|
+
```python
|
|
462
|
+
websocat http://localhost:7145/websocket
|
|
463
|
+
```
|
|
464
|
+
|
|
465
|
+
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
tina4_python/Auth.py,sha256=W_erOFDc9wTF9G6mWkucMT5Xbf28bfXw8YPnXxcArvQ,7887
|
|
2
|
+
tina4_python/Constant.py,sha256=s9R_X7Ok5h80eWVGFyhs9IycYoDCobLVtomDkdAwnfA,1280
|
|
3
|
+
tina4_python/Database.py,sha256=c-aeWg5D-oTEruUL0FYEnef-3n5ad12nFieDFCm1qqU,24615
|
|
4
|
+
tina4_python/DatabaseResult.py,sha256=L29NPO86gp6BjSDmiwSPN7Cp_vb_wXuPeM8SmwWyBQo,3277
|
|
5
|
+
tina4_python/DatabaseTypes.py,sha256=5SJDThyOmQpLNnPDAqjKASLWvJeGWcwXqIdfafGnVY4,582
|
|
6
|
+
tina4_python/Debug.py,sha256=Mc4I8_T204dTF534U1SApMiEMrviGJSCdvkhlTzORuU,4186
|
|
7
|
+
tina4_python/Env.py,sha256=OLO1vRyEyRYZ0IIEpLFZoKoA089BkGr6K1KS0XCtxoM,1359
|
|
8
|
+
tina4_python/Localization.py,sha256=2PBY02TN6G45L7WyjlmC70rOHWYTtNvQGeOErXmD0os,1288
|
|
9
|
+
tina4_python/Messages.py,sha256=g2aCY9fMfo1vdKley2pMYODZMYCDuITrVNV_Ts1nCNI,1121
|
|
10
|
+
tina4_python/MiddleWare.py,sha256=tJwXLSeGe30t-xt3QCmZHGzdPN9lCUICE_AWHGigRgQ,2876
|
|
11
|
+
tina4_python/Migration.py,sha256=sZVD1TGQEyGZjoVOKY4iefxBS7AN5LSkHw5CZ1rePUc,5874
|
|
12
|
+
tina4_python/ORM.py,sha256=sW0WYwO8LgYNfjdw5llZGcZqjSM9A8dID8G2cSVmZpI,22737
|
|
13
|
+
tina4_python/Queue.py,sha256=81tFj4mqXOjrow3DkBPpYC2U7SDHLuHSnzAX8XHNUVM,23772
|
|
14
|
+
tina4_python/Request.py,sha256=1QasnLPIqA0aLtGhhzXxaqrDoSj83taq_Xn6lcsx_5E,358
|
|
15
|
+
tina4_python/Response.py,sha256=msXkxgcrQ8HGF0ZwmD8P1XVOLcOV0ee5gvTjnKvPz2s,4116
|
|
16
|
+
tina4_python/Router.py,sha256=xs3R6hWMQTWrsde7lEMfozbFTyMpnfabWAIil7PUcqk,17368
|
|
17
|
+
tina4_python/Session.py,sha256=Bxufjc0mTOZZZ5vrhTymmgsF3doKnyAKwU_HWFbhLv4,10756
|
|
18
|
+
tina4_python/ShellColors.py,sha256=oVT8X2QWiROo6bakhPQyJhspiRf39bmfsmiXIaf9lwI,561
|
|
19
|
+
tina4_python/Swagger.py,sha256=PdFeWEyMfxrH9Nf-C_Mip6tpqEx8Fp5BZ1I8W3RUYug,7901
|
|
20
|
+
tina4_python/Template.py,sha256=T0R2erPq9gOyewYDLmYOMZr9HI564ueZXSWJfiVEdZk,4155
|
|
21
|
+
tina4_python/Webserver.py,sha256=WadlQ14e6SeJ_j7jrmKJyYUv9ulJFOrU-f43KG37tgI,19431
|
|
22
|
+
tina4_python/Websocket.py,sha256=dtbdBy4nJpXXrzLrlkoKVXRjOH1DDYxORsNFGd3WidA,1661
|
|
23
|
+
tina4_python/__init__.py,sha256=WScgfON9aucirmjqXyLR_qqRwKMo-OFFoDzisxTVF7E,15394
|
|
24
|
+
tina4_python/messages.pot,sha256=pSnLUe3YcYBz35ofTDc4-I2_vL2Qxt1rzkQkyu5r5Rc,1740
|
|
25
|
+
tina4_python/public/favicon.ico,sha256=KHunJ9o9DHIIAkiE1l2dwh8Zuy97sKZK2FoiH8KJSOg,15406
|
|
26
|
+
tina4_python/public/css/readme.md,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
27
|
+
tina4_python/public/images/403.png,sha256=9m1IvR-LN6Y3fSA1um5xtjCUUzyHXZrJxFQRw614iA8,51321
|
|
28
|
+
tina4_python/public/images/404.png,sha256=6HAjf1QAXaTJRZA0YWP04hzQfI1m8PKugvgshxm7yKM,49297
|
|
29
|
+
tina4_python/public/images/500.png,sha256=ZtccQ0aXGBi6L5B86nR7KuMHx3Jw7_M4yCMcWXaYBu8,36786
|
|
30
|
+
tina4_python/public/images/logo.png,sha256=kBqTc-8FXQ0P8eTZGrQqRHw9V3gQ3q5Q_aenR0vOp1k,111876
|
|
31
|
+
tina4_python/public/images/readme.md,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
32
|
+
tina4_python/public/js/readme.md,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
33
|
+
tina4_python/public/js/reconnecting-websocket.js,sha256=fT4QA6FVNHuQtaTg9tK4a2nz7ov8gG2HNM0f0LlYYPw,14803
|
|
34
|
+
tina4_python/public/js/tina4helper.js,sha256=qSJ_EfIaJIK5L95EVntifoD1UW8csb86S7WjMTGjdbc,12647
|
|
35
|
+
tina4_python/public/swagger/index.html,sha256=eo481GzSvIHcsj_EEQfd2xFXeOu2j-hFwQ0LvbgS0gU,4221
|
|
36
|
+
tina4_python/public/swagger/oauth2-redirect.html,sha256=sVjX7irkm-qMcYn5beDVeRCHgRf4QGm6ZThwTRUg0bA,2109
|
|
37
|
+
tina4_python/templates/readme.md,sha256=DIwkobj8Kn49ktegNLvEZjTud-NvPcQ5f5ZACRV_AyI,53
|
|
38
|
+
tina4_python/templates/errors/403.twig,sha256=2XRQeVTyxy7oZa4gg0HNi-sqHIrxzXghnS7THV8lD8w,344
|
|
39
|
+
tina4_python/templates/errors/404.twig,sha256=hY-8aOOP1E6-2EVoCrNtdM0B36wcbu77iZRDCNLkKo0,323
|
|
40
|
+
tina4_python/templates/errors/500.twig,sha256=4uVhgGSiSU5AX2c2Tm1PWEzjpCzFr_yrkwr4BOIUMEQ,343
|
|
41
|
+
tina4_python/translations/en/LC_MESSAGES/messages.mo,sha256=gHsTU2alg9etySBq0eGIu_SzseY35JFpg0NPpn18ebU,1633
|
|
42
|
+
tina4_python/translations/en/LC_MESSAGES/messages.po,sha256=DZWTsJvlyFFNDVQ_OPM54_tmRYkaE5GFIYobWjq_WUU,2374
|
|
43
|
+
tina4_python/translations/fr/LC_MESSAGES/messages.mo,sha256=gIZc1BLprTBKfYG0aU6DaGWBlpTdv60UFblCtvP39jo,1715
|
|
44
|
+
tina4_python/translations/fr/LC_MESSAGES/messages.po,sha256=KmvGCKNQfHw_NrTpeRtBKNWZ8hZar1RO5gn-EuDsNcs,2320
|
|
45
|
+
tina4_python-0.2.122.dist-info/METADATA,sha256=Qs2G4-qpMJoX22sC2dszYJGDIPeskXq2M9Ijg8kpOLs,12186
|
|
46
|
+
tina4_python-0.2.122.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
47
|
+
tina4_python-0.2.122.dist-info/RECORD,,
|