jaaql-middleware-python 4.31.0__tar.gz → 4.32.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.
- {jaaql-middleware-python-4.31.0 → jaaql_middleware_python-4.32.1}/PKG-INFO +12 -3
- {jaaql-middleware-python-4.31.0 → jaaql_middleware_python-4.32.1}/jaaql/constants.py +9 -1
- {jaaql-middleware-python-4.31.0 → jaaql_middleware_python-4.32.1}/jaaql/documentation/documentation_public.py +110 -0
- {jaaql-middleware-python-4.31.0 → jaaql_middleware_python-4.32.1}/jaaql/email/email_manager_service.py +112 -7
- {jaaql-middleware-python-4.31.0 → jaaql_middleware_python-4.32.1}/jaaql/mvc/controller.py +11 -0
- {jaaql-middleware-python-4.31.0 → jaaql_middleware_python-4.32.1}/jaaql/mvc/exception_queries.py +1 -1
- {jaaql-middleware-python-4.31.0 → jaaql_middleware_python-4.32.1}/jaaql/mvc/generated_queries.py +19 -15
- {jaaql-middleware-python-4.31.0 → jaaql_middleware_python-4.32.1}/jaaql/mvc/model.py +53 -0
- {jaaql-middleware-python-4.31.0 → jaaql_middleware_python-4.32.1}/jaaql/scripts/01.install_domains.generated.sql +1 -1
- {jaaql-middleware-python-4.31.0 → jaaql_middleware_python-4.32.1}/jaaql/scripts/04.install_jaaql_data_structures.generated.sql +2 -1
- {jaaql-middleware-python-4.31.0 → jaaql_middleware_python-4.32.1}/jaaql_middleware_python.egg-info/PKG-INFO +12 -3
- {jaaql-middleware-python-4.31.0 → jaaql_middleware_python-4.32.1}/jaaql_middleware_python.egg-info/requires.txt +1 -1
- {jaaql-middleware-python-4.31.0 → jaaql_middleware_python-4.32.1}/LICENSE.txt +0 -0
- {jaaql-middleware-python-4.31.0 → jaaql_middleware_python-4.32.1}/README.md +0 -0
- {jaaql-middleware-python-4.31.0 → jaaql_middleware_python-4.32.1}/jaaql/__init__.py +0 -0
- {jaaql-middleware-python-4.31.0 → jaaql_middleware_python-4.32.1}/jaaql/config/__init__.py +0 -0
- {jaaql-middleware-python-4.31.0 → jaaql_middleware_python-4.32.1}/jaaql/config/config-docker.ini +0 -0
- {jaaql-middleware-python-4.31.0 → jaaql_middleware_python-4.32.1}/jaaql/config/config-test.ini +0 -0
- {jaaql-middleware-python-4.31.0 → jaaql_middleware_python-4.32.1}/jaaql/config/config.ini +0 -0
- {jaaql-middleware-python-4.31.0 → jaaql_middleware_python-4.32.1}/jaaql/config_constants.py +0 -0
- {jaaql-middleware-python-4.31.0 → jaaql_middleware_python-4.32.1}/jaaql/db/__init__.py +0 -0
- {jaaql-middleware-python-4.31.0 → jaaql_middleware_python-4.32.1}/jaaql/db/db_interface.py +0 -0
- {jaaql-middleware-python-4.31.0 → jaaql_middleware_python-4.32.1}/jaaql/db/db_pg_interface.py +0 -0
- {jaaql-middleware-python-4.31.0 → jaaql_middleware_python-4.32.1}/jaaql/db/db_utils.py +0 -0
- {jaaql-middleware-python-4.31.0 → jaaql_middleware_python-4.32.1}/jaaql/db/db_utils_no_circ.py +0 -0
- {jaaql-middleware-python-4.31.0 → jaaql_middleware_python-4.32.1}/jaaql/documentation/__init__.py +0 -0
- {jaaql-middleware-python-4.31.0 → jaaql_middleware_python-4.32.1}/jaaql/documentation/documentation_internal.py +0 -0
- {jaaql-middleware-python-4.31.0 → jaaql_middleware_python-4.32.1}/jaaql/documentation/documentation_shared.py +0 -0
- {jaaql-middleware-python-4.31.0 → jaaql_middleware_python-4.32.1}/jaaql/email/__init__.py +0 -0
- {jaaql-middleware-python-4.31.0 → jaaql_middleware_python-4.32.1}/jaaql/email/email_manager.py +0 -0
- {jaaql-middleware-python-4.31.0 → jaaql_middleware_python-4.32.1}/jaaql/email/patch_ems.py +0 -0
- {jaaql-middleware-python-4.31.0 → jaaql_middleware_python-4.32.1}/jaaql/exceptions/__init__.py +0 -0
- {jaaql-middleware-python-4.31.0 → jaaql_middleware_python-4.32.1}/jaaql/exceptions/custom_http_status.py +0 -0
- {jaaql-middleware-python-4.31.0 → jaaql_middleware_python-4.32.1}/jaaql/exceptions/http_status_exception.py +0 -0
- {jaaql-middleware-python-4.31.0 → jaaql_middleware_python-4.32.1}/jaaql/exceptions/jaaql_interpretable_handled_errors.py +0 -0
- {jaaql-middleware-python-4.31.0 → jaaql_middleware_python-4.32.1}/jaaql/exceptions/not_yet_implement_exception.py +0 -0
- {jaaql-middleware-python-4.31.0 → jaaql_middleware_python-4.32.1}/jaaql/generated_constants.py +0 -0
- {jaaql-middleware-python-4.31.0 → jaaql_middleware_python-4.32.1}/jaaql/interpreter/__init__.py +0 -0
- {jaaql-middleware-python-4.31.0 → jaaql_middleware_python-4.32.1}/jaaql/interpreter/interpret_jaaql.py +0 -0
- {jaaql-middleware-python-4.31.0 → jaaql_middleware_python-4.32.1}/jaaql/jaaql.py +0 -0
- {jaaql-middleware-python-4.31.0 → jaaql_middleware_python-4.32.1}/jaaql/migrations/__init__.py +0 -0
- {jaaql-middleware-python-4.31.0 → jaaql_middleware_python-4.32.1}/jaaql/migrations/migrations.py +0 -0
- {jaaql-middleware-python-4.31.0 → jaaql_middleware_python-4.32.1}/jaaql/mvc/__init__.py +0 -0
- {jaaql-middleware-python-4.31.0 → jaaql_middleware_python-4.32.1}/jaaql/mvc/base_controller.py +0 -0
- {jaaql-middleware-python-4.31.0 → jaaql_middleware_python-4.32.1}/jaaql/mvc/base_model.py +0 -0
- {jaaql-middleware-python-4.31.0 → jaaql_middleware_python-4.32.1}/jaaql/mvc/controller_interface.py +0 -0
- {jaaql-middleware-python-4.31.0 → jaaql_middleware_python-4.32.1}/jaaql/mvc/handmade_queries.py +0 -0
- {jaaql-middleware-python-4.31.0 → jaaql_middleware_python-4.32.1}/jaaql/mvc/model_interface.py +0 -0
- {jaaql-middleware-python-4.31.0 → jaaql_middleware_python-4.32.1}/jaaql/mvc/response.py +0 -0
- {jaaql-middleware-python-4.31.0 → jaaql_middleware_python-4.32.1}/jaaql/openapi/__init__.py +0 -0
- {jaaql-middleware-python-4.31.0 → jaaql_middleware_python-4.32.1}/jaaql/openapi/swagger_documentation.py +0 -0
- {jaaql-middleware-python-4.31.0 → jaaql_middleware_python-4.32.1}/jaaql/patch.py +0 -0
- {jaaql-middleware-python-4.31.0 → jaaql_middleware_python-4.32.1}/jaaql/scripts/02.install_super_user.exceptions.sql +0 -0
- {jaaql-middleware-python-4.31.0 → jaaql_middleware_python-4.32.1}/jaaql/scripts/03.install_super_user.handwritten.sql +0 -0
- {jaaql-middleware-python-4.31.0 → jaaql_middleware_python-4.32.1}/jaaql/scripts/05.install_static_data.generated.sql +0 -0
- {jaaql-middleware-python-4.31.0 → jaaql_middleware_python-4.32.1}/jaaql/scripts/06.install_jaaql.exceptions.sql +0 -0
- {jaaql-middleware-python-4.31.0 → jaaql_middleware_python-4.32.1}/jaaql/scripts/ZZZZ.generated_functions_views_and_permissions.sql +0 -0
- {jaaql-middleware-python-4.31.0 → jaaql_middleware_python-4.32.1}/jaaql/scripts/ZZZZ.reset_references.sql +0 -0
- {jaaql-middleware-python-4.31.0 → jaaql_middleware_python-4.32.1}/jaaql/scripts/swagger_template.html +0 -0
- {jaaql-middleware-python-4.31.0 → jaaql_middleware_python-4.32.1}/jaaql/services/__init__.py +0 -0
- {jaaql-middleware-python-4.31.0 → jaaql_middleware_python-4.32.1}/jaaql/services/cached_canned_query_service.py +0 -0
- {jaaql-middleware-python-4.31.0 → jaaql_middleware_python-4.32.1}/jaaql/services/migrations_manager_service.py +0 -0
- {jaaql-middleware-python-4.31.0 → jaaql_middleware_python-4.32.1}/jaaql/services/patch_mms.py +0 -0
- {jaaql-middleware-python-4.31.0 → jaaql_middleware_python-4.32.1}/jaaql/services/patch_shared_var_service.py +0 -0
- {jaaql-middleware-python-4.31.0 → jaaql_middleware_python-4.32.1}/jaaql/services/shared_var_service.py +0 -0
- {jaaql-middleware-python-4.31.0 → jaaql_middleware_python-4.32.1}/jaaql/utilities/__init__.py +0 -0
- {jaaql-middleware-python-4.31.0 → jaaql_middleware_python-4.32.1}/jaaql/utilities/crypt_utils.py +0 -0
- {jaaql-middleware-python-4.31.0 → jaaql_middleware_python-4.32.1}/jaaql/utilities/options.py +0 -0
- {jaaql-middleware-python-4.31.0 → jaaql_middleware_python-4.32.1}/jaaql/utilities/utils.py +0 -0
- {jaaql-middleware-python-4.31.0 → jaaql_middleware_python-4.32.1}/jaaql/utilities/utils_no_project_imports.py +0 -0
- {jaaql-middleware-python-4.31.0 → jaaql_middleware_python-4.32.1}/jaaql/utilities/vault.py +0 -0
- {jaaql-middleware-python-4.31.0 → jaaql_middleware_python-4.32.1}/jaaql_middleware_python.egg-info/SOURCES.txt +0 -0
- {jaaql-middleware-python-4.31.0 → jaaql_middleware_python-4.32.1}/jaaql_middleware_python.egg-info/dependency_links.txt +0 -0
- {jaaql-middleware-python-4.31.0 → jaaql_middleware_python-4.32.1}/jaaql_middleware_python.egg-info/top_level.txt +0 -0
- {jaaql-middleware-python-4.31.0 → jaaql_middleware_python-4.32.1}/setup.cfg +0 -0
- {jaaql-middleware-python-4.31.0 → jaaql_middleware_python-4.32.1}/setup.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: jaaql-middleware-python
|
|
3
|
-
Version: 4.
|
|
3
|
+
Version: 4.32.1
|
|
4
4
|
Summary: The jaaql package, allowing for rapid development and deployment of RESTful HTTP applications
|
|
5
5
|
Home-page: https://github.com/JAAQL/JAAQL-middleware-python
|
|
6
6
|
Author: Software Quality Measurement and Improvement bv
|
|
@@ -10,7 +10,7 @@ Description-Content-Type: text/markdown
|
|
|
10
10
|
License-File: LICENSE.txt
|
|
11
11
|
Requires-Dist: jaaql-monitor~=1.6.3
|
|
12
12
|
Requires-Dist: psycopg[binary]~=3.1.18
|
|
13
|
-
Requires-Dist: Pillow~=
|
|
13
|
+
Requires-Dist: Pillow~=11.2.1
|
|
14
14
|
Requires-Dist: cryptography~=44.0.2
|
|
15
15
|
Requires-Dist: flask~=3.1.0
|
|
16
16
|
Requires-Dist: coverage~=7.4.3
|
|
@@ -33,6 +33,15 @@ Requires-Dist: jwcrypto~=1.5.6
|
|
|
33
33
|
Requires-Dist: jinja2~=3.1.6
|
|
34
34
|
Requires-Dist: idna~=3.10
|
|
35
35
|
Requires-Dist: certifi~=2025.1.31
|
|
36
|
+
Dynamic: author
|
|
37
|
+
Dynamic: author-email
|
|
38
|
+
Dynamic: description
|
|
39
|
+
Dynamic: description-content-type
|
|
40
|
+
Dynamic: home-page
|
|
41
|
+
Dynamic: license
|
|
42
|
+
Dynamic: license-file
|
|
43
|
+
Dynamic: requires-dist
|
|
44
|
+
Dynamic: summary
|
|
36
45
|
|
|
37
46
|
# JAAQL-middleware-python
|
|
38
47
|
Please navigate to docker/docker.md to see setup instructions
|
|
@@ -45,6 +45,14 @@ KEY__registered = "registered"
|
|
|
45
45
|
KEY__restrictions = "restrictions"
|
|
46
46
|
KEY__command = "command"
|
|
47
47
|
KEY__args = "args"
|
|
48
|
+
KEY__document_id = "document_id"
|
|
49
|
+
KEY__as_attachment = "as_attachment"
|
|
50
|
+
KEY__create_file = "create_file"
|
|
51
|
+
KEY__attachment_name = "name"
|
|
52
|
+
KEY__filename = "filename"
|
|
53
|
+
KEY__completed = "completed"
|
|
54
|
+
KEY__content = "content"
|
|
55
|
+
KEY__render_as = "render_as"
|
|
48
56
|
|
|
49
57
|
CRON_minute = "minute"
|
|
50
58
|
CRON_hour = "hour"
|
|
@@ -183,5 +191,5 @@ ROLE__postgres = "postgres"
|
|
|
183
191
|
|
|
184
192
|
PROTOCOL__postgres = "postgresql://"
|
|
185
193
|
|
|
186
|
-
VERSION = "4.
|
|
194
|
+
VERSION = "4.32.1"
|
|
187
195
|
|
|
@@ -423,3 +423,113 @@ DOCUMENTATION__webhook = SwaggerDocumentation(
|
|
|
423
423
|
)
|
|
424
424
|
]
|
|
425
425
|
)
|
|
426
|
+
|
|
427
|
+
EXAMPLE__document_id = "b47dc954-d608-4e1b-8a8c-d8b754ee554b"
|
|
428
|
+
|
|
429
|
+
ARG_RES__document_id = SwaggerArgumentResponse(
|
|
430
|
+
name=KEY__document_id,
|
|
431
|
+
description="A document that can be used to fetch the document",
|
|
432
|
+
arg_type=str,
|
|
433
|
+
example=EXAMPLE__document_id
|
|
434
|
+
)
|
|
435
|
+
|
|
436
|
+
ARG_RES__renderable_document = [
|
|
437
|
+
SwaggerArgumentResponse(
|
|
438
|
+
name=KEY__attachment_name,
|
|
439
|
+
description="The name of the renderable document in the database",
|
|
440
|
+
arg_type=str,
|
|
441
|
+
example=["my_pdf_template"]
|
|
442
|
+
),
|
|
443
|
+
SwaggerArgumentResponse(
|
|
444
|
+
name=KEY__parameters,
|
|
445
|
+
description="Any parameters to pass to the url as http GET parameters",
|
|
446
|
+
arg_type=ARG_RESP__allow_all
|
|
447
|
+
)
|
|
448
|
+
]
|
|
449
|
+
|
|
450
|
+
DOCUMENTATION__document = SwaggerDocumentation(
|
|
451
|
+
tags="Documents",
|
|
452
|
+
methods=[
|
|
453
|
+
SwaggerMethod(
|
|
454
|
+
name="Triggers a document render",
|
|
455
|
+
description="Triggers a render of a document which can then be downloaded. Document is available for 5 minutes after the document has "
|
|
456
|
+
"been rendered",
|
|
457
|
+
method=REST__POST,
|
|
458
|
+
body=ARG_RES__renderable_document + [
|
|
459
|
+
SwaggerArgumentResponse(
|
|
460
|
+
name=KEY__create_file,
|
|
461
|
+
description="Whether or not to create the file. You will then be provided with a URL when it is ready which can be downloaded "
|
|
462
|
+
"from. Otherwise you will be sent back a boolean",
|
|
463
|
+
arg_type=bool
|
|
464
|
+
),
|
|
465
|
+
SwaggerArgumentResponse(
|
|
466
|
+
name=KEY__application,
|
|
467
|
+
description="The application of the document template",
|
|
468
|
+
arg_type=str,
|
|
469
|
+
example=["out-and-about"]
|
|
470
|
+
)
|
|
471
|
+
],
|
|
472
|
+
response=SwaggerResponse(
|
|
473
|
+
description="A document id",
|
|
474
|
+
response=ARG_RES__document_id
|
|
475
|
+
)
|
|
476
|
+
),
|
|
477
|
+
SwaggerMethod(
|
|
478
|
+
name="Download document",
|
|
479
|
+
description="Downloads the document. Can also be used as a polling endpoint to see if the document is ready",
|
|
480
|
+
method=REST__GET,
|
|
481
|
+
arguments=[
|
|
482
|
+
ARG_RES__document_id,
|
|
483
|
+
SwaggerArgumentResponse(
|
|
484
|
+
name=KEY__as_attachment,
|
|
485
|
+
description="Whether in the browser the 'Content-Disposition' header should be set as attachment",
|
|
486
|
+
arg_type=bool,
|
|
487
|
+
required=False,
|
|
488
|
+
condition="Defaults to false"
|
|
489
|
+
)
|
|
490
|
+
],
|
|
491
|
+
response=[
|
|
492
|
+
SwaggerFlatResponse(
|
|
493
|
+
description="A link to the raw file data. This URL is called with GET and no security parameters. Can only be called once",
|
|
494
|
+
body="https://www.jaaql.io/api/rendered_documents/" + EXAMPLE__document_id + ".pdf"
|
|
495
|
+
),
|
|
496
|
+
SwaggerFlatResponse(
|
|
497
|
+
description="The url to the document. Will be deleted after 5 minutes",
|
|
498
|
+
code=HTTPStatus.CREATED,
|
|
499
|
+
body="https://www.jaaql.io/rendered_documents/" + EXAMPLE__document_id + ".pdf"
|
|
500
|
+
),
|
|
501
|
+
SwaggerFlatResponse(
|
|
502
|
+
description="Document still rendering",
|
|
503
|
+
code=HTTPStatus.TOO_EARLY,
|
|
504
|
+
body=ERR__document_still_rendering
|
|
505
|
+
),
|
|
506
|
+
SwaggerFlatResponse(
|
|
507
|
+
description="Document id not found. Either expired or did not exist",
|
|
508
|
+
body=ERR__document_id_not_found,
|
|
509
|
+
code=HTTPStatus.NOT_FOUND
|
|
510
|
+
)
|
|
511
|
+
]
|
|
512
|
+
)
|
|
513
|
+
]
|
|
514
|
+
)
|
|
515
|
+
|
|
516
|
+
DOCUMENTATION__rendered_document = SwaggerDocumentation(
|
|
517
|
+
tags="Documents",
|
|
518
|
+
security=False,
|
|
519
|
+
methods=SwaggerMethod(
|
|
520
|
+
name="Stream rendered document",
|
|
521
|
+
description="Streams a rendered document as a downlaod",
|
|
522
|
+
method=REST__GET,
|
|
523
|
+
arguments=[ARG_RES__document_id, SwaggerArgumentResponse(
|
|
524
|
+
name=KEY__as_attachment,
|
|
525
|
+
description="Whether in the browser the 'Content-Disposition' header should be set as attachment",
|
|
526
|
+
arg_type=bool,
|
|
527
|
+
required=False,
|
|
528
|
+
condition="Defaults to false"
|
|
529
|
+
)],
|
|
530
|
+
response=SwaggerFlatResponse(
|
|
531
|
+
description="The raw file data. Cannot be re-downloaded after this",
|
|
532
|
+
body=BODY__file
|
|
533
|
+
)
|
|
534
|
+
)
|
|
535
|
+
)
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import os
|
|
2
1
|
import traceback
|
|
3
2
|
import uuid
|
|
4
3
|
import time
|
|
4
|
+
from http import HTTPStatus
|
|
5
|
+
from urllib.parse import urlparse
|
|
5
6
|
|
|
6
7
|
from selenium.common.exceptions import NoSuchElementException
|
|
7
8
|
from datetime import datetime
|
|
@@ -67,6 +68,15 @@ KEY__attachment_application = "application"
|
|
|
67
68
|
KEY__template_base = "template_base"
|
|
68
69
|
|
|
69
70
|
|
|
71
|
+
QUERY__purge_rendered_documents = "DELETE FROM document_request rd USING document_template able WHERE rd.template = able.name AND completed is not null and completed > current_timestamp + interval '5 minutes' RETURNING rd.uuid as document_id, rd.create_file, 'pdf' as render_as"
|
|
72
|
+
QUERY__fetch_unrendered_document = "SELECT able.content_path as url, a.base_url, 'pdf' as render_as, rd.uuid as document_id, rd.encrypted_parameters as parameters, rd.create_file, rd.encrypted_access_token as oauth_token FROM document_request rd INNER JOIN document_template able ON rd.template = able.name INNER JOIN application a ON rd.application = a.name WHERE rd.completed is null ORDER BY rd.request_timestamp LIMIT 1"
|
|
73
|
+
QUERY__mark_rendered_document_completed = "UPDATE document_request SET completed = current_timestamp, file_name = :file_name, content = :content WHERE uuid = :document_id"
|
|
74
|
+
QUERY__mark_rendered_document_completed_with_error = "UPDATE document_request SET completed = current_timestamp WHERE uuid = :document_id"
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
CHROME_DEBUGGING = True
|
|
78
|
+
|
|
79
|
+
|
|
70
80
|
class DrivenChrome:
|
|
71
81
|
def __init__(self, db_interface: DBInterface, db_key: bytes, is_deployed: bool):
|
|
72
82
|
self.attachments = Queue()
|
|
@@ -79,9 +89,21 @@ class DrivenChrome:
|
|
|
79
89
|
self.db_key = db_key
|
|
80
90
|
self.template_dir_path = os.path.join(DIR__www, DIR__render_template)
|
|
81
91
|
|
|
82
|
-
self.a4_params = {
|
|
92
|
+
self.a4_params = {
|
|
93
|
+
"landscape": False,
|
|
94
|
+
"paperWidth": 8.27, # A-4 portrait
|
|
95
|
+
"paperHeight": 11.69,
|
|
96
|
+
"marginTop": 0, # remove default 1 cm margins
|
|
97
|
+
"marginBottom": 0,
|
|
98
|
+
"marginLeft": 0,
|
|
99
|
+
"marginRight": 0,
|
|
100
|
+
"scale": 0.8,
|
|
101
|
+
"printBackground": True, # keep gradient / images
|
|
102
|
+
"preferCSSPageSize": True # honour @page { size:A4; margin:0 }
|
|
103
|
+
}
|
|
83
104
|
|
|
84
105
|
threading.Thread(target=self.start_chrome, daemon=True).start()
|
|
106
|
+
threading.Thread(target=self.purge_rendered_documents, daemon=True).start()
|
|
85
107
|
|
|
86
108
|
def parameters_to_get_str(self, access_token: str, parameters: dict):
|
|
87
109
|
if parameters is None:
|
|
@@ -90,9 +112,25 @@ class DrivenChrome:
|
|
|
90
112
|
|
|
91
113
|
return "?" + "&".join([key + "=" + quote(itm if isinstance(itm, bytes) else itm.encode("UTF-8")) for key, itm in parameters.items()])
|
|
92
114
|
|
|
93
|
-
def chrome_page_to_pdf(self, url: str, access_token: str, parameters: dict):
|
|
115
|
+
def chrome_page_to_pdf(self, url: str, access_token: str, parameters: dict, document_id: str):
|
|
94
116
|
with self.chrome_lock:
|
|
95
|
-
|
|
117
|
+
origin = "{uri.scheme}://{uri.netloc}".format(uri=urlparse(url))
|
|
118
|
+
self.driver.execute_cdp_cmd(
|
|
119
|
+
"Storage.clearDataForOrigin",
|
|
120
|
+
{
|
|
121
|
+
"origin": origin,
|
|
122
|
+
"storageTypes": "local_storage,session_storage"
|
|
123
|
+
}
|
|
124
|
+
)
|
|
125
|
+
|
|
126
|
+
old_handle = self.driver.current_window_handle
|
|
127
|
+
self.driver.switch_to.new_window('tab')
|
|
128
|
+
self.driver.switch_to.window(old_handle)
|
|
129
|
+
self.driver.close()
|
|
130
|
+
survivor_handles = [h for h in self.driver.window_handles if h != old_handle]
|
|
131
|
+
self.driver.switch_to.window(survivor_handles[0])
|
|
132
|
+
|
|
133
|
+
self.driver.get(url + self.parameters_to_get_str(access_token, parameters) + "&BS_document_id=" + document_id)
|
|
96
134
|
start_time = datetime.now()
|
|
97
135
|
while True:
|
|
98
136
|
passed = False
|
|
@@ -122,13 +160,79 @@ class DrivenChrome:
|
|
|
122
160
|
|
|
123
161
|
if time_delta_ms(start_time, datetime.now()) > TIMEOUT__attachment_render:
|
|
124
162
|
raise HttpStatusException(ERR__attachment_timeout_render)
|
|
163
|
+
else:
|
|
164
|
+
time.sleep(0.1)
|
|
125
165
|
|
|
126
|
-
|
|
166
|
+
pdf_data = base64.b64decode(self.driver.execute_cdp_cmd("Page.printToPDF", self.a4_params)["data"])
|
|
167
|
+
self.driver.execute_cdp_cmd("HeapProfiler.collectGarbage", {})
|
|
168
|
+
return filename, pdf_data
|
|
169
|
+
|
|
170
|
+
def purge_rendered_documents(self):
|
|
171
|
+
while True:
|
|
172
|
+
resp = execute_supplied_statement(self.db_interface, QUERY__purge_rendered_documents, as_objects=True)
|
|
173
|
+
for to_purge in resp:
|
|
174
|
+
if to_purge[KEY__create_file]:
|
|
175
|
+
try:
|
|
176
|
+
os.remove(os.path.join(self.template_dir_path,
|
|
177
|
+
str(to_purge[KEY__document_id]) + "." + to_purge[KEY__render_as]))
|
|
178
|
+
except FileNotFoundError:
|
|
179
|
+
pass
|
|
180
|
+
time.sleep(5)
|
|
181
|
+
|
|
182
|
+
def render_document_requests(self):
|
|
183
|
+
while True:
|
|
184
|
+
resp = None
|
|
185
|
+
try:
|
|
186
|
+
resp = execute_supplied_statement_singleton(self.db_interface, QUERY__fetch_unrendered_document,
|
|
187
|
+
as_objects=True,
|
|
188
|
+
decrypt_columns=[KEY__parameters, KEY__oauth_token],
|
|
189
|
+
encryption_key=self.db_key)
|
|
190
|
+
parameters = {}
|
|
191
|
+
if resp[KEY__parameters]:
|
|
192
|
+
parameters = json.loads(resp[KEY__parameters])
|
|
193
|
+
|
|
194
|
+
base_url = EmailAttachment.static_format_attached_url(resp[KG__application__base_url] + "/" + resp["url"], self.is_deployed)
|
|
195
|
+
|
|
196
|
+
filename, content = self.chrome_page_to_pdf(base_url, resp[KEY__oauth_token], parameters, str(resp[KEY__document_id]))
|
|
197
|
+
|
|
198
|
+
inputs = {KEY__document_id: resp[KEY__document_id], KEY__content: None, KG__document_request__file_name: filename}
|
|
199
|
+
if resp[KEY__create_file]:
|
|
200
|
+
if not os.path.exists(self.template_dir_path):
|
|
201
|
+
os.mkdir(self.template_dir_path)
|
|
202
|
+
with open(os.path.join(self.template_dir_path,
|
|
203
|
+
str(resp[KEY__document_id]) + "." + resp[KEY__render_as]), "wb") as f:
|
|
204
|
+
f.write(content)
|
|
205
|
+
else:
|
|
206
|
+
inputs[KEY__content] = content
|
|
207
|
+
|
|
208
|
+
execute_supplied_statement(self.db_interface, QUERY__mark_rendered_document_completed, inputs)
|
|
209
|
+
except HttpStatusException as ex:
|
|
210
|
+
if ex.response_code == HTTPStatus.UNPROCESSABLE_ENTITY:
|
|
211
|
+
if resp is not None:
|
|
212
|
+
execute_supplied_statement(self.db_interface,
|
|
213
|
+
QUERY__mark_rendered_document_completed_with_error,
|
|
214
|
+
{ KEY__document_id: resp[KEY__document_id] })
|
|
215
|
+
time.sleep(0.25)
|
|
216
|
+
else:
|
|
217
|
+
traceback.print_exc()
|
|
127
218
|
|
|
128
219
|
def start_chrome(self):
|
|
129
220
|
options = Options()
|
|
130
221
|
options.add_argument("--window-size=1920,1080")
|
|
131
|
-
options.
|
|
222
|
+
options.add_argument("--force-color-profile=srgb")
|
|
223
|
+
options.add_argument("--font-render-hinting=none")
|
|
224
|
+
options.add_argument("--disable-gpu")
|
|
225
|
+
options.add_argument("--disable-dev-shm-usage") # ✱ stop /dev/shm exhaustion
|
|
226
|
+
options.add_argument("--disable-extensions")
|
|
227
|
+
options.add_argument("--headless=new")
|
|
228
|
+
if CHROME_DEBUGGING:
|
|
229
|
+
options.add_argument("--enable-logging=stderr")
|
|
230
|
+
options.add_argument("--v=1")
|
|
231
|
+
options.set_capability(
|
|
232
|
+
"goog:loggingPrefs",
|
|
233
|
+
{"browser": "ALL", "performance": "ALL"}
|
|
234
|
+
)
|
|
235
|
+
|
|
132
236
|
service_args = []
|
|
133
237
|
|
|
134
238
|
if self.is_deployed:
|
|
@@ -136,6 +240,7 @@ class DrivenChrome:
|
|
|
136
240
|
|
|
137
241
|
with webdriver.Chrome(options=options, service=Service(service_args=service_args)) as driver:
|
|
138
242
|
self.driver = driver
|
|
243
|
+
threading.Thread(target=self.render_document_requests, daemon=True).start()
|
|
139
244
|
while True:
|
|
140
245
|
current_attachment: 'EmailAttachment' = self.attachments.get()
|
|
141
246
|
try:
|
|
@@ -144,7 +249,7 @@ class DrivenChrome:
|
|
|
144
249
|
if not content_path.endswith(".html"):
|
|
145
250
|
content_path += ".html"
|
|
146
251
|
content_path = current_attachment.template_base + "/" + content_path
|
|
147
|
-
filename, content = self.chrome_page_to_pdf(content_path, current_attachment.access_token, current_attachment.parameters)
|
|
252
|
+
filename, content = self.chrome_page_to_pdf(content_path, current_attachment.access_token, current_attachment.parameters, str(uuid.uuid4()))
|
|
148
253
|
current_attachment.content = content
|
|
149
254
|
current_attachment.filename = filename
|
|
150
255
|
except HttpStatusException as ex:
|
|
@@ -182,3 +182,14 @@ class JAAQLController(BaseJAAQLController):
|
|
|
182
182
|
@self.publish_route('/.well-known/jwks', DOCUMENTATION__jwks)
|
|
183
183
|
def fetch_jwks():
|
|
184
184
|
return self.model.fetch_jwks()
|
|
185
|
+
|
|
186
|
+
@self.publish_route('/documents', DOCUMENTATION__document)
|
|
187
|
+
def documents(http_inputs: dict, auth_token: str, ip_address: str, response: JAAQLResponse):
|
|
188
|
+
if self.is_get():
|
|
189
|
+
return self.model.fetch_document(http_inputs, response)
|
|
190
|
+
else:
|
|
191
|
+
return self.model.render_document(http_inputs, auth_token, ip_address)
|
|
192
|
+
|
|
193
|
+
@self.publish_route('/rendered_documents', DOCUMENTATION__rendered_document)
|
|
194
|
+
def documents(http_inputs: dict):
|
|
195
|
+
return self.model.fetch_document_stream(http_inputs)
|
{jaaql-middleware-python-4.31.0 → jaaql_middleware_python-4.32.1}/jaaql/mvc/generated_queries.py
RENAMED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"""
|
|
2
|
-
This script was generated from build_and_run.fxls at 2025-
|
|
2
|
+
This script was generated from build_and_run.fxls at 2025-05-21, 11:25:44
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
5
|
from jaaql.db.db_interface import DBInterface
|
|
@@ -717,17 +717,18 @@ KG__document_request__render_timestamp = "render_timestamp"
|
|
|
717
717
|
KG__document_request__create_file = "create_file"
|
|
718
718
|
KG__document_request__file_name = "file_name"
|
|
719
719
|
KG__document_request__content = "content"
|
|
720
|
+
KG__document_request__completed = "completed"
|
|
720
721
|
|
|
721
722
|
# Generated queries for table 'document_request'
|
|
722
723
|
QG__document_request_delete = "DELETE FROM document_request WHERE uuid = :uuid"
|
|
723
724
|
QG__document_request_insert = """
|
|
724
|
-
INSERT INTO document_request (application, template,
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
VALUES (:application, :template, :
|
|
728
|
-
:
|
|
729
|
-
:
|
|
730
|
-
RETURNING request_timestamp
|
|
725
|
+
INSERT INTO document_request (application, template, encrypted_access_token,
|
|
726
|
+
encrypted_parameters, render_timestamp, create_file,
|
|
727
|
+
file_name, content, completed)
|
|
728
|
+
VALUES (:application, :template, :encrypted_access_token,
|
|
729
|
+
:encrypted_parameters, :render_timestamp, :create_file,
|
|
730
|
+
:file_name, :content, :completed)
|
|
731
|
+
RETURNING uuid, request_timestamp
|
|
731
732
|
"""
|
|
732
733
|
QG__document_request_select_all = "SELECT * FROM document_request"
|
|
733
734
|
QG__document_request_select = "SELECT * FROM document_request WHERE uuid = :uuid"
|
|
@@ -743,7 +744,8 @@ QG__document_request_update = """
|
|
|
743
744
|
render_timestamp = COALESCE(:render_timestamp, render_timestamp),
|
|
744
745
|
create_file = COALESCE(:create_file, create_file),
|
|
745
746
|
file_name = COALESCE(:file_name, file_name),
|
|
746
|
-
content = COALESCE(:content, content)
|
|
747
|
+
content = COALESCE(:content, content),
|
|
748
|
+
completed = COALESCE(:completed, completed)
|
|
747
749
|
WHERE
|
|
748
750
|
uuid = :uuid
|
|
749
751
|
"""
|
|
@@ -769,6 +771,7 @@ def document_request__update(
|
|
|
769
771
|
application=None, template=None, request_timestamp=None,
|
|
770
772
|
encrypted_access_token=None, encrypted_parameters=None, render_timestamp=None,
|
|
771
773
|
create_file=None, file_name=None, content=None,
|
|
774
|
+
completed=None,
|
|
772
775
|
encryption_salts=None
|
|
773
776
|
):
|
|
774
777
|
execute_supplied_statement(
|
|
@@ -786,7 +789,8 @@ def document_request__update(
|
|
|
786
789
|
KG__document_request__render_timestamp: render_timestamp,
|
|
787
790
|
KG__document_request__create_file: create_file,
|
|
788
791
|
KG__document_request__file_name: file_name,
|
|
789
|
-
KG__document_request__content: content
|
|
792
|
+
KG__document_request__content: content,
|
|
793
|
+
KG__document_request__completed: completed
|
|
790
794
|
}, encryption_key=encryption_key, encryption_salts=encryption_salts, encrypt_parameters=[
|
|
791
795
|
KG__document_request__encrypted_access_token,
|
|
792
796
|
KG__document_request__encrypted_parameters
|
|
@@ -826,10 +830,10 @@ def document_request__select_all(
|
|
|
826
830
|
|
|
827
831
|
def document_request__insert(
|
|
828
832
|
connection: DBInterface, encryption_key: bytes,
|
|
829
|
-
application, template,
|
|
830
|
-
|
|
833
|
+
application, template, encrypted_access_token,
|
|
834
|
+
create_file,
|
|
831
835
|
encrypted_parameters=None, render_timestamp=None, file_name=None,
|
|
832
|
-
content=None,
|
|
836
|
+
content=None, completed=None,
|
|
833
837
|
encryption_salts=None
|
|
834
838
|
):
|
|
835
839
|
return execute_supplied_statement_singleton(
|
|
@@ -837,13 +841,13 @@ def document_request__insert(
|
|
|
837
841
|
{
|
|
838
842
|
KG__document_request__application: application,
|
|
839
843
|
KG__document_request__template: template,
|
|
840
|
-
KG__document_request__uuid: uuid,
|
|
841
844
|
KG__document_request__encrypted_access_token: encrypted_access_token,
|
|
842
845
|
KG__document_request__encrypted_parameters: encrypted_parameters,
|
|
843
846
|
KG__document_request__render_timestamp: render_timestamp,
|
|
844
847
|
KG__document_request__create_file: create_file,
|
|
845
848
|
KG__document_request__file_name: file_name,
|
|
846
|
-
KG__document_request__content: content
|
|
849
|
+
KG__document_request__content: content,
|
|
850
|
+
KG__document_request__completed: completed
|
|
847
851
|
}, encryption_key=encryption_key, encryption_salts=encryption_salts, encrypt_parameters=[
|
|
848
852
|
KG__document_request__encrypted_access_token,
|
|
849
853
|
KG__document_request__encrypted_parameters
|
|
@@ -13,6 +13,8 @@ import re
|
|
|
13
13
|
|
|
14
14
|
import jwt
|
|
15
15
|
from jwcrypto import jwe
|
|
16
|
+
from io import BytesIO
|
|
17
|
+
from flask import send_file
|
|
16
18
|
|
|
17
19
|
from jwt import PyJWKClient
|
|
18
20
|
|
|
@@ -112,6 +114,10 @@ SIGNUP__completed = 3
|
|
|
112
114
|
|
|
113
115
|
KEY__is_the_anonymous_user = "is_the_anonymous_user"
|
|
114
116
|
|
|
117
|
+
QUERY__ins_rendered_document = "INSERT INTO document_request (encrypted_parameters, encrypted_access_token, template, create_file, application) VALUES (:parameters, :oauth_token, :name, :create_file, :application) RETURNING uuid as document_id"
|
|
118
|
+
QUERY__purge_rendered_document = "DELETE FROM document_request WHERE completed is not null and uuid = :document_id RETURNING content"
|
|
119
|
+
QUERY__fetch_rendered_document = "SELECT app.base_url, rd.uuid as document_id, 'pdf' as render_as, rd.file_name, rd.create_file, rd.completed, rd.encrypted_access_token as oauth_token FROM document_request rd INNER JOIN document_template able ON rd.template = able.name INNER JOIN application app ON app.name = rd.application WHERE rd.uuid = :document_id"
|
|
120
|
+
|
|
115
121
|
|
|
116
122
|
class JAAQLModel(BaseJAAQLModel):
|
|
117
123
|
VERIFICATION_QUEUE = None
|
|
@@ -1255,6 +1261,53 @@ WHERE
|
|
|
1255
1261
|
KEY__username: account[KG__account__username]
|
|
1256
1262
|
}
|
|
1257
1263
|
|
|
1264
|
+
def fetch_document(self, inputs: dict, response: JAAQLResponse):
|
|
1265
|
+
res = execute_supplied_statement_singleton(self.jaaql_lookup_connection, QUERY__fetch_rendered_document,
|
|
1266
|
+
{KEY__document_id: inputs[KEY__document_id]}, singleton_message=ERR__document_id_not_found,
|
|
1267
|
+
as_objects=True)
|
|
1268
|
+
|
|
1269
|
+
if not res[KEY__completed]:
|
|
1270
|
+
raise HttpStatusException(ERR__document_still_rendering, HTTPStatus.TOO_EARLY)
|
|
1271
|
+
|
|
1272
|
+
if res[KEY__create_file]:
|
|
1273
|
+
if inputs[KEY__as_attachment] is not None:
|
|
1274
|
+
raise HttpStatusException(ERR__as_attachment_unexpected)
|
|
1275
|
+
response.response_code = HTTPStatus.CREATED
|
|
1276
|
+
return res[KG__application__base_url] + "/" + DIR__render_template + "/" + str(res[KEY__document_id]) + "." + res[KEY__render_as]
|
|
1277
|
+
else:
|
|
1278
|
+
return res[KG__application__base_url] + "/api/rendered_documents/" + res[KEY__document_id]
|
|
1279
|
+
|
|
1280
|
+
def fetch_document_stream(self, inputs: dict):
|
|
1281
|
+
res = execute_supplied_statement_singleton(self.jaaql_lookup_connection, QUERY__fetch_rendered_document,
|
|
1282
|
+
{KEY__document_id: inputs[KEY__document_id]}, singleton_message=ERR__document_id_not_found,
|
|
1283
|
+
as_objects=True)
|
|
1284
|
+
|
|
1285
|
+
if not res[KEY__completed]:
|
|
1286
|
+
raise HttpStatusException(ERR__document_still_rendering, HTTPStatus.TOO_EARLY)
|
|
1287
|
+
|
|
1288
|
+
if res[KEY__create_file]:
|
|
1289
|
+
raise HttpStatusException(ERR__document_created_file)
|
|
1290
|
+
else:
|
|
1291
|
+
content = execute_supplied_statement_singleton(self.jaaql_lookup_connection, QUERY__purge_rendered_document,
|
|
1292
|
+
{KEY__document_id: inputs[KEY__document_id]}, as_objects=True)[KEY__content]
|
|
1293
|
+
as_attachment = False
|
|
1294
|
+
if inputs[KEY__as_attachment]:
|
|
1295
|
+
as_attachment = True
|
|
1296
|
+
|
|
1297
|
+
buffer = BytesIO()
|
|
1298
|
+
buffer.write(content)
|
|
1299
|
+
buffer.seek(0)
|
|
1300
|
+
|
|
1301
|
+
return send_file(buffer, as_attachment=as_attachment, download_name=res[KEY__filename])
|
|
1302
|
+
|
|
1303
|
+
def render_document(self, inputs: dict, auth_token: str, ip_address: str):
|
|
1304
|
+
inputs[KEY__oauth_token] = self.refresh_auth_token(auth_token, ip_address)
|
|
1305
|
+
if inputs[KEY__parameters] is not None:
|
|
1306
|
+
inputs[KEY__parameters] = json.dumps(inputs[KEY__parameters])
|
|
1307
|
+
return execute_supplied_statement_singleton(self.jaaql_lookup_connection, QUERY__ins_rendered_document, inputs,
|
|
1308
|
+
encryption_key=self.get_db_crypt_key(), encrypt_parameters=[KEY__parameters, KEY__oauth_token],
|
|
1309
|
+
as_objects=True)
|
|
1310
|
+
|
|
1258
1311
|
def send_email(self, is_the_anonymous_user: bool, account_id: str, inputs: dict, username: str, auth_token: str):
|
|
1259
1312
|
app = application__select(self.jaaql_lookup_connection, inputs[KEY__application])
|
|
1260
1313
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
-- This installation module was generated from ..\..\Packages/DBMS/Postgres/15/domains.jsql.fxlp for Postgres/15
|
|
2
2
|
|
|
3
3
|
CREATE DOMAIN encrypted__email_server_password AS character varying(256);
|
|
4
|
-
CREATE DOMAIN encrypted__access_token AS
|
|
4
|
+
CREATE DOMAIN encrypted__access_token AS text;
|
|
5
5
|
CREATE DOMAIN encrypted__oidc_client_id AS character varying(200);
|
|
6
6
|
CREATE DOMAIN encrypted__oidc_client_secret AS character varying(200);
|
|
7
7
|
CREATE DOMAIN encrypted__oidc_sub AS character varying(200);
|
|
@@ -143,7 +143,7 @@ create table document_template (
|
|
|
143
143
|
create table document_request (
|
|
144
144
|
application internet_name not null,
|
|
145
145
|
template object_name not null,
|
|
146
|
-
uuid uuid not null,
|
|
146
|
+
uuid uuid not null default gen_random_uuid(),
|
|
147
147
|
request_timestamp timestamptz not null default current_timestamp,
|
|
148
148
|
encrypted_access_token encrypted__access_token not null,
|
|
149
149
|
encrypted_parameters text,
|
|
@@ -151,6 +151,7 @@ create table document_request (
|
|
|
151
151
|
create_file bool not null,
|
|
152
152
|
file_name file_name,
|
|
153
153
|
content bytea,
|
|
154
|
+
completed timestamptz,
|
|
154
155
|
primary key (uuid) );
|
|
155
156
|
-- federation_procedure...
|
|
156
157
|
create table federation_procedure (
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: jaaql-middleware-python
|
|
3
|
-
Version: 4.
|
|
3
|
+
Version: 4.32.1
|
|
4
4
|
Summary: The jaaql package, allowing for rapid development and deployment of RESTful HTTP applications
|
|
5
5
|
Home-page: https://github.com/JAAQL/JAAQL-middleware-python
|
|
6
6
|
Author: Software Quality Measurement and Improvement bv
|
|
@@ -10,7 +10,7 @@ Description-Content-Type: text/markdown
|
|
|
10
10
|
License-File: LICENSE.txt
|
|
11
11
|
Requires-Dist: jaaql-monitor~=1.6.3
|
|
12
12
|
Requires-Dist: psycopg[binary]~=3.1.18
|
|
13
|
-
Requires-Dist: Pillow~=
|
|
13
|
+
Requires-Dist: Pillow~=11.2.1
|
|
14
14
|
Requires-Dist: cryptography~=44.0.2
|
|
15
15
|
Requires-Dist: flask~=3.1.0
|
|
16
16
|
Requires-Dist: coverage~=7.4.3
|
|
@@ -33,6 +33,15 @@ Requires-Dist: jwcrypto~=1.5.6
|
|
|
33
33
|
Requires-Dist: jinja2~=3.1.6
|
|
34
34
|
Requires-Dist: idna~=3.10
|
|
35
35
|
Requires-Dist: certifi~=2025.1.31
|
|
36
|
+
Dynamic: author
|
|
37
|
+
Dynamic: author-email
|
|
38
|
+
Dynamic: description
|
|
39
|
+
Dynamic: description-content-type
|
|
40
|
+
Dynamic: home-page
|
|
41
|
+
Dynamic: license
|
|
42
|
+
Dynamic: license-file
|
|
43
|
+
Dynamic: requires-dist
|
|
44
|
+
Dynamic: summary
|
|
36
45
|
|
|
37
46
|
# JAAQL-middleware-python
|
|
38
47
|
Please navigate to docker/docker.md to see setup instructions
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{jaaql-middleware-python-4.31.0 → jaaql_middleware_python-4.32.1}/jaaql/config/config-docker.ini
RENAMED
|
File without changes
|
{jaaql-middleware-python-4.31.0 → jaaql_middleware_python-4.32.1}/jaaql/config/config-test.ini
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{jaaql-middleware-python-4.31.0 → jaaql_middleware_python-4.32.1}/jaaql/db/db_pg_interface.py
RENAMED
|
File without changes
|
|
File without changes
|
{jaaql-middleware-python-4.31.0 → jaaql_middleware_python-4.32.1}/jaaql/db/db_utils_no_circ.py
RENAMED
|
File without changes
|
{jaaql-middleware-python-4.31.0 → jaaql_middleware_python-4.32.1}/jaaql/documentation/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{jaaql-middleware-python-4.31.0 → jaaql_middleware_python-4.32.1}/jaaql/email/email_manager.py
RENAMED
|
File without changes
|
|
File without changes
|
{jaaql-middleware-python-4.31.0 → jaaql_middleware_python-4.32.1}/jaaql/exceptions/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{jaaql-middleware-python-4.31.0 → jaaql_middleware_python-4.32.1}/jaaql/generated_constants.py
RENAMED
|
File without changes
|
{jaaql-middleware-python-4.31.0 → jaaql_middleware_python-4.32.1}/jaaql/interpreter/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{jaaql-middleware-python-4.31.0 → jaaql_middleware_python-4.32.1}/jaaql/migrations/__init__.py
RENAMED
|
File without changes
|
{jaaql-middleware-python-4.31.0 → jaaql_middleware_python-4.32.1}/jaaql/migrations/migrations.py
RENAMED
|
File without changes
|
|
File without changes
|
{jaaql-middleware-python-4.31.0 → jaaql_middleware_python-4.32.1}/jaaql/mvc/base_controller.py
RENAMED
|
File without changes
|
|
File without changes
|
{jaaql-middleware-python-4.31.0 → jaaql_middleware_python-4.32.1}/jaaql/mvc/controller_interface.py
RENAMED
|
File without changes
|
{jaaql-middleware-python-4.31.0 → jaaql_middleware_python-4.32.1}/jaaql/mvc/handmade_queries.py
RENAMED
|
File without changes
|
{jaaql-middleware-python-4.31.0 → jaaql_middleware_python-4.32.1}/jaaql/mvc/model_interface.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{jaaql-middleware-python-4.31.0 → jaaql_middleware_python-4.32.1}/jaaql/services/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{jaaql-middleware-python-4.31.0 → jaaql_middleware_python-4.32.1}/jaaql/services/patch_mms.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{jaaql-middleware-python-4.31.0 → jaaql_middleware_python-4.32.1}/jaaql/utilities/__init__.py
RENAMED
|
File without changes
|
{jaaql-middleware-python-4.31.0 → jaaql_middleware_python-4.32.1}/jaaql/utilities/crypt_utils.py
RENAMED
|
File without changes
|
{jaaql-middleware-python-4.31.0 → jaaql_middleware_python-4.32.1}/jaaql/utilities/options.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|