zenml-nightly 0.68.0.dev20241027__py3-none-any.whl → 0.68.1.dev20241101__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.
- README.md +17 -11
- RELEASE_NOTES.md +9 -0
- zenml/VERSION +1 -1
- zenml/__init__.py +1 -1
- zenml/analytics/context.py +16 -1
- zenml/analytics/utils.py +18 -7
- zenml/artifacts/utils.py +40 -216
- zenml/cli/__init__.py +63 -90
- zenml/cli/base.py +3 -3
- zenml/cli/login.py +951 -0
- zenml/cli/server.py +462 -353
- zenml/cli/service_accounts.py +4 -4
- zenml/cli/stack.py +77 -2
- zenml/cli/stack_components.py +5 -16
- zenml/cli/user_management.py +0 -12
- zenml/cli/utils.py +24 -77
- zenml/client.py +46 -14
- zenml/config/compiler.py +1 -0
- zenml/config/global_config.py +9 -0
- zenml/config/pipeline_configurations.py +2 -1
- zenml/config/pipeline_run_configuration.py +2 -1
- zenml/constants.py +3 -9
- zenml/enums.py +1 -1
- zenml/exceptions.py +11 -0
- zenml/integrations/github/code_repositories/github_code_repository.py +1 -1
- zenml/login/__init__.py +16 -0
- zenml/login/credentials.py +346 -0
- zenml/login/credentials_store.py +603 -0
- zenml/login/pro/__init__.py +16 -0
- zenml/login/pro/client.py +496 -0
- zenml/login/pro/constants.py +34 -0
- zenml/login/pro/models.py +25 -0
- zenml/login/pro/organization/__init__.py +14 -0
- zenml/login/pro/organization/client.py +79 -0
- zenml/login/pro/organization/models.py +32 -0
- zenml/login/pro/tenant/__init__.py +14 -0
- zenml/login/pro/tenant/client.py +92 -0
- zenml/login/pro/tenant/models.py +174 -0
- zenml/login/pro/utils.py +121 -0
- zenml/{cli → login}/web_login.py +64 -28
- zenml/materializers/base_materializer.py +43 -9
- zenml/materializers/built_in_materializer.py +1 -1
- zenml/metadata/metadata_types.py +49 -0
- zenml/model/model.py +0 -38
- zenml/models/__init__.py +3 -0
- zenml/models/v2/base/base.py +12 -8
- zenml/models/v2/base/filter.py +9 -0
- zenml/models/v2/core/artifact_version.py +49 -10
- zenml/models/v2/core/component.py +54 -19
- zenml/models/v2/core/flavor.py +13 -13
- zenml/models/v2/core/model.py +3 -1
- zenml/models/v2/core/model_version.py +3 -5
- zenml/models/v2/core/model_version_artifact.py +3 -1
- zenml/models/v2/core/model_version_pipeline_run.py +3 -1
- zenml/models/v2/core/pipeline.py +3 -1
- zenml/models/v2/core/pipeline_run.py +23 -1
- zenml/models/v2/core/run_template.py +3 -1
- zenml/models/v2/core/stack.py +7 -3
- zenml/models/v2/core/step_run.py +43 -2
- zenml/models/v2/misc/auth_models.py +11 -2
- zenml/models/v2/misc/server_models.py +2 -0
- zenml/orchestrators/base_orchestrator.py +8 -4
- zenml/orchestrators/step_launcher.py +1 -0
- zenml/orchestrators/step_run_utils.py +10 -2
- zenml/orchestrators/step_runner.py +67 -55
- zenml/orchestrators/utils.py +45 -22
- zenml/pipelines/pipeline_decorator.py +5 -0
- zenml/pipelines/pipeline_definition.py +206 -160
- zenml/pipelines/run_utils.py +11 -10
- zenml/services/local/local_daemon_entrypoint.py +4 -4
- zenml/services/service.py +2 -2
- zenml/stack/stack.py +2 -6
- zenml/stack/stack_component.py +2 -7
- zenml/stack/utils.py +26 -14
- zenml/steps/base_step.py +8 -2
- zenml/steps/step_context.py +0 -3
- zenml/steps/step_invocation.py +14 -5
- zenml/steps/utils.py +1 -0
- zenml/utils/materializer_utils.py +1 -1
- zenml/utils/requirements_utils.py +71 -0
- zenml/utils/singleton.py +15 -3
- zenml/utils/source_utils.py +39 -2
- zenml/utils/visualization_utils.py +1 -1
- zenml/zen_server/auth.py +44 -39
- zenml/zen_server/deploy/__init__.py +7 -7
- zenml/zen_server/deploy/base_provider.py +46 -73
- zenml/zen_server/deploy/{local → daemon}/__init__.py +3 -3
- zenml/zen_server/deploy/{local/local_provider.py → daemon/daemon_provider.py} +44 -63
- zenml/zen_server/deploy/{local/local_zen_server.py → daemon/daemon_zen_server.py} +50 -22
- zenml/zen_server/deploy/deployer.py +90 -171
- zenml/zen_server/deploy/deployment.py +20 -12
- zenml/zen_server/deploy/docker/docker_provider.py +9 -28
- zenml/zen_server/deploy/docker/docker_zen_server.py +19 -3
- zenml/zen_server/deploy/helm/Chart.yaml +1 -1
- zenml/zen_server/deploy/helm/README.md +2 -2
- zenml/zen_server/exceptions.py +11 -0
- zenml/zen_server/jwt.py +9 -9
- zenml/zen_server/routers/auth_endpoints.py +30 -8
- zenml/zen_server/routers/stack_components_endpoints.py +1 -1
- zenml/zen_server/routers/workspaces_endpoints.py +1 -1
- zenml/zen_server/template_execution/runner_entrypoint_configuration.py +7 -4
- zenml/zen_server/template_execution/utils.py +6 -61
- zenml/zen_server/utils.py +64 -36
- zenml/zen_stores/base_zen_store.py +4 -49
- zenml/zen_stores/migrations/versions/0.68.1_release.py +23 -0
- zenml/zen_stores/migrations/versions/c22561cbb3a9_add_artifact_unique_constraints.py +86 -0
- zenml/zen_stores/rest_zen_store.py +325 -147
- zenml/zen_stores/schemas/api_key_schemas.py +9 -4
- zenml/zen_stores/schemas/artifact_schemas.py +21 -2
- zenml/zen_stores/schemas/artifact_visualization_schemas.py +1 -1
- zenml/zen_stores/schemas/component_schemas.py +49 -6
- zenml/zen_stores/schemas/device_schemas.py +9 -4
- zenml/zen_stores/schemas/flavor_schemas.py +1 -1
- zenml/zen_stores/schemas/model_schemas.py +1 -1
- zenml/zen_stores/schemas/service_schemas.py +1 -1
- zenml/zen_stores/schemas/step_run_schemas.py +1 -1
- zenml/zen_stores/schemas/trigger_schemas.py +1 -1
- zenml/zen_stores/sql_zen_store.py +393 -140
- zenml/zen_stores/template_utils.py +3 -1
- {zenml_nightly-0.68.0.dev20241027.dist-info → zenml_nightly-0.68.1.dev20241101.dist-info}/METADATA +18 -12
- {zenml_nightly-0.68.0.dev20241027.dist-info → zenml_nightly-0.68.1.dev20241101.dist-info}/RECORD +124 -107
- zenml/api.py +0 -60
- {zenml_nightly-0.68.0.dev20241027.dist-info → zenml_nightly-0.68.1.dev20241101.dist-info}/LICENSE +0 -0
- {zenml_nightly-0.68.0.dev20241027.dist-info → zenml_nightly-0.68.1.dev20241101.dist-info}/WHEEL +0 -0
- {zenml_nightly-0.68.0.dev20241027.dist-info → zenml_nightly-0.68.1.dev20241101.dist-info}/entry_points.txt +0 -0
zenml/cli/service_accounts.py
CHANGED
@@ -86,8 +86,8 @@ def _create_api_key(
|
|
86
86
|
f"The API key value is: '{api_key.key}'\nPlease store it safely as "
|
87
87
|
"it will not be shown again.\nTo configure a ZenML client to use "
|
88
88
|
"this API key, run:\n\n"
|
89
|
-
f"zenml
|
90
|
-
f"
|
89
|
+
f"zenml login {zen_store.config.url} --api-key \n\n"
|
90
|
+
f"and enter the following API key when prompted: {api_key.key}\n"
|
91
91
|
)
|
92
92
|
|
93
93
|
|
@@ -543,8 +543,8 @@ def rotate_api_key(
|
|
543
543
|
f"The new API key value is: '{api_key.key}'\nPlease store it "
|
544
544
|
"safely as it will not be shown again.\nTo configure a ZenML "
|
545
545
|
"client to use this API key, run:\n\n"
|
546
|
-
f"zenml
|
547
|
-
f"
|
546
|
+
f"zenml login {zen_store.config.url} --api-key \n\n"
|
547
|
+
f"and enter the following API key when prompted: {api_key.key}\n"
|
548
548
|
)
|
549
549
|
|
550
550
|
|
zenml/cli/stack.py
CHANGED
@@ -75,6 +75,7 @@ from zenml.models.v2.core.service_connector import (
|
|
75
75
|
from zenml.service_connectors.service_connector_utils import (
|
76
76
|
get_resources_options_from_resource_model_for_full_stack,
|
77
77
|
)
|
78
|
+
from zenml.utils import requirements_utils
|
78
79
|
from zenml.utils.dashboard_utils import get_component_url, get_stack_url
|
79
80
|
from zenml.utils.yaml_utils import read_yaml, write_yaml
|
80
81
|
|
@@ -428,7 +429,7 @@ def register_stack(
|
|
428
429
|
object_type=component_type.value.replace("_", " "),
|
429
430
|
choices=[
|
430
431
|
[
|
431
|
-
component.
|
432
|
+
component.flavor_name,
|
432
433
|
component.name,
|
433
434
|
component.configuration or "",
|
434
435
|
component.connector_resource_id,
|
@@ -1624,7 +1625,7 @@ Stack [{deployed_stack.stack.name}]({get_stack_url(deployed_stack.stack)}):\n"""
|
|
1624
1625
|
if components:
|
1625
1626
|
component = components[0]
|
1626
1627
|
stack_desc += (
|
1627
|
-
f" * `{component.
|
1628
|
+
f" * `{component.flavor_name}` {component_type.value}: "
|
1628
1629
|
f"[{component.name}]({get_component_url(component)})\n"
|
1629
1630
|
)
|
1630
1631
|
|
@@ -1944,3 +1945,77 @@ def _get_stack_component_info(
|
|
1944
1945
|
service_connector_index=service_connector_index,
|
1945
1946
|
service_connector_resource_id=service_connector_resource_id,
|
1946
1947
|
)
|
1948
|
+
|
1949
|
+
|
1950
|
+
@stack.command(
|
1951
|
+
name="export-requirements", help="Export the stack requirements."
|
1952
|
+
)
|
1953
|
+
@click.argument(
|
1954
|
+
"stack_name_or_id",
|
1955
|
+
type=click.STRING,
|
1956
|
+
required=False,
|
1957
|
+
)
|
1958
|
+
@click.option(
|
1959
|
+
"--output-file",
|
1960
|
+
"-o",
|
1961
|
+
"output_file",
|
1962
|
+
type=str,
|
1963
|
+
required=False,
|
1964
|
+
help="File to which to export the stack requirements. If not "
|
1965
|
+
"provided, the requirements will be printed to stdout instead.",
|
1966
|
+
)
|
1967
|
+
@click.option(
|
1968
|
+
"--overwrite",
|
1969
|
+
"-ov",
|
1970
|
+
"overwrite",
|
1971
|
+
type=bool,
|
1972
|
+
required=False,
|
1973
|
+
is_flag=True,
|
1974
|
+
help="Overwrite the output file if it already exists. This option is "
|
1975
|
+
"only valid if the output file is provided.",
|
1976
|
+
)
|
1977
|
+
def export_requirements(
|
1978
|
+
stack_name_or_id: Optional[str] = None,
|
1979
|
+
output_file: Optional[str] = None,
|
1980
|
+
overwrite: bool = False,
|
1981
|
+
) -> None:
|
1982
|
+
"""Exports stack requirements so they can be installed using pip.
|
1983
|
+
|
1984
|
+
Args:
|
1985
|
+
stack_name_or_id: Stack name or ID. If not given, the active stack will
|
1986
|
+
be used.
|
1987
|
+
output_file: Optional path to the requirements output file.
|
1988
|
+
overwrite: Overwrite the output file if it already exists. This option
|
1989
|
+
is only valid if the output file is provided.
|
1990
|
+
"""
|
1991
|
+
try:
|
1992
|
+
stack_model: "StackResponse" = Client().get_stack(
|
1993
|
+
name_id_or_prefix=stack_name_or_id
|
1994
|
+
)
|
1995
|
+
except KeyError as err:
|
1996
|
+
cli_utils.error(str(err))
|
1997
|
+
|
1998
|
+
requirements, _ = requirements_utils.get_requirements_for_stack(
|
1999
|
+
stack_model
|
2000
|
+
)
|
2001
|
+
|
2002
|
+
if not requirements:
|
2003
|
+
cli_utils.declare(f"Stack `{stack_model.name}` has no requirements.")
|
2004
|
+
return
|
2005
|
+
|
2006
|
+
if output_file:
|
2007
|
+
try:
|
2008
|
+
with open(output_file, "x") as f:
|
2009
|
+
f.write("\n".join(requirements))
|
2010
|
+
except FileExistsError:
|
2011
|
+
if overwrite or cli_utils.confirmation(
|
2012
|
+
"A file already exists at the specified path. "
|
2013
|
+
"Would you like to overwrite it?"
|
2014
|
+
):
|
2015
|
+
with open(output_file, "w") as f:
|
2016
|
+
f.write("\n".join(requirements))
|
2017
|
+
cli_utils.declare(
|
2018
|
+
f"Requirements for stack `{stack_model.name}` exported to {output_file}."
|
2019
|
+
)
|
2020
|
+
else:
|
2021
|
+
click.echo(" ".join(requirements), nl=False)
|
zenml/cli/stack_components.py
CHANGED
@@ -123,10 +123,9 @@ def generate_stack_component_describe_command(
|
|
123
123
|
active_component_id = active_components[0].id
|
124
124
|
|
125
125
|
if component_.connector:
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
).connector_requirements
|
126
|
+
connector_requirements = (
|
127
|
+
component_.flavor.connector_requirements
|
128
|
+
)
|
130
129
|
else:
|
131
130
|
connector_requirements = None
|
132
131
|
|
@@ -570,7 +569,7 @@ def generate_stack_component_copy_command(
|
|
570
569
|
|
571
570
|
copied_component = client.create_stack_component(
|
572
571
|
name=target_component,
|
573
|
-
flavor=component_to_copy.
|
572
|
+
flavor=component_to_copy.flavor_name,
|
574
573
|
component_type=component_to_copy.type,
|
575
574
|
configuration=component_to_copy.configuration,
|
576
575
|
labels=component_to_copy.labels,
|
@@ -1366,17 +1365,7 @@ def connect_stack_component_with_service_connector(
|
|
1366
1365
|
except KeyError as err:
|
1367
1366
|
cli_utils.error(str(err))
|
1368
1367
|
|
1369
|
-
|
1370
|
-
flavor_model = client.get_flavor_by_name_and_type(
|
1371
|
-
name=component_model.flavor, component_type=component_type
|
1372
|
-
)
|
1373
|
-
except KeyError as err:
|
1374
|
-
cli_utils.error(
|
1375
|
-
f"Could not find flavor '{component_model.flavor}' for "
|
1376
|
-
f"{display_name} '{name_id_or_prefix}': {str(err)}"
|
1377
|
-
)
|
1378
|
-
|
1379
|
-
requirements = flavor_model.connector_requirements
|
1368
|
+
requirements = component_model.flavor.connector_requirements
|
1380
1369
|
|
1381
1370
|
if not requirements:
|
1382
1371
|
cli_utils.error(
|
zenml/cli/user_management.py
CHANGED
@@ -367,18 +367,6 @@ def change_user_password(
|
|
367
367
|
f"Successfully updated password for active user '{active_user.name}'."
|
368
368
|
)
|
369
369
|
|
370
|
-
store = GlobalConfiguration().store_configuration
|
371
|
-
if store.type == StoreType.REST:
|
372
|
-
from zenml.zen_stores.rest_zen_store import RestZenStoreConfiguration
|
373
|
-
|
374
|
-
assert isinstance(store, RestZenStoreConfiguration)
|
375
|
-
|
376
|
-
if store.password is not None:
|
377
|
-
cli_utils.declare(
|
378
|
-
"You may need to log in again with your new password by "
|
379
|
-
"running `zenml connect`."
|
380
|
-
)
|
381
|
-
|
382
370
|
|
383
371
|
@user.command(
|
384
372
|
"deactivate",
|
zenml/cli/utils.py
CHANGED
@@ -79,7 +79,6 @@ from zenml.services import BaseService, ServiceState
|
|
79
79
|
from zenml.stack import StackComponent
|
80
80
|
from zenml.stack.stack_component import StackComponentConfig
|
81
81
|
from zenml.utils import secret_utils
|
82
|
-
from zenml.zen_server.deploy import ServerDeployment
|
83
82
|
|
84
83
|
if TYPE_CHECKING:
|
85
84
|
from uuid import UUID
|
@@ -223,6 +222,8 @@ def print_table(
|
|
223
222
|
caption: Caption of the table.
|
224
223
|
columns: Optional column configurations to be used in the table.
|
225
224
|
"""
|
225
|
+
from rich.text import Text
|
226
|
+
|
226
227
|
column_keys = {key: None for dict_ in obj for key in dict_}
|
227
228
|
column_names = [columns.get(key, key.upper()) for key in column_keys]
|
228
229
|
rich_table = table.Table(
|
@@ -241,10 +242,19 @@ def print_table(
|
|
241
242
|
if key is None:
|
242
243
|
values.append(None)
|
243
244
|
else:
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
245
|
+
v = dict_.get(key) or " "
|
246
|
+
if isinstance(v, str) and (
|
247
|
+
v.startswith("http://") or v.startswith("https://")
|
248
|
+
):
|
249
|
+
# Display the URL as a hyperlink in a way that doesn't break
|
250
|
+
# the URL when it needs to be wrapped over multiple lines
|
251
|
+
value: Union[str, Text] = Text(v, style=f"link {v}")
|
252
|
+
else:
|
253
|
+
value = str(v)
|
254
|
+
# Escape text when square brackets are used, but allow
|
255
|
+
# links to be decorated as rich style links
|
256
|
+
if "[" in value and "[link=" not in value:
|
257
|
+
value = escape(value)
|
248
258
|
values.append(value)
|
249
259
|
rich_table.add_row(*values)
|
250
260
|
if len(rich_table.columns) > 1:
|
@@ -258,6 +268,7 @@ def print_pydantic_models(
|
|
258
268
|
exclude_columns: Optional[List[str]] = None,
|
259
269
|
active_models: Optional[List[T]] = None,
|
260
270
|
show_active: bool = False,
|
271
|
+
rename_columns: Dict[str, str] = {},
|
261
272
|
) -> None:
|
262
273
|
"""Prints the list of Pydantic models in a table.
|
263
274
|
|
@@ -270,6 +281,7 @@ def print_pydantic_models(
|
|
270
281
|
active_models: Optional list of active models of the given type T.
|
271
282
|
show_active: Flag to decide whether to append the active model on the
|
272
283
|
top of the list.
|
284
|
+
rename_columns: Optional dictionary to rename columns.
|
273
285
|
"""
|
274
286
|
if exclude_columns is None:
|
275
287
|
exclude_columns = list()
|
@@ -326,6 +338,8 @@ def print_pydantic_models(
|
|
326
338
|
|
327
339
|
for k in include_columns:
|
328
340
|
value = getattr(model, k)
|
341
|
+
if k in rename_columns:
|
342
|
+
k = rename_columns[k]
|
329
343
|
# In case the response model contains nested `BaseResponse`s
|
330
344
|
# we want to attempt to represent them by name, if they contain
|
331
345
|
# such a field, else the id is used
|
@@ -350,6 +364,7 @@ def print_pydantic_models(
|
|
350
364
|
items[k] = [str(v) for v in value]
|
351
365
|
else:
|
352
366
|
items[k] = str(value)
|
367
|
+
|
353
368
|
# prepend an active marker if a function to mark active was passed
|
354
369
|
if not active_models and not show_active:
|
355
370
|
return items
|
@@ -613,7 +628,7 @@ def print_stack_component_configuration(
|
|
613
628
|
|
614
629
|
declare(
|
615
630
|
f"{component.type.value.title()} '{component.name}' of flavor "
|
616
|
-
f"'{component.
|
631
|
+
f"'{component.flavor_name}' with id '{component.id}' is owned by "
|
617
632
|
f"user '{user_name}'."
|
618
633
|
)
|
619
634
|
|
@@ -1391,74 +1406,6 @@ def print_served_model_configuration(
|
|
1391
1406
|
console.print(rich_table)
|
1392
1407
|
|
1393
1408
|
|
1394
|
-
def print_server_deployment_list(servers: List["ServerDeployment"]) -> None:
|
1395
|
-
"""Print a table with a list of ZenML server deployments.
|
1396
|
-
|
1397
|
-
Args:
|
1398
|
-
servers: list of ZenML server deployments
|
1399
|
-
"""
|
1400
|
-
server_dicts = []
|
1401
|
-
for server in servers:
|
1402
|
-
status = ""
|
1403
|
-
url = ""
|
1404
|
-
connected = ""
|
1405
|
-
if server.status:
|
1406
|
-
status = get_service_state_emoji(server.status.status)
|
1407
|
-
if server.status.url:
|
1408
|
-
url = server.status.url
|
1409
|
-
if server.status.connected:
|
1410
|
-
connected = ":point_left:"
|
1411
|
-
server_dicts.append(
|
1412
|
-
{
|
1413
|
-
"STATUS": status,
|
1414
|
-
"NAME": server.config.name,
|
1415
|
-
"PROVIDER": server.config.provider.value,
|
1416
|
-
"URL": url,
|
1417
|
-
"CONNECTED": connected,
|
1418
|
-
}
|
1419
|
-
)
|
1420
|
-
print_table(server_dicts)
|
1421
|
-
|
1422
|
-
|
1423
|
-
def print_server_deployment(server: "ServerDeployment") -> None:
|
1424
|
-
"""Prints the configuration and status of a ZenML server deployment.
|
1425
|
-
|
1426
|
-
Args:
|
1427
|
-
server: Server deployment to print
|
1428
|
-
"""
|
1429
|
-
server_name = server.config.name
|
1430
|
-
title_ = f"ZenML server '{server_name}'"
|
1431
|
-
|
1432
|
-
rich_table = table.Table(
|
1433
|
-
box=box.HEAVY_EDGE,
|
1434
|
-
title=title_,
|
1435
|
-
show_header=False,
|
1436
|
-
show_lines=True,
|
1437
|
-
)
|
1438
|
-
rich_table.add_column("", overflow="fold")
|
1439
|
-
rich_table.add_column("", overflow="fold")
|
1440
|
-
|
1441
|
-
server_info = []
|
1442
|
-
|
1443
|
-
if server.status:
|
1444
|
-
server_info.extend(
|
1445
|
-
[
|
1446
|
-
("URL", server.status.url or ""),
|
1447
|
-
("STATUS", get_service_state_emoji(server.status.status)),
|
1448
|
-
("STATUS_MESSAGE", server.status.status_message or ""),
|
1449
|
-
(
|
1450
|
-
"CONNECTED",
|
1451
|
-
":white_check_mark:" if server.status.connected else "",
|
1452
|
-
),
|
1453
|
-
]
|
1454
|
-
)
|
1455
|
-
|
1456
|
-
for item in server_info:
|
1457
|
-
rich_table.add_row(*item)
|
1458
|
-
|
1459
|
-
console.print(rich_table)
|
1460
|
-
|
1461
|
-
|
1462
1409
|
def describe_pydantic_object(schema_json: Dict[str, Any]) -> None:
|
1463
1410
|
"""Describes a Pydantic object based on the dict-representation of its schema.
|
1464
1411
|
|
@@ -1632,7 +1579,7 @@ def print_components_table(
|
|
1632
1579
|
"ACTIVE": ":point_right:" if is_active else "",
|
1633
1580
|
"NAME": component.name,
|
1634
1581
|
"COMPONENT ID": component.id,
|
1635
|
-
"FLAVOR": component.
|
1582
|
+
"FLAVOR": component.flavor_name,
|
1636
1583
|
"OWNER": f"{component.user.name if component.user else '-'}",
|
1637
1584
|
}
|
1638
1585
|
configurations.append(component_config)
|
@@ -2719,8 +2666,8 @@ def print_model_url(url: Optional[str]) -> None:
|
|
2719
2666
|
warning(
|
2720
2667
|
"You can display various ZenML entities including pipelines, "
|
2721
2668
|
"runs, stacks and much more on the ZenML Dashboard. "
|
2722
|
-
"You can try it locally, by running `zenml
|
2723
|
-
"by deploying ZenML on the infrastructure of your choice."
|
2669
|
+
"You can try it locally, by running `zenml local --local`, or "
|
2670
|
+
"remotely, by deploying ZenML on the infrastructure of your choice."
|
2724
2671
|
)
|
2725
2672
|
|
2726
2673
|
|
zenml/client.py
CHANGED
@@ -346,6 +346,8 @@ class Client(metaclass=ClientMetaClass):
|
|
346
346
|
"""
|
347
347
|
|
348
348
|
_active_user: Optional["UserResponse"] = None
|
349
|
+
_active_workspace: Optional["WorkspaceResponse"] = None
|
350
|
+
_active_stack: Optional["StackResponse"] = None
|
349
351
|
|
350
352
|
def __init__(
|
351
353
|
self,
|
@@ -1113,9 +1115,13 @@ class Client(metaclass=ClientMetaClass):
|
|
1113
1115
|
Raises:
|
1114
1116
|
RuntimeError: If the active workspace is not set.
|
1115
1117
|
"""
|
1116
|
-
if
|
1117
|
-
|
1118
|
-
|
1118
|
+
if workspace_id := os.environ.get(ENV_ZENML_ACTIVE_WORKSPACE_ID):
|
1119
|
+
if not self._active_workspace or self._active_workspace.id != UUID(
|
1120
|
+
workspace_id
|
1121
|
+
):
|
1122
|
+
self._active_workspace = self.get_workspace(workspace_id)
|
1123
|
+
|
1124
|
+
return self._active_workspace
|
1119
1125
|
|
1120
1126
|
from zenml.constants import DEFAULT_WORKSPACE_NAME
|
1121
1127
|
|
@@ -1465,8 +1471,13 @@ class Client(metaclass=ClientMetaClass):
|
|
1465
1471
|
Raises:
|
1466
1472
|
RuntimeError: If the active stack is not set.
|
1467
1473
|
"""
|
1468
|
-
if
|
1469
|
-
|
1474
|
+
if env_stack_id := os.environ.get(ENV_ZENML_ACTIVE_STACK_ID):
|
1475
|
+
if not self._active_stack or self._active_stack.id != UUID(
|
1476
|
+
env_stack_id
|
1477
|
+
):
|
1478
|
+
self._active_stack = self.get_stack(env_stack_id)
|
1479
|
+
|
1480
|
+
return self._active_stack
|
1470
1481
|
|
1471
1482
|
stack_id: Optional[UUID] = None
|
1472
1483
|
|
@@ -1534,6 +1545,8 @@ class Client(metaclass=ClientMetaClass):
|
|
1534
1545
|
remote_components: List[str] = []
|
1535
1546
|
assert stack.components is not None
|
1536
1547
|
for component_type, components in stack.components.items():
|
1548
|
+
component_flavor: Union[FlavorResponse, str]
|
1549
|
+
|
1537
1550
|
for component in components:
|
1538
1551
|
if isinstance(component, UUID):
|
1539
1552
|
component_response = self.get_stack_component(
|
@@ -1554,7 +1567,7 @@ class Client(metaclass=ClientMetaClass):
|
|
1554
1567
|
|
1555
1568
|
configuration = validate_stack_component_config(
|
1556
1569
|
configuration_dict=component_config,
|
1557
|
-
|
1570
|
+
flavor=component_flavor,
|
1558
1571
|
component_type=component_type,
|
1559
1572
|
# Always enforce validation of custom flavors
|
1560
1573
|
validate_custom_flavors=True,
|
@@ -1563,13 +1576,18 @@ class Client(metaclass=ClientMetaClass):
|
|
1563
1576
|
# `validate_custom_flavors=True` above
|
1564
1577
|
assert configuration is not None
|
1565
1578
|
warn_if_config_server_mismatch(configuration)
|
1579
|
+
flavor_name = (
|
1580
|
+
component_flavor.name
|
1581
|
+
if isinstance(component_flavor, FlavorResponse)
|
1582
|
+
else component_flavor
|
1583
|
+
)
|
1566
1584
|
if configuration.is_local:
|
1567
1585
|
local_components.append(
|
1568
|
-
f"{component_type.value}: {
|
1586
|
+
f"{component_type.value}: {flavor_name}"
|
1569
1587
|
)
|
1570
1588
|
elif configuration.is_remote:
|
1571
1589
|
remote_components.append(
|
1572
|
-
f"{component_type.value}: {
|
1590
|
+
f"{component_type.value}: {flavor_name}"
|
1573
1591
|
)
|
1574
1592
|
|
1575
1593
|
if local_components and remote_components:
|
@@ -1906,6 +1924,7 @@ class Client(metaclass=ClientMetaClass):
|
|
1906
1924
|
user_id: Optional[Union[str, UUID]] = None,
|
1907
1925
|
connector_id: Optional[Union[str, UUID]] = None,
|
1908
1926
|
stack_id: Optional[Union[str, UUID]] = None,
|
1927
|
+
user: Optional[Union[UUID, str]] = None,
|
1909
1928
|
hydrate: bool = False,
|
1910
1929
|
) -> Page[ComponentResponse]:
|
1911
1930
|
"""Lists all registered stack components.
|
@@ -1925,6 +1944,7 @@ class Client(metaclass=ClientMetaClass):
|
|
1925
1944
|
connector_id: The id of the connector to filter by.
|
1926
1945
|
stack_id: The id of the stack to filter by.
|
1927
1946
|
name: The name of the component to filter by.
|
1947
|
+
user: The ID of name of the user to filter by.
|
1928
1948
|
hydrate: Flag deciding whether to hydrate the output model(s)
|
1929
1949
|
by including metadata fields in the response.
|
1930
1950
|
|
@@ -1946,6 +1966,7 @@ class Client(metaclass=ClientMetaClass):
|
|
1946
1966
|
id=id,
|
1947
1967
|
created=created,
|
1948
1968
|
updated=updated,
|
1969
|
+
user=user,
|
1949
1970
|
)
|
1950
1971
|
component_filter_model.set_scope_workspace(self.active_workspace.id)
|
1951
1972
|
|
@@ -1982,7 +2003,7 @@ class Client(metaclass=ClientMetaClass):
|
|
1982
2003
|
|
1983
2004
|
validated_config = validate_stack_component_config(
|
1984
2005
|
configuration_dict=configuration,
|
1985
|
-
|
2006
|
+
flavor=flavor,
|
1986
2007
|
component_type=component_type,
|
1987
2008
|
# Always enforce validation of custom flavors
|
1988
2009
|
validate_custom_flavors=True,
|
@@ -2083,7 +2104,7 @@ class Client(metaclass=ClientMetaClass):
|
|
2083
2104
|
|
2084
2105
|
validated_config = validate_stack_component_config(
|
2085
2106
|
configuration_dict=existing_configuration,
|
2086
|
-
|
2107
|
+
flavor=component.flavor,
|
2087
2108
|
component_type=component.type,
|
2088
2109
|
# Always enforce validation of custom flavors
|
2089
2110
|
validate_custom_flavors=True,
|
@@ -3778,6 +3799,7 @@ class Client(metaclass=ClientMetaClass):
|
|
3778
3799
|
code_repository: Optional[Union[UUID, str]] = None,
|
3779
3800
|
model: Optional[Union[UUID, str]] = None,
|
3780
3801
|
stack: Optional[Union[UUID, str]] = None,
|
3802
|
+
stack_component: Optional[Union[UUID, str]] = None,
|
3781
3803
|
hydrate: bool = False,
|
3782
3804
|
) -> Page[PipelineRunResponse]:
|
3783
3805
|
"""List all pipeline runs.
|
@@ -3816,6 +3838,7 @@ class Client(metaclass=ClientMetaClass):
|
|
3816
3838
|
code_repository: Filter by code repository name/ID.
|
3817
3839
|
model: Filter by model name/ID.
|
3818
3840
|
stack: Filter by stack name/ID.
|
3841
|
+
stack_component: Filter by stack component name/ID.
|
3819
3842
|
hydrate: Flag deciding whether to hydrate the output model(s)
|
3820
3843
|
by including metadata fields in the response.
|
3821
3844
|
|
@@ -3854,6 +3877,7 @@ class Client(metaclass=ClientMetaClass):
|
|
3854
3877
|
code_repository=code_repository,
|
3855
3878
|
stack=stack,
|
3856
3879
|
model=model,
|
3880
|
+
stack_component=stack_component,
|
3857
3881
|
templatable=templatable,
|
3858
3882
|
)
|
3859
3883
|
runs_filter_model.set_scope_workspace(self.active_workspace.id)
|
@@ -3919,7 +3943,7 @@ class Client(metaclass=ClientMetaClass):
|
|
3919
3943
|
workspace_id: Optional[Union[str, UUID]] = None,
|
3920
3944
|
user_id: Optional[Union[str, UUID]] = None,
|
3921
3945
|
model_version_id: Optional[Union[str, UUID]] = None,
|
3922
|
-
|
3946
|
+
model: Optional[Union[UUID, str]] = None,
|
3923
3947
|
hydrate: bool = False,
|
3924
3948
|
) -> Page[StepRunResponse]:
|
3925
3949
|
"""List all pipelines.
|
@@ -3940,11 +3964,11 @@ class Client(metaclass=ClientMetaClass):
|
|
3940
3964
|
deployment_id: The id of the deployment to filter by.
|
3941
3965
|
original_step_run_id: The id of the original step run to filter by.
|
3942
3966
|
model_version_id: The ID of the model version to filter by.
|
3967
|
+
model: Filter by model name/ID.
|
3943
3968
|
name: The name of the step run to filter by.
|
3944
3969
|
cache_key: The cache key of the step run to filter by.
|
3945
3970
|
code_hash: The code hash of the step run to filter by.
|
3946
3971
|
status: The name of the run to filter by.
|
3947
|
-
num_outputs: The number of outputs for the step run
|
3948
3972
|
hydrate: Flag deciding whether to hydrate the output model(s)
|
3949
3973
|
by including metadata fields in the response.
|
3950
3974
|
|
@@ -3971,7 +3995,7 @@ class Client(metaclass=ClientMetaClass):
|
|
3971
3995
|
workspace_id=workspace_id,
|
3972
3996
|
user_id=user_id,
|
3973
3997
|
model_version_id=model_version_id,
|
3974
|
-
|
3998
|
+
model=model,
|
3975
3999
|
)
|
3976
4000
|
step_run_filter_model.set_scope_workspace(self.active_workspace.id)
|
3977
4001
|
return self.zen_store.list_run_steps(
|
@@ -7243,6 +7267,7 @@ class Client(metaclass=ClientMetaClass):
|
|
7243
7267
|
NotImplementedError: If the client is not connected to a ZenML
|
7244
7268
|
server.
|
7245
7269
|
"""
|
7270
|
+
from zenml.login.credentials_store import get_credentials_store
|
7246
7271
|
from zenml.zen_stores.rest_zen_store import RestZenStore
|
7247
7272
|
|
7248
7273
|
zen_store = self.zen_store
|
@@ -7251,8 +7276,15 @@ class Client(metaclass=ClientMetaClass):
|
|
7251
7276
|
"API key configuration is only supported if connected to a "
|
7252
7277
|
"ZenML server."
|
7253
7278
|
)
|
7279
|
+
|
7280
|
+
credentials_store = get_credentials_store()
|
7254
7281
|
assert isinstance(zen_store, RestZenStore)
|
7255
|
-
|
7282
|
+
|
7283
|
+
credentials_store.set_api_key(server_url=zen_store.url, api_key=key)
|
7284
|
+
|
7285
|
+
# Force a re-authentication to start using the new API key
|
7286
|
+
# right away.
|
7287
|
+
zen_store.authenticate(force=True)
|
7256
7288
|
|
7257
7289
|
def list_api_keys(
|
7258
7290
|
self,
|
zenml/config/compiler.py
CHANGED
@@ -208,6 +208,7 @@ class Compiler:
|
|
208
208
|
enable_artifact_visualization=config.enable_artifact_visualization,
|
209
209
|
enable_step_logs=config.enable_step_logs,
|
210
210
|
settings=config.settings,
|
211
|
+
tags=config.tags,
|
211
212
|
extra=config.extra,
|
212
213
|
model=config.model,
|
213
214
|
parameters=config.parameters,
|
zenml/config/global_config.py
CHANGED
@@ -689,6 +689,15 @@ class GlobalConfiguration(BaseModel, metaclass=GlobalConfigMetaClass):
|
|
689
689
|
self._configure_store(config, skip_default_registrations, **kwargs)
|
690
690
|
logger.info("Updated the global store configuration.")
|
691
691
|
|
692
|
+
@property
|
693
|
+
def is_initialized(self) -> bool:
|
694
|
+
"""Check if the global configuration is initialized.
|
695
|
+
|
696
|
+
Returns:
|
697
|
+
`True` if the global configuration is initialized.
|
698
|
+
"""
|
699
|
+
return self._zen_store is not None
|
700
|
+
|
692
701
|
@property
|
693
702
|
def zen_store(self) -> "BaseZenStore":
|
694
703
|
"""Initialize and/or return the global zen store.
|
@@ -13,7 +13,7 @@
|
|
13
13
|
# permissions and limitations under the License.
|
14
14
|
"""Pipeline configuration classes."""
|
15
15
|
|
16
|
-
from typing import TYPE_CHECKING, Any, Dict, Optional
|
16
|
+
from typing import TYPE_CHECKING, Any, Dict, List, Optional
|
17
17
|
|
18
18
|
from pydantic import SerializeAsAny, field_validator
|
19
19
|
|
@@ -39,6 +39,7 @@ class PipelineConfigurationUpdate(StrictBaseModel):
|
|
39
39
|
enable_artifact_visualization: Optional[bool] = None
|
40
40
|
enable_step_logs: Optional[bool] = None
|
41
41
|
settings: Dict[str, SerializeAsAny[BaseSettings]] = {}
|
42
|
+
tags: Optional[List[str]] = None
|
42
43
|
extra: Dict[str, Any] = {}
|
43
44
|
failure_hook_source: Optional[SourceWithValidator] = None
|
44
45
|
success_hook_source: Optional[SourceWithValidator] = None
|
@@ -13,7 +13,7 @@
|
|
13
13
|
# permissions and limitations under the License.
|
14
14
|
"""Pipeline run configuration class."""
|
15
15
|
|
16
|
-
from typing import Any, Dict, Optional, Union
|
16
|
+
from typing import Any, Dict, List, Optional, Union
|
17
17
|
from uuid import UUID
|
18
18
|
|
19
19
|
from pydantic import Field, SerializeAsAny
|
@@ -45,6 +45,7 @@ class PipelineRunConfiguration(
|
|
45
45
|
)
|
46
46
|
steps: Dict[str, StepConfigurationUpdate] = {}
|
47
47
|
settings: Dict[str, SerializeAsAny[BaseSettings]] = {}
|
48
|
+
tags: Optional[List[str]] = None
|
48
49
|
extra: Dict[str, Any] = {}
|
49
50
|
model: Optional[Model] = None
|
50
51
|
parameters: Optional[Dict[str, Any]] = None
|
zenml/constants.py
CHANGED
@@ -134,6 +134,7 @@ APP_NAME = "zenml"
|
|
134
134
|
# Environment variables
|
135
135
|
ENV_ZENML_LOGGING_COLORS_DISABLED = "ZENML_LOGGING_COLORS_DISABLED"
|
136
136
|
ENV_ZENML_ANALYTICS_OPT_IN = "ZENML_ANALYTICS_OPT_IN"
|
137
|
+
ENV_ZENML_USER_ID = "ZENML_USER_ID"
|
137
138
|
ENV_ZENML_CONFIG_PATH = "ZENML_CONFIG_PATH"
|
138
139
|
ENV_ZENML_DEBUG = "ZENML_DEBUG"
|
139
140
|
ENV_ZENML_LOGGING_VERBOSITY = "ZENML_LOGGING_VERBOSITY"
|
@@ -163,7 +164,6 @@ ENV_ZENML_DISABLE_CLIENT_SERVER_MISMATCH_WARNING = (
|
|
163
164
|
ENV_ZENML_DISABLE_WORKSPACE_WARNINGS = "ZENML_DISABLE_WORKSPACE_WARNINGS"
|
164
165
|
ENV_ZENML_SKIP_IMAGE_BUILDER_DEFAULT = "ZENML_SKIP_IMAGE_BUILDER_DEFAULT"
|
165
166
|
ENV_ZENML_SERVER = "ZENML_SERVER"
|
166
|
-
ENV_ZENML_LOCAL_SERVER = "ZENML_LOCAL_SERVER"
|
167
167
|
ENV_ZENML_ENFORCE_TYPE_ANNOTATIONS = "ZENML_ENFORCE_TYPE_ANNOTATIONS"
|
168
168
|
ENV_ZENML_ENABLE_IMPLICIT_AUTH_METHODS = "ZENML_ENABLE_IMPLICIT_AUTH_METHODS"
|
169
169
|
ENV_ZENML_DISABLE_STEP_LOGS_STORAGE = "ZENML_DISABLE_STEP_LOGS_STORAGE"
|
@@ -186,6 +186,7 @@ ENV_ZENML_RUN_SINGLE_STEPS_WITHOUT_STACK = (
|
|
186
186
|
"ZENML_RUN_SINGLE_STEPS_WITHOUT_STACK"
|
187
187
|
)
|
188
188
|
ENV_ZENML_PREVENT_CLIENT_SIDE_CACHING = "ZENML_PREVENT_CLIENT_SIDE_CACHING"
|
189
|
+
ENV_ZENML_DISABLE_CREDENTIALS_DISK_CACHING = "DISABLE_CREDENTIALS_DISK_CACHING"
|
189
190
|
|
190
191
|
# Logging variables
|
191
192
|
IS_DEBUG_ENV: bool = handle_bool_env_var(ENV_ZENML_DEBUG, default=False)
|
@@ -336,6 +337,7 @@ API_TOKEN = "/api_token"
|
|
336
337
|
ARTIFACTS = "/artifacts"
|
337
338
|
ARTIFACT_VERSIONS = "/artifact_versions"
|
338
339
|
ARTIFACT_VISUALIZATIONS = "/artifact_visualizations"
|
340
|
+
AUTH = "/auth"
|
339
341
|
CODE_REFERENCES = "/code_references"
|
340
342
|
CODE_REPOSITORIES = "/code_repositories"
|
341
343
|
COMPONENT_TYPES = "/component-types"
|
@@ -468,11 +470,3 @@ BANNED_NAME_CHARACTERS = "\t\n\r\v\f"
|
|
468
470
|
|
469
471
|
|
470
472
|
STACK_DEPLOYMENT_API_TOKEN_EXPIRATION = 60 * 6 # 6 hours
|
471
|
-
|
472
|
-
# ZenML Pro
|
473
|
-
ZENML_PRO_CONNECTION_ISSUES_SUSPENDED_PAUSED_TENANT_HINT = (
|
474
|
-
"\nHINT: Since you are trying to communicate with the ZenML Pro Tenant, "
|
475
|
-
"please make sure that your tenant is in RUNNING state on your "
|
476
|
-
"Organization page. If the tenant is PAUSED you can `Resume` it via UI "
|
477
|
-
"and try again."
|
478
|
-
)
|