Skip to content
Merged
Show file tree
Hide file tree
Changes from 16 commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
6223aab
feat(folder_path): data_folder generated with uuid
MaxNumerique Jul 23, 2025
878be26
Apply prepare changes
MaxNumerique Jul 23, 2025
d626e4a
fix args
MaxNumerique Jul 23, 2025
7847778
Merge branch 'feat/folder_path' of https://github.com/Geode-solutions…
MaxNumerique Jul 23, 2025
8017752
Apply prepare changes
MaxNumerique Jul 23, 2025
e6e3755
light_viewable removed
MaxNumerique Jul 23, 2025
9d7ea19
Merge branch 'feat/folder_path' of https://github.com/Geode-solutions…
MaxNumerique Jul 23, 2025
cf9589a
Generate a unique project UUID and create a dedicated upload director…
MaxNumerique Jul 23, 2025
5605db7
Merge branch 'feat/folder_path' of https://github.com/Geode-solutions…
MaxNumerique Jul 24, 2025
c1d3a9b
Validate folder path in test_generate_native_viewable_and_light_viewa…
MaxNumerique Jul 24, 2025
cd7d83f
folder_path halfway there. light_viewable missing still
MaxNumerique Jul 24, 2025
d504bc8
feat(folder_path): upload files ino upload folder into project folder…
MaxNumerique Jul 25, 2025
12bff86
id to mesh_components schema
MaxNumerique Jul 25, 2025
9027f76
revert changes to test function
MaxNumerique Jul 25, 2025
7451bf7
test modified to fit with new folder_path (refacto needed)
MaxNumerique Jul 25, 2025
7061126
Apply prepare changes
MaxNumerique Jul 28, 2025
a734e8a
id added to texture_coordinates, vertex_attribute_names, polygon_attr…
MaxNumerique Jul 29, 2025
061ecf4
Merge branch 'feat/folder_path' of https://github.com/Geode-solutions…
MaxNumerique Jul 29, 2025
5d13ad8
Apply prepare changes
MaxNumerique Jul 29, 2025
500906d
models_routes & test_models_routes adjusted to fit data/id/ path
MaxNumerique Jul 29, 2025
0e7d610
Merge branch 'feat/folder_path' of https://github.com/Geode-solutions…
MaxNumerique Jul 29, 2025
01469ec
Apply prepare changes
MaxNumerique Jul 29, 2025
a0022d8
geode_functions for refacto
MaxNumerique Jul 29, 2025
6544070
Merge branch 'feat/folder_path' of https://github.com/Geode-solutions…
MaxNumerique Jul 29, 2025
b312038
Apply prepare changes
MaxNumerique Jul 29, 2025
5ebb91d
test
MaxNumerique Jul 29, 2025
4c19434
Merge branch 'feat/folder_path' of https://github.com/Geode-solutions…
MaxNumerique Jul 29, 2025
1ccfa9b
Apply prepare changes
MaxNumerique Jul 29, 2025
eddbc9c
test
MaxNumerique Jul 29, 2025
b0c91a2
Merge branch 'feat/folder_path' of https://github.com/Geode-solutions…
MaxNumerique Jul 29, 2025
6085729
Apply prepare changes
MaxNumerique Jul 29, 2025
e8596a3
test
MaxNumerique Jul 29, 2025
1c3305c
Apply prepare changes
MaxNumerique Jul 29, 2025
01fa755
test
MaxNumerique Jul 29, 2025
a3c4016
Merge branch 'feat/folder_path' of https://github.com/Geode-solutions…
MaxNumerique Jul 29, 2025
d37e32a
Apply prepare changes
MaxNumerique Jul 29, 2025
4d9f503
test
MaxNumerique Jul 29, 2025
094b85e
Merge branch 'feat/folder_path' of https://github.com/Geode-solutions…
MaxNumerique Jul 29, 2025
5612c04
Apply prepare changes
MaxNumerique Jul 29, 2025
5a81dd2
Refactored blueprints_routes and blueprint_models for improved organi…
MaxNumerique Jul 30, 2025
86d0a0c
Apply prepare changes
MaxNumerique Jul 30, 2025
5195202
add shared var for both pytest.fixture
MaxNumerique Jul 30, 2025
605b59e
removed try/catch
MaxNumerique Jul 30, 2025
e74b50f
Apply prepare changes
MaxNumerique Jul 30, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,5 @@ __pycache__
.vscode
uploads
node_modules
schemas.json
schemas.json
tmp
8 changes: 3 additions & 5 deletions src/opengeodeweb_back/routes/blueprint_routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ def upload_file():

UPLOAD_FOLDER = flask.current_app.config["UPLOAD_FOLDER"]
if not os.path.exists(UPLOAD_FOLDER):
os.mkdir(UPLOAD_FOLDER)
os.makedirs(UPLOAD_FOLDER)
file = flask.request.files["file"]
filename = werkzeug.utils.secure_filename(os.path.basename(file.filename))
file.save(os.path.join(UPLOAD_FOLDER, filename))
Expand Down Expand Up @@ -242,13 +242,12 @@ def geode_objects_and_output_extensions():
def save_viewable_file():
utils_functions.validate_request(flask.request, save_viewable_file_json)
UPLOAD_FOLDER = flask.current_app.config["UPLOAD_FOLDER"]
DATA_FOLDER_PATH = flask.current_app.config["DATA_FOLDER_PATH"]
secure_filename = werkzeug.utils.secure_filename(flask.request.json["filename"])
file_path = os.path.abspath(os.path.join(UPLOAD_FOLDER, secure_filename))
data = geode_functions.load(flask.request.json["input_geode_object"], file_path)
return flask.make_response(
utils_functions.generate_native_viewable_and_light_viewable(
flask.request.json["input_geode_object"], data, DATA_FOLDER_PATH
flask.request.json["input_geode_object"], data
),
200,
)
Expand All @@ -261,7 +260,6 @@ def save_viewable_file():
@routes.route(create_point_json["route"], methods=create_point_json["methods"])
def create_point():
utils_functions.validate_request(flask.request, create_point_json)
DATA_FOLDER_PATH = flask.current_app.config["DATA_FOLDER_PATH"]
title = flask.request.json["title"]
x = flask.request.json["x"]
y = flask.request.json["y"]
Expand All @@ -273,7 +271,7 @@ def create_point():
builder.set_name(title)
return flask.make_response(
utils_functions.generate_native_viewable_and_light_viewable(
"PointSet3D", PointSet3D, DATA_FOLDER_PATH
"PointSet3D", PointSet3D
),
200,
)
Expand Down
8 changes: 6 additions & 2 deletions src/opengeodeweb_back/routes/models/blueprint_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@
def uuid_to_flat_index():
utils_functions.validate_request(flask.request, vtm_component_indices_json)
vtm_file_path = os.path.join(
flask.current_app.config["DATA_FOLDER_PATH"], flask.request.json["id"] + ".vtm"
flask.current_app.config["DATA_FOLDER_PATH"],
flask.request.json["id"],
"viewable.vtm",
)
tree = ET.parse(vtm_file_path)
root = tree.find("vtkMultiBlockDataSet")
Expand Down Expand Up @@ -59,7 +61,9 @@ def extract_model_uuids(geode_object, file_path):
def extract_uuids_endpoint():
utils_functions.validate_request(flask.request, mesh_components_json)
file_path = os.path.join(
flask.current_app.config["DATA_FOLDER_PATH"], flask.request.json["filename"]
flask.current_app.config["DATA_FOLDER_PATH"],
flask.request.json["id"],
flask.request.json["filename"],
)
if not os.path.exists(file_path):
return flask.make_response({"error": "File not found"}, 404)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
],
"type": "object",
"properties": {
"id": {
"type": "string"
},
"filename": {
"type": "string"
},
Expand All @@ -13,6 +16,7 @@
}
},
"required": [
"id",
"filename",
"geode_object"
],
Expand Down
17 changes: 9 additions & 8 deletions src/opengeodeweb_back/utils_functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -143,24 +143,25 @@ def handle_exception(e):
return response


def generate_native_viewable_and_light_viewable(
geode_object, data, folder_absolute_path
):
def generate_native_viewable_and_light_viewable(geode_object, data):
generated_id = str(uuid.uuid4()).replace("-", "")
DATA_FOLDER_PATH = flask.current_app.config["DATA_FOLDER_PATH"]
data_path = os.path.join(DATA_FOLDER_PATH, generated_id)
name = data.name()
object_type = geode_functions.get_object_type(geode_object)

saved_native_file_path = geode_functions.save(
geode_object,
data,
folder_absolute_path,
generated_id + "." + data.native_extension(),
data_path,
"native." + data.native_extension(),
)
saved_viewable_file_path = geode_functions.save_viewable(
geode_object, data, folder_absolute_path, generated_id
geode_object, data, data_path, "viewable"
)
viewable_file_name = os.path.basename(saved_viewable_file_path)
saved_light_viewable_file_path = geode_functions.save_light_viewable(
geode_object, data, folder_absolute_path, "light_" + generated_id
geode_object, data, data_path, "light_viewable"
)
f = open(saved_light_viewable_file_path, "rb")
binary_light_viewable = f.read()
Expand All @@ -169,7 +170,7 @@ def generate_native_viewable_and_light_viewable(
return {
"name": name,
"native_file_name": os.path.basename(saved_native_file_path[0]),
"viewable_file_name": os.path.basename(saved_viewable_file_path),
"viewable_file_name": viewable_file_name,
"id": generated_id,
"object_type": object_type,
"binary_light_viewable": str(binary_light_viewable, "utf-8"),
Expand Down
23 changes: 23 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
# Standard library imports
import time
import shutil
import os

# Third party imports
import pytest
import uuid

# Local application imports
from app import app
Expand Down Expand Up @@ -31,3 +33,24 @@ def client():
def app_context():
with app.app_context():
yield


@pytest.fixture
def uuid_project_structure():
uuid_project = uuid.uuid4().hex
uuid_data = uuid.uuid4().hex

base_path = os.path.join("tmp", "vease", uuid_project)
data_path = os.path.join(base_path, uuid_data)
uploads_path = os.path.join(base_path, "uploads")

os.makedirs(data_path, exist_ok=True)
os.makedirs(uploads_path, exist_ok=True)

return {
"uuid_project": uuid_project,
"uuid_data": uuid_data,
"base_path": base_path,
"data_path": data_path,
"uploads_path": uploads_path,
}
77 changes: 52 additions & 25 deletions tests/test_models_routes.py
Original file line number Diff line number Diff line change
@@ -1,30 +1,57 @@
def test_model_mesh_components(client):
route = f"/models/vtm_component_indices"
get_full_data = lambda: {"id": "cube"}
json = get_full_data()
response = client.post(route, json=json)
assert response.status_code == 200
import shutil
import os

uuid_dict = response.json["uuid_to_flat_index"]
assert isinstance(uuid_dict, dict)

indices = list(uuid_dict.values())
indices.sort()
assert all(indices[i] > indices[i - 1] for i in range(1, len(indices)))
for uuid in uuid_dict.keys():
assert isinstance(uuid, str)
def test_model_mesh_components(client, uuid_project_structure):
route = "/models/vtm_component_indices"
uuid_data = uuid_project_structure["uuid_data"]
data_path = uuid_project_structure["data_path"]

shutil.copy("./tests/data/cube.vtm", os.path.join(data_path, "viewable.vtm"))

def test_extract_brep_uuids(client):
original_path = client.application.config["DATA_FOLDER_PATH"]
client.application.config["DATA_FOLDER_PATH"] = uuid_project_structure["base_path"]

try:
response = client.post(route, json={"id": uuid_data})
assert response.status_code == 200
uuid_dict = response.json["uuid_to_flat_index"]
assert isinstance(uuid_dict, dict)

indices = list(uuid_dict.values())
indices.sort()
assert all(indices[i] > indices[i - 1] for i in range(1, len(indices)))
for uuid_key in uuid_dict.keys():
assert isinstance(uuid_key, str)
finally:
client.application.config["DATA_FOLDER_PATH"] = original_path


def test_extract_brep_uuids(client, uuid_project_structure):
route = "/models/mesh_components"
json_data = {"filename": "cube.og_brep", "geode_object": "BRep"}
response = client.post(route, json=json_data)

assert response.status_code == 200
uuid_dict = response.json["uuid_dict"]
assert isinstance(uuid_dict, dict)
expected_keys = {"Block", "Line", "Surface", "Corner"}
assert any(key in uuid_dict for key in expected_keys)
for key, value in uuid_dict.items():
assert isinstance(value, list)
assert all(isinstance(v, str) for v in value)
uuid_data = uuid_project_structure["uuid_data"]
data_path = uuid_project_structure["data_path"]

shutil.copy("./tests/data/cube.og_brep", os.path.join(data_path, "cube.og_brep"))

original_path = client.application.config["DATA_FOLDER_PATH"]
client.application.config["DATA_FOLDER_PATH"] = uuid_project_structure["base_path"]

try:
json_data = {
"filename": "cube.og_brep",
"geode_object": "BRep",
"id": uuid_data,
}
response = client.post(route, json=json_data)
assert response.status_code == 200

uuid_dict = response.json["uuid_dict"]
assert isinstance(uuid_dict, dict)
expected_keys = {"Block", "Line", "Surface", "Corner"}
assert any(key in uuid_dict for key in expected_keys)
for key, value in uuid_dict.items():
assert isinstance(value, list)
assert all(isinstance(v, str) for v in value)
finally:
client.application.config["DATA_FOLDER_PATH"] = original_path
24 changes: 12 additions & 12 deletions tests/test_utils_functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,22 +71,22 @@ def test_handle_exception(client):
assert type(data["code"]) is int


def test_generate_native_viewable_and_light_viewable():
geode_object = "BRep"
folder_absolute_path = os.path.abspath("./data")
data = geode_functions.load(
geode_object, os.path.join(folder_absolute_path, "test.og_brep")
)
folder_absolute_path = "None"
result = utils_functions.generate_native_viewable_and_light_viewable(
geode_object, data, folder_absolute_path
)
def test_generate_native_viewable_and_light_viewable(client):
app = client.application
with app.app_context():
geode_object = "BRep"
data = geode_functions.load(geode_object, "./tests/data/test.og_brep")

result = utils_functions.generate_native_viewable_and_light_viewable(
geode_object, data
)

assert type(result) is dict
assert type(result["name"]) is str
assert type(result["native_file_name"]) is str
assert re.match(r"[0-9a-f]{32}\.[a-zA-Z0-9]+", result["native_file_name"])
assert result["native_file_name"] == "native.og_brep"
assert type(result["viewable_file_name"]) is str
assert re.match(r"[0-9a-f]{32}\.[a-zA-Z0-9]+", result["viewable_file_name"])
assert result["viewable_file_name"] == "viewable.vtm"
assert type(result["id"]) is str
assert re.match(r"[0-9a-f]{32}", result["id"])
assert type(result["object_type"]) is str
Expand Down