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.
Files changed (42) hide show
  1. {vantage6-algorithm-store-4.3.4 → vantage6-algorithm-store-4.4.0}/PKG-INFO +1 -1
  2. {vantage6-algorithm-store-4.3.4 → vantage6-algorithm-store-4.4.0}/setup.py +1 -0
  3. {vantage6-algorithm-store-4.3.4 → vantage6-algorithm-store-4.4.0}/vantage6/algorithm/store/__init__.py +2 -1
  4. {vantage6-algorithm-store-4.3.4 → vantage6-algorithm-store-4.4.0}/vantage6/algorithm/store/_version.py +1 -1
  5. {vantage6-algorithm-store-4.3.4 → vantage6-algorithm-store-4.4.0}/vantage6/algorithm/store/globals.py +0 -3
  6. {vantage6-algorithm-store-4.3.4 → vantage6-algorithm-store-4.4.0}/vantage6/algorithm/store/model/__init__.py +1 -0
  7. {vantage6-algorithm-store-4.3.4 → vantage6-algorithm-store-4.4.0}/vantage6/algorithm/store/model/algorithm.py +4 -1
  8. {vantage6-algorithm-store-4.3.4 → vantage6-algorithm-store-4.4.0}/vantage6/algorithm/store/model/common/enums.py +11 -2
  9. vantage6-algorithm-store-4.4.0/vantage6/algorithm/store/model/common/ui_visualization_schemas.py +62 -0
  10. {vantage6-algorithm-store-4.3.4 → vantage6-algorithm-store-4.4.0}/vantage6/algorithm/store/model/function.py +6 -5
  11. {vantage6-algorithm-store-4.3.4 → vantage6-algorithm-store-4.4.0}/vantage6/algorithm/store/model/review.py +4 -0
  12. vantage6-algorithm-store-4.4.0/vantage6/algorithm/store/model/ui_visualization.py +35 -0
  13. {vantage6-algorithm-store-4.3.4 → vantage6-algorithm-store-4.4.0}/vantage6/algorithm/store/model/user.py +8 -0
  14. {vantage6-algorithm-store-4.3.4 → vantage6-algorithm-store-4.4.0}/vantage6/algorithm/store/model/vantage6_server.py +2 -0
  15. {vantage6-algorithm-store-4.3.4 → vantage6-algorithm-store-4.4.0}/vantage6/algorithm/store/resource/algorithm.py +84 -42
  16. {vantage6-algorithm-store-4.3.4 → vantage6-algorithm-store-4.4.0}/vantage6/algorithm/store/resource/schema/input_schema.py +49 -6
  17. {vantage6-algorithm-store-4.3.4 → vantage6-algorithm-store-4.4.0}/vantage6/algorithm/store/resource/schema/output_schema.py +15 -4
  18. {vantage6-algorithm-store-4.3.4 → vantage6-algorithm-store-4.4.0}/vantage6_algorithm_store.egg-info/PKG-INFO +1 -1
  19. {vantage6-algorithm-store-4.3.4 → vantage6-algorithm-store-4.4.0}/vantage6_algorithm_store.egg-info/SOURCES.txt +2 -0
  20. {vantage6-algorithm-store-4.3.4 → vantage6-algorithm-store-4.4.0}/vantage6_algorithm_store.egg-info/requires.txt +3 -2
  21. {vantage6-algorithm-store-4.3.4 → vantage6-algorithm-store-4.4.0}/setup.cfg +0 -0
  22. {vantage6-algorithm-store-4.3.4 → vantage6-algorithm-store-4.4.0}/vantage6/algorithm/store/__build__ +0 -0
  23. {vantage6-algorithm-store-4.3.4 → vantage6-algorithm-store-4.4.0}/vantage6/algorithm/store/db.py +0 -0
  24. {vantage6-algorithm-store-4.3.4 → vantage6-algorithm-store-4.4.0}/vantage6/algorithm/store/default_roles.py +0 -0
  25. {vantage6-algorithm-store-4.3.4 → vantage6-algorithm-store-4.4.0}/vantage6/algorithm/store/model/argument.py +2 -2
  26. {vantage6-algorithm-store-4.3.4 → vantage6-algorithm-store-4.4.0}/vantage6/algorithm/store/model/base.py +0 -0
  27. {vantage6-algorithm-store-4.3.4 → vantage6-algorithm-store-4.4.0}/vantage6/algorithm/store/model/database.py +0 -0
  28. {vantage6-algorithm-store-4.3.4 → vantage6-algorithm-store-4.4.0}/vantage6/algorithm/store/model/developer_algorithm_association.py +0 -0
  29. {vantage6-algorithm-store-4.3.4 → vantage6-algorithm-store-4.4.0}/vantage6/algorithm/store/model/permission.py +0 -0
  30. {vantage6-algorithm-store-4.3.4 → vantage6-algorithm-store-4.4.0}/vantage6/algorithm/store/model/role.py +0 -0
  31. {vantage6-algorithm-store-4.3.4 → vantage6-algorithm-store-4.4.0}/vantage6/algorithm/store/model/role_rule_association.py +0 -0
  32. {vantage6-algorithm-store-4.3.4 → vantage6-algorithm-store-4.4.0}/vantage6/algorithm/store/model/rule.py +0 -0
  33. {vantage6-algorithm-store-4.3.4 → vantage6-algorithm-store-4.4.0}/vantage6/algorithm/store/permission.py +0 -0
  34. {vantage6-algorithm-store-4.3.4 → vantage6-algorithm-store-4.4.0}/vantage6/algorithm/store/resource/__init__.py +0 -0
  35. {vantage6-algorithm-store-4.3.4 → vantage6-algorithm-store-4.4.0}/vantage6/algorithm/store/resource/role.py +0 -0
  36. {vantage6-algorithm-store-4.3.4 → vantage6-algorithm-store-4.4.0}/vantage6/algorithm/store/resource/rule.py +0 -0
  37. {vantage6-algorithm-store-4.3.4 → vantage6-algorithm-store-4.4.0}/vantage6/algorithm/store/resource/user.py +0 -0
  38. {vantage6-algorithm-store-4.3.4 → vantage6-algorithm-store-4.4.0}/vantage6/algorithm/store/resource/vantage6_server.py +0 -0
  39. {vantage6-algorithm-store-4.3.4 → vantage6-algorithm-store-4.4.0}/vantage6/algorithm/store/resource/version.py +0 -0
  40. {vantage6-algorithm-store-4.3.4 → vantage6-algorithm-store-4.4.0}/vantage6/algorithm/store/wsgi.py +0 -0
  41. {vantage6-algorithm-store-4.3.4 → vantage6-algorithm-store-4.4.0}/vantage6_algorithm_store.egg-info/dependency_links.txt +0 -0
  42. {vantage6-algorithm-store-4.3.4 → vantage6-algorithm-store-4.4.0}/vantage6_algorithm_store.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: vantage6-algorithm-store
3
- Version: 4.3.4
3
+ Version: 4.4.0
4
4
  Summary: Vantage6 algorithm store
5
5
  Home-page: https://github.com/vantage6/vantage6
6
6
  Requires-Python: >=3.10
@@ -38,6 +38,7 @@ setup(
38
38
  "flask-marshmallow==0.15.0",
39
39
  "Flask-RESTful==0.3.10",
40
40
  "gevent==23.9.1",
41
+ "jsonschema==4.21.1",
41
42
  "marshmallow==3.19.0",
42
43
  "requests==2.31.0",
43
44
  "schema==0.7.5",
@@ -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, HOST_URI_ENV
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, 3, 4, "final", __build__, 0)
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"
@@ -13,3 +13,4 @@ from vantage6.algorithm.store.model.developer_algorithm_association import (
13
13
  developer_algorithm_association,
14
14
  )
15
15
  from vantage6.algorithm.store.model.review import Review
16
+ from vantage6.algorithm.store.model.ui_visualization import UIVisualization
@@ -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):
@@ -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.algorithm`
24
+ algorithm : :class:`~.model.algorithm.Algorithm`
26
25
  Algorithm that this function belongs to
27
- databases : list[:class:`~.model.database.database`]
26
+ databases : list[:class:`~.model.database.Database`]
28
27
  List of databases that this function uses
29
- arguments : list[:class:`~.model.argument.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
- # output = relationship("Output", back_populates='function')
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
@@ -15,6 +15,8 @@ class Vantage6Server(Base):
15
15
  ----------
16
16
  url : str
17
17
  URL of the vantage6 server
18
+ users : list[:class:`~.model.user.User`]
19
+ List of known vantage6 users from that server
18
20
  """
19
21
 
20
22
  # 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
- arguments = function.get("arguments")
283
- if arguments:
284
- for argument in arguments:
285
- arg = Argument(
286
- name=argument["name"],
287
- description=argument.get("description", ""),
288
- type_=argument["type"],
289
- function_id=func.id,
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
- databases = function.get("databases")
294
- if databases:
295
- for database in databases:
296
- db = Database(
297
- name=database["name"],
298
- description=database.get("description", ""),
299
- function_id=func.id,
300
- )
301
- db.save()
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("name"))
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
- arguments = new_function.get("arguments")
517
- if arguments:
518
- for argument in arguments:
519
- arg = Argument(
520
- name=argument["name"],
521
- description=argument.get("description", ""),
522
- type_=argument["type"],
523
- function_id=func.id,
524
- )
525
- arg.save()
526
-
527
- # create the databases
528
- databases = new_function.get("databases")
529
- if databases:
530
- for database in databases:
531
- db = Database(
532
- name=database["name"],
533
- description=database.get("description", ""),
534
- function_id=func.id,
535
- )
536
- db.save()
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
- type = fields.String(required=True)
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("type")
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
- type = fields.String(required=True)
83
+ type_ = fields.String(required=True, data_key="type")
78
84
 
79
- @validates("type")
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 " f"{types}"
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
- type = fields.String(attribute="type_")
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
- type = fields.String(attribute="type_")
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):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: vantage6-algorithm-store
3
- Version: 4.3.4
3
+ Version: 4.4.0
4
4
  Summary: Vantage6 algorithm store
5
5
  Home-page: https://github.com/vantage6/vantage6
6
6
  Requires-Python: >=3.10
@@ -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.3.4
14
- vantage6-common==4.3.4
14
+ vantage6==4.4.0
15
+ vantage6-common==4.4.0
15
16
 
16
17
  [dev]
17
18
  coverage==6.4.4
@@ -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