OpenGeodeWeb-Back 5.10.4__py3-none-any.whl → 5.14.1__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.
- opengeodeweb_back/app.py +20 -14
- opengeodeweb_back/geode_functions.py +44 -283
- opengeodeweb_back/geode_objects/__init__.py +61 -0
- opengeodeweb_back/geode_objects/geode_brep.py +102 -0
- opengeodeweb_back/geode_objects/geode_cross_section.py +75 -0
- opengeodeweb_back/geode_objects/geode_edged_curve2d.py +107 -0
- opengeodeweb_back/geode_objects/geode_edged_curve3d.py +107 -0
- opengeodeweb_back/geode_objects/geode_graph.py +76 -0
- opengeodeweb_back/geode_objects/geode_grid2d.py +30 -0
- opengeodeweb_back/geode_objects/geode_grid3d.py +30 -0
- opengeodeweb_back/geode_objects/geode_hybrid_solid3d.py +71 -0
- opengeodeweb_back/geode_objects/geode_implicit_cross_section.py +81 -0
- opengeodeweb_back/geode_objects/geode_implicit_structural_model.py +85 -0
- opengeodeweb_back/geode_objects/geode_light_regular_grid2d.py +72 -0
- opengeodeweb_back/geode_objects/geode_light_regular_grid3d.py +72 -0
- opengeodeweb_back/geode_objects/geode_mesh.py +19 -0
- opengeodeweb_back/geode_objects/geode_model.py +22 -0
- opengeodeweb_back/geode_objects/geode_object.py +78 -0
- opengeodeweb_back/geode_objects/geode_point_set2d.py +105 -0
- opengeodeweb_back/geode_objects/geode_point_set3d.py +105 -0
- opengeodeweb_back/geode_objects/geode_polygonal_surface2d.py +73 -0
- opengeodeweb_back/geode_objects/geode_polygonal_surface3d.py +73 -0
- opengeodeweb_back/geode_objects/geode_polyhedral_solid3d.py +73 -0
- opengeodeweb_back/geode_objects/geode_raster_image2d.py +83 -0
- opengeodeweb_back/geode_objects/geode_raster_image3d.py +83 -0
- opengeodeweb_back/geode_objects/geode_regular_grid2d.py +78 -0
- opengeodeweb_back/geode_objects/geode_regular_grid3d.py +78 -0
- opengeodeweb_back/geode_objects/geode_section.py +106 -0
- opengeodeweb_back/geode_objects/geode_solid_mesh3d.py +61 -0
- opengeodeweb_back/geode_objects/geode_structural_model.py +78 -0
- opengeodeweb_back/geode_objects/geode_surface_mesh2d.py +66 -0
- opengeodeweb_back/geode_objects/geode_surface_mesh3d.py +66 -0
- opengeodeweb_back/geode_objects/geode_tetrahedral_solid3d.py +73 -0
- opengeodeweb_back/geode_objects/geode_triangulated_surface2d.py +77 -0
- opengeodeweb_back/geode_objects/geode_triangulated_surface3d.py +77 -0
- opengeodeweb_back/geode_objects/geode_vertex_set.py +81 -0
- opengeodeweb_back/geode_objects/types.py +75 -0
- opengeodeweb_back/routes/blueprint_routes.py +346 -225
- opengeodeweb_back/routes/create/blueprint_create.py +121 -0
- opengeodeweb_back/routes/create/schemas/__init__.py +3 -0
- opengeodeweb_back/routes/create/schemas/create_aoi.json +45 -0
- opengeodeweb_back/routes/create/schemas/create_aoi.py +25 -0
- opengeodeweb_back/routes/create/schemas/create_point.json +29 -0
- opengeodeweb_back/routes/create/schemas/create_point.py +13 -0
- opengeodeweb_back/routes/create/schemas/create_voi.json +36 -0
- opengeodeweb_back/routes/create/schemas/create_voi.py +24 -0
- opengeodeweb_back/routes/models/blueprint_models.py +27 -27
- opengeodeweb_back/routes/models/schemas/__init__.py +2 -0
- opengeodeweb_back/routes/models/schemas/mesh_components.py +10 -0
- opengeodeweb_back/routes/models/schemas/vtm_component_indices.py +10 -0
- opengeodeweb_back/routes/schemas/__init__.py +17 -0
- opengeodeweb_back/routes/schemas/allowed_files.json +6 -8
- opengeodeweb_back/routes/schemas/allowed_files.py +10 -0
- opengeodeweb_back/routes/schemas/allowed_objects.json +1 -8
- opengeodeweb_back/routes/schemas/allowed_objects.py +10 -0
- opengeodeweb_back/routes/schemas/cell_attribute_names.json +13 -0
- opengeodeweb_back/routes/schemas/cell_attribute_names.py +10 -0
- opengeodeweb_back/routes/schemas/export_project.json +21 -0
- opengeodeweb_back/routes/schemas/export_project.py +12 -0
- opengeodeweb_back/routes/schemas/geode_objects_and_output_extensions.json +2 -2
- opengeodeweb_back/routes/schemas/geode_objects_and_output_extensions.py +11 -0
- opengeodeweb_back/routes/schemas/geographic_coordinate_systems.json +2 -2
- opengeodeweb_back/routes/schemas/geographic_coordinate_systems.py +10 -0
- opengeodeweb_back/routes/schemas/import_project.json +10 -0
- opengeodeweb_back/routes/schemas/import_project.py +10 -0
- opengeodeweb_back/routes/schemas/inspect_file.json +2 -2
- opengeodeweb_back/routes/schemas/inspect_file.py +11 -0
- opengeodeweb_back/routes/schemas/kill.py +10 -0
- opengeodeweb_back/routes/schemas/missing_files.json +2 -2
- opengeodeweb_back/routes/schemas/missing_files.py +11 -0
- opengeodeweb_back/routes/schemas/ping.py +10 -0
- opengeodeweb_back/routes/schemas/polygon_attribute_names.py +10 -0
- opengeodeweb_back/routes/schemas/polyhedron_attribute_names.py +10 -0
- opengeodeweb_back/routes/schemas/save_viewable_file.json +2 -2
- opengeodeweb_back/routes/schemas/save_viewable_file.py +11 -0
- opengeodeweb_back/routes/schemas/texture_coordinates.py +10 -0
- opengeodeweb_back/routes/schemas/upload_file.py +11 -0
- opengeodeweb_back/routes/schemas/vertex_attribute_names.py +10 -0
- opengeodeweb_back/test_utils.py +9 -3
- opengeodeweb_back/utils_functions.py +77 -74
- {opengeodeweb_back-5.10.4.dist-info → opengeodeweb_back-5.14.1.dist-info}/METADATA +9 -9
- opengeodeweb_back-5.14.1.dist-info/RECORD +98 -0
- opengeodeweb_back/geode_objects.py +0 -570
- opengeodeweb_back/routes/schemas/create_point.json +0 -29
- opengeodeweb_back-5.10.4.dist-info/RECORD +0 -33
- {opengeodeweb_back-5.10.4.dist-info → opengeodeweb_back-5.14.1.dist-info}/WHEEL +0 -0
- {opengeodeweb_back-5.10.4.dist-info → opengeodeweb_back-5.14.1.dist-info}/entry_points.txt +0 -0
- {opengeodeweb_back-5.10.4.dist-info → opengeodeweb_back-5.14.1.dist-info}/licenses/LICENSE +0 -0
- {opengeodeweb_back-5.10.4.dist-info → opengeodeweb_back-5.14.1.dist-info}/top_level.txt +0 -0
|
@@ -1,17 +1,31 @@
|
|
|
1
1
|
# Standard library imports
|
|
2
|
-
import json
|
|
3
2
|
import os
|
|
4
3
|
import time
|
|
4
|
+
import shutil
|
|
5
|
+
from typing import Any
|
|
5
6
|
|
|
6
7
|
# Third party imports
|
|
7
8
|
import flask
|
|
8
|
-
import opengeode
|
|
9
9
|
import werkzeug
|
|
10
|
+
import zipfile
|
|
11
|
+
import opengeode_geosciences as og_geosciences
|
|
12
|
+
from opengeodeweb_microservice.schemas import get_schemas_dict
|
|
13
|
+
from opengeodeweb_microservice.database.data import Data
|
|
14
|
+
from opengeodeweb_microservice.database.connection import get_session
|
|
15
|
+
from opengeodeweb_microservice.database import connection
|
|
10
16
|
|
|
11
17
|
# Local application imports
|
|
12
|
-
from .. import geode_functions, utils_functions
|
|
13
|
-
|
|
14
18
|
from .models import blueprint_models
|
|
19
|
+
from . import schemas
|
|
20
|
+
from opengeodeweb_back import geode_functions, utils_functions
|
|
21
|
+
from opengeodeweb_back.geode_objects import geode_objects
|
|
22
|
+
from opengeodeweb_back.geode_objects.types import geode_object_type
|
|
23
|
+
from opengeodeweb_back.geode_objects.geode_mesh import GeodeMesh
|
|
24
|
+
from opengeodeweb_back.geode_objects.geode_grid2d import GeodeGrid2D
|
|
25
|
+
from opengeodeweb_back.geode_objects.geode_grid3d import GeodeGrid3D
|
|
26
|
+
from opengeodeweb_back.geode_objects.geode_surface_mesh2d import GeodeSurfaceMesh2D
|
|
27
|
+
from opengeodeweb_back.geode_objects.geode_surface_mesh3d import GeodeSurfaceMesh3D
|
|
28
|
+
from opengeodeweb_back.geode_objects.geode_solid_mesh3d import GeodeSolidMesh3D
|
|
15
29
|
|
|
16
30
|
routes = flask.Blueprint("routes", __name__, url_prefix="/opengeodeweb_back")
|
|
17
31
|
|
|
@@ -22,108 +36,87 @@ routes.register_blueprint(
|
|
|
22
36
|
name=blueprint_models.routes.name,
|
|
23
37
|
)
|
|
24
38
|
|
|
25
|
-
|
|
26
|
-
schemas = os.path.join(os.path.dirname(__file__), "schemas")
|
|
27
|
-
|
|
28
|
-
with open(
|
|
29
|
-
os.path.join(schemas, "allowed_files.json"),
|
|
30
|
-
"r",
|
|
31
|
-
) as file:
|
|
32
|
-
allowed_files_json = json.load(file)
|
|
39
|
+
schemas_dict = get_schemas_dict(os.path.join(os.path.dirname(__file__), "schemas"))
|
|
33
40
|
|
|
34
41
|
|
|
35
42
|
@routes.route(
|
|
36
|
-
|
|
37
|
-
methods=
|
|
43
|
+
schemas_dict["allowed_files"]["route"],
|
|
44
|
+
methods=schemas_dict["allowed_files"]["methods"],
|
|
38
45
|
)
|
|
39
|
-
def allowed_files():
|
|
40
|
-
utils_functions.validate_request(flask.request,
|
|
41
|
-
extensions =
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
with open(
|
|
48
|
-
os.path.join(schemas, "upload_file.json"),
|
|
49
|
-
"r",
|
|
50
|
-
) as file:
|
|
51
|
-
upload_file_json = json.load(file)
|
|
46
|
+
def allowed_files() -> flask.Response:
|
|
47
|
+
utils_functions.validate_request(flask.request, schemas_dict["allowed_files"])
|
|
48
|
+
extensions: set[str] = set()
|
|
49
|
+
for geode_object in geode_objects.values():
|
|
50
|
+
for extension in geode_object.input_extensions():
|
|
51
|
+
extensions.add(extension)
|
|
52
|
+
return flask.make_response({"extensions": list(extensions)}, 200)
|
|
52
53
|
|
|
53
54
|
|
|
54
55
|
@routes.route(
|
|
55
|
-
|
|
56
|
-
methods=
|
|
56
|
+
schemas_dict["upload_file"]["route"],
|
|
57
|
+
methods=schemas_dict["upload_file"]["methods"],
|
|
57
58
|
)
|
|
58
|
-
def upload_file():
|
|
59
|
-
if flask.request.method == "OPTIONS":
|
|
60
|
-
return flask.make_response({}, 200)
|
|
61
|
-
|
|
59
|
+
def upload_file() -> flask.Response:
|
|
62
60
|
UPLOAD_FOLDER = flask.current_app.config["UPLOAD_FOLDER"]
|
|
63
61
|
if not os.path.exists(UPLOAD_FOLDER):
|
|
64
|
-
os.
|
|
62
|
+
os.makedirs(UPLOAD_FOLDER, exist_ok=True)
|
|
63
|
+
|
|
65
64
|
file = flask.request.files["file"]
|
|
66
65
|
filename = werkzeug.utils.secure_filename(os.path.basename(file.filename))
|
|
67
66
|
file.save(os.path.join(UPLOAD_FOLDER, filename))
|
|
68
67
|
return flask.make_response({"message": "File uploaded"}, 201)
|
|
69
68
|
|
|
70
69
|
|
|
71
|
-
with open(
|
|
72
|
-
os.path.join(schemas, "allowed_objects.json"),
|
|
73
|
-
"r",
|
|
74
|
-
) as file:
|
|
75
|
-
allowed_objects_json = json.load(file)
|
|
76
|
-
|
|
77
|
-
|
|
78
70
|
@routes.route(
|
|
79
|
-
|
|
80
|
-
methods=
|
|
71
|
+
schemas_dict["allowed_objects"]["route"],
|
|
72
|
+
methods=schemas_dict["allowed_objects"]["methods"],
|
|
81
73
|
)
|
|
82
|
-
def allowed_objects():
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
utils_functions.validate_request(flask.request, allowed_objects_json)
|
|
87
|
-
file_absolute_path = geode_functions.upload_file_path(
|
|
88
|
-
flask.request.get_json()["filename"]
|
|
74
|
+
def allowed_objects() -> flask.Response:
|
|
75
|
+
json_data = utils_functions.validate_request(
|
|
76
|
+
flask.request, schemas_dict["allowed_objects"]
|
|
89
77
|
)
|
|
90
|
-
|
|
91
|
-
|
|
78
|
+
params = schemas.AllowedObjects.from_dict(json_data)
|
|
79
|
+
file_absolute_path = geode_functions.upload_file_path(params.filename)
|
|
80
|
+
file_extension = utils_functions.extension_from_filename(
|
|
81
|
+
os.path.basename(file_absolute_path)
|
|
92
82
|
)
|
|
83
|
+
allowed_objects = {}
|
|
84
|
+
for geode_object_type, geode_object in geode_objects.items():
|
|
85
|
+
if file_extension not in geode_object.input_extensions():
|
|
86
|
+
continue
|
|
87
|
+
loadability_score = geode_object.is_loadable(file_absolute_path)
|
|
88
|
+
priority_score = geode_object.object_priority(file_absolute_path)
|
|
89
|
+
allowed_objects[geode_object_type] = {
|
|
90
|
+
"is_loadable": loadability_score.value(),
|
|
91
|
+
"object_priority": priority_score,
|
|
92
|
+
}
|
|
93
93
|
return flask.make_response({"allowed_objects": allowed_objects}, 200)
|
|
94
94
|
|
|
95
95
|
|
|
96
|
-
with open(
|
|
97
|
-
os.path.join(schemas, "missing_files.json"),
|
|
98
|
-
"r",
|
|
99
|
-
) as file:
|
|
100
|
-
missing_files_json = json.load(file)
|
|
101
|
-
|
|
102
|
-
|
|
103
96
|
@routes.route(
|
|
104
|
-
|
|
105
|
-
methods=
|
|
97
|
+
schemas_dict["missing_files"]["route"],
|
|
98
|
+
methods=schemas_dict["missing_files"]["methods"],
|
|
106
99
|
)
|
|
107
|
-
def missing_files():
|
|
108
|
-
utils_functions.validate_request(
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
100
|
+
def missing_files() -> flask.Response:
|
|
101
|
+
json_data = utils_functions.validate_request(
|
|
102
|
+
flask.request, schemas_dict["missing_files"]
|
|
103
|
+
)
|
|
104
|
+
params = schemas.MissingFiles.from_dict(json_data)
|
|
105
|
+
file_path = geode_functions.upload_file_path(params.filename)
|
|
106
|
+
geode_object = geode_functions.geode_object_from_string(params.geode_object_type)
|
|
107
|
+
additional_files = geode_object.additional_files(
|
|
113
108
|
file_path,
|
|
114
109
|
)
|
|
115
|
-
|
|
116
110
|
has_missing_files = any(
|
|
117
111
|
file.is_missing
|
|
118
112
|
for file in additional_files.mandatory_files + additional_files.optional_files
|
|
119
113
|
)
|
|
120
|
-
|
|
121
114
|
mandatory_files = [
|
|
122
115
|
os.path.basename(file.filename)
|
|
123
116
|
for file in additional_files.mandatory_files
|
|
124
117
|
if file.is_missing
|
|
125
118
|
]
|
|
126
|
-
|
|
119
|
+
additional_files_array = [
|
|
127
120
|
os.path.basename(file.filename)
|
|
128
121
|
for file in additional_files.optional_files
|
|
129
122
|
if file.is_missing
|
|
@@ -133,27 +126,26 @@ def missing_files():
|
|
|
133
126
|
{
|
|
134
127
|
"has_missing_files": has_missing_files,
|
|
135
128
|
"mandatory_files": mandatory_files,
|
|
136
|
-
"additional_files":
|
|
129
|
+
"additional_files": additional_files_array,
|
|
137
130
|
},
|
|
138
131
|
200,
|
|
139
132
|
)
|
|
140
133
|
|
|
141
134
|
|
|
142
|
-
with open(
|
|
143
|
-
os.path.join(schemas, "geographic_coordinate_systems.json"),
|
|
144
|
-
"r",
|
|
145
|
-
) as file:
|
|
146
|
-
geographic_coordinate_systems_json = json.load(file)
|
|
147
|
-
|
|
148
|
-
|
|
149
135
|
@routes.route(
|
|
150
|
-
|
|
151
|
-
methods=
|
|
136
|
+
schemas_dict["geographic_coordinate_systems"]["route"],
|
|
137
|
+
methods=schemas_dict["geographic_coordinate_systems"]["methods"],
|
|
152
138
|
)
|
|
153
|
-
def crs_converter_geographic_coordinate_systems():
|
|
154
|
-
utils_functions.validate_request(
|
|
155
|
-
|
|
156
|
-
|
|
139
|
+
def crs_converter_geographic_coordinate_systems() -> flask.Response:
|
|
140
|
+
json_data = utils_functions.validate_request(
|
|
141
|
+
flask.request, schemas_dict["geographic_coordinate_systems"]
|
|
142
|
+
)
|
|
143
|
+
params = schemas.GeographicCoordinateSystems.from_dict(json_data)
|
|
144
|
+
geode_object = geode_functions.geode_object_from_string(params.geode_object_type)
|
|
145
|
+
infos = (
|
|
146
|
+
og_geosciences.GeographicCoordinateSystem3D.geographic_coordinate_systems()
|
|
147
|
+
if geode_object.is_3D()
|
|
148
|
+
else og_geosciences.GeographicCoordinateSystem2D.geographic_coordinate_systems()
|
|
157
149
|
)
|
|
158
150
|
crs_list = []
|
|
159
151
|
for info in infos:
|
|
@@ -162,59 +154,70 @@ def crs_converter_geographic_coordinate_systems():
|
|
|
162
154
|
crs["code"] = info.code
|
|
163
155
|
crs["authority"] = info.authority
|
|
164
156
|
crs_list.append(crs)
|
|
165
|
-
|
|
166
157
|
return flask.make_response({"crs_list": crs_list}, 200)
|
|
167
158
|
|
|
168
159
|
|
|
169
|
-
with open(
|
|
170
|
-
os.path.join(schemas, "inspect_file.json"),
|
|
171
|
-
"r",
|
|
172
|
-
) as file:
|
|
173
|
-
inspect_file_json = json.load(file)
|
|
174
|
-
|
|
175
|
-
|
|
176
160
|
@routes.route(
|
|
177
|
-
|
|
178
|
-
methods=
|
|
161
|
+
schemas_dict["inspect_file"]["route"],
|
|
162
|
+
methods=schemas_dict["inspect_file"]["methods"],
|
|
179
163
|
)
|
|
180
|
-
def inspect_file():
|
|
181
|
-
utils_functions.validate_request(
|
|
182
|
-
|
|
183
|
-
file_path = geode_functions.upload_file_path(flask.request.get_json()["filename"])
|
|
184
|
-
data = geode_functions.load(
|
|
185
|
-
flask.request.get_json()["input_geode_object"], file_path
|
|
186
|
-
)
|
|
187
|
-
class_inspector = geode_functions.inspect(
|
|
188
|
-
flask.request.get_json()["input_geode_object"], data
|
|
164
|
+
def inspect_file() -> flask.Response:
|
|
165
|
+
json_data = utils_functions.validate_request(
|
|
166
|
+
flask.request, schemas_dict["inspect_file"]
|
|
189
167
|
)
|
|
190
|
-
|
|
168
|
+
params = schemas.InspectFile.from_dict(json_data)
|
|
169
|
+
file_path = geode_functions.upload_file_path(params.filename)
|
|
170
|
+
geode_object = geode_functions.geode_object_from_string(
|
|
171
|
+
params.geode_object_type
|
|
172
|
+
).load(file_path)
|
|
173
|
+
inspection_data = geode_object.inspect()
|
|
174
|
+
inspection_result = extract_inspector_result(inspection_data)
|
|
191
175
|
return flask.make_response({"inspection_result": inspection_result}, 200)
|
|
192
176
|
|
|
193
177
|
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
178
|
+
def extract_inspector_result(inspection_data: Any) -> object:
|
|
179
|
+
new_object = {}
|
|
180
|
+
|
|
181
|
+
if hasattr(inspection_data, "inspection_type"):
|
|
182
|
+
new_object["title"] = inspection_data.inspection_type()
|
|
183
|
+
new_object["nb_issues"] = 0
|
|
184
|
+
new_object["children"] = []
|
|
185
|
+
for child in dir(inspection_data):
|
|
186
|
+
if child.startswith("__") or child in [
|
|
187
|
+
"inspection_type",
|
|
188
|
+
"string",
|
|
189
|
+
]:
|
|
190
|
+
continue
|
|
191
|
+
child_instance = getattr(inspection_data, child)
|
|
192
|
+
child_object = extract_inspector_result(child_instance)
|
|
193
|
+
new_object["children"].append(child_object)
|
|
194
|
+
if hasattr(child_object, "nb_issues"):
|
|
195
|
+
new_object["nb_issues"] += child_object.nb_issues()
|
|
196
|
+
else:
|
|
197
|
+
new_object["title"] = inspection_data.description()
|
|
198
|
+
nb_issues = inspection_data.nb_issues()
|
|
199
|
+
new_object["nb_issues"] = nb_issues
|
|
200
|
+
if nb_issues > 0:
|
|
201
|
+
issues = inspection_data.string().split("\n")
|
|
202
|
+
new_object["issues"] = issues
|
|
203
|
+
return new_object
|
|
199
204
|
|
|
200
205
|
|
|
201
206
|
@routes.route(
|
|
202
|
-
|
|
203
|
-
methods=
|
|
207
|
+
schemas_dict["geode_objects_and_output_extensions"]["route"],
|
|
208
|
+
methods=schemas_dict["geode_objects_and_output_extensions"]["methods"],
|
|
204
209
|
)
|
|
205
|
-
def geode_objects_and_output_extensions():
|
|
206
|
-
utils_functions.validate_request(
|
|
207
|
-
flask.request,
|
|
208
|
-
)
|
|
209
|
-
file_path = geode_functions.upload_file_path(flask.request.get_json()["filename"])
|
|
210
|
-
data = geode_functions.load(
|
|
211
|
-
flask.request.get_json()["input_geode_object"],
|
|
212
|
-
file_path,
|
|
210
|
+
def geode_objects_and_output_extensions() -> flask.Response:
|
|
211
|
+
json_data = utils_functions.validate_request(
|
|
212
|
+
flask.request, schemas_dict["geode_objects_and_output_extensions"]
|
|
213
213
|
)
|
|
214
|
+
params = schemas.GeodeObjectsAndOutputExtensions.from_dict(json_data)
|
|
215
|
+
file_path = geode_functions.upload_file_path(params.filename)
|
|
216
|
+
geode_object = geode_functions.geode_object_from_string(
|
|
217
|
+
params.geode_object_type
|
|
218
|
+
).load(file_path)
|
|
214
219
|
geode_objects_and_output_extensions = (
|
|
215
|
-
geode_functions.
|
|
216
|
-
flask.request.get_json()["input_geode_object"], data
|
|
217
|
-
)
|
|
220
|
+
geode_functions.geode_object_output_extensions(geode_object)
|
|
218
221
|
)
|
|
219
222
|
return flask.make_response(
|
|
220
223
|
{"geode_objects_and_output_extensions": geode_objects_and_output_extensions},
|
|
@@ -222,82 +225,53 @@ def geode_objects_and_output_extensions():
|
|
|
222
225
|
)
|
|
223
226
|
|
|
224
227
|
|
|
225
|
-
with open(
|
|
226
|
-
os.path.join(schemas, "save_viewable_file.json"),
|
|
227
|
-
"r",
|
|
228
|
-
) as file:
|
|
229
|
-
save_viewable_file_json = json.load(file)
|
|
230
|
-
|
|
231
|
-
|
|
232
228
|
@routes.route(
|
|
233
|
-
|
|
234
|
-
methods=
|
|
229
|
+
schemas_dict["save_viewable_file"]["route"],
|
|
230
|
+
methods=schemas_dict["save_viewable_file"]["methods"],
|
|
235
231
|
)
|
|
236
|
-
def save_viewable_file():
|
|
237
|
-
utils_functions.validate_request(
|
|
238
|
-
|
|
239
|
-
utils_functions.generate_native_viewable_and_light_viewable_from_file(
|
|
240
|
-
geode_object=flask.request.get_json()["input_geode_object"],
|
|
241
|
-
input_filename=flask.request.get_json()["filename"],
|
|
242
|
-
),
|
|
243
|
-
200,
|
|
232
|
+
def save_viewable_file() -> flask.Response:
|
|
233
|
+
json_data = utils_functions.validate_request(
|
|
234
|
+
flask.request, schemas_dict["save_viewable_file"]
|
|
244
235
|
)
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
with open(os.path.join(schemas, "create_point.json"), "r") as file:
|
|
248
|
-
create_point_json = json.load(file)
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
@routes.route(create_point_json["route"], methods=create_point_json["methods"])
|
|
252
|
-
def create_point():
|
|
253
|
-
utils_functions.validate_request(flask.request, create_point_json)
|
|
254
|
-
title = flask.request.get_json()["title"]
|
|
255
|
-
x = flask.request.get_json()["x"]
|
|
256
|
-
y = flask.request.get_json()["y"]
|
|
257
|
-
z = flask.request.get_json()["z"]
|
|
258
|
-
class_ = geode_functions.geode_object_class("PointSet3D")
|
|
259
|
-
PointSet3D = class_.create()
|
|
260
|
-
builder = geode_functions.create_builder("PointSet3D", PointSet3D)
|
|
261
|
-
builder.create_point(opengeode.Point3D([x, y, z]))
|
|
262
|
-
builder.set_name(title)
|
|
236
|
+
params = schemas.SaveViewableFile.from_dict(json_data)
|
|
263
237
|
return flask.make_response(
|
|
264
|
-
utils_functions.
|
|
265
|
-
|
|
238
|
+
utils_functions.generate_native_viewable_and_light_viewable_from_file(
|
|
239
|
+
geode_object_type=geode_object_type(params.geode_object_type),
|
|
240
|
+
input_file=params.filename,
|
|
266
241
|
),
|
|
267
242
|
200,
|
|
268
243
|
)
|
|
269
244
|
|
|
270
245
|
|
|
271
|
-
with open(os.path.join(schemas, "texture_coordinates.json"), "r") as file:
|
|
272
|
-
texture_coordinates_json = json.load(file)
|
|
273
|
-
|
|
274
|
-
|
|
275
246
|
@routes.route(
|
|
276
|
-
|
|
277
|
-
methods=
|
|
247
|
+
schemas_dict["texture_coordinates"]["route"],
|
|
248
|
+
methods=schemas_dict["texture_coordinates"]["methods"],
|
|
278
249
|
)
|
|
279
|
-
def texture_coordinates():
|
|
280
|
-
utils_functions.validate_request(
|
|
281
|
-
|
|
282
|
-
|
|
250
|
+
def texture_coordinates() -> flask.Response:
|
|
251
|
+
json_data = utils_functions.validate_request(
|
|
252
|
+
flask.request, schemas_dict["texture_coordinates"]
|
|
253
|
+
)
|
|
254
|
+
params = schemas.TextureCoordinates.from_dict(json_data)
|
|
255
|
+
geode_object = geode_functions.load_geode_object(params.id)
|
|
256
|
+
if not isinstance(geode_object, GeodeSurfaceMesh2D | GeodeSurfaceMesh3D):
|
|
257
|
+
flask.abort(400, f"{params.id} is not a GeodeSurfaceMesh")
|
|
258
|
+
texture_coordinates = geode_object.texture_manager().texture_names()
|
|
283
259
|
return flask.make_response({"texture_coordinates": texture_coordinates}, 200)
|
|
284
260
|
|
|
285
261
|
|
|
286
|
-
with open(
|
|
287
|
-
os.path.join(schemas, "vertex_attribute_names.json"),
|
|
288
|
-
"r",
|
|
289
|
-
) as file:
|
|
290
|
-
vertex_attribute_names_json = json.load(file)
|
|
291
|
-
|
|
292
|
-
|
|
293
262
|
@routes.route(
|
|
294
|
-
|
|
295
|
-
methods=
|
|
263
|
+
schemas_dict["vertex_attribute_names"]["route"],
|
|
264
|
+
methods=schemas_dict["vertex_attribute_names"]["methods"],
|
|
296
265
|
)
|
|
297
|
-
def vertex_attribute_names():
|
|
298
|
-
utils_functions.validate_request(
|
|
299
|
-
|
|
300
|
-
|
|
266
|
+
def vertex_attribute_names() -> flask.Response:
|
|
267
|
+
json_data = utils_functions.validate_request(
|
|
268
|
+
flask.request, schemas_dict["vertex_attribute_names"]
|
|
269
|
+
)
|
|
270
|
+
params = schemas.VertexAttributeNames.from_dict(json_data)
|
|
271
|
+
geode_object = geode_functions.load_geode_object(params.id)
|
|
272
|
+
if not isinstance(geode_object, GeodeMesh):
|
|
273
|
+
flask.abort(400, f"{params.id} is not a GeodeMesh")
|
|
274
|
+
vertex_attribute_names = geode_object.vertex_attribute_manager().attribute_names()
|
|
301
275
|
return flask.make_response(
|
|
302
276
|
{
|
|
303
277
|
"vertex_attribute_names": vertex_attribute_names,
|
|
@@ -306,21 +280,40 @@ def vertex_attribute_names():
|
|
|
306
280
|
)
|
|
307
281
|
|
|
308
282
|
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
"
|
|
312
|
-
)
|
|
313
|
-
|
|
283
|
+
@routes.route(
|
|
284
|
+
schemas_dict["cell_attribute_names"]["route"],
|
|
285
|
+
methods=schemas_dict["cell_attribute_names"]["methods"],
|
|
286
|
+
)
|
|
287
|
+
def cell_attribute_names() -> flask.Response:
|
|
288
|
+
json_data = utils_functions.validate_request(
|
|
289
|
+
flask.request, schemas_dict["cell_attribute_names"]
|
|
290
|
+
)
|
|
291
|
+
params = schemas.PolygonAttributeNames.from_dict(json_data)
|
|
292
|
+
geode_object = geode_functions.load_geode_object(params.id)
|
|
293
|
+
if not isinstance(geode_object, GeodeGrid2D | GeodeGrid3D):
|
|
294
|
+
flask.abort(400, f"{params.id} is not a GeodeGrid")
|
|
295
|
+
cell_attribute_names = geode_object.cell_attribute_manager().attribute_names()
|
|
296
|
+
return flask.make_response(
|
|
297
|
+
{
|
|
298
|
+
"cell_attribute_names": cell_attribute_names,
|
|
299
|
+
},
|
|
300
|
+
200,
|
|
301
|
+
)
|
|
314
302
|
|
|
315
303
|
|
|
316
304
|
@routes.route(
|
|
317
|
-
|
|
318
|
-
methods=
|
|
305
|
+
schemas_dict["polygon_attribute_names"]["route"],
|
|
306
|
+
methods=schemas_dict["polygon_attribute_names"]["methods"],
|
|
319
307
|
)
|
|
320
|
-
def polygon_attribute_names():
|
|
321
|
-
utils_functions.validate_request(
|
|
322
|
-
|
|
323
|
-
|
|
308
|
+
def polygon_attribute_names() -> flask.Response:
|
|
309
|
+
json_data = utils_functions.validate_request(
|
|
310
|
+
flask.request, schemas_dict["polygon_attribute_names"]
|
|
311
|
+
)
|
|
312
|
+
params = schemas.PolygonAttributeNames.from_dict(json_data)
|
|
313
|
+
geode_object = geode_functions.load_geode_object(params.id)
|
|
314
|
+
if not isinstance(geode_object, GeodeSurfaceMesh2D | GeodeSurfaceMesh3D):
|
|
315
|
+
flask.abort(400, f"{params.id} is not a GeodeSurfaceMesh")
|
|
316
|
+
polygon_attribute_names = geode_object.polygon_attribute_manager().attribute_names()
|
|
324
317
|
return flask.make_response(
|
|
325
318
|
{
|
|
326
319
|
"polygon_attribute_names": polygon_attribute_names,
|
|
@@ -329,21 +322,21 @@ def polygon_attribute_names():
|
|
|
329
322
|
)
|
|
330
323
|
|
|
331
324
|
|
|
332
|
-
with open(
|
|
333
|
-
os.path.join(schemas, "polyhedron_attribute_names.json"),
|
|
334
|
-
"r",
|
|
335
|
-
) as file:
|
|
336
|
-
polyhedron_attribute_names_json = json.load(file)
|
|
337
|
-
|
|
338
|
-
|
|
339
325
|
@routes.route(
|
|
340
|
-
|
|
341
|
-
methods=
|
|
326
|
+
schemas_dict["polyhedron_attribute_names"]["route"],
|
|
327
|
+
methods=schemas_dict["polyhedron_attribute_names"]["methods"],
|
|
342
328
|
)
|
|
343
|
-
def polyhedron_attribute_names():
|
|
344
|
-
utils_functions.validate_request(
|
|
345
|
-
|
|
346
|
-
|
|
329
|
+
def polyhedron_attribute_names() -> flask.Response:
|
|
330
|
+
json_data = utils_functions.validate_request(
|
|
331
|
+
flask.request, schemas_dict["polyhedron_attribute_names"]
|
|
332
|
+
)
|
|
333
|
+
params = schemas.PolyhedronAttributeNames.from_dict(json_data)
|
|
334
|
+
geode_object = geode_functions.load_geode_object(params.id)
|
|
335
|
+
if not isinstance(geode_object, GeodeSolidMesh3D):
|
|
336
|
+
flask.abort(400, f"{params.id} is not a GeodeSolidMesh")
|
|
337
|
+
polyhedron_attribute_names = (
|
|
338
|
+
geode_object.polyhedron_attribute_manager().attribute_names()
|
|
339
|
+
)
|
|
347
340
|
return flask.make_response(
|
|
348
341
|
{
|
|
349
342
|
"polyhedron_attribute_names": polyhedron_attribute_names,
|
|
@@ -352,32 +345,160 @@ def polyhedron_attribute_names():
|
|
|
352
345
|
)
|
|
353
346
|
|
|
354
347
|
|
|
355
|
-
with open(
|
|
356
|
-
os.path.join(schemas, "ping.json"),
|
|
357
|
-
"r",
|
|
358
|
-
) as file:
|
|
359
|
-
ping_json = json.load(file)
|
|
360
|
-
|
|
361
|
-
|
|
362
348
|
@routes.route(
|
|
363
|
-
|
|
364
|
-
methods=
|
|
349
|
+
schemas_dict["ping"]["route"],
|
|
350
|
+
methods=schemas_dict["ping"]["methods"],
|
|
365
351
|
)
|
|
366
|
-
def ping():
|
|
367
|
-
utils_functions.validate_request(flask.request,
|
|
352
|
+
def ping() -> flask.Response:
|
|
353
|
+
utils_functions.validate_request(flask.request, schemas_dict["ping"])
|
|
368
354
|
flask.current_app.config.update(LAST_PING_TIME=time.time())
|
|
369
355
|
return flask.make_response({"message": "Flask server is running"}, 200)
|
|
370
356
|
|
|
371
357
|
|
|
372
|
-
|
|
373
|
-
os.path.join(schemas, "kill.json"),
|
|
374
|
-
"r",
|
|
375
|
-
) as file:
|
|
376
|
-
kill_json = json.load(file)
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
@routes.route(kill_json["route"], methods=kill_json["methods"])
|
|
358
|
+
@routes.route(schemas_dict["kill"]["route"], methods=schemas_dict["kill"]["methods"])
|
|
380
359
|
def kill() -> flask.Response:
|
|
381
360
|
print("Manual server kill, shutting down...", flush=True)
|
|
382
361
|
os._exit(0)
|
|
383
362
|
return flask.make_response({"message": "Flask server is dead"}, 200)
|
|
363
|
+
|
|
364
|
+
|
|
365
|
+
@routes.route(
|
|
366
|
+
schemas_dict["export_project"]["route"],
|
|
367
|
+
methods=schemas_dict["export_project"]["methods"],
|
|
368
|
+
)
|
|
369
|
+
def export_project() -> flask.Response:
|
|
370
|
+
json_data = utils_functions.validate_request(
|
|
371
|
+
flask.request, schemas_dict["export_project"]
|
|
372
|
+
)
|
|
373
|
+
params = schemas.ExportProject.from_dict(json_data)
|
|
374
|
+
|
|
375
|
+
project_folder: str = flask.current_app.config["DATA_FOLDER_PATH"]
|
|
376
|
+
os.makedirs(project_folder, exist_ok=True)
|
|
377
|
+
|
|
378
|
+
filename: str = werkzeug.utils.secure_filename(os.path.basename(params.filename))
|
|
379
|
+
if not filename.lower().endswith(".vease"):
|
|
380
|
+
flask.abort(400, "Requested filename must end with .vease")
|
|
381
|
+
export_vease_path = os.path.join(project_folder, filename)
|
|
382
|
+
|
|
383
|
+
with get_session() as session:
|
|
384
|
+
rows = session.query(Data.id, Data.input_file, Data.additional_files).all()
|
|
385
|
+
|
|
386
|
+
with zipfile.ZipFile(
|
|
387
|
+
export_vease_path, "w", compression=zipfile.ZIP_DEFLATED
|
|
388
|
+
) as zip_file:
|
|
389
|
+
database_root_path = os.path.join(project_folder, "project.db")
|
|
390
|
+
if os.path.isfile(database_root_path):
|
|
391
|
+
zip_file.write(database_root_path, "project.db")
|
|
392
|
+
|
|
393
|
+
for data_id, input_file, additional_files in rows:
|
|
394
|
+
base_dir = os.path.join(project_folder, data_id)
|
|
395
|
+
|
|
396
|
+
input_path = os.path.join(base_dir, str(input_file))
|
|
397
|
+
if os.path.isfile(input_path):
|
|
398
|
+
zip_file.write(input_path, os.path.join(data_id, str(input_file)))
|
|
399
|
+
|
|
400
|
+
for relative_path in (
|
|
401
|
+
additional_files if isinstance(additional_files, list) else []
|
|
402
|
+
):
|
|
403
|
+
additional_path = os.path.join(base_dir, relative_path)
|
|
404
|
+
if os.path.isfile(additional_path):
|
|
405
|
+
zip_file.write(
|
|
406
|
+
additional_path, os.path.join(data_id, relative_path)
|
|
407
|
+
)
|
|
408
|
+
|
|
409
|
+
zip_file.writestr("snapshot.json", flask.json.dumps(params.snapshot))
|
|
410
|
+
|
|
411
|
+
return utils_functions.send_file(project_folder, [export_vease_path], filename)
|
|
412
|
+
|
|
413
|
+
|
|
414
|
+
@routes.route(
|
|
415
|
+
schemas_dict["import_project"]["route"],
|
|
416
|
+
methods=schemas_dict["import_project"]["methods"],
|
|
417
|
+
)
|
|
418
|
+
def import_project() -> flask.Response:
|
|
419
|
+
utils_functions.validate_request(flask.request, schemas_dict["import_project"])
|
|
420
|
+
if "file" not in flask.request.files:
|
|
421
|
+
flask.abort(400, "No .vease file provided under 'file'")
|
|
422
|
+
zip_file = flask.request.files["file"]
|
|
423
|
+
assert zip_file.filename is not None
|
|
424
|
+
filename = werkzeug.utils.secure_filename(os.path.basename(zip_file.filename))
|
|
425
|
+
if not filename.lower().endswith(".vease"):
|
|
426
|
+
flask.abort(400, "Uploaded file must be a .vease")
|
|
427
|
+
|
|
428
|
+
data_folder_path: str = flask.current_app.config["DATA_FOLDER_PATH"]
|
|
429
|
+
|
|
430
|
+
# 423 Locked bypass : remove stopped requests
|
|
431
|
+
if connection.scoped_session_registry:
|
|
432
|
+
connection.scoped_session_registry.remove()
|
|
433
|
+
if connection.engine:
|
|
434
|
+
connection.engine.dispose()
|
|
435
|
+
connection.engine = connection.session_factory = (
|
|
436
|
+
connection.scoped_session_registry
|
|
437
|
+
) = None
|
|
438
|
+
|
|
439
|
+
try:
|
|
440
|
+
if os.path.exists(data_folder_path):
|
|
441
|
+
shutil.rmtree(data_folder_path)
|
|
442
|
+
os.makedirs(data_folder_path, exist_ok=True)
|
|
443
|
+
except PermissionError:
|
|
444
|
+
flask.abort(423, "Project files are locked; cannot overwrite")
|
|
445
|
+
|
|
446
|
+
zip_file.stream.seek(0)
|
|
447
|
+
with zipfile.ZipFile(zip_file.stream) as zip_archive:
|
|
448
|
+
project_folder = os.path.abspath(data_folder_path)
|
|
449
|
+
for member in zip_archive.namelist():
|
|
450
|
+
target = os.path.abspath(
|
|
451
|
+
os.path.normpath(os.path.join(project_folder, member))
|
|
452
|
+
)
|
|
453
|
+
if not (
|
|
454
|
+
target == project_folder or target.startswith(project_folder + os.sep)
|
|
455
|
+
):
|
|
456
|
+
flask.abort(400, "Vease file contains unsafe paths")
|
|
457
|
+
zip_archive.extractall(project_folder)
|
|
458
|
+
|
|
459
|
+
database_root_path = os.path.join(project_folder, "project.db")
|
|
460
|
+
if not os.path.isfile(database_root_path):
|
|
461
|
+
flask.abort(400, "Missing project.db at project root")
|
|
462
|
+
|
|
463
|
+
connection.init_database(database_root_path, create_tables=False)
|
|
464
|
+
|
|
465
|
+
try:
|
|
466
|
+
with get_session() as session:
|
|
467
|
+
rows = session.query(Data).all()
|
|
468
|
+
except Exception:
|
|
469
|
+
connection.init_database(database_root_path, create_tables=True)
|
|
470
|
+
with get_session() as session:
|
|
471
|
+
rows = session.query(Data).all()
|
|
472
|
+
|
|
473
|
+
with get_session() as session:
|
|
474
|
+
for data in rows:
|
|
475
|
+
data_path = geode_functions.data_file_path(data.id)
|
|
476
|
+
viewable_name = data.viewable_file
|
|
477
|
+
if viewable_name:
|
|
478
|
+
vpath = geode_functions.data_file_path(data.id, viewable_name)
|
|
479
|
+
if os.path.isfile(vpath):
|
|
480
|
+
continue
|
|
481
|
+
|
|
482
|
+
input_file = str(data.input_file or "")
|
|
483
|
+
if not input_file:
|
|
484
|
+
continue
|
|
485
|
+
|
|
486
|
+
input_full = geode_functions.data_file_path(data.id, input_file)
|
|
487
|
+
if not os.path.isfile(input_full):
|
|
488
|
+
continue
|
|
489
|
+
|
|
490
|
+
geode_object = geode_functions.geode_object_from_string(
|
|
491
|
+
data.geode_object
|
|
492
|
+
).load(input_full)
|
|
493
|
+
utils_functions.save_all_viewables_and_return_info(
|
|
494
|
+
geode_object, data, data_path
|
|
495
|
+
)
|
|
496
|
+
session.commit()
|
|
497
|
+
|
|
498
|
+
snapshot = {}
|
|
499
|
+
try:
|
|
500
|
+
raw = zip_archive.read("snapshot.json").decode("utf-8")
|
|
501
|
+
snapshot = flask.json.loads(raw)
|
|
502
|
+
except KeyError:
|
|
503
|
+
snapshot = {}
|
|
504
|
+
return flask.make_response({"snapshot": snapshot}, 200)
|