-
Notifications
You must be signed in to change notification settings - Fork 36
/
Copy pathcli.py
177 lines (147 loc) · 5.11 KB
/
cli.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
import subprocess
from pathlib import Path
import click
from kedro.framework.cli.utils import _add_src_to_path
from kedro.framework.session import KedroSession
from kedro.framework.startup import _get_project_metadata, _is_project
from kedro_mlflow.framework.cli.cli_utils import write_jinja_template
from kedro_mlflow.framework.context import get_mlflow_config
TEMPLATE_FOLDER_PATH = Path(__file__).parent.parent.parent / "template" / "project"
class KedroClickGroup(click.Group):
def reset_commands(self):
self.commands = {}
# add commands on the fly based on conditions
if _is_project(Path.cwd()):
self.add_command(init)
self.add_command(ui)
# self.add_command(run) # TODO : IMPLEMENT THIS FUNCTION
else:
self.add_command(new)
def list_commands(self, ctx):
self.reset_commands()
commands_list = sorted(self.commands)
return commands_list
def get_command(self, ctx, cmd_name):
self.reset_commands()
return self.commands.get(cmd_name)
@click.group(name="Mlflow")
def commands():
"""Kedro plugin for interactions with mlflow."""
pass # pragma: no cover
@commands.command(name="mlflow", cls=KedroClickGroup)
def mlflow_commands():
"""Use mlflow-specific commands inside kedro project."""
pass # pragma: no cover
@mlflow_commands.command()
@click.option(
"--env",
"-e",
default="local",
help="The name of the kedro environment where the 'mlflow.yml' should be created. Default to 'local'",
)
@click.option(
"--force",
"-f",
is_flag=True,
default=False,
help="Update the template without any checks.",
)
@click.option(
"--silent",
"-s",
is_flag=True,
default=False,
help="Should message be logged when files are modified?",
)
def init(env, force, silent):
"""Updates the template of a kedro project.
Running this command is mandatory to use kedro-mlflow.
This adds "conf/base/mlflow.yml": This is a configuration file
used for run parametrization when calling "kedro run" command.
See INSERT_DOC_URL for further details.
"""
# get constants
mlflow_yml = "mlflow.yml"
project_path = Path().cwd()
project_metadata = _get_project_metadata(project_path)
_add_src_to_path(project_metadata.source_dir, project_path)
session = KedroSession.create(
project_metadata.package_name, project_path=project_path
)
context = session.load_context()
mlflow_yml_path = project_path / context.CONF_ROOT / env / mlflow_yml
# mlflow.yml is just a static file,
# but the name of the experiment is set to be the same as the project
if mlflow_yml_path.is_file() and not force:
click.secho(
click.style(
f"A 'mlflow.yml' already exists at '{mlflow_yml_path}' You can use the ``--force`` option to override it.",
fg="red",
)
)
else:
try:
write_jinja_template(
src=TEMPLATE_FOLDER_PATH / mlflow_yml,
is_cookiecutter=False,
dst=mlflow_yml_path,
python_package=project_metadata.package_name,
)
except FileNotFoundError:
click.secho(
click.style(
f"No env '{env}' found. Please check this folder exists inside '{context.CONF_ROOT}' folder.",
fg="red",
)
)
if not silent:
click.secho(
click.style(
f"'{context.CONF_ROOT}/{env}/{mlflow_yml}' successfully updated.",
fg="green",
)
)
@mlflow_commands.command()
@click.option(
"--env",
"-e",
required=False,
default="local",
help="The environment within conf folder we want to retrieve.",
)
def ui(env):
"""Opens the mlflow user interface with the
project-specific settings of mlflow.yml. This interface
enables to browse and compares runs.
"""
project_path = Path().cwd()
project_metadata = _get_project_metadata(project_path)
_add_src_to_path(project_metadata.source_dir, project_path)
with KedroSession.create(
package_name=project_metadata.package_name,
project_path=project_path,
env=env,
):
mlflow_conf = get_mlflow_config()
# call mlflow ui with specific options
# TODO : add more options for ui
subprocess.call(
["mlflow", "ui", "--backend-store-uri", mlflow_conf.mlflow_tracking_uri]
)
@mlflow_commands.command()
def run():
"""Re-run an old run with mlflow-logged info."""
# TODO (HARD) : define general assumptions to check whether a run
# is reproductible or not
# TODO retrieve command
# TODO retrieve parameters
# TODO perform checks on data
# TODO launch run
raise NotImplementedError # pragma: no cover
@mlflow_commands.command()
def new():
"""Create a new kedro project with updated template."""
raise NotImplementedError # pragma: no cover
class KedroMlflowCliError(Exception):
"""kedro-mlflow cli specific error"""
pass