OpenGeodeWeb-Back 5.10.0rc6__py3-none-any.whl → 5.10.0rc8__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.
@@ -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
- DATA_FOLDER_PATH = "./data/"
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
@@ -2,7 +2,6 @@
2
2
  import os
3
3
  import threading
4
4
  import time
5
- import uuid
6
5
  import zipfile
7
6
  from collections.abc import Callable
8
7
  from typing import Any
@@ -17,6 +16,8 @@ import werkzeug
17
16
 
18
17
  # Local application imports
19
18
  from . import geode_functions
19
+ from .data import Data
20
+ from .database import database
20
21
 
21
22
 
22
23
  def increment_request_counter(current_app: flask.Flask) -> None:
@@ -152,17 +153,29 @@ def handle_exception(exception: HTTPException) -> flask.Response:
152
153
  return response
153
154
 
154
155
 
155
- def create_unique_data_folder() -> tuple[str, str]:
156
+ def create_data_folder_from_id(data_id: str) -> str:
156
157
  base_data_folder = flask.current_app.config["DATA_FOLDER_PATH"]
157
- generated_id = str(uuid.uuid4()).replace("-", "")
158
- data_path = os.path.join(base_data_folder, generated_id)
158
+ data_path = os.path.join(base_data_folder, data_id)
159
159
  os.makedirs(data_path, exist_ok=True)
160
- return generated_id, data_path
160
+ return data_path
161
161
 
162
162
 
163
163
  def save_all_viewables_and_return_info(
164
- geode_object, data, generated_id, data_path, additional_files=None
165
- ):
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)
166
179
  saved_native_file_path = geode_functions.save(
167
180
  geode_object,
168
181
  data,
@@ -177,28 +190,42 @@ def save_all_viewables_and_return_info(
177
190
  )
178
191
  with open(saved_light_viewable_file_path, "rb") as f:
179
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()
180
198
 
181
199
  return {
182
- "name": data.name(),
183
- "native_file_name": os.path.basename(saved_native_file_path[0]),
184
- "viewable_file_name": os.path.basename(saved_viewable_file_path),
185
- "id": generated_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,
186
204
  "object_type": geode_functions.get_object_type(geode_object),
187
205
  "binary_light_viewable": binary_light_viewable.decode("utf-8"),
188
- "geode_object": geode_object,
189
- "input_files": additional_files or [],
206
+ "geode_object": data_entry.geode_object,
207
+ "input_files": data_entry.input_file,
208
+ "additional_files": data_entry.additional_files,
190
209
  }
191
210
 
192
211
 
193
- def generate_native_viewable_and_light_viewable_from_object(geode_object, data):
194
- generated_id, data_path = create_unique_data_folder()
195
- return save_all_viewables_and_return_info(
196
- geode_object, data, generated_id, data_path
197
- )
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="")
198
216
 
199
217
 
200
- def generate_native_viewable_and_light_viewable_from_file(geode_object, input_filename):
201
- generated_id, data_path = create_unique_data_folder()
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)
202
229
 
203
230
  full_input_filename = geode_functions.upload_file_path(input_filename)
204
231
  copied_full_path = os.path.join(
@@ -206,7 +233,7 @@ def generate_native_viewable_and_light_viewable_from_file(geode_object, input_fi
206
233
  )
207
234
  shutil.copy2(full_input_filename, copied_full_path)
208
235
 
209
- additional_files_copied = []
236
+ additional_files_copied: list[str] = []
210
237
  additional = geode_functions.additional_files(geode_object, full_input_filename)
211
238
  for additional_file in additional.mandatory_files + additional.optional_files:
212
239
  if additional_file.is_missing:
@@ -221,12 +248,14 @@ def generate_native_viewable_and_light_viewable_from_file(geode_object, input_fi
221
248
  shutil.copy2(source_path, dest_path)
222
249
  additional_files_copied.append(additional_file.filename)
223
250
 
224
- data = geode_functions.load_data(geode_object, generated_id, input_filename)
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()
225
255
 
226
256
  return save_all_viewables_and_return_info(
227
257
  geode_object,
228
258
  data,
229
- generated_id,
230
- data_path,
259
+ input_file=input_filename,
231
260
  additional_files=additional_files_copied,
232
261
  )
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: OpenGeodeWeb-Back
3
- Version: 5.10.0rc6
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
 
@@ -1,9 +1,11 @@
1
1
  opengeodeweb_back/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- opengeodeweb_back/app_config.py,sha256=gJfYxDJOa_PYLqjqgdXacp3W3F109uujE9LGPvzHOkc,728
2
+ opengeodeweb_back/app_config.py,sha256=XFl5KqrOWifVxdudiLm-LXmczYDBCbZtNboSYnNbLf8,1142
3
+ opengeodeweb_back/data.py,sha256=6705K-Z6amrsCYxeYFEbYJa6d4SjvPbqZbr7X7ziZCU,1552
4
+ opengeodeweb_back/database.py,sha256=lXbbJRZCdqLcQU-Xqi1jPmo8cIitbHOqUJW5uLBF85w,381
3
5
  opengeodeweb_back/geode_functions.py,sha256=1Y7o3NjGJxoW1O2s4KEIZ1C5tN5x-EqPNGVnIPzi-Ak,10208
4
6
  opengeodeweb_back/geode_objects.py,sha256=uXCKX8AOdXkItqmYItLnFfHcIBiMFaeN_WmGs4j64Ro,27782
5
7
  opengeodeweb_back/test_utils.py,sha256=18AbRW9-tfKkPcmRGilTTHXI7S3armYyV7Vdy5UvUKM,794
6
- opengeodeweb_back/utils_functions.py,sha256=LGff8qlAnpJ2AI2XRF7YFTWNFwnrrl_ddKuMi7buwx4,7676
8
+ opengeodeweb_back/utils_functions.py,sha256=KAlXp689N-51RXSAdBiDylVBeeozY_rzDBGH1VgqH6w,8543
7
9
  opengeodeweb_back/routes/blueprint_routes.py,sha256=3fxMR9fs0BqnOiYhKFacGdxWm7JFLz5i5PvUqYgB5z4,11308
8
10
  opengeodeweb_back/routes/models/blueprint_models.py,sha256=PAyHSKjsvVm5gGfjUyWAnODmE0BJMsIWc1AWl0F3bO0,1955
9
11
  opengeodeweb_back/routes/models/schemas/mesh_components.json,sha256=3OQvI4pUCe77WGC46tEr37rEWigQ6n2nsfGUTZRY074,419
@@ -22,8 +24,8 @@ opengeodeweb_back/routes/schemas/save_viewable_file.json,sha256=pvvEdaC7bNASPMrl
22
24
  opengeodeweb_back/routes/schemas/texture_coordinates.json,sha256=oW84Vh34KfleK935fmMXnqJXy-vaLDd7g87O_PtSzfY,429
23
25
  opengeodeweb_back/routes/schemas/upload_file.json,sha256=LJ3U3L5ApKuQDVFIpVT_y2alq4HW_suTvZ3HUucNbhg,219
24
26
  opengeodeweb_back/routes/schemas/vertex_attribute_names.json,sha256=bmXG0pzVHMUTZY_0iu6ruX7eMUVk8wr2H1o4eEtBlg0,432
25
- opengeodeweb_back-5.10.0rc6.dist-info/licenses/LICENSE,sha256=LoTB-aqQvzTGxoTRXNnhNV0LKiqdk2bQv6MB34l8zkI,1079
26
- opengeodeweb_back-5.10.0rc6.dist-info/METADATA,sha256=A9HvSi33ZOiIF50sSHtqlI1Ml0yno415I1wIpVFm-xE,2676
27
- opengeodeweb_back-5.10.0rc6.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
28
- opengeodeweb_back-5.10.0rc6.dist-info/top_level.txt,sha256=tN1FZeLIVBrdja2-pbmhg5-tK-JILmmT9OeIBnhlUrQ,18
29
- opengeodeweb_back-5.10.0rc6.dist-info/RECORD,,
27
+ opengeodeweb_back-5.10.0rc8.dist-info/licenses/LICENSE,sha256=LoTB-aqQvzTGxoTRXNnhNV0LKiqdk2bQv6MB34l8zkI,1079
28
+ opengeodeweb_back-5.10.0rc8.dist-info/METADATA,sha256=Ra3r2pMEyjKTkKGk7vNfOk54CJb5Kmmn8S1xNqEex5Y,2821
29
+ opengeodeweb_back-5.10.0rc8.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
30
+ opengeodeweb_back-5.10.0rc8.dist-info/top_level.txt,sha256=tN1FZeLIVBrdja2-pbmhg5-tK-JILmmT9OeIBnhlUrQ,18
31
+ opengeodeweb_back-5.10.0rc8.dist-info/RECORD,,