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.
Files changed (47) hide show
  1. tina4_python/Auth.py +222 -0
  2. tina4_python/Constant.py +43 -0
  3. tina4_python/Database.py +591 -0
  4. tina4_python/DatabaseResult.py +107 -0
  5. tina4_python/DatabaseTypes.py +15 -0
  6. tina4_python/Debug.py +126 -0
  7. tina4_python/Env.py +37 -0
  8. tina4_python/Localization.py +42 -0
  9. tina4_python/Messages.py +30 -0
  10. tina4_python/MiddleWare.py +90 -0
  11. tina4_python/Migration.py +107 -0
  12. tina4_python/ORM.py +639 -0
  13. tina4_python/Queue.py +615 -0
  14. tina4_python/Request.py +19 -0
  15. tina4_python/Response.py +121 -0
  16. tina4_python/Router.py +423 -0
  17. tina4_python/Session.py +342 -0
  18. tina4_python/ShellColors.py +20 -0
  19. tina4_python/Swagger.py +228 -0
  20. tina4_python/Template.py +107 -0
  21. tina4_python/Webserver.py +429 -0
  22. tina4_python/Websocket.py +49 -0
  23. tina4_python/__init__.py +392 -0
  24. tina4_python/messages.pot +83 -0
  25. tina4_python/public/css/readme.md +0 -0
  26. tina4_python/public/favicon.ico +0 -0
  27. tina4_python/public/images/403.png +0 -0
  28. tina4_python/public/images/404.png +0 -0
  29. tina4_python/public/images/500.png +0 -0
  30. tina4_python/public/images/logo.png +0 -0
  31. tina4_python/public/images/readme.md +0 -0
  32. tina4_python/public/js/readme.md +0 -0
  33. tina4_python/public/js/reconnecting-websocket.js +365 -0
  34. tina4_python/public/js/tina4helper.js +397 -0
  35. tina4_python/public/swagger/index.html +90 -0
  36. tina4_python/public/swagger/oauth2-redirect.html +63 -0
  37. tina4_python/templates/errors/403.twig +10 -0
  38. tina4_python/templates/errors/404.twig +10 -0
  39. tina4_python/templates/errors/500.twig +11 -0
  40. tina4_python/templates/readme.md +1 -0
  41. tina4_python/translations/en/LC_MESSAGES/messages.mo +0 -0
  42. tina4_python/translations/en/LC_MESSAGES/messages.po +80 -0
  43. tina4_python/translations/fr/LC_MESSAGES/messages.mo +0 -0
  44. tina4_python/translations/fr/LC_MESSAGES/messages.po +84 -0
  45. tina4_python-0.2.122.dist-info/METADATA +465 -0
  46. tina4_python-0.2.122.dist-info/RECORD +47 -0
  47. 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,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.27.0
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any