• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

SwissDataScienceCenter / renku-python / 7796321857

06 Feb 2024 07:49AM UTC coverage: 85.162% (-0.009%) from 85.171%
7796321857

Pull #3700

github

web-flow
Merge 5dcd46c70 into e98f11228
Pull Request #3700: chore: combined dependency update

26659 of 31304 relevant lines covered (85.16%)

3.87 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

96.95
/renku/ui/cli/__init__.py
1
# Copyright Swiss Data Science Center (SDSC). A partnership between
2
# École Polytechnique Fédérale de Lausanne (EPFL) and
3
# Eidgenössische Technische Hochschule Zürich (ETHZ).
4
#
5
# Licensed under the Apache License, Version 2.0 (the "License");
6
# you may not use this file except in compliance with the License.
7
# You may obtain a copy of the License at
8
#
9
#     http://www.apache.org/licenses/LICENSE-2.0
10
#
11
# Unless required by applicable law or agreed to in writing, software
12
# distributed under the License is distributed on an "AS IS" BASIS,
13
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
# See the License for the specific language governing permissions and
15
# limitations under the License.
16
r"""The base command for interacting with the Renku platform.
8✔
17

18
renku (base command)
19
********************
20

21
To list the available commands, either run ``renku`` with no parameters or
22
execute ``renku help``:
23

24
.. code-block:: console
25

26
    $ renku help
27
    Usage: renku [OPTIONS] COMMAND [ARGS]...
28

29
    Check common Renku commands used in various situations.
30

31

32
    Options:
33
      --version                       Print version number.
34
      --global-config-path            Print global application's config path.
35
      --path <path>                   Location of a Renku repository.
36
                                      [default: (dynamic)]
37
      --external-storage / -S, --no-external-storage
38
                                      Use an external file storage service.
39
      -h, --help                      Show this message and exit.
40

41
    Commands:
42
      # [...]
43

44
Configuration files
45
~~~~~~~~~~~~~~~~~~~
46

47
Depending on your system, you may find the configuration files used by Renku
48
command line in a different folder. By default, the following rules are used:
49

50
MacOS:
51
  ``~/Library/Application Support/Renku``
52
Unix:
53
  ``~/.config/renku``
54
Windows:
55
  ``C:\Users\<user>\AppData\Roaming\Renku``
56

57
If in doubt where to look for the configuration file, you can display its path
58
by running ``renku --global-config-path``.
59

60
.. cheatsheet::
61
   :group: Typical Workflow
62
   :command: $ git status
63
   :description: Take a look at what you have done since the last save.
64
   :target: ui,rp
65

66
.. cheatsheet::
67
   :group: Typical Workflow
68
   :command: $ renku save -m <msg>
69
   :description: Save your latest work, providing a message explaining what you have done.
70
   :target: ui,rp
71

72
.. cheatsheet::
73
   :group: Typical Workflow
74
   :command: $ renku run …
75
   :description: Run your code, capturing lineage of the inputs and outputs using Renku.
76
   :target: ui,rp
77

78
"""
79
import os
8✔
80
import sys
8✔
81
import uuid
8✔
82
from pathlib import Path
8✔
83

84
import click
8✔
85
import yaml
8✔
86
from click_plugins import with_plugins
8✔
87

88
from renku.command.options import option_external_storage_requested
8✔
89
from renku.command.util import WARNING
8✔
90
from renku.command.version import print_version
8✔
91
from renku.core import errors
8✔
92
from renku.core.constant import DATABASE_PATH
8✔
93
from renku.core.util.git import get_git_path
8✔
94
from renku.domain_model.project_context import project_context
8✔
95
from renku.ui.cli.clone import clone
8✔
96
from renku.ui.cli.config import config
8✔
97
from renku.ui.cli.dataset import dataset
8✔
98
from renku.ui.cli.doctor import doctor
8✔
99
from renku.ui.cli.env import env
8✔
100
from renku.ui.cli.exception_handler import IssueFromTraceback
8✔
101
from renku.ui.cli.gc import gc
8✔
102
from renku.ui.cli.githooks import githooks as githooks_command
8✔
103
from renku.ui.cli.graph import graph
8✔
104
from renku.ui.cli.init import init
8✔
105
from renku.ui.cli.lfs import lfs
8✔
106
from renku.ui.cli.log import log
8✔
107
from renku.ui.cli.login import credentials, login, logout
8✔
108
from renku.ui.cli.mergetool import mergetool
8✔
109
from renku.ui.cli.migrate import check_immutable_template_files, migrate, migrationscheck
8✔
110
from renku.ui.cli.move import move
8✔
111
from renku.ui.cli.project import project
8✔
112
from renku.ui.cli.remove import remove
8✔
113
from renku.ui.cli.rerun import rerun
8✔
114
from renku.ui.cli.rollback import rollback
8✔
115
from renku.ui.cli.run import run
8✔
116
from renku.ui.cli.save import save
8✔
117
from renku.ui.cli.service import service
8✔
118
from renku.ui.cli.session import session
8✔
119
from renku.ui.cli.status import status
8✔
120
from renku.ui.cli.storage import storage
8✔
121
from renku.ui.cli.template import template
8✔
122
from renku.ui.cli.update import update
8✔
123
from renku.ui.cli.workflow import workflow
8✔
124

125
try:
8✔
126
    from importlib.metadata import entry_points
8✔
127
except ImportError:
×
128
    from importlib_metadata import entry_points  # type: ignore
×
129

130

131
def get_entry_points(name: str):
8✔
132
    """Get entry points from importlib."""
133
    all_entry_points = entry_points()
8✔
134

135
    if hasattr(all_entry_points, "select"):
8✔
136
        return all_entry_points.select(group=name)  # type: ignore
8✔
137
    else:
138
        # Prior to Python 3.10, this returns a dict instead of the selection interface, which is slightly slower
139
        return all_entry_points.get(name, [])
×
140

141

142
WARNING_UNPROTECTED_COMMANDS = ["clone", "credentials", "env", "help", "init", "login", "logout", "service", "template"]
8✔
143

144
WARNING_UNPROTECTED_SUBCOMMANDS = {"template": ["ls", "show", "validate"]}
8✔
145

146

147
def _uuid_representer(dumper, data):
8✔
148
    """Add UUID serializer for YAML."""
149
    return dumper.represent_str(str(data))
×
150

151

152
def _is_renku_project(path: Path) -> bool:
8✔
153
    """Check if a path is a renku project."""
154
    from renku.core.constant import RENKU_HOME
7✔
155
    from renku.core.migration.utils import OLD_METADATA_PATH
7✔
156
    from renku.infrastructure.database import Database
7✔
157

158
    metadata_path = Path(path) / RENKU_HOME
7✔
159
    old_metadata = metadata_path / OLD_METADATA_PATH
7✔
160
    new_metadata = metadata_path / DATABASE_PATH / Database.ROOT_OID
7✔
161

162
    return old_metadata.exists() or new_metadata.exists()
7✔
163

164

165
yaml.add_representer(uuid.UUID, _uuid_representer)
8✔
166

167

168
def print_global_config_path(ctx, _, value):
8✔
169
    """Print global application's config path."""
170
    if not value or ctx.resilient_parsing:
7✔
171
        return
7✔
172

173
    click.echo(project_context.global_config_path)
1✔
174
    ctx.exit()
1✔
175

176

177
def is_allowed_subcommand(ctx):
8✔
178
    """Called from subcommands to check if their sub-subcommand is allowed.
179

180
    Subcommands where some sub-subcommands are allowed should be added to ``WARNING_UNPROTECTED_COMMANDS`` so they pass
181
    through the parent check and then added to ``WARNING_UNPROTECTED_SUBCOMMANDS`` so they get checked here.
182
    """
183
    from renku.domain_model.project_context import project_context
3✔
184

185
    if not _is_renku_project(project_context.path) and (
3✔
186
        not WARNING_UNPROTECTED_SUBCOMMANDS.get(ctx.command.name, False)
187
        or ctx.invoked_subcommand not in WARNING_UNPROTECTED_SUBCOMMANDS[ctx.command.name]
188
    ):
189
        raise errors.UsageError(
2✔
190
            f"{project_context.path} is not a renku repository.\n"
191
            "To initialize this as a renku repository use: 'renku init'"
192
        )
193

194

195
def is_allowed_command(ctx):
8✔
196
    """Check if invoked command contains help command."""
197

198
    return ctx.invoked_subcommand in WARNING_UNPROTECTED_COMMANDS or "-h" in sys.argv or "--help" in sys.argv
7✔
199

200

201
@with_plugins(get_entry_points("renku.cli_plugins"))
8✔
202
@click.group(
8✔
203
    cls=IssueFromTraceback, context_settings={"auto_envvar_prefix": "RENKU", "help_option_names": ["-h", "--help"]}
204
)
205
@click.option(
8✔
206
    "--version", is_flag=True, callback=print_version, expose_value=False, is_eager=True, help=print_version.__doc__
207
)
208
@click.option(
8✔
209
    "--global-config-path",
210
    is_flag=True,
211
    callback=print_global_config_path,
212
    expose_value=False,
213
    is_eager=True,
214
    help=print_global_config_path.__doc__,
215
)
216
@click.option(
8✔
217
    "--path", show_default=True, metavar="<path>", default=get_git_path, help="Location of a Renku repository."
218
)
219
@option_external_storage_requested
8✔
220
@click.pass_context
8✔
221
def cli(ctx, path, external_storage_requested):
8✔
222
    """Check common Renku commands used in various situations."""
223
    from renku.domain_model.project_context import project_context
7✔
224

225
    path = Path(path)
7✔
226

227
    is_command_allowed = is_allowed_command(ctx)
7✔
228
    is_renku_project = _is_renku_project(path)
7✔
229

230
    if not is_renku_project and not is_command_allowed:
7✔
231
        raise errors.UsageError(
2✔
232
            f"{path} is not a renku repository.\n" "To initialize this as a renku repository use: 'renku init'"
233
        )
234

235
    project_context.push_path(path)
7✔
236
    project_context.external_storage_requested = external_storage_requested
7✔
237

238
    if is_renku_project and path != Path(os.getcwd()) and not is_command_allowed:
7✔
239
        click.secho(WARNING + "Run CLI commands only from project's root directory.\n", err=True)
3✔
240

241

242
@cli.command()
8✔
243
@click.pass_context
8✔
244
def help(ctx):
8✔
245
    """Show help message and exit."""
246
    click.echo(ctx.parent.get_help())
3✔
247

248

249
# Register subcommands:
250
cli.add_command(check_immutable_template_files)
8✔
251
cli.add_command(clone)
8✔
252
cli.add_command(config)
8✔
253
cli.add_command(credentials)
8✔
254
cli.add_command(dataset)
8✔
255
cli.add_command(doctor)
8✔
256
cli.add_command(env)
8✔
257
cli.add_command(gc)
8✔
258
cli.add_command(githooks_command)
8✔
259
cli.add_command(graph)
8✔
260
cli.add_command(init)
8✔
261
cli.add_command(lfs)
8✔
262
cli.add_command(log)
8✔
263
cli.add_command(login)
8✔
264
cli.add_command(logout)
8✔
265
cli.add_command(mergetool)
8✔
266
cli.add_command(migrate)
8✔
267
cli.add_command(migrationscheck)
8✔
268
cli.add_command(move)
8✔
269
cli.add_command(project)
8✔
270
cli.add_command(remove)
8✔
271
cli.add_command(rerun)
8✔
272
cli.add_command(rollback)
8✔
273
cli.add_command(run)
8✔
274
cli.add_command(save)
8✔
275
cli.add_command(service)
8✔
276
cli.add_command(session)
8✔
277
cli.add_command(status)
8✔
278
cli.add_command(storage)
8✔
279
cli.add_command(template)
8✔
280
cli.add_command(update)
8✔
281
cli.add_command(workflow)
8✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc