OpenGeodeWeb-Back 5.10.0rc5__tar.gz → 5.10.0rc8__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.
- {opengeodeweb_back-5.10.0rc5/src/OpenGeodeWeb_Back.egg-info → opengeodeweb_back-5.10.0rc8}/PKG-INFO +5 -1
- {opengeodeweb_back-5.10.0rc5 → opengeodeweb_back-5.10.0rc8}/pyproject.toml +1 -1
- {opengeodeweb_back-5.10.0rc5 → opengeodeweb_back-5.10.0rc8}/requirements.txt +9 -0
- {opengeodeweb_back-5.10.0rc5 → opengeodeweb_back-5.10.0rc8/src/OpenGeodeWeb_Back.egg-info}/PKG-INFO +5 -1
- {opengeodeweb_back-5.10.0rc5 → opengeodeweb_back-5.10.0rc8}/src/OpenGeodeWeb_Back.egg-info/SOURCES.txt +2 -0
- {opengeodeweb_back-5.10.0rc5 → opengeodeweb_back-5.10.0rc8}/src/OpenGeodeWeb_Back.egg-info/requires.txt +4 -0
- {opengeodeweb_back-5.10.0rc5 → opengeodeweb_back-5.10.0rc8}/src/opengeodeweb_back/app_config.py +11 -2
- opengeodeweb_back-5.10.0rc8/src/opengeodeweb_back/data.py +44 -0
- opengeodeweb_back-5.10.0rc8/src/opengeodeweb_back/database.py +19 -0
- {opengeodeweb_back-5.10.0rc5 → opengeodeweb_back-5.10.0rc8}/src/opengeodeweb_back/geode_functions.py +2 -2
- {opengeodeweb_back-5.10.0rc5 → opengeodeweb_back-5.10.0rc8}/src/opengeodeweb_back/geode_objects.py +6 -6
- {opengeodeweb_back-5.10.0rc5 → opengeodeweb_back-5.10.0rc8}/src/opengeodeweb_back/utils_functions.py +91 -55
- {opengeodeweb_back-5.10.0rc5 → opengeodeweb_back-5.10.0rc8}/tests/test_routes.py +12 -0
- {opengeodeweb_back-5.10.0rc5 → opengeodeweb_back-5.10.0rc8}/tests/test_utils_functions.py +63 -18
- {opengeodeweb_back-5.10.0rc5 → opengeodeweb_back-5.10.0rc8}/LICENSE +0 -0
- {opengeodeweb_back-5.10.0rc5 → opengeodeweb_back-5.10.0rc8}/README.md +0 -0
- {opengeodeweb_back-5.10.0rc5 → opengeodeweb_back-5.10.0rc8}/setup.cfg +0 -0
- {opengeodeweb_back-5.10.0rc5 → opengeodeweb_back-5.10.0rc8}/src/OpenGeodeWeb_Back.egg-info/dependency_links.txt +0 -0
- {opengeodeweb_back-5.10.0rc5 → opengeodeweb_back-5.10.0rc8}/src/OpenGeodeWeb_Back.egg-info/top_level.txt +0 -0
- {opengeodeweb_back-5.10.0rc5 → opengeodeweb_back-5.10.0rc8}/src/opengeodeweb_back/__init__.py +0 -0
- {opengeodeweb_back-5.10.0rc5 → opengeodeweb_back-5.10.0rc8}/src/opengeodeweb_back/routes/blueprint_routes.py +0 -0
- {opengeodeweb_back-5.10.0rc5 → opengeodeweb_back-5.10.0rc8}/src/opengeodeweb_back/routes/models/blueprint_models.py +0 -0
- {opengeodeweb_back-5.10.0rc5 → opengeodeweb_back-5.10.0rc8}/src/opengeodeweb_back/routes/models/schemas/mesh_components.json +0 -0
- {opengeodeweb_back-5.10.0rc5 → opengeodeweb_back-5.10.0rc8}/src/opengeodeweb_back/routes/models/schemas/vtm_component_indices.json +0 -0
- {opengeodeweb_back-5.10.0rc5 → opengeodeweb_back-5.10.0rc8}/src/opengeodeweb_back/routes/schemas/allowed_files.json +0 -0
- {opengeodeweb_back-5.10.0rc5 → opengeodeweb_back-5.10.0rc8}/src/opengeodeweb_back/routes/schemas/allowed_objects.json +0 -0
- {opengeodeweb_back-5.10.0rc5 → opengeodeweb_back-5.10.0rc8}/src/opengeodeweb_back/routes/schemas/create_point.json +0 -0
- {opengeodeweb_back-5.10.0rc5 → opengeodeweb_back-5.10.0rc8}/src/opengeodeweb_back/routes/schemas/geode_objects_and_output_extensions.json +0 -0
- {opengeodeweb_back-5.10.0rc5 → opengeodeweb_back-5.10.0rc8}/src/opengeodeweb_back/routes/schemas/geographic_coordinate_systems.json +0 -0
- {opengeodeweb_back-5.10.0rc5 → opengeodeweb_back-5.10.0rc8}/src/opengeodeweb_back/routes/schemas/inspect_file.json +0 -0
- {opengeodeweb_back-5.10.0rc5 → opengeodeweb_back-5.10.0rc8}/src/opengeodeweb_back/routes/schemas/missing_files.json +0 -0
- {opengeodeweb_back-5.10.0rc5 → opengeodeweb_back-5.10.0rc8}/src/opengeodeweb_back/routes/schemas/ping.json +0 -0
- {opengeodeweb_back-5.10.0rc5 → opengeodeweb_back-5.10.0rc8}/src/opengeodeweb_back/routes/schemas/polygon_attribute_names.json +0 -0
- {opengeodeweb_back-5.10.0rc5 → opengeodeweb_back-5.10.0rc8}/src/opengeodeweb_back/routes/schemas/polyhedron_attribute_names.json +0 -0
- {opengeodeweb_back-5.10.0rc5 → opengeodeweb_back-5.10.0rc8}/src/opengeodeweb_back/routes/schemas/save_viewable_file.json +0 -0
- {opengeodeweb_back-5.10.0rc5 → opengeodeweb_back-5.10.0rc8}/src/opengeodeweb_back/routes/schemas/texture_coordinates.json +0 -0
- {opengeodeweb_back-5.10.0rc5 → opengeodeweb_back-5.10.0rc8}/src/opengeodeweb_back/routes/schemas/upload_file.json +0 -0
- {opengeodeweb_back-5.10.0rc5 → opengeodeweb_back-5.10.0rc8}/src/opengeodeweb_back/routes/schemas/vertex_attribute_names.json +0 -0
- {opengeodeweb_back-5.10.0rc5 → opengeodeweb_back-5.10.0rc8}/src/opengeodeweb_back/test_utils.py +0 -0
- {opengeodeweb_back-5.10.0rc5 → opengeodeweb_back-5.10.0rc8}/tests/test_geode_functions.py +0 -0
- {opengeodeweb_back-5.10.0rc5 → opengeodeweb_back-5.10.0rc8}/tests/test_models_routes.py +0 -0
{opengeodeweb_back-5.10.0rc5/src/OpenGeodeWeb_Back.egg-info → opengeodeweb_back-5.10.0rc8}/PKG-INFO
RENAMED
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: OpenGeodeWeb-Back
|
3
|
-
Version: 5.10.
|
3
|
+
Version: 5.10.0rc8
|
4
4
|
Summary: OpenGeodeWeb-Back is an open source framework that proposes handy python functions and wrappers for the OpenGeode ecosystem
|
5
5
|
Author-email: Geode-solutions <team-web@geode-solutions.com>
|
6
6
|
Project-URL: Homepage, https://github.com/Geode-solutions/OpenGeodeWeb-Back
|
@@ -17,8 +17,10 @@ Requires-Dist: click==8.2.1
|
|
17
17
|
Requires-Dist: fastjsonschema==2.16.2
|
18
18
|
Requires-Dist: flask[async]==3.0.3
|
19
19
|
Requires-Dist: flask-cors==6.0.1
|
20
|
+
Requires-Dist: flask-sqlalchemy==3.1.1
|
20
21
|
Requires-Dist: geode-common==33.9.0
|
21
22
|
Requires-Dist: geode-viewables==3.2.0
|
23
|
+
Requires-Dist: greenlet==3.2.4
|
22
24
|
Requires-Dist: itsdangerous==2.2.0
|
23
25
|
Requires-Dist: jinja2==3.1.6
|
24
26
|
Requires-Dist: markupsafe==3.0.2
|
@@ -27,6 +29,8 @@ Requires-Dist: opengeode-geosciences==9.2.2
|
|
27
29
|
Requires-Dist: opengeode-geosciencesio==5.7.2
|
28
30
|
Requires-Dist: opengeode-inspector==6.7.0
|
29
31
|
Requires-Dist: opengeode-io==7.3.2
|
32
|
+
Requires-Dist: sqlalchemy==2.0.43
|
33
|
+
Requires-Dist: typing-extensions==4.15.0
|
30
34
|
Requires-Dist: werkzeug==3.0.3
|
31
35
|
Dynamic: license-file
|
32
36
|
|
@@ -17,12 +17,17 @@ flask[async]==3.0.3
|
|
17
17
|
# -r requirements.in
|
18
18
|
# flask
|
19
19
|
# flask-cors
|
20
|
+
# flask-sqlalchemy
|
20
21
|
flask-cors==6.0.1
|
21
22
|
# via -r requirements.in
|
23
|
+
flask-sqlalchemy==3.1.1
|
24
|
+
# via -r requirements.in
|
22
25
|
geode-common==33.9.0
|
23
26
|
# via geode-viewables
|
24
27
|
geode-viewables==3.2.0
|
25
28
|
# via -r requirements.in
|
29
|
+
greenlet==3.2.4
|
30
|
+
# via sqlalchemy
|
26
31
|
itsdangerous==2.2.0
|
27
32
|
# via flask
|
28
33
|
jinja2==3.1.6
|
@@ -54,6 +59,10 @@ opengeode-io==7.3.2
|
|
54
59
|
# -r requirements.in
|
55
60
|
# geode-viewables
|
56
61
|
# opengeode-geosciencesio
|
62
|
+
sqlalchemy==2.0.43
|
63
|
+
# via flask-sqlalchemy
|
64
|
+
typing-extensions==4.15.0
|
65
|
+
# via sqlalchemy
|
57
66
|
werkzeug==3.0.3
|
58
67
|
# via
|
59
68
|
# -r requirements.in
|
{opengeodeweb_back-5.10.0rc5 → opengeodeweb_back-5.10.0rc8/src/OpenGeodeWeb_Back.egg-info}/PKG-INFO
RENAMED
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: OpenGeodeWeb-Back
|
3
|
-
Version: 5.10.
|
3
|
+
Version: 5.10.0rc8
|
4
4
|
Summary: OpenGeodeWeb-Back is an open source framework that proposes handy python functions and wrappers for the OpenGeode ecosystem
|
5
5
|
Author-email: Geode-solutions <team-web@geode-solutions.com>
|
6
6
|
Project-URL: Homepage, https://github.com/Geode-solutions/OpenGeodeWeb-Back
|
@@ -17,8 +17,10 @@ Requires-Dist: click==8.2.1
|
|
17
17
|
Requires-Dist: fastjsonschema==2.16.2
|
18
18
|
Requires-Dist: flask[async]==3.0.3
|
19
19
|
Requires-Dist: flask-cors==6.0.1
|
20
|
+
Requires-Dist: flask-sqlalchemy==3.1.1
|
20
21
|
Requires-Dist: geode-common==33.9.0
|
21
22
|
Requires-Dist: geode-viewables==3.2.0
|
23
|
+
Requires-Dist: greenlet==3.2.4
|
22
24
|
Requires-Dist: itsdangerous==2.2.0
|
23
25
|
Requires-Dist: jinja2==3.1.6
|
24
26
|
Requires-Dist: markupsafe==3.0.2
|
@@ -27,6 +29,8 @@ Requires-Dist: opengeode-geosciences==9.2.2
|
|
27
29
|
Requires-Dist: opengeode-geosciencesio==5.7.2
|
28
30
|
Requires-Dist: opengeode-inspector==6.7.0
|
29
31
|
Requires-Dist: opengeode-io==7.3.2
|
32
|
+
Requires-Dist: sqlalchemy==2.0.43
|
33
|
+
Requires-Dist: typing-extensions==4.15.0
|
30
34
|
Requires-Dist: werkzeug==3.0.3
|
31
35
|
Dynamic: license-file
|
32
36
|
|
@@ -9,6 +9,8 @@ src/OpenGeodeWeb_Back.egg-info/requires.txt
|
|
9
9
|
src/OpenGeodeWeb_Back.egg-info/top_level.txt
|
10
10
|
src/opengeodeweb_back/__init__.py
|
11
11
|
src/opengeodeweb_back/app_config.py
|
12
|
+
src/opengeodeweb_back/data.py
|
13
|
+
src/opengeodeweb_back/database.py
|
12
14
|
src/opengeodeweb_back/geode_functions.py
|
13
15
|
src/opengeodeweb_back/geode_objects.py
|
14
16
|
src/opengeodeweb_back/test_utils.py
|
@@ -4,8 +4,10 @@ click==8.2.1
|
|
4
4
|
fastjsonschema==2.16.2
|
5
5
|
flask[async]==3.0.3
|
6
6
|
flask-cors==6.0.1
|
7
|
+
flask-sqlalchemy==3.1.1
|
7
8
|
geode-common==33.9.0
|
8
9
|
geode-viewables==3.2.0
|
10
|
+
greenlet==3.2.4
|
9
11
|
itsdangerous==2.2.0
|
10
12
|
jinja2==3.1.6
|
11
13
|
markupsafe==3.0.2
|
@@ -14,4 +16,6 @@ opengeode-geosciences==9.2.2
|
|
14
16
|
opengeode-geosciencesio==5.7.2
|
15
17
|
opengeode-inspector==6.7.0
|
16
18
|
opengeode-io==7.3.2
|
19
|
+
sqlalchemy==2.0.43
|
20
|
+
typing-extensions==4.15.0
|
17
21
|
werkzeug==3.0.3
|
{opengeodeweb_back-5.10.0rc5 → opengeodeweb_back-5.10.0rc8}/src/opengeodeweb_back/app_config.py
RENAMED
@@ -4,6 +4,7 @@ import time
|
|
4
4
|
|
5
5
|
# Third party imports
|
6
6
|
# Local application imports
|
7
|
+
from .database import DATABASE_FILENAME
|
7
8
|
|
8
9
|
|
9
10
|
class Config(object):
|
@@ -15,6 +16,7 @@ class Config(object):
|
|
15
16
|
REQUEST_COUNTER = 0
|
16
17
|
LAST_REQUEST_TIME = time.time()
|
17
18
|
LAST_PING_TIME = time.time()
|
19
|
+
SQLALCHEMY_TRACK_MODIFICATIONS = False
|
18
20
|
|
19
21
|
|
20
22
|
class ProdConfig(Config):
|
@@ -22,7 +24,10 @@ class ProdConfig(Config):
|
|
22
24
|
ORIGINS = ""
|
23
25
|
MINUTES_BEFORE_TIMEOUT = "1"
|
24
26
|
SECONDS_BETWEEN_SHUTDOWNS = "10"
|
25
|
-
DATA_FOLDER_PATH = "/data
|
27
|
+
DATA_FOLDER_PATH = "/data"
|
28
|
+
SQLALCHEMY_DATABASE_URI = f"sqlite:///{os.path.abspath(
|
29
|
+
os.path.join(DATA_FOLDER_PATH, DATABASE_FILENAME)
|
30
|
+
)}"
|
26
31
|
|
27
32
|
|
28
33
|
class DevConfig(Config):
|
@@ -30,4 +35,8 @@ class DevConfig(Config):
|
|
30
35
|
ORIGINS = "*"
|
31
36
|
MINUTES_BEFORE_TIMEOUT = "1"
|
32
37
|
SECONDS_BETWEEN_SHUTDOWNS = "10"
|
33
|
-
|
38
|
+
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
|
39
|
+
DATA_FOLDER_PATH = os.path.join(BASE_DIR, "data")
|
40
|
+
SQLALCHEMY_DATABASE_URI = f"sqlite:///{os.path.join(
|
41
|
+
BASE_DIR, DATA_FOLDER_PATH, DATABASE_FILENAME
|
42
|
+
)}"
|
@@ -0,0 +1,44 @@
|
|
1
|
+
from sqlalchemy import String, JSON
|
2
|
+
from sqlalchemy.orm import Mapped, mapped_column
|
3
|
+
from .database import database, Base
|
4
|
+
import uuid
|
5
|
+
|
6
|
+
|
7
|
+
class Data(Base):
|
8
|
+
__tablename__ = "datas"
|
9
|
+
|
10
|
+
id: Mapped[str] = mapped_column(
|
11
|
+
String, primary_key=True, default=lambda: str(uuid.uuid4()).replace("-", "")
|
12
|
+
)
|
13
|
+
name: Mapped[str] = mapped_column(String, nullable=False)
|
14
|
+
native_file_name: Mapped[str] = mapped_column(String, nullable=False)
|
15
|
+
viewable_file_name: Mapped[str] = mapped_column(String, nullable=False)
|
16
|
+
geode_object: Mapped[str] = mapped_column(String, nullable=False)
|
17
|
+
|
18
|
+
light_viewable: Mapped[str | None] = mapped_column(String, nullable=True)
|
19
|
+
input_file: Mapped[str | None] = mapped_column(String, nullable=True)
|
20
|
+
additional_files: Mapped[list[str] | None] = mapped_column(JSON, nullable=True)
|
21
|
+
|
22
|
+
@staticmethod
|
23
|
+
def create(
|
24
|
+
name: str,
|
25
|
+
geode_object: str,
|
26
|
+
input_file: str | None = None,
|
27
|
+
additional_files: list[str] | None = None,
|
28
|
+
) -> "Data":
|
29
|
+
input_file = input_file if input_file is not None else ""
|
30
|
+
additional_files = additional_files if additional_files is not None else []
|
31
|
+
|
32
|
+
data_entry = Data(
|
33
|
+
name=name,
|
34
|
+
geode_object=geode_object,
|
35
|
+
input_file=input_file,
|
36
|
+
additional_files=additional_files,
|
37
|
+
native_file_name="",
|
38
|
+
viewable_file_name="",
|
39
|
+
light_viewable=None,
|
40
|
+
)
|
41
|
+
|
42
|
+
database.session.add(data_entry)
|
43
|
+
database.session.flush()
|
44
|
+
return data_entry
|
@@ -0,0 +1,19 @@
|
|
1
|
+
from flask import Flask
|
2
|
+
from flask_sqlalchemy import SQLAlchemy
|
3
|
+
from sqlalchemy.orm import DeclarativeBase
|
4
|
+
|
5
|
+
DATABASE_FILENAME = "project.db"
|
6
|
+
|
7
|
+
|
8
|
+
class Base(DeclarativeBase):
|
9
|
+
pass
|
10
|
+
|
11
|
+
|
12
|
+
database = SQLAlchemy(model_class=Base)
|
13
|
+
|
14
|
+
|
15
|
+
def initialize_database(app: Flask) -> SQLAlchemy:
|
16
|
+
database.init_app(app)
|
17
|
+
with app.app_context():
|
18
|
+
database.create_all()
|
19
|
+
return database
|
{opengeodeweb_back-5.10.0rc5 → opengeodeweb_back-5.10.0rc8}/src/opengeodeweb_back/geode_objects.py
RENAMED
@@ -1,12 +1,12 @@
|
|
1
1
|
# Standard library imports
|
2
2
|
|
3
3
|
# Third party imports
|
4
|
-
import opengeode as og
|
5
|
-
import opengeode_io as og_io
|
6
|
-
import opengeode_inspector as og_inspector
|
7
|
-
import opengeode_geosciences as og_gs
|
8
|
-
import opengeode_geosciencesio as og_gs_io
|
9
|
-
import geode_viewables as g_v
|
4
|
+
import opengeode as og # type: ignore
|
5
|
+
import opengeode_io as og_io # type: ignore
|
6
|
+
import opengeode_inspector as og_inspector # type: ignore
|
7
|
+
import opengeode_geosciences as og_gs # type: ignore
|
8
|
+
import opengeode_geosciencesio as og_gs_io # type: ignore
|
9
|
+
import geode_viewables as g_v # type: ignore
|
10
10
|
|
11
11
|
# Local application imports
|
12
12
|
|
{opengeodeweb_back-5.10.0rc5 → opengeodeweb_back-5.10.0rc8}/src/opengeodeweb_back/utils_functions.py
RENAMED
@@ -2,54 +2,58 @@
|
|
2
2
|
import os
|
3
3
|
import threading
|
4
4
|
import time
|
5
|
-
import uuid
|
6
5
|
import zipfile
|
6
|
+
from collections.abc import Callable
|
7
|
+
from typing import Any
|
7
8
|
|
8
9
|
# Third party imports
|
9
10
|
import flask
|
10
|
-
import fastjsonschema
|
11
|
+
import fastjsonschema # type: ignore
|
11
12
|
import importlib.metadata as metadata
|
12
13
|
import shutil
|
14
|
+
from werkzeug.exceptions import HTTPException
|
13
15
|
import werkzeug
|
14
16
|
|
15
17
|
# Local application imports
|
16
18
|
from . import geode_functions
|
19
|
+
from .data import Data
|
20
|
+
from .database import database
|
17
21
|
|
18
22
|
|
19
|
-
def increment_request_counter(current_app):
|
23
|
+
def increment_request_counter(current_app: flask.Flask) -> None:
|
20
24
|
if "REQUEST_COUNTER" in current_app.config:
|
21
|
-
REQUEST_COUNTER = int(current_app.config.get("REQUEST_COUNTER"))
|
25
|
+
REQUEST_COUNTER = int(current_app.config.get("REQUEST_COUNTER", 0))
|
22
26
|
REQUEST_COUNTER += 1
|
23
27
|
current_app.config.update(REQUEST_COUNTER=REQUEST_COUNTER)
|
24
28
|
|
25
29
|
|
26
|
-
def decrement_request_counter(current_app):
|
30
|
+
def decrement_request_counter(current_app: flask.Flask) -> None:
|
27
31
|
if "REQUEST_COUNTER" in current_app.config:
|
28
|
-
REQUEST_COUNTER = int(current_app.config.get("REQUEST_COUNTER"))
|
32
|
+
REQUEST_COUNTER = int(current_app.config.get("REQUEST_COUNTER", 0))
|
29
33
|
REQUEST_COUNTER -= 1
|
30
34
|
current_app.config.update(REQUEST_COUNTER=REQUEST_COUNTER)
|
31
35
|
|
32
36
|
|
33
|
-
def update_last_request_time(current_app):
|
37
|
+
def update_last_request_time(current_app: flask.Flask) -> None:
|
34
38
|
if "LAST_REQUEST_TIME" in current_app.config:
|
35
39
|
LAST_REQUEST_TIME = time.time()
|
36
40
|
current_app.config.update(LAST_REQUEST_TIME=LAST_REQUEST_TIME)
|
37
41
|
|
38
42
|
|
39
|
-
def before_request(current_app):
|
43
|
+
def before_request(current_app: flask.Flask) -> None:
|
40
44
|
increment_request_counter(current_app)
|
41
45
|
|
42
46
|
|
43
|
-
def teardown_request(current_app):
|
47
|
+
def teardown_request(current_app: flask.Flask) -> None:
|
44
48
|
decrement_request_counter(current_app)
|
45
49
|
update_last_request_time(current_app)
|
46
50
|
|
47
51
|
|
48
|
-
def kill_task(current_app):
|
49
|
-
REQUEST_COUNTER = int(current_app.config.get("REQUEST_COUNTER"))
|
50
|
-
LAST_PING_TIME = float(current_app.config.get("LAST_PING_TIME"))
|
51
|
-
LAST_REQUEST_TIME = float(current_app.config.get("LAST_REQUEST_TIME"))
|
52
|
-
MINUTES_BEFORE_TIMEOUT = float(current_app.config.get("MINUTES_BEFORE_TIMEOUT"))
|
52
|
+
def kill_task(current_app: flask.Flask) -> None:
|
53
|
+
REQUEST_COUNTER = int(current_app.config.get("REQUEST_COUNTER", 0))
|
54
|
+
LAST_PING_TIME = float(current_app.config.get("LAST_PING_TIME", 0))
|
55
|
+
LAST_REQUEST_TIME = float(current_app.config.get("LAST_REQUEST_TIME", 0))
|
56
|
+
MINUTES_BEFORE_TIMEOUT = float(current_app.config.get("MINUTES_BEFORE_TIMEOUT", 0))
|
53
57
|
current_time = time.time()
|
54
58
|
minutes_since_last_request = (current_time - LAST_REQUEST_TIME) / 60
|
55
59
|
minutes_since_last_ping = (current_time - LAST_PING_TIME) / 60
|
@@ -64,12 +68,12 @@ def kill_task(current_app):
|
|
64
68
|
kill_server()
|
65
69
|
|
66
70
|
|
67
|
-
def kill_server():
|
71
|
+
def kill_server() -> None:
|
68
72
|
print("Server timed out due to inactivity, shutting down...", flush=True)
|
69
73
|
os._exit(0)
|
70
74
|
|
71
75
|
|
72
|
-
def versions(list_packages: list):
|
76
|
+
def versions(list_packages: list[str]) -> list[dict[str, str]]:
|
73
77
|
list_with_versions = []
|
74
78
|
for package in list_packages:
|
75
79
|
list_with_versions.append(
|
@@ -78,7 +82,7 @@ def versions(list_packages: list):
|
|
78
82
|
return list_with_versions
|
79
83
|
|
80
84
|
|
81
|
-
def validate_request(request, schema):
|
85
|
+
def validate_request(request: flask.Request, schema: dict[str, str]) -> None:
|
82
86
|
json_data = request.get_json(force=True, silent=True)
|
83
87
|
|
84
88
|
if json_data is None:
|
@@ -92,22 +96,26 @@ def validate_request(request, schema):
|
|
92
96
|
flask.abort(400, error_msg)
|
93
97
|
|
94
98
|
|
95
|
-
def set_interval(
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
+
def set_interval(
|
100
|
+
function: Callable[[Any], None], seconds: float, args: Any
|
101
|
+
) -> threading.Timer:
|
102
|
+
def function_wrapper() -> None:
|
103
|
+
set_interval(function, seconds, args)
|
104
|
+
function(args)
|
99
105
|
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
return
|
106
|
+
timer = threading.Timer(seconds, function_wrapper)
|
107
|
+
timer.daemon = True
|
108
|
+
timer.start()
|
109
|
+
return timer
|
104
110
|
|
105
111
|
|
106
|
-
def extension_from_filename(filename):
|
112
|
+
def extension_from_filename(filename: str) -> str:
|
107
113
|
return os.path.splitext(filename)[1][1:]
|
108
114
|
|
109
115
|
|
110
|
-
def send_file(
|
116
|
+
def send_file(
|
117
|
+
upload_folder: str, saved_files: str, new_file_name: str
|
118
|
+
) -> flask.Response:
|
111
119
|
if len(saved_files) == 1:
|
112
120
|
mimetype = "application/octet-binary"
|
113
121
|
else:
|
@@ -132,30 +140,42 @@ def send_file(upload_folder, saved_files, new_file_name):
|
|
132
140
|
return response
|
133
141
|
|
134
142
|
|
135
|
-
def handle_exception(
|
136
|
-
response =
|
143
|
+
def handle_exception(exception: HTTPException) -> flask.Response:
|
144
|
+
response = exception.get_response()
|
137
145
|
response.data = flask.json.dumps(
|
138
146
|
{
|
139
|
-
"code":
|
140
|
-
"name":
|
141
|
-
"description":
|
147
|
+
"code": exception.code,
|
148
|
+
"name": exception.name,
|
149
|
+
"description": exception.description,
|
142
150
|
}
|
143
151
|
)
|
144
152
|
response.content_type = "application/json"
|
145
153
|
return response
|
146
154
|
|
147
155
|
|
148
|
-
def
|
156
|
+
def create_data_folder_from_id(data_id: str) -> str:
|
149
157
|
base_data_folder = flask.current_app.config["DATA_FOLDER_PATH"]
|
150
|
-
|
151
|
-
data_path = os.path.join(base_data_folder, generated_id)
|
158
|
+
data_path = os.path.join(base_data_folder, data_id)
|
152
159
|
os.makedirs(data_path, exist_ok=True)
|
153
|
-
return
|
160
|
+
return data_path
|
154
161
|
|
155
162
|
|
156
163
|
def save_all_viewables_and_return_info(
|
157
|
-
geode_object
|
158
|
-
|
164
|
+
geode_object: str,
|
165
|
+
data: Any,
|
166
|
+
input_file: str,
|
167
|
+
additional_files: list[str] | None = None,
|
168
|
+
) -> dict[str, Any]:
|
169
|
+
if additional_files is None:
|
170
|
+
additional_files = []
|
171
|
+
|
172
|
+
data_entry = Data.create(
|
173
|
+
name=data.name(),
|
174
|
+
geode_object=geode_object,
|
175
|
+
input_file=input_file,
|
176
|
+
additional_files=additional_files,
|
177
|
+
)
|
178
|
+
data_path = create_data_folder_from_id(data_entry.id)
|
159
179
|
saved_native_file_path = geode_functions.save(
|
160
180
|
geode_object,
|
161
181
|
data,
|
@@ -170,28 +190,42 @@ def save_all_viewables_and_return_info(
|
|
170
190
|
)
|
171
191
|
with open(saved_light_viewable_file_path, "rb") as f:
|
172
192
|
binary_light_viewable = f.read()
|
193
|
+
data_entry.native_file_name = os.path.basename(saved_native_file_path[0])
|
194
|
+
data_entry.viewable_file_name = os.path.basename(saved_viewable_file_path)
|
195
|
+
data_entry.light_viewable = os.path.basename(saved_light_viewable_file_path)
|
196
|
+
|
197
|
+
database.session.commit()
|
173
198
|
|
174
199
|
return {
|
175
|
-
"name":
|
176
|
-
"native_file_name":
|
177
|
-
"viewable_file_name":
|
178
|
-
"id":
|
200
|
+
"name": data_entry.name,
|
201
|
+
"native_file_name": data_entry.native_file_name,
|
202
|
+
"viewable_file_name": data_entry.viewable_file_name,
|
203
|
+
"id": data_entry.id,
|
179
204
|
"object_type": geode_functions.get_object_type(geode_object),
|
180
205
|
"binary_light_viewable": binary_light_viewable.decode("utf-8"),
|
181
|
-
"geode_object": geode_object,
|
182
|
-
"input_files":
|
206
|
+
"geode_object": data_entry.geode_object,
|
207
|
+
"input_files": data_entry.input_file,
|
208
|
+
"additional_files": data_entry.additional_files,
|
183
209
|
}
|
184
210
|
|
185
211
|
|
186
|
-
def generate_native_viewable_and_light_viewable_from_object(
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
)
|
212
|
+
def generate_native_viewable_and_light_viewable_from_object(
|
213
|
+
geode_object: str, data: Any
|
214
|
+
) -> dict[str, Any]:
|
215
|
+
return save_all_viewables_and_return_info(geode_object, data, input_file="")
|
191
216
|
|
192
217
|
|
193
|
-
def generate_native_viewable_and_light_viewable_from_file(
|
194
|
-
|
218
|
+
def generate_native_viewable_and_light_viewable_from_file(
|
219
|
+
geode_object: str, input_filename: str
|
220
|
+
) -> dict[str, Any]:
|
221
|
+
temp_data_entry = Data.create(
|
222
|
+
name="temp",
|
223
|
+
geode_object=geode_object,
|
224
|
+
input_file=input_filename,
|
225
|
+
additional_files=[],
|
226
|
+
)
|
227
|
+
|
228
|
+
data_path = create_data_folder_from_id(temp_data_entry.id)
|
195
229
|
|
196
230
|
full_input_filename = geode_functions.upload_file_path(input_filename)
|
197
231
|
copied_full_path = os.path.join(
|
@@ -199,7 +233,7 @@ def generate_native_viewable_and_light_viewable_from_file(geode_object, input_fi
|
|
199
233
|
)
|
200
234
|
shutil.copy2(full_input_filename, copied_full_path)
|
201
235
|
|
202
|
-
additional_files_copied = []
|
236
|
+
additional_files_copied: list[str] = []
|
203
237
|
additional = geode_functions.additional_files(geode_object, full_input_filename)
|
204
238
|
for additional_file in additional.mandatory_files + additional.optional_files:
|
205
239
|
if additional_file.is_missing:
|
@@ -214,12 +248,14 @@ def generate_native_viewable_and_light_viewable_from_file(geode_object, input_fi
|
|
214
248
|
shutil.copy2(source_path, dest_path)
|
215
249
|
additional_files_copied.append(additional_file.filename)
|
216
250
|
|
217
|
-
data = geode_functions.load_data(geode_object,
|
251
|
+
data = geode_functions.load_data(geode_object, temp_data_entry.id, input_filename)
|
252
|
+
|
253
|
+
database.session.delete(temp_data_entry)
|
254
|
+
database.session.flush()
|
218
255
|
|
219
256
|
return save_all_viewables_and_return_info(
|
220
257
|
geode_object,
|
221
258
|
data,
|
222
|
-
|
223
|
-
data_path,
|
259
|
+
input_file=input_filename,
|
224
260
|
additional_files=additional_files_copied,
|
225
261
|
)
|
@@ -321,3 +321,15 @@ def test_create_point(client):
|
|
321
321
|
|
322
322
|
# Test all params
|
323
323
|
test_utils.test_route_wrong_params(client, route, get_full_data)
|
324
|
+
|
325
|
+
|
326
|
+
def test_database_uri_path(client):
|
327
|
+
app = client.application
|
328
|
+
with app.app_context():
|
329
|
+
base_dir = os.path.abspath(os.path.dirname(__file__))
|
330
|
+
expected_db_path = os.path.join(base_dir, "data", "project.db")
|
331
|
+
expected_uri = f"sqlite:///{expected_db_path}"
|
332
|
+
|
333
|
+
assert app.config["SQLALCHEMY_DATABASE_URI"] == expected_uri
|
334
|
+
|
335
|
+
assert os.path.exists(expected_db_path)
|
@@ -5,8 +5,11 @@ import os
|
|
5
5
|
# Third party imports
|
6
6
|
import flask
|
7
7
|
import shutil
|
8
|
+
import uuid
|
8
9
|
|
9
10
|
# Local application imports
|
11
|
+
from src.opengeodeweb_back.database import database
|
12
|
+
from src.opengeodeweb_back.data import Data
|
10
13
|
from src.opengeodeweb_back import geode_functions, utils_functions
|
11
14
|
|
12
15
|
|
@@ -72,15 +75,15 @@ def test_handle_exception(client):
|
|
72
75
|
assert type(data["code"]) is int
|
73
76
|
|
74
77
|
|
75
|
-
def
|
78
|
+
def test_create_data_folder_from_id(client):
|
76
79
|
app = client.application
|
77
80
|
with app.app_context():
|
78
|
-
|
79
|
-
|
80
|
-
assert
|
81
|
+
test_id = str(uuid.uuid4()).replace("-", "")
|
82
|
+
data_path = utils_functions.create_data_folder_from_id(test_id)
|
83
|
+
assert isinstance(data_path, str)
|
81
84
|
assert os.path.exists(data_path)
|
82
85
|
assert data_path.startswith(flask.current_app.config["DATA_FOLDER_PATH"])
|
83
|
-
assert
|
86
|
+
assert test_id in data_path
|
84
87
|
shutil.rmtree(data_path, ignore_errors=True)
|
85
88
|
assert not os.path.exists(data_path)
|
86
89
|
|
@@ -88,24 +91,66 @@ def test_create_unique_data_folder(client):
|
|
88
91
|
def test_save_all_viewables_and_return_info(client):
|
89
92
|
app = client.application
|
90
93
|
with app.app_context():
|
94
|
+
base_dir = os.path.abspath(os.path.dirname(__file__))
|
95
|
+
expected_db_path = os.path.join(base_dir, "data", "project.db")
|
96
|
+
expected_uri = f"sqlite:///{expected_db_path}"
|
97
|
+
|
98
|
+
assert app.config["SQLALCHEMY_DATABASE_URI"] == expected_uri
|
99
|
+
assert os.path.exists(expected_db_path)
|
100
|
+
|
91
101
|
geode_object = "BRep"
|
92
102
|
data = geode_functions.load(geode_object, "./tests/data/test.og_brep")
|
93
|
-
|
103
|
+
input_file = "test.og_brep"
|
94
104
|
additional_files = ["additional_file.txt"]
|
95
105
|
|
96
106
|
result = utils_functions.save_all_viewables_and_return_info(
|
97
|
-
geode_object, data,
|
107
|
+
geode_object, data, input_file, additional_files
|
98
108
|
)
|
99
109
|
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
110
|
+
assert isinstance(result, dict)
|
111
|
+
assert result["name"] == data.name()
|
112
|
+
assert result["native_file_name"].startswith("native.")
|
113
|
+
assert result["viewable_file_name"].endswith(".vtm")
|
114
|
+
assert isinstance(result["id"], str)
|
115
|
+
assert len(result["id"]) == 32
|
116
|
+
assert re.match(r"[0-9a-f]{32}", result["id"])
|
117
|
+
assert isinstance(result["object_type"], str)
|
118
|
+
assert isinstance(result["binary_light_viewable"], str)
|
119
|
+
assert result["geode_object"] == geode_object
|
120
|
+
assert result["input_files"] == input_file
|
121
|
+
|
122
|
+
db_entry = database.session.get(Data, result["id"])
|
123
|
+
assert db_entry is not None
|
124
|
+
assert db_entry.name == data.name()
|
125
|
+
assert db_entry.native_file_name == result["native_file_name"]
|
126
|
+
assert db_entry.viewable_file_name == result["viewable_file_name"]
|
127
|
+
assert db_entry.geode_object == geode_object
|
128
|
+
assert db_entry.input_file == input_file
|
129
|
+
assert db_entry.additional_files == additional_files
|
130
|
+
|
131
|
+
expected_data_path = os.path.join(app.config["DATA_FOLDER_PATH"], result["id"])
|
132
|
+
assert os.path.exists(expected_data_path)
|
133
|
+
|
134
|
+
|
135
|
+
def test_save_all_viewables_commits_to_db_properly(client):
|
136
|
+
app = client.application
|
137
|
+
with app.app_context():
|
138
|
+
geode_object = "BRep"
|
139
|
+
data = geode_functions.load(geode_object, "./tests/data/test.og_brep")
|
140
|
+
input_file = "test.og_brep"
|
141
|
+
result = utils_functions.save_all_viewables_and_return_info(
|
142
|
+
geode_object, data, input_file
|
143
|
+
)
|
144
|
+
data_id = result["id"]
|
145
|
+
db_entry_before = database.session.get(Data, data_id)
|
146
|
+
assert db_entry_before is not None
|
147
|
+
assert db_entry_before.native_file_name == result["native_file_name"]
|
148
|
+
database.session.rollback()
|
149
|
+
db_entry_after = database.session.get(Data, data_id)
|
150
|
+
assert (
|
151
|
+
db_entry_after is not None
|
152
|
+
), "database.session.commit() was not called - entry missing after rollback"
|
153
|
+
assert db_entry_after.native_file_name == result["native_file_name"]
|
109
154
|
|
110
155
|
|
111
156
|
def test_generate_native_viewable_and_light_viewable_from_object(client):
|
@@ -130,7 +175,7 @@ def test_generate_native_viewable_and_light_viewable_from_object(client):
|
|
130
175
|
assert re.match(r"[0-9a-f]{32}", result["id"])
|
131
176
|
assert isinstance(result["object_type"], str)
|
132
177
|
assert isinstance(result["binary_light_viewable"], str)
|
133
|
-
assert result["input_files"] ==
|
178
|
+
assert result["input_files"] == ""
|
134
179
|
|
135
180
|
|
136
181
|
def test_generate_native_viewable_and_light_viewable_from_file(client):
|
@@ -153,4 +198,4 @@ def test_generate_native_viewable_and_light_viewable_from_file(client):
|
|
153
198
|
assert re.match(r"[0-9a-f]{32}", result["id"])
|
154
199
|
assert isinstance(result["object_type"], str)
|
155
200
|
assert isinstance(result["binary_light_viewable"], str)
|
156
|
-
assert isinstance(result["input_files"],
|
201
|
+
assert isinstance(result["input_files"], str)
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{opengeodeweb_back-5.10.0rc5 → opengeodeweb_back-5.10.0rc8}/src/opengeodeweb_back/__init__.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
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{opengeodeweb_back-5.10.0rc5 → opengeodeweb_back-5.10.0rc8}/src/opengeodeweb_back/test_utils.py
RENAMED
File without changes
|
File without changes
|
File without changes
|