5
5
import sys
6
6
from typing import Dict , Optional , Tuple
7
7
8
+ import click
8
9
import requests
9
10
from packaging .version import Version
10
11
14
15
logger = Logger (__name__ )
15
16
16
17
17
- def gallery_component (name : str , yes_arg : bool , version_arg : str , cwd : str = None ) -> None :
18
+ @click .group (name = "install" )
19
+ def install () -> None :
20
+ """Install Lightning AI selfresources."""
21
+ pass
22
+
23
+
24
+ @install .command ("app" )
25
+ @click .argument ("name" , type = str )
26
+ @click .option (
27
+ "--yes" ,
28
+ "-y" ,
29
+ is_flag = True ,
30
+ help = "disables prompt to ask permission to create env and run install cmds" ,
31
+ )
32
+ @click .option (
33
+ "--version" ,
34
+ "-v" ,
35
+ type = str ,
36
+ help = "Specify the version to install. By default it uses 'latest'" ,
37
+ default = "latest" ,
38
+ show_default = True ,
39
+ )
40
+ @click .option (
41
+ "--overwrite" ,
42
+ "-f" ,
43
+ is_flag = True ,
44
+ default = False ,
45
+ help = "When set, overwrite the app directory without asking if it already exists." ,
46
+ )
47
+ def install_app (name : str , yes : bool , version : str , overwrite : bool = False ) -> None :
48
+ _install_app_command (name , yes , version , overwrite = overwrite )
49
+
50
+
51
+ @install .command ("component" )
52
+ @click .argument ("name" , type = str )
53
+ @click .option (
54
+ "--yes" ,
55
+ "-y" ,
56
+ is_flag = True ,
57
+ help = "disables prompt to ask permission to create env and run install cmds" ,
58
+ )
59
+ @click .option (
60
+ "--version" ,
61
+ "-v" ,
62
+ type = str ,
63
+ help = "Specify the version to install. By default it uses 'latest'" ,
64
+ default = "latest" ,
65
+ show_default = True ,
66
+ )
67
+ def install_component (name : str , yes : bool , version : str ) -> None :
68
+ _install_component_command (name , yes , version )
69
+
70
+
71
+ def _install_app_command (name : str , yes : bool , version : str , overwrite : bool = False ) -> None :
72
+ if "github.com" in name :
73
+ if version != "latest" :
74
+ logger .warn (
75
+ "When installing from GitHub, only the 'latest' version is supported. "
76
+ f"The provided version ({ version } ) will be ignored."
77
+ )
78
+ return non_gallery_app (name , yes , overwrite = overwrite )
79
+ else :
80
+ return gallery_app (name , yes , version , overwrite = overwrite )
81
+
82
+
83
+ def _install_component_command (name : str , yes : bool , version : str , overwrite : bool = False ) -> None :
84
+ if "github.com" in name :
85
+ if version != "latest" :
86
+ logger .warn (
87
+ "When installing from GitHub, only the 'latest' version is supported. "
88
+ f"The provided version ({ version } ) will be ignored."
89
+ )
90
+ return non_gallery_component (name , yes )
91
+ else :
92
+ return gallery_component (name , yes , version )
93
+
94
+
95
+ def gallery_apps_and_components (
96
+ name : str , yes_arg : bool , version_arg : str , cwd : str = None , overwrite : bool = False
97
+ ) -> Optional [str ]:
98
+
99
+ try :
100
+ org , app_or_component = name .split ("/" )
101
+ except Exception :
102
+ return None
103
+
104
+ entry , kind = _resolve_entry (app_or_component , version_arg )
105
+
106
+ if kind == "app" :
107
+ # give the user the chance to do a manual install
108
+ source_url , git_url , folder_name , git_sha = _show_install_app_prompt (
109
+ entry , app_or_component , org , yes_arg , resource_type = "app"
110
+ )
111
+ # run installation if requested
112
+ _install_app_from_source (source_url , git_url , folder_name , cwd = cwd , overwrite = overwrite , git_sha = git_sha )
113
+
114
+ return os .path .join (os .getcwd (), folder_name , entry ["appEntrypointFile" ])
115
+
116
+ elif kind == "component" :
117
+ # give the user the chance to do a manual install
118
+ git_url = _show_install_component_prompt (entry , app_or_component , org , yes_arg )
119
+
120
+ # run installation if requested
121
+ _install_component_from_source (git_url )
122
+
123
+ return os .path .join (os .getcwd (), entry ["appEntrypointFile" ])
124
+
125
+ return None
126
+
127
+
128
+ def gallery_component (name : str , yes_arg : bool , version_arg : str , cwd : str = None ) -> str :
18
129
# make sure org/component-name name is correct
19
130
org , component = _validate_name (name , resource_type = "component" , example = "lightning/LAI-slack-component" )
20
131
@@ -28,7 +139,9 @@ def gallery_component(name: str, yes_arg: bool, version_arg: str, cwd: str = Non
28
139
git_url = _show_install_component_prompt (component_entry , component , org , yes_arg )
29
140
30
141
# run installation if requested
31
- _install_component (git_url )
142
+ _install_component_from_source (git_url )
143
+
144
+ return os .path .join (os .getcwd (), component_entry ["entrypointFile" ])
32
145
33
146
34
147
def non_gallery_component (gh_url : str , yes_arg : bool , cwd : str = None ) -> None :
@@ -37,10 +150,10 @@ def non_gallery_component(gh_url: str, yes_arg: bool, cwd: str = None) -> None:
37
150
git_url = _show_non_gallery_install_component_prompt (gh_url , yes_arg )
38
151
39
152
# run installation if requested
40
- _install_component (git_url )
153
+ _install_component_from_source (git_url )
41
154
42
155
43
- def gallery_app (name : str , yes_arg : bool , version_arg : str , cwd : str = None , overwrite : bool = False ) -> None :
156
+ def gallery_app (name : str , yes_arg : bool , version_arg : str , cwd : str = None , overwrite : bool = False ) -> str :
44
157
45
158
# make sure org/app-name syntax is correct
46
159
org , app = _validate_name (name , resource_type = "app" , example = "lightning/quick-start" )
@@ -57,7 +170,9 @@ def gallery_app(name: str, yes_arg: bool, version_arg: str, cwd: str = None, ove
57
170
)
58
171
59
172
# run installation if requested
60
- _install_app (source_url , git_url , folder_name , cwd = cwd , overwrite = overwrite , git_sha = git_sha )
173
+ _install_app_from_source (source_url , git_url , folder_name , cwd = cwd , overwrite = overwrite , git_sha = git_sha )
174
+
175
+ return os .path .join (os .getcwd (), folder_name , app_entry ["appEntrypointFile" ])
61
176
62
177
63
178
def non_gallery_app (gh_url : str , yes_arg : bool , cwd : str = None , overwrite : bool = False ) -> None :
@@ -66,7 +181,7 @@ def non_gallery_app(gh_url: str, yes_arg: bool, cwd: str = None, overwrite: bool
66
181
repo_url , folder_name = _show_non_gallery_install_app_prompt (gh_url , yes_arg )
67
182
68
183
# run installation if requested
69
- _install_app (repo_url , repo_url , folder_name , cwd = cwd , overwrite = overwrite )
184
+ _install_app_from_source (repo_url , repo_url , folder_name , cwd = cwd , overwrite = overwrite )
70
185
71
186
72
187
def _show_install_component_prompt (entry : Dict [str , str ], component : str , org : str , yes_arg : bool ) -> str :
@@ -299,7 +414,35 @@ def _validate_name(name: str, resource_type: str, example: str) -> Tuple[str, st
299
414
return org , resource
300
415
301
416
302
- def _resolve_resource (registry_url : str , name : str , version_arg : str , resource_type : str ) -> Dict [str , str ]:
417
+ def _resolve_entry (name , version_arg ) -> Tuple [Optional [Dict ], Optional [str ]]:
418
+ entry = None
419
+ kind = None
420
+
421
+ # resolve registry (orgs can have a private registry through their environment variables)
422
+ registry_url = _resolve_app_registry ()
423
+
424
+ # load the app resource
425
+ entry = _resolve_resource (registry_url , name = name , version_arg = version_arg , resource_type = "app" , raise_error = False )
426
+
427
+ if not entry :
428
+
429
+ registry_url = _resolve_component_registry ()
430
+
431
+ # load the component resource
432
+ entry = _resolve_resource (
433
+ registry_url , name = name , version_arg = version_arg , resource_type = "component" , raise_error = False
434
+ )
435
+ kind = "component" if entry else None
436
+
437
+ else :
438
+ kind = "app"
439
+
440
+ return entry , kind
441
+
442
+
443
+ def _resolve_resource (
444
+ registry_url : str , name : str , version_arg : str , resource_type : str , raise_error : bool = True
445
+ ) -> Dict [str , str ]:
303
446
gallery_entries = []
304
447
try :
305
448
response = requests .get (registry_url )
@@ -327,7 +470,10 @@ def _resolve_resource(registry_url: str, name: str, version_arg: str, resource_t
327
470
all_versions .append (x ["version" ])
328
471
329
472
if len (entries ) == 0 :
330
- raise SystemExit (f"{ resource_type } : '{ name } ' is not available on ⚡ Lightning AI ⚡" )
473
+ if raise_error :
474
+ raise SystemExit (f"{ resource_type } : '{ name } ' is not available on ⚡ Lightning AI ⚡" )
475
+ else :
476
+ return None
331
477
332
478
entry = None
333
479
if version_arg == "latest" :
@@ -337,11 +483,14 @@ def _resolve_resource(registry_url: str, name: str, version_arg: str, resource_t
337
483
if e ["version" ] == version_arg :
338
484
entry = e
339
485
break
340
- if entry is None :
341
- raise Exception (
342
- f"{ resource_type } : 'Version { version_arg } for { name } ' is not available on ⚡ Lightning AI ⚡. "
343
- f"Here is the list of all availables versions:{ os .linesep } { os .linesep .join (all_versions )} "
344
- )
486
+ if entry is None and raise_error :
487
+ if raise_error :
488
+ raise Exception (
489
+ f"{ resource_type } : 'Version { version_arg } for { name } ' is not available on ⚡ Lightning AI ⚡. "
490
+ f"Here is the list of all availables versions:{ os .linesep } { os .linesep .join (all_versions )} "
491
+ )
492
+ else :
493
+ return None
345
494
346
495
return entry
347
496
@@ -381,7 +530,7 @@ def _install_with_env(repo_url: str, folder_name: str, cwd: str = None) -> None:
381
530
logger .info (m )
382
531
383
532
384
- def _install_app (
533
+ def _install_app_from_source (
385
534
source_url : str , git_url : str , folder_name : str , cwd : str = None , overwrite : bool = False , git_sha : str = None
386
535
) -> None :
387
536
"""Installing lighting app from the `git_url`
@@ -458,7 +607,7 @@ def _install_app(
458
607
logger .info (m )
459
608
460
609
461
- def _install_component (git_url : str ) -> None :
610
+ def _install_component_from_source (git_url : str ) -> None :
462
611
logger .info ("⚡ RUN: pip install" )
463
612
464
613
out = subprocess .check_output (["pip" , "install" , git_url ])
0 commit comments