vantage6-algorithm-store 4.3.4__tar.gz → 4.4.0__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.
- {vantage6-algorithm-store-4.3.4 → vantage6-algorithm-store-4.4.0}/PKG-INFO +1 -1
- {vantage6-algorithm-store-4.3.4 → vantage6-algorithm-store-4.4.0}/setup.py +1 -0
- {vantage6-algorithm-store-4.3.4 → vantage6-algorithm-store-4.4.0}/vantage6/algorithm/store/__init__.py +2 -1
- {vantage6-algorithm-store-4.3.4 → vantage6-algorithm-store-4.4.0}/vantage6/algorithm/store/_version.py +1 -1
- {vantage6-algorithm-store-4.3.4 → vantage6-algorithm-store-4.4.0}/vantage6/algorithm/store/globals.py +0 -3
- {vantage6-algorithm-store-4.3.4 → vantage6-algorithm-store-4.4.0}/vantage6/algorithm/store/model/__init__.py +1 -0
- {vantage6-algorithm-store-4.3.4 → vantage6-algorithm-store-4.4.0}/vantage6/algorithm/store/model/algorithm.py +4 -1
- {vantage6-algorithm-store-4.3.4 → vantage6-algorithm-store-4.4.0}/vantage6/algorithm/store/model/common/enums.py +11 -2
- vantage6-algorithm-store-4.4.0/vantage6/algorithm/store/model/common/ui_visualization_schemas.py +62 -0
- {vantage6-algorithm-store-4.3.4 → vantage6-algorithm-store-4.4.0}/vantage6/algorithm/store/model/function.py +6 -5
- {vantage6-algorithm-store-4.3.4 → vantage6-algorithm-store-4.4.0}/vantage6/algorithm/store/model/review.py +4 -0
- vantage6-algorithm-store-4.4.0/vantage6/algorithm/store/model/ui_visualization.py +35 -0
- {vantage6-algorithm-store-4.3.4 → vantage6-algorithm-store-4.4.0}/vantage6/algorithm/store/model/user.py +8 -0
- {vantage6-algorithm-store-4.3.4 → vantage6-algorithm-store-4.4.0}/vantage6/algorithm/store/model/vantage6_server.py +2 -0
- {vantage6-algorithm-store-4.3.4 → vantage6-algorithm-store-4.4.0}/vantage6/algorithm/store/resource/algorithm.py +84 -42
- {vantage6-algorithm-store-4.3.4 → vantage6-algorithm-store-4.4.0}/vantage6/algorithm/store/resource/schema/input_schema.py +49 -6
- {vantage6-algorithm-store-4.3.4 → vantage6-algorithm-store-4.4.0}/vantage6/algorithm/store/resource/schema/output_schema.py +15 -4
- {vantage6-algorithm-store-4.3.4 → vantage6-algorithm-store-4.4.0}/vantage6_algorithm_store.egg-info/PKG-INFO +1 -1
- {vantage6-algorithm-store-4.3.4 → vantage6-algorithm-store-4.4.0}/vantage6_algorithm_store.egg-info/SOURCES.txt +2 -0
- {vantage6-algorithm-store-4.3.4 → vantage6-algorithm-store-4.4.0}/vantage6_algorithm_store.egg-info/requires.txt +3 -2
- {vantage6-algorithm-store-4.3.4 → vantage6-algorithm-store-4.4.0}/setup.cfg +0 -0
- {vantage6-algorithm-store-4.3.4 → vantage6-algorithm-store-4.4.0}/vantage6/algorithm/store/__build__ +0 -0
- {vantage6-algorithm-store-4.3.4 → vantage6-algorithm-store-4.4.0}/vantage6/algorithm/store/db.py +0 -0
- {vantage6-algorithm-store-4.3.4 → vantage6-algorithm-store-4.4.0}/vantage6/algorithm/store/default_roles.py +0 -0
- {vantage6-algorithm-store-4.3.4 → vantage6-algorithm-store-4.4.0}/vantage6/algorithm/store/model/argument.py +2 -2
- {vantage6-algorithm-store-4.3.4 → vantage6-algorithm-store-4.4.0}/vantage6/algorithm/store/model/base.py +0 -0
- {vantage6-algorithm-store-4.3.4 → vantage6-algorithm-store-4.4.0}/vantage6/algorithm/store/model/database.py +0 -0
- {vantage6-algorithm-store-4.3.4 → vantage6-algorithm-store-4.4.0}/vantage6/algorithm/store/model/developer_algorithm_association.py +0 -0
- {vantage6-algorithm-store-4.3.4 → vantage6-algorithm-store-4.4.0}/vantage6/algorithm/store/model/permission.py +0 -0
- {vantage6-algorithm-store-4.3.4 → vantage6-algorithm-store-4.4.0}/vantage6/algorithm/store/model/role.py +0 -0
- {vantage6-algorithm-store-4.3.4 → vantage6-algorithm-store-4.4.0}/vantage6/algorithm/store/model/role_rule_association.py +0 -0
- {vantage6-algorithm-store-4.3.4 → vantage6-algorithm-store-4.4.0}/vantage6/algorithm/store/model/rule.py +0 -0
- {vantage6-algorithm-store-4.3.4 → vantage6-algorithm-store-4.4.0}/vantage6/algorithm/store/permission.py +0 -0
- {vantage6-algorithm-store-4.3.4 → vantage6-algorithm-store-4.4.0}/vantage6/algorithm/store/resource/__init__.py +0 -0
- {vantage6-algorithm-store-4.3.4 → vantage6-algorithm-store-4.4.0}/vantage6/algorithm/store/resource/role.py +0 -0
- {vantage6-algorithm-store-4.3.4 → vantage6-algorithm-store-4.4.0}/vantage6/algorithm/store/resource/rule.py +0 -0
- {vantage6-algorithm-store-4.3.4 → vantage6-algorithm-store-4.4.0}/vantage6/algorithm/store/resource/user.py +0 -0
- {vantage6-algorithm-store-4.3.4 → vantage6-algorithm-store-4.4.0}/vantage6/algorithm/store/resource/vantage6_server.py +0 -0
- {vantage6-algorithm-store-4.3.4 → vantage6-algorithm-store-4.4.0}/vantage6/algorithm/store/resource/version.py +0 -0
- {vantage6-algorithm-store-4.3.4 → vantage6-algorithm-store-4.4.0}/vantage6/algorithm/store/wsgi.py +0 -0
- {vantage6-algorithm-store-4.3.4 → vantage6-algorithm-store-4.4.0}/vantage6_algorithm_store.egg-info/dependency_links.txt +0 -0
- {vantage6-algorithm-store-4.3.4 → vantage6-algorithm-store-4.4.0}/vantage6_algorithm_store.egg-info/top_level.txt +0 -0
|
@@ -36,11 +36,12 @@ from pathlib import Path
|
|
|
36
36
|
from vantage6.common import logger_name
|
|
37
37
|
from vantage6.common.globals import APPNAME
|
|
38
38
|
from vantage6.backend.common.resource.output_schema import BaseHATEOASModelSchema
|
|
39
|
+
from vantage6.backend.common.globals import HOST_URI_ENV
|
|
39
40
|
|
|
40
41
|
# TODO move this to common, then remove dependency on CLI in algorithm store
|
|
41
42
|
from vantage6.cli.context.algorithm_store import AlgorithmStoreContext
|
|
42
43
|
from vantage6.algorithm.store._version import __version__
|
|
43
|
-
from vantage6.algorithm.store.globals import API_PATH
|
|
44
|
+
from vantage6.algorithm.store.globals import API_PATH
|
|
44
45
|
from vantage6.algorithm.store.globals import RESOURCES, SERVER_MODULE_NAME
|
|
45
46
|
|
|
46
47
|
# TODO the following are simply copies of the same files in the server - refactor
|
|
@@ -7,7 +7,7 @@ with open(os.path.join(here, "__build__")) as fp:
|
|
|
7
7
|
__build__ = json.load(fp)
|
|
8
8
|
|
|
9
9
|
# Module version
|
|
10
|
-
version_info = (4,
|
|
10
|
+
version_info = (4, 4, 0, "final", __build__, 0)
|
|
11
11
|
|
|
12
12
|
# Module version stage suffix map
|
|
13
13
|
_specifier_ = {"alpha": "a", "beta": "b", "candidate": "rc", "final": ""}
|
|
@@ -17,6 +17,3 @@ API_PATH = "/api"
|
|
|
17
17
|
# Which resources should be initialized. These names correspond to the
|
|
18
18
|
# file-names in the resource directory
|
|
19
19
|
RESOURCES = ["version", "algorithm", "vantage6_server", "role", "rule", "user"]
|
|
20
|
-
|
|
21
|
-
# environment variable name for host URI
|
|
22
|
-
HOST_URI_ENV = "HOST_URI_ENV_VAR"
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
1
|
from sqlalchemy import Column, String
|
|
3
2
|
from sqlalchemy.orm import relationship
|
|
4
3
|
|
|
@@ -24,6 +23,10 @@ class Algorithm(Base):
|
|
|
24
23
|
|
|
25
24
|
functions : list[:class:`~.model.function.function`]
|
|
26
25
|
List of functions that are available in the algorithm
|
|
26
|
+
developer : list[:class:`~.model.user.User`]
|
|
27
|
+
List of users that have developed the algorithm
|
|
28
|
+
review : :class:`~.model.review.Review`
|
|
29
|
+
Review of the algorithm
|
|
27
30
|
"""
|
|
28
31
|
|
|
29
32
|
# fields
|
|
@@ -19,14 +19,23 @@ class ArgumentType(str, enum.Enum):
|
|
|
19
19
|
"""Enum for argument types"""
|
|
20
20
|
|
|
21
21
|
COLUMN = "column"
|
|
22
|
+
COLUMNS = "column_list"
|
|
22
23
|
STRING = "string"
|
|
24
|
+
STRINGS = "string_list"
|
|
23
25
|
INTEGER = "integer"
|
|
26
|
+
INTEGERS = "integer_list"
|
|
24
27
|
FLOAT = "float"
|
|
28
|
+
FLOATS = "float_list"
|
|
25
29
|
BOOLEAN = "boolean"
|
|
26
|
-
DATE = "date"
|
|
27
30
|
JSON = "json"
|
|
28
|
-
ORGANIZATIONS = "organizations"
|
|
29
31
|
ORGANIZATION = "organization"
|
|
32
|
+
ORGANIZATIONS = "organization_list"
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class VisualizationType(str, enum.Enum):
|
|
36
|
+
"""Enum for visualization types"""
|
|
37
|
+
|
|
38
|
+
TABLE = "table"
|
|
30
39
|
|
|
31
40
|
|
|
32
41
|
class ReviewStatus(str, enum.Enum):
|
vantage6-algorithm-store-4.4.0/vantage6/algorithm/store/model/common/ui_visualization_schemas.py
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
"""
|
|
2
|
+
This file describes how the JSON schema for different types of UI visualizations
|
|
3
|
+
should be structured. The schema is used to validate input data.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from vantage6.algorithm.store.model.common.enums import VisualizationType
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
# To visualize a table in the UI, the algorithm result should contain a table that
|
|
10
|
+
# is structured as follows:
|
|
11
|
+
# [
|
|
12
|
+
# { "column1": "value1", "column2": "value2", ... },
|
|
13
|
+
# { "column1": "value3", "column2": "value4", ... },
|
|
14
|
+
# ]
|
|
15
|
+
table_schema = {
|
|
16
|
+
"type": "object",
|
|
17
|
+
"properties": {
|
|
18
|
+
# indicate where in the results the table can be found. E.g. if the table is
|
|
19
|
+
# in results['data']['table'], the location should be ['data', 'table']. If it
|
|
20
|
+
# is not specified, the table is assumed to be the root of the results.
|
|
21
|
+
"location": {
|
|
22
|
+
"type": "array",
|
|
23
|
+
"items": {
|
|
24
|
+
"type": "string",
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
# columns of the table. Specify this if you only want to visualize a subset of
|
|
28
|
+
# the columns in the table. Example value: ["column1", "column2"]
|
|
29
|
+
"columns": {
|
|
30
|
+
"type": "array",
|
|
31
|
+
"items": {
|
|
32
|
+
"type": "string",
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
"additionalProperties": False,
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def get_schema_for_visualization(visualization_type: str) -> dict:
|
|
41
|
+
"""
|
|
42
|
+
Get the schema for a specific visualization type.
|
|
43
|
+
|
|
44
|
+
Parameters
|
|
45
|
+
----------
|
|
46
|
+
visualization_type : str
|
|
47
|
+
Type of the visualization.
|
|
48
|
+
|
|
49
|
+
Returns
|
|
50
|
+
-------
|
|
51
|
+
dict
|
|
52
|
+
JSON validation schema for the visualization type.
|
|
53
|
+
|
|
54
|
+
Raises
|
|
55
|
+
------
|
|
56
|
+
ValueError
|
|
57
|
+
If the visualization type is not supported.
|
|
58
|
+
"""
|
|
59
|
+
if visualization_type == VisualizationType.TABLE.value:
|
|
60
|
+
return table_schema
|
|
61
|
+
else:
|
|
62
|
+
raise ValueError(f"Visualization type '{visualization_type}' is not supported.")
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
1
|
from sqlalchemy import Column, String, ForeignKey, Integer
|
|
3
2
|
from sqlalchemy.orm import relationship
|
|
4
3
|
|
|
@@ -22,12 +21,14 @@ class Function(Base):
|
|
|
22
21
|
Type of function
|
|
23
22
|
algorithm_id : int
|
|
24
23
|
ID of the algorithm that this function belongs to
|
|
25
|
-
algorithm : :class:`~.model.algorithm.
|
|
24
|
+
algorithm : :class:`~.model.algorithm.Algorithm`
|
|
26
25
|
Algorithm that this function belongs to
|
|
27
|
-
databases : list[:class:`~.model.database.
|
|
26
|
+
databases : list[:class:`~.model.database.Database`]
|
|
28
27
|
List of databases that this function uses
|
|
29
|
-
arguments : list[:class:`~.model.argument.
|
|
28
|
+
arguments : list[:class:`~.model.argument.Argument`]
|
|
30
29
|
List of arguments that this function uses
|
|
30
|
+
ui_visualizations : list[:class:`~.model.ui_visualization.UIVisualization`]
|
|
31
|
+
List of user interface visualizations that this function produces
|
|
31
32
|
"""
|
|
32
33
|
|
|
33
34
|
# fields
|
|
@@ -40,4 +41,4 @@ class Function(Base):
|
|
|
40
41
|
algorithm = relationship("Algorithm", back_populates="functions")
|
|
41
42
|
databases = relationship("Database", back_populates="function")
|
|
42
43
|
arguments = relationship("Argument", back_populates="function")
|
|
43
|
-
|
|
44
|
+
ui_visualizations = relationship("UIVisualization", back_populates="function")
|
|
@@ -16,6 +16,10 @@ class Review(Base):
|
|
|
16
16
|
Id of the user appointed as reviewer
|
|
17
17
|
status : str
|
|
18
18
|
Review status
|
|
19
|
+
reviewers : list[:class:`~.model.user.User`]
|
|
20
|
+
List of users that have written reviews
|
|
21
|
+
algorithm : :class:`~.model.algorithm.Algorithm`
|
|
22
|
+
Algorithm that the review is linked to
|
|
19
23
|
"""
|
|
20
24
|
|
|
21
25
|
# fields
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
from sqlalchemy import Column, String, Integer, ForeignKey, JSON
|
|
2
|
+
from sqlalchemy.orm import relationship
|
|
3
|
+
|
|
4
|
+
from vantage6.algorithm.store.model.base import Base
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class UIVisualization(Base):
|
|
8
|
+
"""
|
|
9
|
+
Table that describes how the algorithm should be visualized in the UI.
|
|
10
|
+
|
|
11
|
+
Attributes
|
|
12
|
+
----------
|
|
13
|
+
name : str
|
|
14
|
+
Name of the visualization
|
|
15
|
+
description: str
|
|
16
|
+
Description of the visualization
|
|
17
|
+
type_: str
|
|
18
|
+
Type of the visualization. Currently available: 'table'
|
|
19
|
+
schema : dict
|
|
20
|
+
Schema that describes the visualization, e.g. column names of a table
|
|
21
|
+
function_id : int
|
|
22
|
+
Id of the function that the visualization is linked to
|
|
23
|
+
function : Function
|
|
24
|
+
Function that the visualization is linked to
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
# fields
|
|
28
|
+
name = Column(String)
|
|
29
|
+
description = Column(String)
|
|
30
|
+
type_ = Column("type", String)
|
|
31
|
+
schema = Column(JSON)
|
|
32
|
+
function_id = Column(Integer, ForeignKey("function.id"))
|
|
33
|
+
|
|
34
|
+
# relationships
|
|
35
|
+
function = relationship("Function", back_populates="ui_visualizations")
|
|
@@ -17,6 +17,14 @@ class User(Base):
|
|
|
17
17
|
Username
|
|
18
18
|
v6_server_id : int
|
|
19
19
|
Id of the whitelisted server through which the user is authenticated
|
|
20
|
+
server : :class:`~.model.vantage6_server.Vantage6Server`
|
|
21
|
+
Server through which the user is authenticated
|
|
22
|
+
roles : list[:class:`~.model.role.Role`]
|
|
23
|
+
List of roles that the user has
|
|
24
|
+
algorithms : list[:class:`~.model.algorithm.Algorithm`]
|
|
25
|
+
List of algorithms that the user has developed
|
|
26
|
+
reviews : list[:class:`~.model.review.Review`]
|
|
27
|
+
List of reviews that the user has written
|
|
20
28
|
"""
|
|
21
29
|
|
|
22
30
|
# fields
|
|
@@ -7,6 +7,7 @@ from http import HTTPStatus
|
|
|
7
7
|
from vantage6.algorithm.store import db
|
|
8
8
|
from vantage6.algorithm.store.model.rule import Operation
|
|
9
9
|
from vantage6.common import logger_name
|
|
10
|
+
from vantage6.algorithm.store.model.ui_visualization import UIVisualization
|
|
10
11
|
from vantage6.algorithm.store.resource.schema.input_schema import AlgorithmInputSchema
|
|
11
12
|
from vantage6.algorithm.store.resource.schema.output_schema import AlgorithmOutputSchema
|
|
12
13
|
from vantage6.algorithm.store.model.algorithm import Algorithm as db_Algorithm
|
|
@@ -144,9 +145,19 @@ class Algorithms(AlgorithmStoreResources):
|
|
|
144
145
|
|
|
145
146
|
tags: ["Algorithm"]
|
|
146
147
|
"""
|
|
147
|
-
# TODO add filtering
|
|
148
148
|
q = g.session.query(db_Algorithm)
|
|
149
149
|
|
|
150
|
+
# filter on properties
|
|
151
|
+
for field in [
|
|
152
|
+
"name",
|
|
153
|
+
"description",
|
|
154
|
+
"image",
|
|
155
|
+
"partitioning",
|
|
156
|
+
"vantage6_version",
|
|
157
|
+
]:
|
|
158
|
+
if (value := request.args.get(field)) is not None:
|
|
159
|
+
q = q.filter(getattr(db_Algorithm, field).like(f"%{value}%"))
|
|
160
|
+
|
|
150
161
|
# paginate results
|
|
151
162
|
try:
|
|
152
163
|
page = Pagination.from_query(q, request, db.Algorithm)
|
|
@@ -234,6 +245,24 @@ class Algorithms(AlgorithmStoreResources):
|
|
|
234
245
|
description: Type of argument. Can be 'string',
|
|
235
246
|
'integer', 'float', 'boolean', 'json',
|
|
236
247
|
'column', 'organizations' or 'organization'
|
|
248
|
+
ui_visualizations:
|
|
249
|
+
type: array
|
|
250
|
+
description: List of visualizations that are available in
|
|
251
|
+
the algorithm
|
|
252
|
+
items:
|
|
253
|
+
properties:
|
|
254
|
+
name:
|
|
255
|
+
type: string
|
|
256
|
+
description: Name of the visualization
|
|
257
|
+
description:
|
|
258
|
+
type: string
|
|
259
|
+
description: Description of the visualization
|
|
260
|
+
type:
|
|
261
|
+
type: string
|
|
262
|
+
description: Type of visualization.
|
|
263
|
+
schema:
|
|
264
|
+
type: object
|
|
265
|
+
description: Schema that describes the visualization
|
|
237
266
|
|
|
238
267
|
responses:
|
|
239
268
|
201:
|
|
@@ -279,26 +308,32 @@ class Algorithms(AlgorithmStoreResources):
|
|
|
279
308
|
)
|
|
280
309
|
func.save()
|
|
281
310
|
# create the arguments
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
)
|
|
291
|
-
arg.save()
|
|
311
|
+
for argument in function.get("arguments", []):
|
|
312
|
+
arg = Argument(
|
|
313
|
+
name=argument["name"],
|
|
314
|
+
description=argument.get("description", ""),
|
|
315
|
+
type_=argument["type"],
|
|
316
|
+
function_id=func.id,
|
|
317
|
+
)
|
|
318
|
+
arg.save()
|
|
292
319
|
# create the databases
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
320
|
+
for database in function.get("databases", []):
|
|
321
|
+
db = Database(
|
|
322
|
+
name=database["name"],
|
|
323
|
+
description=database.get("description", ""),
|
|
324
|
+
function_id=func.id,
|
|
325
|
+
)
|
|
326
|
+
db.save()
|
|
327
|
+
# create the visualizations
|
|
328
|
+
for visualization in function.get("ui_visualizations", []):
|
|
329
|
+
vis = UIVisualization(
|
|
330
|
+
name=visualization["name"],
|
|
331
|
+
description=visualization.get("description", ""),
|
|
332
|
+
type_=visualization["type"],
|
|
333
|
+
schema=visualization.get("schema", {}),
|
|
334
|
+
function_id=func.id,
|
|
335
|
+
)
|
|
336
|
+
vis.save()
|
|
302
337
|
|
|
303
338
|
return algorithm_output_schema.dump(algorithm, many=False), HTTPStatus.CREATED
|
|
304
339
|
|
|
@@ -374,6 +409,8 @@ class Algorithm(AlgorithmStoreResources):
|
|
|
374
409
|
database.delete()
|
|
375
410
|
for argument in function.arguments:
|
|
376
411
|
argument.delete()
|
|
412
|
+
for visualization in function.ui_visualizations:
|
|
413
|
+
visualization.delete()
|
|
377
414
|
function.delete()
|
|
378
415
|
algorithm.delete()
|
|
379
416
|
|
|
@@ -494,7 +531,7 @@ class Algorithm(AlgorithmStoreResources):
|
|
|
494
531
|
fields = ["name", "description", "image", "partitioning", "vantage6_version"]
|
|
495
532
|
for field in fields:
|
|
496
533
|
if field in data and data.get(field) is not None:
|
|
497
|
-
setattr(algorithm, field, data.get(
|
|
534
|
+
setattr(algorithm, field, data.get(field))
|
|
498
535
|
|
|
499
536
|
if (functions := data.get("functions")) is not None:
|
|
500
537
|
for function in algorithm.functions:
|
|
@@ -502,6 +539,8 @@ class Algorithm(AlgorithmStoreResources):
|
|
|
502
539
|
argument.delete()
|
|
503
540
|
for db in function.databases:
|
|
504
541
|
db.delete()
|
|
542
|
+
for visualization in function.ui_visualizations:
|
|
543
|
+
visualization.delete()
|
|
505
544
|
function.delete()
|
|
506
545
|
|
|
507
546
|
for new_function in functions:
|
|
@@ -513,27 +552,30 @@ class Algorithm(AlgorithmStoreResources):
|
|
|
513
552
|
)
|
|
514
553
|
func.save()
|
|
515
554
|
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
555
|
+
for argument in new_function.get("arguments", []):
|
|
556
|
+
arg = Argument(
|
|
557
|
+
name=argument["name"],
|
|
558
|
+
description=argument.get("description", ""),
|
|
559
|
+
type_=argument["type"],
|
|
560
|
+
function_id=func.id,
|
|
561
|
+
)
|
|
562
|
+
arg.save()
|
|
563
|
+
for database in new_function.get("databases", []):
|
|
564
|
+
db = Database(
|
|
565
|
+
name=database["name"],
|
|
566
|
+
description=database.get("description", ""),
|
|
567
|
+
function_id=func.id,
|
|
568
|
+
)
|
|
569
|
+
db.save()
|
|
570
|
+
for visualization in new_function.get("ui_visualizations", []):
|
|
571
|
+
vis = UIVisualization(
|
|
572
|
+
name=visualization["name"],
|
|
573
|
+
description=visualization.get("description", ""),
|
|
574
|
+
type_=visualization["type"],
|
|
575
|
+
schema=visualization.get("schema", {}),
|
|
576
|
+
function_id=func.id,
|
|
577
|
+
)
|
|
578
|
+
vis.save()
|
|
537
579
|
|
|
538
580
|
algorithm.save()
|
|
539
581
|
|
|
@@ -1,10 +1,15 @@
|
|
|
1
|
-
from marshmallow import Schema, fields, ValidationError, validates
|
|
1
|
+
from marshmallow import Schema, fields, ValidationError, validates, validates_schema
|
|
2
2
|
from marshmallow.validate import Range
|
|
3
|
+
from jsonschema import validate as json_validate
|
|
3
4
|
|
|
4
5
|
from vantage6.algorithm.store.model.common.enums import (
|
|
5
6
|
Partitioning,
|
|
6
7
|
FunctionType,
|
|
7
8
|
ArgumentType,
|
|
9
|
+
VisualizationType,
|
|
10
|
+
)
|
|
11
|
+
from vantage6.algorithm.store.model.common.ui_visualization_schemas import (
|
|
12
|
+
get_schema_for_visualization,
|
|
8
13
|
)
|
|
9
14
|
|
|
10
15
|
|
|
@@ -44,11 +49,12 @@ class FunctionInputSchema(_NameDescriptionSchema):
|
|
|
44
49
|
Schema for the input of a function.
|
|
45
50
|
"""
|
|
46
51
|
|
|
47
|
-
|
|
52
|
+
type_ = fields.String(required=True, data_key="type")
|
|
48
53
|
databases = fields.Nested("DatabaseInputSchema", many=True)
|
|
49
54
|
arguments = fields.Nested("ArgumentInputSchema", many=True)
|
|
55
|
+
ui_visualizations = fields.Nested("UIVisualizationInputSchema", many=True)
|
|
50
56
|
|
|
51
|
-
@validates("
|
|
57
|
+
@validates("type_")
|
|
52
58
|
def validate_type(self, value):
|
|
53
59
|
"""
|
|
54
60
|
Validate that the type is one of the allowed values.
|
|
@@ -74,9 +80,9 @@ class ArgumentInputSchema(_NameDescriptionSchema):
|
|
|
74
80
|
Schema for the input of an argument.
|
|
75
81
|
"""
|
|
76
82
|
|
|
77
|
-
|
|
83
|
+
type_ = fields.String(required=True, data_key="type")
|
|
78
84
|
|
|
79
|
-
@validates("
|
|
85
|
+
@validates("type_")
|
|
80
86
|
def validate_type(self, value):
|
|
81
87
|
"""
|
|
82
88
|
Validate that the type is one of the allowed values.
|
|
@@ -84,10 +90,47 @@ class ArgumentInputSchema(_NameDescriptionSchema):
|
|
|
84
90
|
types = [a.value for a in ArgumentType]
|
|
85
91
|
if value not in types:
|
|
86
92
|
raise ValidationError(
|
|
87
|
-
f"Argument type '{value}' is not one of the allowed values
|
|
93
|
+
f"Argument type '{value}' is not one of the allowed values: {types}"
|
|
88
94
|
)
|
|
89
95
|
|
|
90
96
|
|
|
97
|
+
class UIVisualizationInputSchema(_NameDescriptionSchema):
|
|
98
|
+
"""
|
|
99
|
+
Schema for the input of a UI visualization.
|
|
100
|
+
"""
|
|
101
|
+
|
|
102
|
+
type_ = fields.String(required=True, data_key="type")
|
|
103
|
+
schema = fields.Dict()
|
|
104
|
+
|
|
105
|
+
@validates("type_")
|
|
106
|
+
def validate_type(self, value):
|
|
107
|
+
"""
|
|
108
|
+
Validate that the type is one of the allowed values.
|
|
109
|
+
"""
|
|
110
|
+
types = [v.value for v in VisualizationType]
|
|
111
|
+
if value not in types:
|
|
112
|
+
raise ValidationError(
|
|
113
|
+
f"UI visualization type '{value}' is not one of the allowed values "
|
|
114
|
+
f"{types}"
|
|
115
|
+
)
|
|
116
|
+
|
|
117
|
+
@validates_schema
|
|
118
|
+
def validate_schema(self, data, **kwargs):
|
|
119
|
+
"""
|
|
120
|
+
Validate that the schema is a valid JSON schema.
|
|
121
|
+
"""
|
|
122
|
+
schema = data.get("schema")
|
|
123
|
+
type_ = data.get("type_")
|
|
124
|
+
if schema and type_:
|
|
125
|
+
try:
|
|
126
|
+
json_validate(schema, get_schema_for_visualization(type_))
|
|
127
|
+
except Exception as exc:
|
|
128
|
+
raise ValidationError(
|
|
129
|
+
"Schema does not match requirements for that visualization type: "
|
|
130
|
+
f"{exc}",
|
|
131
|
+
) from exc
|
|
132
|
+
|
|
133
|
+
|
|
91
134
|
class UserInputSchema(Schema):
|
|
92
135
|
"""Schema for validating input for creating a user."""
|
|
93
136
|
|
|
@@ -9,6 +9,7 @@ from vantage6.algorithm.store.model.function import Function
|
|
|
9
9
|
from vantage6.algorithm.store.model import Base
|
|
10
10
|
from vantage6.algorithm.store.model.role import Role
|
|
11
11
|
from vantage6.algorithm.store.model.rule import Rule
|
|
12
|
+
from vantage6.algorithm.store.model.ui_visualization import UIVisualization
|
|
12
13
|
from vantage6.algorithm.store.model.user import User
|
|
13
14
|
from vantage6.algorithm.store.model.review import Review
|
|
14
15
|
from vantage6.algorithm.store.model.vantage6_server import Vantage6Server
|
|
@@ -80,12 +81,14 @@ class FunctionOutputSchema(HATEOASModelSchema):
|
|
|
80
81
|
|
|
81
82
|
class Meta:
|
|
82
83
|
model = Function
|
|
83
|
-
exclude = ["type_"]
|
|
84
84
|
|
|
85
|
-
|
|
85
|
+
type_ = fields.String(data_key="type")
|
|
86
86
|
|
|
87
87
|
databases = fields.Nested("DatabaseOutputSchema", many=True, exclude=["id"])
|
|
88
88
|
arguments = fields.Nested("ArgumentOutputSchema", many=True, exclude=["id"])
|
|
89
|
+
ui_visualizations = fields.Nested(
|
|
90
|
+
"UIVisualizationOutputSchema", many=True, exclude=["id"]
|
|
91
|
+
)
|
|
89
92
|
|
|
90
93
|
|
|
91
94
|
class DatabaseOutputSchema(HATEOASModelSchema):
|
|
@@ -100,9 +103,17 @@ class ArgumentOutputSchema(HATEOASModelSchema):
|
|
|
100
103
|
|
|
101
104
|
class Meta:
|
|
102
105
|
model = Argument
|
|
103
|
-
exclude = ["type_"]
|
|
104
106
|
|
|
105
|
-
|
|
107
|
+
type_ = fields.String(data_key="type")
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
class UIVisualizationOutputSchema(HATEOASModelSchema):
|
|
111
|
+
"""Marshmallow output schema to serialize the UIVisualization model"""
|
|
112
|
+
|
|
113
|
+
class Meta:
|
|
114
|
+
model = UIVisualization
|
|
115
|
+
|
|
116
|
+
type_ = fields.String(data_key="type")
|
|
106
117
|
|
|
107
118
|
|
|
108
119
|
class Vantage6ServerOutputSchema(HATEOASModelSchema):
|
|
@@ -19,9 +19,11 @@ vantage6/algorithm/store/model/review.py
|
|
|
19
19
|
vantage6/algorithm/store/model/role.py
|
|
20
20
|
vantage6/algorithm/store/model/role_rule_association.py
|
|
21
21
|
vantage6/algorithm/store/model/rule.py
|
|
22
|
+
vantage6/algorithm/store/model/ui_visualization.py
|
|
22
23
|
vantage6/algorithm/store/model/user.py
|
|
23
24
|
vantage6/algorithm/store/model/vantage6_server.py
|
|
24
25
|
vantage6/algorithm/store/model/common/enums.py
|
|
26
|
+
vantage6/algorithm/store/model/common/ui_visualization_schemas.py
|
|
25
27
|
vantage6/algorithm/store/resource/__init__.py
|
|
26
28
|
vantage6/algorithm/store/resource/algorithm.py
|
|
27
29
|
vantage6/algorithm/store/resource/role.py
|
|
@@ -5,13 +5,14 @@ Flask-Principal==0.4.0
|
|
|
5
5
|
flask-marshmallow==0.15.0
|
|
6
6
|
Flask-RESTful==0.3.10
|
|
7
7
|
gevent==23.9.1
|
|
8
|
+
jsonschema==4.21.1
|
|
8
9
|
marshmallow==3.19.0
|
|
9
10
|
requests==2.31.0
|
|
10
11
|
schema==0.7.5
|
|
11
12
|
SQLAlchemy==1.4.46
|
|
12
13
|
werkzeug==3.0.1
|
|
13
|
-
vantage6==4.
|
|
14
|
-
vantage6-common==4.
|
|
14
|
+
vantage6==4.4.0
|
|
15
|
+
vantage6-common==4.4.0
|
|
15
16
|
|
|
16
17
|
[dev]
|
|
17
18
|
coverage==6.4.4
|
|
File without changes
|
{vantage6-algorithm-store-4.3.4 → vantage6-algorithm-store-4.4.0}/vantage6/algorithm/store/__build__
RENAMED
|
File without changes
|
{vantage6-algorithm-store-4.3.4 → vantage6-algorithm-store-4.4.0}/vantage6/algorithm/store/db.py
RENAMED
|
File without changes
|
|
File without changes
|
|
@@ -20,10 +20,10 @@ class Argument(Base):
|
|
|
20
20
|
Description of the argument
|
|
21
21
|
function_id : int
|
|
22
22
|
ID of the algorithm that this function belongs to
|
|
23
|
-
function : :class:`~.model.algorithm.algorithm`
|
|
24
|
-
Algorithm function that this argument belongs to
|
|
25
23
|
type_ : str
|
|
26
24
|
Type of the argument
|
|
25
|
+
function : :class:`~.model.algorithm.algorithm`
|
|
26
|
+
Algorithm function that this argument belongs to
|
|
27
27
|
"""
|
|
28
28
|
|
|
29
29
|
# fields
|
|
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
|
{vantage6-algorithm-store-4.3.4 → vantage6-algorithm-store-4.4.0}/vantage6/algorithm/store/wsgi.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|