Skip to content

Commit 68c4f67

Browse files
authored
Merge pull request #30 from unity-sds/breakout_interface
Decouple command line argument processing from handling.
2 parents 3156be3 + 5c92f66 commit 68c4f67

File tree

3 files changed

+120
-96
lines changed

3 files changed

+120
-96
lines changed

unity_app_generator/__main__.py

Lines changed: 15 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -13,97 +13,20 @@
1313
# * Creates CWL files from application metadata and Docker registry URL
1414
# * Register application and pushes CWL files into Dockstore
1515

16-
STATE_DIRECTORY = ".unity_app_gen"
17-
18-
import os
1916
import logging
2017
from argparse import ArgumentParser
2118

22-
from unity_app_generator.generator import UnityApplicationGenerator, ApplicationGenerationError
23-
24-
logger = logging.getLogger()
25-
26-
class SubCommandError(Exception):
27-
pass
28-
29-
def state_directory_path(args):
30-
31-
if args.state_directory is not None:
32-
return os.path.realpath(args.state_directory)
33-
34-
if hasattr(args, "destination_directory") and args.destination_directory is not None:
35-
return os.path.realpath(os.path.join(args.destination_directory, STATE_DIRECTORY))
36-
37-
if hasattr(args, "source_repository") and os.path.isdir(args.source_repository):
38-
return os.path.realpath(os.path.join(args.source_repository, STATE_DIRECTORY))
39-
40-
return os.path.realpath(os.path.join(os.curdir, STATE_DIRECTORY))
41-
42-
def check_state_directory(state_dir):
43-
44-
if not os.path.exists(state_dir):
45-
raise SubCommandError(f"Application state directory {state_dir} does not exist, please run init sub-command first")
46-
47-
return state_dir
48-
49-
def init(args):
50-
state_dir = state_directory_path(args)
51-
52-
app_gen = UnityApplicationGenerator(state_dir, args.source_repository, args.destination_directory, args.checkout)
53-
54-
def build_docker(args):
55-
state_dir = check_state_directory(state_directory_path(args))
56-
57-
app_gen = UnityApplicationGenerator(state_dir,
58-
repo2docker_config=args.config_file,
59-
use_namespace=args.image_namespace,
60-
use_repository=args.image_repository,
61-
use_tag=args.image_tag)
62-
63-
app_gen.create_docker_image()
19+
from unity_app_generator.generator import ApplicationGenerationError
6420

65-
def push_docker(args):
66-
state_dir = check_state_directory(state_directory_path(args))
21+
from . import interface
6722

68-
app_gen = UnityApplicationGenerator(state_dir)
69-
70-
app_gen.push_to_docker_registry(args.container_registry)
71-
72-
def push_ecr(args):
73-
state_dir = check_state_directory(state_directory_path(args))
74-
75-
app_gen = UnityApplicationGenerator(state_dir)
76-
77-
app_gen.push_to_aws_ecr()
78-
79-
def notebook_parameters(args):
80-
81-
state_dir = check_state_directory(state_directory_path(args))
82-
83-
app_gen = UnityApplicationGenerator(state_dir)
84-
85-
print()
86-
print(app_gen.notebook_parameters())
87-
88-
def build_cwl(args):
89-
state_dir = check_state_directory(state_directory_path(args))
90-
91-
app_gen = UnityApplicationGenerator(state_dir)
92-
93-
app_gen.create_cwl(cwl_output_path=args.cwl_output_path, docker_url=args.image_url, monolithic=args.monolithic)
94-
95-
def push_app_registry(args):
96-
state_dir = check_state_directory(state_directory_path(args))
97-
98-
app_gen = UnityApplicationGenerator(state_dir)
99-
100-
app_gen.push_to_application_registry(args.dockstore_api_url, args.dockstore_token)
23+
logger = logging.getLogger()
10124

10225
def main():
10326
parser = ArgumentParser(description="Unity Application Package Generator")
10427

10528
parser.add_argument("--state_directory",
106-
help=f"An alternative location to store the application state other than {STATE_DIRECTORY}")
29+
help=f"An alternative location to store the application state other than {interface.DEFAULT_STATE_DIRECTORY}")
10730

10831
parser.add_argument("--verbose", "-v", action="store_true", default=False,
10932
help=f"Enable verbose logging")
@@ -112,9 +35,9 @@ def main():
11235
subparsers = parser.add_subparsers(required=True)
11336

11437
parser_init = subparsers.add_parser('init',
115-
help=f"Initialize a Git repository for use by this application. Creates a {STATE_DIRECTORY} directory in the destination directory")
38+
help=f"Initialize a Git repository for use by this application. Creates a {interface.DEFAULT_STATE_DIRECTORY} directory in the destination directory")
11639

117-
parser_init.add_argument("source_repository",
40+
parser_init.add_argument("source_repository",
11841
help="Directory or Git URL of application source files, default is current directory")
11942

12043
parser_init.add_argument("destination_directory", nargs="?",
@@ -123,7 +46,7 @@ def main():
12346
parser_init.add_argument("-c", "--checkout", required=False,
12447
help="Git hash, tag or branch to checkout from the source repository")
12548

126-
parser_init.set_defaults(func=init)
49+
parser_init.set_defaults(func=interface.init)
12750

12851
# build_docker
12952

@@ -142,7 +65,7 @@ def main():
14265
parser_build_docker.add_argument("-c", "--config_file",
14366
help="JSON or Python Traitlets style config file for repo2docker. Use 'repo2docker --help-all' to see configurable options.")
14467

145-
parser_build_docker.set_defaults(func=build_docker)
68+
parser_build_docker.set_defaults(func=interface.build_docker)
14669

14770
# push_docker
14871

@@ -152,21 +75,21 @@ def main():
15275
parser_push_docker.add_argument("container_registry",
15376
help="URL or Dockerhub username of a Docker registry for pushing of the built image")
15477

155-
parser_push_docker.set_defaults(func=push_docker)
78+
parser_push_docker.set_defaults(func=interface.push_docker)
15679

15780
# push_ecr
15881

15982
parser_push_ecr = subparsers.add_parser('push_ecr',
16083
help=f"Push a Docker image from the initialized application directory to an AWS Elastic Container Registry (ECR)")
16184

162-
parser_push_ecr.set_defaults(func=push_ecr)
85+
parser_push_ecr.set_defaults(func=interface.push_ecr)
16386

16487
# notebook_parameters
16588

16689
parser_parameters = subparsers.add_parser('parameters',
16790
help=f"Display parsed notebook parameters")
16891

169-
parser_parameters.set_defaults(func=notebook_parameters)
92+
parser_parameters.set_defaults(func=interface.notebook_parameters)
17093

17194
# build_cwl
17295

@@ -182,7 +105,7 @@ def main():
182105
parser_build_cwl.add_argument("--monolithic", action="store_true",
183106
help="Use the deprecated 'monolithic' approach to generating CWL where stage in and out are bundled inside the application")
184107

185-
parser_build_cwl.set_defaults(func=build_cwl)
108+
parser_build_cwl.set_defaults(func=interface.build_cwl)
186109

187110
# push_app_registry
188111

@@ -195,7 +118,7 @@ def main():
195118
parser_app_registry.add_argument("--token", dest="dockstore_token", required=True,
196119
help="Dockstore API token obtained from the My Services / Account page")
197120

198-
parser_app_registry.set_defaults(func=push_app_registry)
121+
parser_app_registry.set_defaults(func=interface.push_app_registry)
199122

200123
# Process arguments
201124

@@ -207,12 +130,9 @@ def main():
207130
logging.basicConfig(level=logging.INFO)
208131

209132
try:
210-
args.func(args)
211-
except (SubCommandError, ApplicationGenerationError) as err:
133+
args.func(**vars(args))
134+
except ApplicationGenerationError as err:
212135
parser.error(err)
213136

214-
215-
#app_gen.push_to_application_registry(None)
216-
217137
if __name__ == '__main__':
218138
main()

unity_app_generator/generator.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,9 @@ def create_cwl(self, cwl_output_path=None, docker_url=None, monolithic=False):
147147

148148
def notebook_parameters(self):
149149

150-
nb = ApplicationNotebook(self.repo_info)
150+
notebook_filename = os.path.join(self.repo_info.directory, "process.ipynb")
151+
152+
nb = ApplicationNotebook(notebook_filename)
151153

152154
params_str = "Parsed Notebook Parameters:\n"
153155
params_str += nb.parameter_summary()

unity_app_generator/interface.py

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
"""
2+
Provides a programmatic interface mirroring the command line interface of build_ogc_app
3+
"""
4+
5+
DEFAULT_STATE_DIRECTORY = ".unity_app_gen"
6+
7+
import os
8+
import logging
9+
10+
from unity_app_generator.generator import UnityApplicationGenerator, ApplicationGenerationError
11+
12+
logger = logging.getLogger()
13+
14+
# Defaulty name of place where application generation state data is kept
15+
DEFAULT_STATE_DIRECTORY = ".unity_app_gen"
16+
17+
def state_directory_path(state_directory=None):
18+
"Resolve a path to the state directory based on which arguments are provided"
19+
20+
if state_directory is not None:
21+
return os.path.realpath(state_directory)
22+
23+
return os.path.realpath(os.path.join(os.curdir, DEFAULT_STATE_DIRECTORY))
24+
25+
def check_state_directory(state_dir):
26+
"Check that the application state directory exists"
27+
28+
if not os.path.exists(state_dir):
29+
raise ApplicationGenerationError(f"Application state directory {state_dir} does not exist, please run init sub-command first")
30+
31+
return state_dir
32+
33+
def init(state_directory, source_repository, destination_directory=None, checkout=None, **kwargs):
34+
"Initialize a Git repository for use by subsequent commands"
35+
36+
state_dir = state_directory_path(state_directory)
37+
38+
app_gen = UnityApplicationGenerator(state_dir, source_repository, destination_directory, checkout)
39+
40+
return app_gen
41+
42+
def build_docker(state_directory, image_namespace=None, image_repository=None, image_tag=None, config_file=None, **kwargs):
43+
"Build a Docker image from the initialized application directory"
44+
45+
state_dir = check_state_directory(state_directory_path(state_directory))
46+
47+
app_gen = UnityApplicationGenerator(state_dir,
48+
repo2docker_config=config_file,
49+
use_namespace=image_namespace,
50+
use_repository=image_repository,
51+
use_tag=image_tag)
52+
53+
app_gen.create_docker_image()
54+
55+
return app_gen
56+
57+
def push_docker(state_directory, container_registry, **kwargs):
58+
state_dir = check_state_directory(state_directory_path(state_directory))
59+
60+
app_gen = UnityApplicationGenerator(state_dir)
61+
62+
app_gen.push_to_docker_registry(container_registry)
63+
64+
return app_gen
65+
66+
def push_ecr(state_directory, **kwargs):
67+
state_dir = check_state_directory(state_directory_path(state_directory))
68+
69+
app_gen = UnityApplicationGenerator(state_dir)
70+
71+
app_gen.push_to_aws_ecr()
72+
73+
return app_gen
74+
75+
def notebook_parameters(state_directory, **kwargs):
76+
77+
state_dir = check_state_directory(state_directory_path(state_directory))
78+
79+
app_gen = UnityApplicationGenerator(state_dir)
80+
81+
print()
82+
print(app_gen.notebook_parameters())
83+
84+
return app_gen
85+
86+
def build_cwl(state_directory, cwl_output_path=None, image_url=None, monolithic=False, **kwargs):
87+
state_dir = check_state_directory(state_directory_path(state_directory))
88+
89+
app_gen = UnityApplicationGenerator(state_dir)
90+
91+
app_gen.create_cwl(cwl_output_path=cwl_output_path, docker_url=image_url, monolithic=monolithic)
92+
93+
return app_gen
94+
95+
def push_app_registry(state_directory, dockstore_api_url, dockstore_token, **kwargs):
96+
state_dir = check_state_directory(state_directory_path(state_directory))
97+
98+
app_gen = UnityApplicationGenerator(state_dir)
99+
100+
app_gen.push_to_application_registry(dockstore_api_url, dockstore_token)
101+
102+
return app_gen

0 commit comments

Comments
 (0)