mlrun 1.3.1rc5__py3-none-any.whl → 1.4.0rc2__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 mlrun might be problematic. Click here for more details.

Files changed (67) hide show
  1. mlrun/__main__.py +57 -4
  2. mlrun/api/api/endpoints/marketplace.py +57 -4
  3. mlrun/api/api/endpoints/runs.py +2 -0
  4. mlrun/api/api/utils.py +102 -0
  5. mlrun/api/crud/__init__.py +1 -0
  6. mlrun/api/crud/marketplace.py +133 -44
  7. mlrun/api/crud/notifications.py +80 -0
  8. mlrun/api/crud/runs.py +2 -0
  9. mlrun/api/crud/secrets.py +1 -0
  10. mlrun/api/db/base.py +32 -0
  11. mlrun/api/db/session.py +3 -11
  12. mlrun/api/db/sqldb/db.py +162 -1
  13. mlrun/api/db/sqldb/models/models_mysql.py +41 -0
  14. mlrun/api/db/sqldb/models/models_sqlite.py +35 -0
  15. mlrun/api/main.py +54 -1
  16. mlrun/api/migrations_mysql/versions/c905d15bd91d_notifications.py +70 -0
  17. mlrun/api/migrations_sqlite/versions/959ae00528ad_notifications.py +61 -0
  18. mlrun/api/schemas/__init__.py +1 -0
  19. mlrun/api/schemas/marketplace.py +18 -8
  20. mlrun/api/{db/filedb/__init__.py → schemas/notification.py} +17 -1
  21. mlrun/api/utils/singletons/db.py +8 -14
  22. mlrun/builder.py +37 -26
  23. mlrun/config.py +12 -2
  24. mlrun/data_types/spark.py +9 -2
  25. mlrun/datastore/base.py +10 -1
  26. mlrun/datastore/sources.py +1 -1
  27. mlrun/db/__init__.py +6 -4
  28. mlrun/db/base.py +1 -2
  29. mlrun/db/httpdb.py +32 -6
  30. mlrun/db/nopdb.py +463 -0
  31. mlrun/db/sqldb.py +47 -7
  32. mlrun/execution.py +3 -0
  33. mlrun/feature_store/api.py +26 -12
  34. mlrun/feature_store/common.py +1 -1
  35. mlrun/feature_store/steps.py +110 -13
  36. mlrun/k8s_utils.py +10 -0
  37. mlrun/model.py +43 -0
  38. mlrun/projects/operations.py +5 -2
  39. mlrun/projects/pipelines.py +4 -3
  40. mlrun/projects/project.py +50 -10
  41. mlrun/run.py +5 -4
  42. mlrun/runtimes/__init__.py +2 -6
  43. mlrun/runtimes/base.py +82 -31
  44. mlrun/runtimes/function.py +22 -0
  45. mlrun/runtimes/kubejob.py +10 -8
  46. mlrun/runtimes/serving.py +1 -1
  47. mlrun/runtimes/sparkjob/__init__.py +0 -1
  48. mlrun/runtimes/sparkjob/abstract.py +0 -2
  49. mlrun/serving/states.py +2 -2
  50. mlrun/utils/helpers.py +1 -1
  51. mlrun/utils/notifications/notification/__init__.py +1 -1
  52. mlrun/utils/notifications/notification/base.py +14 -13
  53. mlrun/utils/notifications/notification/console.py +6 -3
  54. mlrun/utils/notifications/notification/git.py +19 -12
  55. mlrun/utils/notifications/notification/ipython.py +6 -3
  56. mlrun/utils/notifications/notification/slack.py +13 -12
  57. mlrun/utils/notifications/notification_pusher.py +185 -37
  58. mlrun/utils/version/version.json +2 -2
  59. {mlrun-1.3.1rc5.dist-info → mlrun-1.4.0rc2.dist-info}/METADATA +6 -2
  60. {mlrun-1.3.1rc5.dist-info → mlrun-1.4.0rc2.dist-info}/RECORD +64 -63
  61. mlrun/api/db/filedb/db.py +0 -518
  62. mlrun/db/filedb.py +0 -899
  63. mlrun/runtimes/sparkjob/spark2job.py +0 -59
  64. {mlrun-1.3.1rc5.dist-info → mlrun-1.4.0rc2.dist-info}/LICENSE +0 -0
  65. {mlrun-1.3.1rc5.dist-info → mlrun-1.4.0rc2.dist-info}/WHEEL +0 -0
  66. {mlrun-1.3.1rc5.dist-info → mlrun-1.4.0rc2.dist-info}/entry_points.txt +0 -0
  67. {mlrun-1.3.1rc5.dist-info → mlrun-1.4.0rc2.dist-info}/top_level.txt +0 -0
@@ -13,7 +13,7 @@
13
13
  # limitations under the License.
14
14
  #
15
15
  from datetime import datetime, timezone
16
- from typing import List, Optional
16
+ from typing import Dict, List, Optional
17
17
 
18
18
  from pydantic import BaseModel, Extra, Field
19
19
 
@@ -23,7 +23,7 @@ from mlrun.api.schemas.object import ObjectKind, ObjectSpec, ObjectStatus
23
23
  from mlrun.config import config
24
24
 
25
25
 
26
- # Defining a different base class (not ObjectMetadata), as there's no project and it differs enough to
26
+ # Defining a different base class (not ObjectMetadata), as there's no project, and it differs enough to
27
27
  # justify a new class
28
28
  class MarketplaceObjectMetadata(BaseModel):
29
29
  name: str
@@ -46,6 +46,9 @@ class MarketplaceSourceSpec(ObjectSpec):
46
46
  path: str # URL to base directory, should include schema (s3://, etc...)
47
47
  channel: str
48
48
  credentials: Optional[dict] = {}
49
+ object_type: MarketplaceSourceType = Field(
50
+ MarketplaceSourceType.functions, const=True
51
+ )
49
52
 
50
53
 
51
54
  class MarketplaceSource(BaseModel):
@@ -55,8 +58,11 @@ class MarketplaceSource(BaseModel):
55
58
  status: Optional[ObjectStatus] = ObjectStatus(state="created")
56
59
 
57
60
  def get_full_uri(self, relative_path):
58
- return "{base}/{channel}/{relative_path}".format(
59
- base=self.spec.path, channel=self.spec.channel, relative_path=relative_path
61
+ return "{base}/{object_type}/{channel}/{relative_path}".format(
62
+ base=self.spec.path,
63
+ object_type=self.spec.object_type,
64
+ channel=self.spec.channel,
65
+ relative_path=relative_path,
60
66
  )
61
67
 
62
68
  def get_catalog_uri(self):
@@ -79,6 +85,9 @@ class MarketplaceSource(BaseModel):
79
85
  spec=MarketplaceSourceSpec(
80
86
  path=config.marketplace.default_source.url,
81
87
  channel=config.marketplace.default_source.channel,
88
+ object_type=MarketplaceSourceType(
89
+ config.marketplace.default_source.object_type
90
+ ),
82
91
  ),
83
92
  status=ObjectStatus(state="created"),
84
93
  )
@@ -88,14 +97,13 @@ last_source_index = -1
88
97
 
89
98
 
90
99
  class IndexedMarketplaceSource(BaseModel):
91
- index: int = last_source_index # Default last. Otherwise must be > 0
100
+ index: int = last_source_index # Default last. Otherwise, must be > 0
92
101
  source: MarketplaceSource
93
102
 
94
103
 
95
104
  # Item-related objects
96
105
  class MarketplaceItemMetadata(MarketplaceObjectMetadata):
97
106
  source: MarketplaceSourceType = Field(MarketplaceSourceType.functions, const=True)
98
- channel: str
99
107
  version: str
100
108
  tag: Optional[str]
101
109
 
@@ -103,9 +111,9 @@ class MarketplaceItemMetadata(MarketplaceObjectMetadata):
103
111
  if self.source == MarketplaceSourceType.functions:
104
112
  # This is needed since the marketplace deployment script modifies the paths to use _ instead of -.
105
113
  modified_name = self.name.replace("-", "_")
106
- # Prefer using the tag if exists. Otherwise use version.
114
+ # Prefer using the tag if exists. Otherwise, use version.
107
115
  version = self.tag or self.version
108
- return f"{self.source.value}/{self.channel}/{modified_name}/{version}/"
116
+ return f"{modified_name}/{version}/"
109
117
  else:
110
118
  raise mlrun.errors.MLRunInvalidArgumentError(
111
119
  f"Bad source for marketplace item - {self.source}"
@@ -114,6 +122,7 @@ class MarketplaceItemMetadata(MarketplaceObjectMetadata):
114
122
 
115
123
  class MarketplaceItemSpec(ObjectSpec):
116
124
  item_uri: str
125
+ assets: Dict[str, str] = {}
117
126
 
118
127
 
119
128
  class MarketplaceItem(BaseModel):
@@ -125,4 +134,5 @@ class MarketplaceItem(BaseModel):
125
134
 
126
135
  class MarketplaceCatalog(BaseModel):
127
136
  kind: ObjectKind = Field(ObjectKind.marketplace_catalog, const=True)
137
+ channel: str
128
138
  catalog: List[MarketplaceItem]
@@ -11,4 +11,20 @@
11
11
  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
- #
14
+
15
+
16
+ import mlrun.api.utils.helpers
17
+
18
+
19
+ class NotificationSeverity(mlrun.api.utils.helpers.StrEnum):
20
+ INFO = "info"
21
+ DEBUG = "debug"
22
+ VERBOSE = "verbose"
23
+ WARNING = "warning"
24
+ ERROR = "error"
25
+
26
+
27
+ class NotificationStatus(mlrun.api.utils.helpers.StrEnum):
28
+ PENDING = "pending"
29
+ SENT = "sent"
30
+ ERROR = "error"
@@ -13,7 +13,6 @@
13
13
  # limitations under the License.
14
14
  #
15
15
  from mlrun.api.db.base import DBInterface
16
- from mlrun.api.db.filedb.db import FileDB
17
16
  from mlrun.api.db.sqldb.db import SQLDB
18
17
  from mlrun.api.db.sqldb.session import create_session
19
18
  from mlrun.config import config
@@ -33,16 +32,11 @@ def initialize_db(override_db=None):
33
32
  if override_db:
34
33
  db = override_db
35
34
  return
36
- if config.httpdb.db_type == "filedb":
37
- logger.info("Creating file db")
38
- db = FileDB(config.httpdb.dirpath)
39
- db.initialize(None)
40
- else:
41
- logger.info("Creating sql db")
42
- db = SQLDB(config.httpdb.dsn)
43
- db_session = None
44
- try:
45
- db_session = create_session()
46
- db.initialize(db_session)
47
- finally:
48
- db_session.close()
35
+ logger.info("Creating sql db")
36
+ db = SQLDB(config.httpdb.dsn)
37
+ db_session = None
38
+ try:
39
+ db_session = create_session()
40
+ db.initialize(db_session)
41
+ finally:
42
+ db_session.close()
mlrun/builder.py CHANGED
@@ -35,14 +35,14 @@ IMAGE_NAME_ENRICH_REGISTRY_PREFIX = "."
35
35
 
36
36
 
37
37
  def make_dockerfile(
38
- base_image,
39
- commands=None,
40
- source=None,
41
- requirements=None,
42
- workdir="/mlrun",
43
- extra="",
44
- user_unix_id=None,
45
- enriched_group_id=None,
38
+ base_image: str,
39
+ commands: list = None,
40
+ source: str = None,
41
+ requirements_path: str = None,
42
+ workdir: str = "/mlrun",
43
+ extra: str = "",
44
+ user_unix_id: int = None,
45
+ enriched_group_id: int = None,
46
46
  ):
47
47
  dock = f"FROM {base_image}\n"
48
48
 
@@ -76,10 +76,13 @@ def make_dockerfile(
76
76
  dock += f"RUN chown -R {user_unix_id}:{enriched_group_id} {workdir}\n"
77
77
 
78
78
  dock += f"ENV PYTHONPATH {workdir}\n"
79
- if requirements:
80
- dock += f"RUN python -m pip install -r {requirements}\n"
81
79
  if commands:
82
80
  dock += "".join([f"RUN {command}\n" for command in commands])
81
+ if requirements_path:
82
+ dock += (
83
+ f"RUN echo 'Installing {requirements_path}...'; cat {requirements_path}\n"
84
+ )
85
+ dock += f"RUN python -m pip install -r {requirements_path}\n"
83
86
  if extra:
84
87
  dock += extra
85
88
  logger.debug("Resolved dockerfile", dockfile_contents=dock)
@@ -95,6 +98,7 @@ def make_kaniko_pod(
95
98
  inline_code=None,
96
99
  inline_path=None,
97
100
  requirements=None,
101
+ requirements_path=None,
98
102
  secret_name=None,
99
103
  name="",
100
104
  verbose=False,
@@ -193,19 +197,23 @@ def make_kaniko_pod(
193
197
  commands = []
194
198
  env = {}
195
199
  if dockertext:
196
- commands.append("echo ${DOCKERFILE} | base64 -d > /empty/Dockerfile")
200
+ # set and encode docker content to the DOCKERFILE environment variable in the kaniko pod
197
201
  env["DOCKERFILE"] = b64encode(dockertext.encode("utf-8")).decode("utf-8")
202
+ # dump dockerfile content and decode to Dockerfile destination
203
+ commands.append("echo ${DOCKERFILE} | base64 -d > /empty/Dockerfile")
198
204
  if inline_code:
199
205
  name = inline_path or "main.py"
200
- commands.append("echo ${CODE} | base64 -d > /empty/" + name)
201
206
  env["CODE"] = b64encode(inline_code.encode("utf-8")).decode("utf-8")
207
+ commands.append("echo ${CODE} | base64 -d > /empty/" + name)
202
208
  if requirements:
203
- commands.append(
204
- "echo ${REQUIREMENTS} | base64 -d > /empty/requirements.txt"
205
- )
209
+ # set and encode requirements to the REQUIREMENTS environment variable in the kaniko pod
206
210
  env["REQUIREMENTS"] = b64encode(
207
211
  "\n".join(requirements).encode("utf-8")
208
212
  ).decode("utf-8")
213
+ # dump requirement content and decode to the requirement.txt destination
214
+ commands.append(
215
+ "echo ${REQUIREMENTS}" + " | " + f"base64 -d > {requirements_path}"
216
+ )
209
217
 
210
218
  kpod.append_init_container(
211
219
  config.httpdb.builder.kaniko_init_container_image,
@@ -312,7 +320,6 @@ def build_image(
312
320
  image_target,
313
321
  commands=None,
314
322
  source="",
315
- mounter="v3io",
316
323
  base_image=None,
317
324
  requirements=None,
318
325
  inline_code=None,
@@ -335,15 +342,12 @@ def build_image(
335
342
  image_target, secret_name = _resolve_image_target_and_registry_secret(
336
343
  image_target, registry, secret_name
337
344
  )
338
-
339
- if isinstance(requirements, list):
345
+ if requirements and isinstance(requirements, list):
340
346
  requirements_list = requirements
341
- requirements_path = "requirements.txt"
342
- if source:
343
- raise ValueError("requirements list only works with inline code")
347
+ requirements_path = "/empty/requirements.txt"
344
348
  else:
345
349
  requirements_list = None
346
- requirements_path = requirements
350
+ requirements_path = requirements or ""
347
351
 
348
352
  commands = commands or []
349
353
  if with_mlrun:
@@ -358,7 +362,7 @@ def build_image(
358
362
  if mlrun_command:
359
363
  commands.append(mlrun_command)
360
364
 
361
- if not inline_code and not source and not commands:
365
+ if not inline_code and not source and not commands and not requirements:
362
366
  logger.info("skipping build, nothing to add")
363
367
  return "skipped"
364
368
 
@@ -431,7 +435,7 @@ def build_image(
431
435
  base_image,
432
436
  commands,
433
437
  source=source_to_copy,
434
- requirements=requirements_path,
438
+ requirements_path=requirements_path,
435
439
  extra=extra,
436
440
  user_unix_id=user_unix_id,
437
441
  enriched_group_id=enriched_group_id,
@@ -446,6 +450,7 @@ def build_image(
446
450
  inline_code=inline_code,
447
451
  inline_path=inline_path,
448
452
  requirements=requirements_list,
453
+ requirements_path=requirements_path,
449
454
  secret_name=secret_name,
450
455
  name=name,
451
456
  verbose=verbose,
@@ -555,7 +560,13 @@ def build_runtime(
555
560
  # if the base is one of mlrun images - no need to install mlrun
556
561
  if any([image in build.base_image for image in mlrun_images]):
557
562
  with_mlrun = False
558
- if not build.source and not build.commands and not build.extra and not with_mlrun:
563
+ if (
564
+ not build.source
565
+ and not build.commands
566
+ and not build.requirements
567
+ and not build.extra
568
+ and not with_mlrun
569
+ ):
559
570
  if not runtime.spec.image:
560
571
  if build.base_image:
561
572
  runtime.spec.image = build.base_image
@@ -599,8 +610,8 @@ def build_runtime(
599
610
  image_target=build.image,
600
611
  base_image=enriched_base_image,
601
612
  commands=build.commands,
613
+ requirements=build.requirements,
602
614
  namespace=namespace,
603
- # inline_code=inline,
604
615
  source=build.source,
605
616
  secret_name=build.secret,
606
617
  interactive=interactive,
mlrun/config.py CHANGED
@@ -372,6 +372,15 @@ default_config = {
372
372
  },
373
373
  "v3io_api": "",
374
374
  "v3io_framesd": "",
375
+ # If running from sdk and MLRUN_DBPATH is not set, the db will fallback to a nop db which will not preform any
376
+ # run db operations.
377
+ "nop_db": {
378
+ # if set to true, will raise an error for trying to use run db functionality
379
+ # if set to false, will use a nop db which will not preform any run db operations
380
+ "raise_error": False,
381
+ # if set to true, will log a warning for trying to use run db functionality while in nop db mode
382
+ "verbose": True,
383
+ },
375
384
  },
376
385
  "model_endpoint_monitoring": {
377
386
  "serving_stream_args": {"shard_count": 1, "retention_period_hours": 24},
@@ -432,11 +441,12 @@ default_config = {
432
441
  "k8s_secrets_project_name": "-marketplace-secrets",
433
442
  "catalog_filename": "catalog.json",
434
443
  "default_source": {
435
- # Set to false to avoid creating a global source (for example in a dark site)
444
+ # Set false to avoid creating a global source (for example in a dark site)
436
445
  "create": True,
437
446
  "name": "mlrun_global_hub",
438
447
  "description": "MLRun global function hub",
439
- "url": "https://raw.githubusercontent.com/mlrun/marketplace",
448
+ "url": "https://raw.githubusercontent.com/mlrun/marketplace/master",
449
+ "object_type": "functions",
440
450
  "channel": "master",
441
451
  },
442
452
  },
mlrun/data_types/spark.py CHANGED
@@ -16,6 +16,8 @@ from datetime import datetime
16
16
  from os import environ
17
17
 
18
18
  import numpy as np
19
+ import pytz
20
+ from pyspark.sql.functions import to_utc_timestamp
19
21
  from pyspark.sql.types import BooleanType, DoubleType, TimestampType
20
22
 
21
23
  from mlrun.utils import logger
@@ -143,6 +145,9 @@ def get_df_stats_spark(df, options, num_bins=20, sample_size=None):
143
145
  is_timestamp = isinstance(field.dataType, TimestampType)
144
146
  is_boolean = isinstance(field.dataType, BooleanType)
145
147
  if is_timestamp:
148
+ df_after_type_casts = df_after_type_casts.withColumn(
149
+ field.name, to_utc_timestamp(df_after_type_casts[field.name], "UTC")
150
+ )
146
151
  timestamp_columns.add(field.name)
147
152
  if is_boolean:
148
153
  boolean_columns.add(field.name)
@@ -210,11 +215,13 @@ def get_df_stats_spark(df, options, num_bins=20, sample_size=None):
210
215
  if col in timestamp_columns:
211
216
  for stat, val in stats.items():
212
217
  if stat == "mean" or stat in original_type_stats:
213
- stats[stat] = datetime.fromtimestamp(val).isoformat()
218
+ stats[stat] = datetime.fromtimestamp(val, tz=pytz.UTC).isoformat()
214
219
  elif stat == "hist":
215
220
  values = stats[stat][1]
216
221
  for i in range(len(values)):
217
- values[i] = datetime.fromtimestamp(values[i]).isoformat()
222
+ values[i] = datetime.fromtimestamp(
223
+ values[i], tz=pytz.UTC
224
+ ).isoformat()
218
225
  # for boolean values, keep mean and histogram values numeric (0 to 1 representation)
219
226
  if col in boolean_columns:
220
227
  for stat, val in stats.items():
mlrun/datastore/base.py CHANGED
@@ -383,7 +383,7 @@ class DataItem:
383
383
  return self._store.listdir(self._path)
384
384
 
385
385
  def local(self):
386
- """get the local path of the file, download to tmp first if its a remote object"""
386
+ """get the local path of the file, download to tmp first if it's a remote object"""
387
387
  if self.kind == "file":
388
388
  return self._path
389
389
  if self._local_path:
@@ -397,6 +397,15 @@ class DataItem:
397
397
  self.download(self._local_path)
398
398
  return self._local_path
399
399
 
400
+ def remove_local(self):
401
+ """remove the local file if it exists and was downloaded from a remote object"""
402
+ if self.kind == "file":
403
+ return
404
+
405
+ if self._local_path:
406
+ remove(self._local_path)
407
+ self._local_path = ""
408
+
400
409
  def as_df(
401
410
  self,
402
411
  columns=None,
@@ -885,7 +885,7 @@ class SQLSource(BaseSourceDriver):
885
885
  Reads SqlDB as input source for a flow.
886
886
  example::
887
887
  db_path = "mysql+pymysql://<username>:<password>@<host>:<port>/<db_name>"
888
- source = SqlDBSource(
888
+ source = SQLSource(
889
889
  collection_name='source_name', db_path=self.db, key_field='key'
890
890
  )
891
891
  :param name: source name
mlrun/db/__init__.py CHANGED
@@ -18,7 +18,7 @@ from ..config import config
18
18
  from ..platforms import add_or_refresh_credentials
19
19
  from ..utils import logger
20
20
  from .base import RunDBError, RunDBInterface # noqa
21
- from .filedb import FileRunDB
21
+ from .nopdb import NopDB
22
22
  from .sqldb import SQLDB
23
23
 
24
24
 
@@ -69,12 +69,14 @@ def get_run_db(url="", secrets=None, force_reconnect=False):
69
69
  kwargs = {}
70
70
  if "://" not in str(url) or scheme in ["file", "s3", "v3io", "v3ios"]:
71
71
  logger.warning(
72
- "Could not detect path to API server, Using Deprecated client interface"
72
+ "Could not detect path to API server, not connected to API server!"
73
73
  )
74
74
  logger.warning(
75
- "Please make sure your env variable MLRUN_DBPATH is configured correctly to point to the API server!"
75
+ "MLRUN_DBPATH is not set. Set this environment variable to the URL of the API server"
76
+ " in order to connect"
76
77
  )
77
- cls = FileRunDB
78
+ cls = NopDB
79
+
78
80
  elif scheme in ("http", "https"):
79
81
  # import here to avoid circular imports
80
82
  from .httpdb import HTTPRunDB
mlrun/db/base.py CHANGED
@@ -76,6 +76,7 @@ class RunDBInterface(ABC):
76
76
  partition_sort_by: Union[schemas.SortField, str] = None,
77
77
  partition_order: Union[schemas.OrderType, str] = schemas.OrderType.desc,
78
78
  max_partitions: int = 0,
79
+ with_notifications: bool = False,
79
80
  ):
80
81
  pass
81
82
 
@@ -555,7 +556,6 @@ class RunDBInterface(ABC):
555
556
  def get_marketplace_catalog(
556
557
  self,
557
558
  source_name: str,
558
- channel: str = None,
559
559
  version: str = None,
560
560
  tag: str = None,
561
561
  force_refresh: bool = False,
@@ -567,7 +567,6 @@ class RunDBInterface(ABC):
567
567
  self,
568
568
  source_name: str,
569
569
  item_name: str,
570
- channel: str = "development",
571
570
  version: str = None,
572
571
  tag: str = "latest",
573
572
  force_refresh: bool = False,
mlrun/db/httpdb.py CHANGED
@@ -565,6 +565,7 @@ class HTTPRunDB(RunDBInterface):
565
565
  partition_sort_by: Union[schemas.SortField, str] = None,
566
566
  partition_order: Union[schemas.OrderType, str] = schemas.OrderType.desc,
567
567
  max_partitions: int = 0,
568
+ with_notifications: bool = False,
568
569
  ) -> RunList:
569
570
  """Retrieve a list of runs, filtered by various options.
570
571
  Example::
@@ -598,6 +599,7 @@ class HTTPRunDB(RunDBInterface):
598
599
  :param partition_order: Order of sorting within partitions - `asc` or `desc`. Default is `desc`.
599
600
  :param max_partitions: Maximal number of partitions to include in the result. Default is `0` which means no
600
601
  limit.
602
+ :param with_notifications: Return runs with notifications, and join them to the response. Default is `False`.
601
603
  """
602
604
 
603
605
  project = project or config.default_project
@@ -613,6 +615,7 @@ class HTTPRunDB(RunDBInterface):
613
615
  "start_time_to": datetime_to_iso(start_time_to),
614
616
  "last_update_time_from": datetime_to_iso(last_update_time_from),
615
617
  "last_update_time_to": datetime_to_iso(last_update_time_to),
618
+ "with_notifications": with_notifications,
616
619
  }
617
620
 
618
621
  if partition_by:
@@ -2847,7 +2850,6 @@ class HTTPRunDB(RunDBInterface):
2847
2850
  def get_marketplace_catalog(
2848
2851
  self,
2849
2852
  source_name: str,
2850
- channel: str = None,
2851
2853
  version: str = None,
2852
2854
  tag: str = None,
2853
2855
  force_refresh: bool = False,
@@ -2857,7 +2859,6 @@ class HTTPRunDB(RunDBInterface):
2857
2859
  The list of items can be filtered according to various filters, using item's metadata to filter.
2858
2860
 
2859
2861
  :param source_name: Name of the source.
2860
- :param channel: Filter items according to their channel. For example ``development``.
2861
2862
  :param version: Filter items according to their version.
2862
2863
  :param tag: Filter items based on tag.
2863
2864
  :param force_refresh: Make the server fetch the catalog from the actual marketplace source,
@@ -2869,7 +2870,6 @@ class HTTPRunDB(RunDBInterface):
2869
2870
  """
2870
2871
  path = (f"marketplace/sources/{source_name}/items",)
2871
2872
  params = {
2872
- "channel": channel,
2873
2873
  "version": version,
2874
2874
  "tag": tag,
2875
2875
  "force-refresh": force_refresh,
@@ -2881,7 +2881,6 @@ class HTTPRunDB(RunDBInterface):
2881
2881
  self,
2882
2882
  source_name: str,
2883
2883
  item_name: str,
2884
- channel: str = "development",
2885
2884
  version: str = None,
2886
2885
  tag: str = "latest",
2887
2886
  force_refresh: bool = False,
@@ -2891,7 +2890,6 @@ class HTTPRunDB(RunDBInterface):
2891
2890
 
2892
2891
  :param source_name: Name of source.
2893
2892
  :param item_name: Name of the item to retrieve, as it appears in the catalog.
2894
- :param channel: Get the item from the specified channel. Default is ``development``.
2895
2893
  :param version: Get a specific version of the item. Default is ``None``.
2896
2894
  :param tag: Get a specific version of the item identified by tag. Default is ``latest``.
2897
2895
  :param force_refresh: Make the server fetch the information from the actual marketplace
@@ -2901,7 +2899,6 @@ class HTTPRunDB(RunDBInterface):
2901
2899
  """
2902
2900
  path = (f"marketplace/sources/{source_name}/items/{item_name}",)
2903
2901
  params = {
2904
- "channel": channel,
2905
2902
  "version": version,
2906
2903
  "tag": tag,
2907
2904
  "force-refresh": force_refresh,
@@ -2909,6 +2906,35 @@ class HTTPRunDB(RunDBInterface):
2909
2906
  response = self.api_call(method="GET", path=path, params=params)
2910
2907
  return schemas.MarketplaceItem(**response.json())
2911
2908
 
2909
+ def get_marketplace_asset(
2910
+ self,
2911
+ source_name: str,
2912
+ item_name: str,
2913
+ asset_name: str,
2914
+ version: str = None,
2915
+ tag: str = "latest",
2916
+ ):
2917
+ """
2918
+ Get marketplace asset from item.
2919
+
2920
+ :param source_name: Name of source.
2921
+ :param item_name: Name of the item which holds the asset.
2922
+ :param asset_name: Name of the asset to retrieve.
2923
+ :param version: Get a specific version of the item. Default is ``None``.
2924
+ :param tag: Get a specific version of the item identified by tag. Default is ``latest``.
2925
+
2926
+ :return: http response with the asset in the content attribute
2927
+ """
2928
+ path = (
2929
+ f"marketplace/sources/{source_name}/items/{item_name}/assets/{asset_name}",
2930
+ )
2931
+ params = {
2932
+ "version": version,
2933
+ "tag": tag,
2934
+ }
2935
+ response = self.api_call(method="GET", path=path, params=params)
2936
+ return response
2937
+
2912
2938
  def verify_authorization(
2913
2939
  self, authorization_verification_input: schemas.AuthorizationVerificationInput
2914
2940
  ):