OpenGeodeWeb-Back 5.10.1__py3-none-any.whl → 5.10.3__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.
Potentially problematic release.
This version of OpenGeodeWeb-Back might be problematic. Click here for more details.
- opengeodeweb_back/app.py +157 -0
- opengeodeweb_back/app_config.py +1 -10
- opengeodeweb_back/routes/blueprint_routes.py +14 -0
- opengeodeweb_back/routes/schemas/kill.json +10 -0
- opengeodeweb_back/utils_functions.py +4 -7
- {opengeodeweb_back-5.10.1.dist-info → opengeodeweb_back-5.10.3.dist-info}/METADATA +11 -16
- {opengeodeweb_back-5.10.1.dist-info → opengeodeweb_back-5.10.3.dist-info}/RECORD +11 -8
- opengeodeweb_back-5.10.3.dist-info/entry_points.txt +2 -0
- {opengeodeweb_back-5.10.1.dist-info → opengeodeweb_back-5.10.3.dist-info}/WHEEL +0 -0
- {opengeodeweb_back-5.10.1.dist-info → opengeodeweb_back-5.10.3.dist-info}/licenses/LICENSE +0 -0
- {opengeodeweb_back-5.10.1.dist-info → opengeodeweb_back-5.10.3.dist-info}/top_level.txt +0 -0
opengeodeweb_back/app.py
ADDED
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
"""Packages"""
|
|
2
|
+
|
|
3
|
+
import argparse
|
|
4
|
+
import os
|
|
5
|
+
import time
|
|
6
|
+
from typing import Any
|
|
7
|
+
|
|
8
|
+
import flask
|
|
9
|
+
import flask_cors # type: ignore
|
|
10
|
+
from flask import Flask, Response
|
|
11
|
+
from flask_cors import cross_origin
|
|
12
|
+
from werkzeug.exceptions import HTTPException
|
|
13
|
+
|
|
14
|
+
from opengeodeweb_back import utils_functions, app_config
|
|
15
|
+
from opengeodeweb_back.routes import blueprint_routes
|
|
16
|
+
from opengeodeweb_back.routes.models import blueprint_models
|
|
17
|
+
from opengeodeweb_microservice.database.connection import init_database
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
""" Global config """
|
|
21
|
+
app: Flask = flask.Flask(__name__)
|
|
22
|
+
|
|
23
|
+
""" Config variables """
|
|
24
|
+
FLASK_DEBUG = True if os.environ.get("FLASK_DEBUG", default=None) == "True" else False
|
|
25
|
+
|
|
26
|
+
if FLASK_DEBUG == False:
|
|
27
|
+
app.config.from_object(app_config.ProdConfig)
|
|
28
|
+
else:
|
|
29
|
+
app.config.from_object(app_config.DevConfig)
|
|
30
|
+
|
|
31
|
+
DEFAULT_HOST: str = app.config.get("DEFAULT_HOST") or "localhost"
|
|
32
|
+
DEFAULT_PORT: int = int(app.config.get("DEFAULT_PORT") or 5000)
|
|
33
|
+
DEFAULT_DATA_FOLDER_PATH: str = app.config.get("DEFAULT_DATA_FOLDER_PATH") or "./data"
|
|
34
|
+
ORIGINS: Any = app.config.get("ORIGINS")
|
|
35
|
+
TIMEOUT: int = int(app.config.get("MINUTES_BEFORE_TIMEOUT") or 30)
|
|
36
|
+
SSL: Any = app.config.get("SSL")
|
|
37
|
+
SECONDS_BETWEEN_SHUTDOWNS: float = float(
|
|
38
|
+
app.config.get("SECONDS_BETWEEN_SHUTDOWNS") or 60.0
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
app.register_blueprint(
|
|
43
|
+
blueprint_routes.routes,
|
|
44
|
+
url_prefix="/opengeodeweb_back",
|
|
45
|
+
name="opengeodeweb_back",
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
app.register_blueprint(
|
|
49
|
+
blueprint_models.routes,
|
|
50
|
+
url_prefix="/opengeodeweb_back/models",
|
|
51
|
+
name="opengeodeweb_models",
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
if FLASK_DEBUG == False:
|
|
55
|
+
utils_functions.set_interval(
|
|
56
|
+
utils_functions.kill_task, SECONDS_BETWEEN_SHUTDOWNS, app
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
@app.errorhandler(HTTPException)
|
|
61
|
+
def errorhandler(e: HTTPException) -> tuple[dict[str, Any], int] | Response:
|
|
62
|
+
return utils_functions.handle_exception(e)
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
@app.route(
|
|
66
|
+
"/error",
|
|
67
|
+
methods=["POST"],
|
|
68
|
+
)
|
|
69
|
+
def return_error() -> Response:
|
|
70
|
+
flask.abort(500, f"Test")
|
|
71
|
+
return flask.make_response({}, 500)
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
@app.route("/", methods=["POST"])
|
|
75
|
+
@cross_origin()
|
|
76
|
+
def root() -> Response:
|
|
77
|
+
return flask.make_response({}, 200)
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
@app.route("/kill", methods=["POST"])
|
|
81
|
+
@cross_origin()
|
|
82
|
+
def kill() -> None:
|
|
83
|
+
print("Manual server kill, shutting down...", flush=True)
|
|
84
|
+
os._exit(0)
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def run_server() -> None:
|
|
88
|
+
parser = argparse.ArgumentParser(
|
|
89
|
+
prog="OpenGeodeWeb-Back", description="Backend server for OpenGeodeWeb"
|
|
90
|
+
)
|
|
91
|
+
parser.add_argument("--host", type=str, default=DEFAULT_HOST, help="Host to run on")
|
|
92
|
+
parser.add_argument(
|
|
93
|
+
"-p", "--port", type=int, default=DEFAULT_PORT, help="Port to listen on"
|
|
94
|
+
)
|
|
95
|
+
parser.add_argument(
|
|
96
|
+
"-d",
|
|
97
|
+
"--debug",
|
|
98
|
+
default=FLASK_DEBUG,
|
|
99
|
+
help="Whether to run in debug mode",
|
|
100
|
+
action="store_true",
|
|
101
|
+
)
|
|
102
|
+
parser.add_argument(
|
|
103
|
+
"-dfp",
|
|
104
|
+
"--data_folder_path",
|
|
105
|
+
type=str,
|
|
106
|
+
default=DEFAULT_DATA_FOLDER_PATH,
|
|
107
|
+
help="Path to the folder where data is stored",
|
|
108
|
+
)
|
|
109
|
+
parser.add_argument(
|
|
110
|
+
"-ufp",
|
|
111
|
+
"--upload_folder_path",
|
|
112
|
+
type=str,
|
|
113
|
+
default=DEFAULT_DATA_FOLDER_PATH,
|
|
114
|
+
help="Path to the folder where uploads are stored",
|
|
115
|
+
)
|
|
116
|
+
parser.add_argument(
|
|
117
|
+
"-origins",
|
|
118
|
+
"--allowed_origins",
|
|
119
|
+
default=ORIGINS,
|
|
120
|
+
help="Origins that are allowed to connect to the server",
|
|
121
|
+
)
|
|
122
|
+
parser.add_argument(
|
|
123
|
+
"-t",
|
|
124
|
+
"--timeout",
|
|
125
|
+
default=TIMEOUT,
|
|
126
|
+
help="Number of minutes before the server times out",
|
|
127
|
+
)
|
|
128
|
+
args = parser.parse_args()
|
|
129
|
+
|
|
130
|
+
app.config.update(DATA_FOLDER_PATH=args.data_folder_path)
|
|
131
|
+
app.config.update(UPLOAD_FOLDER=args.upload_folder_path)
|
|
132
|
+
app.config.update(MINUTES_BEFORE_TIMEOUT=args.timeout)
|
|
133
|
+
|
|
134
|
+
flask_cors.CORS(app, origins=args.allowed_origins)
|
|
135
|
+
|
|
136
|
+
print(
|
|
137
|
+
f"Host: {args.host}, Port: {args.port}, Debug: {args.debug}, "
|
|
138
|
+
f"Data folder path: {args.data_folder_path}, Timeout: {args.timeout}, "
|
|
139
|
+
f"Origins: {args.allowed_origins}",
|
|
140
|
+
flush=True,
|
|
141
|
+
)
|
|
142
|
+
|
|
143
|
+
db_filename: str = app.config.get("DATABASE_FILENAME") or "project.db"
|
|
144
|
+
db_path = os.path.join(args.data_folder_path, db_filename)
|
|
145
|
+
os.makedirs(os.path.dirname(db_path), exist_ok=True)
|
|
146
|
+
app.config["SQLALCHEMY_DATABASE_URI"] = f"sqlite:///{db_path}"
|
|
147
|
+
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False
|
|
148
|
+
|
|
149
|
+
init_database(db_path)
|
|
150
|
+
print(f"Database initialized at: {db_path}", flush=True)
|
|
151
|
+
|
|
152
|
+
app.run(debug=args.debug, host=args.host, port=args.port, ssl_context=SSL)
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
# ''' Main '''
|
|
156
|
+
if __name__ == "__main__":
|
|
157
|
+
run_server()
|
opengeodeweb_back/app_config.py
CHANGED
|
@@ -4,9 +4,6 @@ import time
|
|
|
4
4
|
|
|
5
5
|
# Third party imports
|
|
6
6
|
# Local application imports
|
|
7
|
-
from opengeodeweb_microservice.database.connection import get_database
|
|
8
|
-
|
|
9
|
-
DATABASE_FILENAME = "project.db"
|
|
10
7
|
|
|
11
8
|
|
|
12
9
|
class Config(object):
|
|
@@ -18,7 +15,7 @@ class Config(object):
|
|
|
18
15
|
REQUEST_COUNTER = 0
|
|
19
16
|
LAST_REQUEST_TIME = time.time()
|
|
20
17
|
LAST_PING_TIME = time.time()
|
|
21
|
-
|
|
18
|
+
DATABASE_FILENAME = "project.db"
|
|
22
19
|
|
|
23
20
|
|
|
24
21
|
class ProdConfig(Config):
|
|
@@ -27,9 +24,6 @@ class ProdConfig(Config):
|
|
|
27
24
|
MINUTES_BEFORE_TIMEOUT = "1"
|
|
28
25
|
SECONDS_BETWEEN_SHUTDOWNS = "10"
|
|
29
26
|
DATA_FOLDER_PATH = "/data"
|
|
30
|
-
SQLALCHEMY_DATABASE_URI = f"sqlite:///{os.path.abspath(
|
|
31
|
-
os.path.join(DATA_FOLDER_PATH, DATABASE_FILENAME)
|
|
32
|
-
)}"
|
|
33
27
|
|
|
34
28
|
|
|
35
29
|
class DevConfig(Config):
|
|
@@ -39,6 +33,3 @@ class DevConfig(Config):
|
|
|
39
33
|
SECONDS_BETWEEN_SHUTDOWNS = "10"
|
|
40
34
|
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
|
|
41
35
|
DATA_FOLDER_PATH = os.path.join(BASE_DIR, "data")
|
|
42
|
-
SQLALCHEMY_DATABASE_URI = f"sqlite:///{os.path.join(
|
|
43
|
-
BASE_DIR, DATA_FOLDER_PATH, DATABASE_FILENAME
|
|
44
|
-
)}"
|
|
@@ -381,3 +381,17 @@ def ping():
|
|
|
381
381
|
utils_functions.validate_request(flask.request, ping_json)
|
|
382
382
|
flask.current_app.config.update(LAST_PING_TIME=time.time())
|
|
383
383
|
return flask.make_response({"message": "Flask server is running"}, 200)
|
|
384
|
+
|
|
385
|
+
|
|
386
|
+
with open(
|
|
387
|
+
os.path.join(schemas, "kill.json"),
|
|
388
|
+
"r",
|
|
389
|
+
) as file:
|
|
390
|
+
kill_json = json.load(file)
|
|
391
|
+
|
|
392
|
+
|
|
393
|
+
@routes.route(kill_json["route"], methods=kill_json["methods"])
|
|
394
|
+
def kill() -> flask.Response:
|
|
395
|
+
print("Manual server kill, shutting down...", flush=True)
|
|
396
|
+
os._exit(0)
|
|
397
|
+
return flask.make_response({"message": "Flask server is dead"}, 200)
|
|
@@ -88,7 +88,6 @@ def validate_request(request: flask.Request, schema: dict[str, str]) -> None:
|
|
|
88
88
|
|
|
89
89
|
if json_data is None:
|
|
90
90
|
json_data = {}
|
|
91
|
-
|
|
92
91
|
try:
|
|
93
92
|
validate = fastjsonschema.compile(schema)
|
|
94
93
|
validate(json_data)
|
|
@@ -164,7 +163,7 @@ def create_data_folder_from_id(data_id: str) -> str:
|
|
|
164
163
|
def save_all_viewables_and_return_info(
|
|
165
164
|
geode_object: str,
|
|
166
165
|
data: Any,
|
|
167
|
-
input_file: str,
|
|
166
|
+
input_file: str | None = None,
|
|
168
167
|
additional_files: list[str] | None = None,
|
|
169
168
|
) -> dict[str, Any]:
|
|
170
169
|
if additional_files is None:
|
|
@@ -228,6 +227,8 @@ def generate_native_viewable_and_light_viewable_from_object(
|
|
|
228
227
|
def generate_native_viewable_and_light_viewable_from_file(
|
|
229
228
|
geode_object: str, input_filename: str
|
|
230
229
|
) -> dict[str, Any]:
|
|
230
|
+
|
|
231
|
+
session = get_session()
|
|
231
232
|
temp_data_entry = Data.create(
|
|
232
233
|
geode_object=geode_object,
|
|
233
234
|
input_file=input_filename,
|
|
@@ -259,14 +260,10 @@ def generate_native_viewable_and_light_viewable_from_file(
|
|
|
259
260
|
|
|
260
261
|
data = geode_functions.load(geode_object, copied_full_path)
|
|
261
262
|
|
|
262
|
-
# Remplacer :
|
|
263
|
-
# database.session.delete(temp_data_entry)
|
|
264
|
-
# database.session.flush()
|
|
265
|
-
# Par :
|
|
266
|
-
session = get_session()
|
|
267
263
|
if session:
|
|
268
264
|
session.delete(temp_data_entry)
|
|
269
265
|
session.flush()
|
|
266
|
+
session.commit()
|
|
270
267
|
|
|
271
268
|
return save_all_viewables_and_return_info(
|
|
272
269
|
geode_object,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: OpenGeodeWeb-Back
|
|
3
|
-
Version: 5.10.
|
|
3
|
+
Version: 5.10.3
|
|
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
|
|
@@ -11,28 +11,23 @@ Classifier: Operating System :: OS Independent
|
|
|
11
11
|
Requires-Python: <3.13,>=3.9
|
|
12
12
|
Description-Content-Type: text/markdown
|
|
13
13
|
License-File: LICENSE
|
|
14
|
-
Requires-Dist: asgiref
|
|
15
|
-
Requires-Dist: blinker
|
|
16
|
-
Requires-Dist: click
|
|
17
|
-
Requires-Dist:
|
|
18
|
-
Requires-Dist: flask
|
|
19
|
-
Requires-Dist: flask-cors~=6.0
|
|
20
|
-
Requires-Dist: flask-sqlalchemy~=3.1
|
|
14
|
+
Requires-Dist: asgiref>=3
|
|
15
|
+
Requires-Dist: blinker>=1
|
|
16
|
+
Requires-Dist: click>=8
|
|
17
|
+
Requires-Dist: flask[async]>=3
|
|
18
|
+
Requires-Dist: flask-cors==6.0.1
|
|
21
19
|
Requires-Dist: geode-common==33.11.0
|
|
22
20
|
Requires-Dist: geode-viewables==3.3.0
|
|
23
|
-
Requires-Dist:
|
|
24
|
-
Requires-Dist:
|
|
25
|
-
Requires-Dist:
|
|
26
|
-
Requires-Dist: markupsafe~=3.0
|
|
21
|
+
Requires-Dist: itsdangerous>=2
|
|
22
|
+
Requires-Dist: jinja2>=3
|
|
23
|
+
Requires-Dist: markupsafe>=3
|
|
27
24
|
Requires-Dist: opengeode-core==15.27.4
|
|
28
25
|
Requires-Dist: opengeode-geosciences==9.4.1
|
|
29
26
|
Requires-Dist: opengeode-geosciencesio==5.8.0
|
|
30
27
|
Requires-Dist: opengeode-inspector==6.8.1
|
|
31
28
|
Requires-Dist: opengeode-io==7.4.0
|
|
32
|
-
Requires-Dist:
|
|
33
|
-
Requires-Dist:
|
|
34
|
-
Requires-Dist: typing-extensions~=4.15
|
|
35
|
-
Requires-Dist: werkzeug==3.0.3
|
|
29
|
+
Requires-Dist: werkzeug==3.1.2
|
|
30
|
+
Requires-Dist: opengeodeweb-microservice==1.*,>=1.0.4rc9
|
|
36
31
|
Dynamic: license-file
|
|
37
32
|
|
|
38
33
|
<h1 align="center">OpenGeodeWeb-Back<sup><i>by Geode-solutions</i></sup></h1>
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
opengeodeweb_back/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
-
opengeodeweb_back/
|
|
2
|
+
opengeodeweb_back/app.py,sha256=7sacDhOn73S4SBACvwvHonS5pOeu4ttuxrg32FRHlPQ,4509
|
|
3
|
+
opengeodeweb_back/app_config.py,sha256=z-omTiGj3-y0BZ1IchAM6EoTdC7vAX6B4OymEnuM0T4,843
|
|
3
4
|
opengeodeweb_back/geode_functions.py,sha256=NzELy9s6AETDnm7tyA_uM2N89zrfeLdblRhzYrBONmw,10804
|
|
4
5
|
opengeodeweb_back/geode_objects.py,sha256=_NclGPa024kCwUHdORkFuXYtiZBmQpgq6sO3LRkBhe8,27776
|
|
5
6
|
opengeodeweb_back/py.typed,sha256=la67KBlbjXN-_-DfGNcdOcjYumVpKG_Tkw-8n5dnGB4,8
|
|
6
7
|
opengeodeweb_back/test_utils.py,sha256=18AbRW9-tfKkPcmRGilTTHXI7S3armYyV7Vdy5UvUKM,794
|
|
7
|
-
opengeodeweb_back/utils_functions.py,sha256=
|
|
8
|
-
opengeodeweb_back/routes/blueprint_routes.py,sha256=
|
|
8
|
+
opengeodeweb_back/utils_functions.py,sha256=rGxBhz_t6JJ7eEi4PZS0b3SyGBFRCohZN5e3DQscpeQ,9111
|
|
9
|
+
opengeodeweb_back/routes/blueprint_routes.py,sha256=19W90mI3-jL80prgOU3aq8mBp3TM5-TO1rg244eZg2k,11394
|
|
9
10
|
opengeodeweb_back/routes/models/blueprint_models.py,sha256=Jo9pUDeu1nO3_IbBiuHGk57cc4_fhwxjM0EKNyv1FT0,1874
|
|
10
11
|
opengeodeweb_back/routes/models/schemas/mesh_components.json,sha256=JmQUvpy7HpGS6FlThZLx1YjHqiInRTqUZ_Ft5MfOzEE,239
|
|
11
12
|
opengeodeweb_back/routes/models/schemas/vtm_component_indices.json,sha256=0XILVxhAxi0RhQFDZZoUeGcAnBMroWz3kNJS7-6_dKQ,239
|
|
@@ -15,6 +16,7 @@ opengeodeweb_back/routes/schemas/create_point.json,sha256=XjmXLMkr4jgWYHUKSwAhsx
|
|
|
15
16
|
opengeodeweb_back/routes/schemas/geode_objects_and_output_extensions.json,sha256=tp83tPQaxTltQrdL8D3TnG8pqY_2fgAaYVeTWPXO0qI,371
|
|
16
17
|
opengeodeweb_back/routes/schemas/geographic_coordinate_systems.json,sha256=lnPqevRRlUASF4ObmpG8ChH3c2LHNB99Si292S3OsLU,279
|
|
17
18
|
opengeodeweb_back/routes/schemas/inspect_file.json,sha256=WoFF2hgZCUfqSDFJRq1sLpivjCQ6TCvSHPH8pKFY6KM,348
|
|
19
|
+
opengeodeweb_back/routes/schemas/kill.json,sha256=tZEv4TuTNNthet2MsxUPLV3ivW6tIGjYTfxd6Jl9zaM,144
|
|
18
20
|
opengeodeweb_back/routes/schemas/missing_files.json,sha256=eOBAkiphA-2xG6e-OAy7wcJK2FeY0YFYXJlLdr8SNSc,349
|
|
19
21
|
opengeodeweb_back/routes/schemas/ping.json,sha256=MhI5jtrjMsAsfIKEzdY8p1HyV9xv4O3hYfESWw6tkyE,162
|
|
20
22
|
opengeodeweb_back/routes/schemas/polygon_attribute_names.json,sha256=1BrpfjcbRL1ZOL4azHIHirqXIc8tpu4xGnMRFEMEshU,241
|
|
@@ -23,8 +25,9 @@ opengeodeweb_back/routes/schemas/save_viewable_file.json,sha256=pvvEdaC7bNASPMrl
|
|
|
23
25
|
opengeodeweb_back/routes/schemas/texture_coordinates.json,sha256=2uQueIl1jOmxFG_gIi_vJETR4IurrwuSf8GAnzphk9g,237
|
|
24
26
|
opengeodeweb_back/routes/schemas/upload_file.json,sha256=LJ3U3L5ApKuQDVFIpVT_y2alq4HW_suTvZ3HUucNbhg,219
|
|
25
27
|
opengeodeweb_back/routes/schemas/vertex_attribute_names.json,sha256=ECIflohiqPZNsflAdkfEzksL4we0JvZhIxUd84Ubctg,240
|
|
26
|
-
opengeodeweb_back-5.10.
|
|
27
|
-
opengeodeweb_back-5.10.
|
|
28
|
-
opengeodeweb_back-5.10.
|
|
29
|
-
opengeodeweb_back-5.10.
|
|
30
|
-
opengeodeweb_back-5.10.
|
|
28
|
+
opengeodeweb_back-5.10.3.dist-info/licenses/LICENSE,sha256=LoTB-aqQvzTGxoTRXNnhNV0LKiqdk2bQv6MB34l8zkI,1079
|
|
29
|
+
opengeodeweb_back-5.10.3.dist-info/METADATA,sha256=278ZgWWQWo8TvvsBj2q9I9QXGuJWCKWWv0_4atiDoZc,2665
|
|
30
|
+
opengeodeweb_back-5.10.3.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
31
|
+
opengeodeweb_back-5.10.3.dist-info/entry_points.txt,sha256=3W_t5GFc9ROHSIZ55IGvYU3DLHUFQmYOM4Bm9u3Z0cE,71
|
|
32
|
+
opengeodeweb_back-5.10.3.dist-info/top_level.txt,sha256=tN1FZeLIVBrdja2-pbmhg5-tK-JILmmT9OeIBnhlUrQ,18
|
|
33
|
+
opengeodeweb_back-5.10.3.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|