Skip to content

Commit 9be395c

Browse files
Merge pull request 'loading the yaml files in a more structured way' (#5) from fix/pymcs/module-imports into main
Reviewed-on: https://git.myzel.io/PyMC/PyMC-Server/pulls/5
2 parents 92884da + d646e81 commit 9be395c

File tree

17 files changed

+465
-123
lines changed

17 files changed

+465
-123
lines changed

.gitignore

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -147,16 +147,16 @@ dmypy.json
147147

148148
# Pyre type checker
149149
.pyre/
150-
151150
# pytype static type analyzer
152151
.pytype/
153152

154153
# Cython debug symbols
155154
cython_debug/
156-
155+
*pymc.yaml
157156
# PyCharm
158157
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
159158
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
160159
# and can be added to the global gitignore or merged into this file. For a more nuclear
161160
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
162-
#.idea/
161+
.idea/
162+

examples/cluster/dev.yaml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
num_nodes: 1
2+
resources:
3+
# Optional; if left out, automatically pick the cheapest cloud.
4+
cloud: gcp
5+
cpus: 1
6+
# 1x NVIDIA V100 GPU
7+
#accelerators: V200:2
8+
ports : 80
9+
10+
workdir: ./src/pymc_server/workDir_test
11+
pymc_module: pymc-marketing
12+
run: |
13+
echo "Hello, SkyPilot!"
14+
uname -a
15+
python test.py
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# start and stop GCP instances
2+
name: gcp-start-stop
3+
4+
resources:
5+
cloud: gcp
6+
cpus: 1+
7+
8+
num_nodes: 1
9+
10+
# The setup command. Will be run under the working directory.
11+
setup: 'echo "hi"'
12+
workdir: ./src/pymc_server/workDir_test
13+
14+
# The command to run. Will be run under the working directory.
15+
run: 'python test.py'

requirements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,4 @@ numba
55
ray[default]
66
skypilot
77
skypilot[gcp]
8+
hiyapyco

setup.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
from setuptools import setup
2+
3+
setup()

src/pymc_server/cli.py

Lines changed: 48 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,60 @@
1-
21
import click
3-
#import colorama
4-
#import dotenv
52
import sky
6-
from file_merger import mergeYaml
7-
from launch_cli import launch as cli_launch
3+
from typing import Any, Dict, List, Optional, Tuple, Union
4+
from pymc_server.utils.yaml import merge_yaml
5+
from pymc_server.launch_cli import launch as cli_launch
6+
from pymc_server.cli_factory import setup_launch_factory, setup_status_factory
7+
from sky.usage import usage_lib
8+
9+
10+
from sky.cli import (
11+
status as sky_status,
12+
launch as sky_launch,
13+
check as sky_check
14+
)
15+
16+
17+
# TODO: remove, check pyproject.py for a reference to this function
818
@click.group()
919
def cli():
1020
pass
1121

12-
@click.command()
13-
#@click.option('--count', default=1, help='Number of greetings.')
14-
#@click.option('--name', prompt='Your name',
15-
# help='The person to greet.')
16-
def status():
17-
task = sky.Task(run='echo hello SkyPilot')
18-
task.set_resources(sky.Resources(cloud=sky.AWS(), accelerators='V100:4'))
19-
sky.launch(task, cluster_name='my-cluster')
20-
click.echo(sky.status(cluster_names=None, refresh=False))
21-
"""Simple program that greets NAME for a total of COUNT times."""
22-
#for x in range(count):
23-
# click.echo(f"Hello {name}!")
22+
@setup_status_factory
23+
@usage_lib.entrypoint
24+
def status(*args, **kwargs):
25+
""" calls the sky status command by passing the click context"""
26+
ctx = click.get_current_context()
27+
ctx.invoke(sky_status, *args, **kwargs)
2428

25-
cli.add_command(status)
2629

27-
@click.command()
28-
#@click.option('--count', default=1, help='Number of greetings.')
29-
#@click.option('--name', prompt='Your name',
30-
# help='The person to greet.')
31-
def launch():
32-
print('Launch Mode ::')
33-
'''
34-
task = sky.Task(run='echo hello SkyPilot')
35-
task.set_resources(sky.Resources(cloud=sky.AWS(), accelerators='V100:4'))
36-
sky.launch(task, cluster_name='my-cluster')
37-
click.echo(sky.status(cluster_names=None, refresh=False))
38-
'''
39-
40-
# print(mergeYaml(devPath='dev.yaml',pymcPath='pymc.yaml'))
41-
cli_launch()
42-
43-
"""Simple program that greets NAME for a total of COUNT times."""
44-
#for x in range(count):
45-
# click.echo(f"Hello {name}!")
30+
@setup_launch_factory
31+
@usage_lib.entrypoint
32+
def launch(*args, **kwargs):
33+
"""Launch a cluster or task.
34+
35+
If ENTRYPOINT points to a valid YAML file, it is read in as the task
36+
specification. Otherwise, it is interpreted as a bash command.
4637
38+
In both cases, the commands are run under the task's workdir (if specified)
39+
and they undergo job queue scheduling.
40+
"""
41+
# cli_launch(*args, **kwargs)
42+
ctx = click.get_current_context()
43+
ctx.invoke(cli_launch, *args, **kwargs)
44+
45+
@setup_status_factory
46+
@usage_lib.entrypoint
47+
def check(*args, **kwargs):
48+
""" calls the sky status command by passing the click context"""
49+
ctx = click.get_current_context()
50+
#sky_check(*args, **kwargs)
51+
ctx.invoke(sky_check, *args, **kwargs)
52+
53+
54+
cli.add_command(status)
4755
cli.add_command(launch)
56+
cli.add_command(check)
57+
4858
if __name__ == '__main__':
4959
cli()
60+

src/pymc_server/cli_factory.py

Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
import click
2+
from sky.cli import (
3+
_DocumentedCodeCommand,
4+
_get_shell_complete_args,
5+
_complete_file_name,
6+
_complete_cluster_name,
7+
_CLUSTER_FLAG_HELP,
8+
_TASK_OPTIONS_WITH_NAME,
9+
_EXTRA_RESOURCES_OPTIONS,
10+
usage_lib,
11+
backends,
12+
_add_click_options
13+
14+
)
15+
16+
17+
def setup_status_factory(func):
18+
options = [
19+
click.command(),
20+
click.option('--all',
21+
'-a',
22+
default=False,
23+
is_flag=True,
24+
required=False,
25+
help='Show all information in full.'),
26+
click.option(
27+
'--refresh',
28+
'-r',
29+
default=False,
30+
is_flag=True,
31+
required=False,
32+
help='Query the latest cluster statuses from the cloud provider(s).'),
33+
click.option('--ip',
34+
default=False,
35+
is_flag=True,
36+
required=False,
37+
help=('Get the IP address of the head node of a cluster. This '
38+
'option will override all other options. For Kubernetes '
39+
'clusters, the returned IP address is the internal IP '
40+
'of the head pod, and may not be accessible from outside '
41+
'the cluster.')),
42+
click.option('--endpoints',
43+
default=False,
44+
is_flag=True,
45+
required=False,
46+
help=('Get all exposed endpoints and corresponding URLs for a'
47+
'cluster. This option will override all other options.')),
48+
click.option('--endpoint',
49+
required=False,
50+
default=None,
51+
type=int,
52+
help=('Get the endpoint URL for the specified port number on the '
53+
'cluster. This option will override all other options.')),
54+
click.option('--show-managed-jobs/--no-show-managed-jobs',
55+
default=True,
56+
is_flag=True,
57+
required=False,
58+
help='Also show recent in-progress managed jobs, if any.'),
59+
click.option('--show-services/--no-show-services',
60+
default=True,
61+
is_flag=True,
62+
required=False,
63+
help='Also show sky serve services, if any.'),
64+
click.argument('clusters',
65+
required=False,
66+
type=str,
67+
nargs=-1,
68+
**_get_shell_complete_args(_complete_cluster_name)),
69+
]
70+
for option in reversed(options):
71+
func = option(func)
72+
return func
73+
74+
def setup_launch_factory(func):
75+
options = [
76+
click.command(cls=_DocumentedCodeCommand),
77+
click.argument('entrypoint',
78+
required=False,
79+
type=str,
80+
nargs=-1,
81+
**_get_shell_complete_args(_complete_file_name)),
82+
click.option('--pymc_module',
83+
'-m',
84+
required=False,
85+
type=str,
86+
help=('Define the PyMC module / project you need tu use')),
87+
click.option('--cluster',
88+
'-c',
89+
default=None,
90+
type=str,
91+
**_get_shell_complete_args(_complete_cluster_name),
92+
help=_CLUSTER_FLAG_HELP),
93+
click.option('--dryrun',
94+
default=False,
95+
is_flag=True,
96+
help='If True, do not actually run the job.'),
97+
click.option(
98+
'--detach-setup',
99+
'-s',
100+
default=False,
101+
is_flag=True,
102+
help=
103+
('If True, run setup in non-interactive mode as part of the job itself. '
104+
'You can safely ctrl-c to detach from logging, and it will not interrupt '
105+
'the setup process. To see the logs again after detaching, use `sky logs`.'
106+
' To cancel setup, cancel the job via `sky cancel`. Useful for long-'
107+
'running setup commands.')),
108+
click.option(
109+
'--detach-run',
110+
'-d',
111+
default=False,
112+
is_flag=True,
113+
help=('If True, as soon as a job is submitted, return from this call '
114+
'and do not stream execution logs.')),
115+
click.option('--docker',
116+
'backend_name',
117+
flag_value=backends.LocalDockerBackend.NAME,
118+
default=False,
119+
help='If used, runs locally inside a docker container.'),
120+
_add_click_options(_TASK_OPTIONS_WITH_NAME + _EXTRA_RESOURCES_OPTIONS),
121+
click.option(
122+
'--idle-minutes-to-autostop',
123+
'-i',
124+
default=None,
125+
type=int,
126+
required=False,
127+
help=('Automatically stop the cluster after this many minutes '
128+
'of idleness, i.e., no running or pending jobs in the cluster\'s job '
129+
'queue. Idleness gets reset whenever setting-up/running/pending jobs '
130+
'are found in the job queue. '
131+
'Setting this flag is equivalent to '
132+
'running ``sky launch -d ...`` and then ``sky autostop -i <minutes>``'
133+
'. If not set, the cluster will not be autostopped.')),
134+
click.option(
135+
'--retry-until-up',
136+
'-r',
137+
default=False,
138+
is_flag=True,
139+
required=False,
140+
help=('Whether to retry provisioning infinitely until the cluster is up, '
141+
'if we fail to launch the cluster on any possible region/cloud due '
142+
'to unavailability errors.'),
143+
),
144+
click.option(
145+
'--yes',
146+
'-y',
147+
is_flag=True,
148+
default=False,
149+
required=False,
150+
# Disabling quote check here, as there seems to be a bug in pylint,
151+
# which incorrectly recognizes the help string as a docstring.
152+
# pylint: disable=bad-docstring-quotes
153+
help='Skip confirmation prompt.'),
154+
click.option('--no-setup',
155+
is_flag=True,
156+
default=False,
157+
required=False,
158+
help='Skip setup phase when (re-)launching cluster.'),
159+
click.option(
160+
'--clone-disk-from',
161+
'--clone',
162+
default=None,
163+
type=str,
164+
**_get_shell_complete_args(_complete_cluster_name),
165+
help=('[Experimental] Clone disk from an existing cluster to launch '
166+
'a new one. This is useful when the new cluster needs to have '
167+
'the same data on the boot disk as an existing cluster.'))
168+
]
169+
170+
for option in reversed(options):
171+
func = option(func)
172+
return func
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
resources:
2+
# Optional; if left out, automatically pick the cheapest cloud.
3+
cloud: aws
4+
#disk_tier: medium
5+
# 1x NVIDIA V100 GPU
6+
#accelerators: V100:1
7+
ports: 9000
8+
9+
# Working directory (optional) containing the project codebase.
10+
# Its contents are synced to ~/sky_workdir/ on the cluster.
11+
workdir: .
12+
13+
# Typical use: pip install -r requirements.txt
14+
# Invoked under the workdir (i.e., can use its files).
15+
setup: |
16+
echo "Running setup."
17+
18+
# Typical use: make use of resources, such as running training.
19+
# Invoked under the workdir (i.e., can use its files).
20+
run: |
21+
echo "Hello, SkyPilot!"
22+
#conda env list

src/pymc_server/pymc.yaml renamed to src/pymc_server/config/pymc-test/base.yaml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ resources:
44
disk_tier: medium
55
# 1x NVIDIA V100 GPU
66
accelerators: V100:1
7+
ports: 9000
78

89
# Working directory (optional) containing the project codebase.
910
# Its contents are synced to ~/sky_workdir/ on the cluster.
@@ -18,4 +19,4 @@ setup: |
1819
# Invoked under the workdir (i.e., can use its files).
1920
run: |
2021
echo "Hello, SkyPilot!"
21-
conda env list
22+
conda env list
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
resources:
2+
# Optional; if left out, automatically pick the cheapest cloud.
3+
cloud: aws
4+
disk_tier: medium
5+
# 1x NVIDIA V100 GPU
6+
accelerators: V100:1
7+
ports: 9000
8+
9+
# Working directory (optional) containing the project codebase.
10+
# Its contents are synced to ~/sky_workdir/ on the cluster.
11+
workdir: .
12+
13+
# Typical use: pip install -r requirements.txt
14+
# Invoked under the workdir (i.e., can use its files).
15+
setup: |
16+
echo "Running setup."
17+
18+
# Typical use: make use of resources, such as running training.
19+
# Invoked under the workdir (i.e., can use its files).
20+
run: |
21+
echo "Hello, SkyPilot!"
22+
conda env list

0 commit comments

Comments
 (0)