basepair 1.5__0-py3.8.egg
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- EGG-INFO/PKG-INFO +27 -0
- EGG-INFO/SOURCES.txt +38 -0
- EGG-INFO/dependency_links.txt +1 -0
- EGG-INFO/requires.txt +5 -0
- EGG-INFO/scripts/basepair +637 -0
- EGG-INFO/top_level.txt +1 -0
- EGG-INFO/zip-safe +1 -0
- basepair/__init__.py +32 -0
- basepair/__pycache__/__init__.cpython-38.pyc +0 -0
- basepair/__pycache__/api.cpython-38.pyc +0 -0
- basepair/api.py +1353 -0
- basepair/helpers/__init__.py +3 -0
- basepair/helpers/__pycache__/__init__.cpython-38.pyc +0 -0
- basepair/helpers/__pycache__/eprint.cpython-38.pyc +0 -0
- basepair/helpers/__pycache__/nice_print.cpython-38.pyc +0 -0
- basepair/helpers/__pycache__/set_filter.cpython-38.pyc +0 -0
- basepair/helpers/eprint.py +8 -0
- basepair/helpers/nice_print.py +170 -0
- basepair/helpers/set_filter.py +18 -0
- basepair/infra/__init__.py +0 -0
- basepair/infra/__pycache__/__init__.cpython-38.pyc +0 -0
- basepair/infra/configuration/__init__.py +1 -0
- basepair/infra/configuration/__pycache__/__init__.cpython-38.pyc +0 -0
- basepair/infra/configuration/__pycache__/parser.cpython-38.pyc +0 -0
- basepair/infra/configuration/parser.py +67 -0
- basepair/infra/webapp/__init__.py +12 -0
- basepair/infra/webapp/__pycache__/__init__.cpython-38.pyc +0 -0
- basepair/infra/webapp/__pycache__/abstract.cpython-38.pyc +0 -0
- basepair/infra/webapp/__pycache__/analysis.cpython-38.pyc +0 -0
- basepair/infra/webapp/__pycache__/file.cpython-38.pyc +0 -0
- basepair/infra/webapp/__pycache__/gene.cpython-38.pyc +0 -0
- basepair/infra/webapp/__pycache__/genome.cpython-38.pyc +0 -0
- basepair/infra/webapp/__pycache__/genome_file.cpython-38.pyc +0 -0
- basepair/infra/webapp/__pycache__/host.cpython-38.pyc +0 -0
- basepair/infra/webapp/__pycache__/module.cpython-38.pyc +0 -0
- basepair/infra/webapp/__pycache__/pipeline.cpython-38.pyc +0 -0
- basepair/infra/webapp/__pycache__/project.cpython-38.pyc +0 -0
- basepair/infra/webapp/__pycache__/sample.cpython-38.pyc +0 -0
- basepair/infra/webapp/__pycache__/upload.cpython-38.pyc +0 -0
- basepair/infra/webapp/__pycache__/user.cpython-38.pyc +0 -0
- basepair/infra/webapp/abstract.py +128 -0
- basepair/infra/webapp/analysis.py +10 -0
- basepair/infra/webapp/file.py +10 -0
- basepair/infra/webapp/gene.py +10 -0
- basepair/infra/webapp/genome.py +10 -0
- basepair/infra/webapp/genome_file.py +10 -0
- basepair/infra/webapp/host.py +10 -0
- basepair/infra/webapp/module.py +10 -0
- basepair/infra/webapp/pipeline.py +10 -0
- basepair/infra/webapp/project.py +10 -0
- basepair/infra/webapp/sample.py +10 -0
- basepair/infra/webapp/upload.py +10 -0
- basepair/infra/webapp/user.py +48 -0
- basepair/utils/__init__.py +0 -0
- basepair/utils/__pycache__/__init__.cpython-38.pyc +0 -0
- basepair/utils/__pycache__/colors.cpython-38.pyc +0 -0
- basepair/utils/__pycache__/monitor.cpython-38.pyc +0 -0
- basepair/utils/__pycache__/s3.cpython-38.pyc +0 -0
- basepair/utils/__pycache__/sqs.cpython-38.pyc +0 -0
- basepair/utils/__pycache__/swf.cpython-38.pyc +0 -0
- basepair/utils/colors.py +43 -0
- basepair/utils/monitor.py +38 -0
- basepair/utils/s3.py +77 -0
- basepair/utils/sqs.py +147 -0
- basepair/utils/swf.py +129 -0
basepair/utils/colors.py
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
|
|
3
|
+
from __future__ import print_function
|
|
4
|
+
from builtins import object
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class color(object):
|
|
8
|
+
HEADER = '\033[95m'
|
|
9
|
+
BLUE = '\033[34m'
|
|
10
|
+
CYAN = '\033[36;1m'
|
|
11
|
+
GREEN = '\033[38;5;28m'
|
|
12
|
+
BROWN = '\033[33m'
|
|
13
|
+
RED = '\033[31m'
|
|
14
|
+
ENDC = '\033[0m'
|
|
15
|
+
|
|
16
|
+
@staticmethod
|
|
17
|
+
def primary(text):
|
|
18
|
+
return color.BLUE + text + color.ENDC
|
|
19
|
+
|
|
20
|
+
@staticmethod
|
|
21
|
+
def info(text):
|
|
22
|
+
return color.CYAN + text + color.ENDC
|
|
23
|
+
|
|
24
|
+
@staticmethod
|
|
25
|
+
def success(text):
|
|
26
|
+
return color.GREEN + text + color.ENDC
|
|
27
|
+
|
|
28
|
+
@staticmethod
|
|
29
|
+
def warning(text):
|
|
30
|
+
return color.BROWN + text + color.ENDC
|
|
31
|
+
|
|
32
|
+
@staticmethod
|
|
33
|
+
def error(text):
|
|
34
|
+
return color.RED + text + color.ENDC
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
if __name__ == '__main__':
|
|
38
|
+
print(color.primary('primary'))
|
|
39
|
+
print(color.primary('info'))
|
|
40
|
+
print(color.success('success'))
|
|
41
|
+
print(color.warning('warning'))
|
|
42
|
+
print(color.error('error'))
|
|
43
|
+
print('ok')
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# monitors multiple files for modification
|
|
2
|
+
# can check for modification of one or all of them
|
|
3
|
+
#
|
|
4
|
+
# usage:
|
|
5
|
+
# monitor = Monitor()
|
|
6
|
+
# monitor.monitor('decider.py')
|
|
7
|
+
|
|
8
|
+
# if monitor.is_modified('decider.py'): # check one specific file
|
|
9
|
+
# if monitor.is_modified(): # check all monitored files
|
|
10
|
+
|
|
11
|
+
from builtins import object
|
|
12
|
+
import os
|
|
13
|
+
|
|
14
|
+
class Monitor(object):
|
|
15
|
+
def __init__(self, filename=None):
|
|
16
|
+
self.last_modified = {}
|
|
17
|
+
if filename:
|
|
18
|
+
self.monitor(filename)
|
|
19
|
+
|
|
20
|
+
def monitor(self, filename):
|
|
21
|
+
self.last_modified[filename] = os.path.getmtime(filename)
|
|
22
|
+
|
|
23
|
+
def is_modified(self, filename=None):
|
|
24
|
+
if filename:
|
|
25
|
+
return self.is_modified_filename(filename)
|
|
26
|
+
else:
|
|
27
|
+
# if any single file is modified, return True
|
|
28
|
+
for filename in list(self.last_modified.keys()):
|
|
29
|
+
if self.is_modified_filename(filename):
|
|
30
|
+
return True
|
|
31
|
+
return False
|
|
32
|
+
|
|
33
|
+
def is_modified_filename(self, filename):
|
|
34
|
+
if os.path.getmtime(filename) > self.last_modified[filename]:
|
|
35
|
+
self.last_modified[filename] = os.path.getmtime(filename)
|
|
36
|
+
return True
|
|
37
|
+
else:
|
|
38
|
+
return False
|
basepair/utils/s3.py
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
|
|
3
|
+
from builtins import object
|
|
4
|
+
import argparse
|
|
5
|
+
import json
|
|
6
|
+
|
|
7
|
+
import boto
|
|
8
|
+
from boto.s3.key import Key
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class BpS3(object):
|
|
12
|
+
def __init__(self, conf):
|
|
13
|
+
self.conf = conf
|
|
14
|
+
|
|
15
|
+
region = None
|
|
16
|
+
try:
|
|
17
|
+
for reg in boto.sqs.regions():
|
|
18
|
+
if reg.name == self.conf['aws']['s3']['region']:
|
|
19
|
+
region = reg
|
|
20
|
+
break
|
|
21
|
+
except KeyError:
|
|
22
|
+
region = None
|
|
23
|
+
|
|
24
|
+
self.conn = boto.connect_s3(
|
|
25
|
+
aws_access_key_id=self.conf['aws']['aws_id'],
|
|
26
|
+
aws_secret_access_key=self.conf['aws']['aws_secret'],
|
|
27
|
+
region=region,
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
def save_data(self, data, bucket_name, key_name):
|
|
31
|
+
bucket = self.conn.create_bucket(
|
|
32
|
+
bucket_name, location=boto.s3.connection.Location.DEFAULT)
|
|
33
|
+
k = Key(bucket)
|
|
34
|
+
k.key = key_name
|
|
35
|
+
k.set_contents_from_string(json.dumps(data, indent=2))
|
|
36
|
+
|
|
37
|
+
# TODO: URL valid for 1 year
|
|
38
|
+
# generate s3 path
|
|
39
|
+
def get_s3_url(self, path, expires_in=None):
|
|
40
|
+
if not expires_in:
|
|
41
|
+
expires_in = 3600 * 24 * 365
|
|
42
|
+
|
|
43
|
+
bucket = self.conn.get_bucket(self.conf['aws']['s3']['bucket'])
|
|
44
|
+
key = bucket.get_key(path)
|
|
45
|
+
url = key.generate_url(expires_in) if key else ''
|
|
46
|
+
|
|
47
|
+
return url
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def main():
|
|
51
|
+
args = read_args()
|
|
52
|
+
conf = json.load(open(args.config_file))
|
|
53
|
+
s3 = BpS3(conf)
|
|
54
|
+
|
|
55
|
+
data = {
|
|
56
|
+
'abc': 'def',
|
|
57
|
+
'rst': 'xyz',
|
|
58
|
+
}
|
|
59
|
+
bucket_name = 'bpdev0'
|
|
60
|
+
key_name = 'analysis/1890/__private__/workflow.json'
|
|
61
|
+
s3.save_data(data, bucket_name, key_name)
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def read_args():
|
|
65
|
+
parser = argparse.ArgumentParser(description='cmd line instance control')
|
|
66
|
+
parser.add_argument('-c', '--config-file')
|
|
67
|
+
parser.set_defaults(
|
|
68
|
+
config_file='setup/config.dev.json'
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
args = parser.parse_args()
|
|
72
|
+
|
|
73
|
+
return args
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
if __name__ == '__main__':
|
|
77
|
+
main()
|
basepair/utils/sqs.py
ADDED
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
'''wrapper for boto AWS SQS'''
|
|
3
|
+
from __future__ import print_function
|
|
4
|
+
|
|
5
|
+
from builtins import object
|
|
6
|
+
import sys
|
|
7
|
+
# import os
|
|
8
|
+
import json
|
|
9
|
+
import argparse
|
|
10
|
+
import random
|
|
11
|
+
# import time
|
|
12
|
+
|
|
13
|
+
import boto
|
|
14
|
+
from boto.sqs.jsonmessage import JSONMessage
|
|
15
|
+
import requests
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class BpSQS(object):
|
|
19
|
+
'''wrapper for boto AWS SQS'''
|
|
20
|
+
def __init__(self, conf, config_file=None, queue='decider', timeout=120, wait_time=20):
|
|
21
|
+
if config_file:
|
|
22
|
+
self.conf = json.load(open(config_file))
|
|
23
|
+
else:
|
|
24
|
+
self.conf = conf
|
|
25
|
+
self.wait_time = wait_time
|
|
26
|
+
self.q = None
|
|
27
|
+
|
|
28
|
+
internet = True
|
|
29
|
+
try:
|
|
30
|
+
requests.get('https://www.google.com/', timeout=1)
|
|
31
|
+
except requests.exceptions.ConnectionError:
|
|
32
|
+
print('warning: no internet', file=sys.stderr)
|
|
33
|
+
internet = False
|
|
34
|
+
|
|
35
|
+
region = None
|
|
36
|
+
try:
|
|
37
|
+
for reg in boto.sqs.regions():
|
|
38
|
+
if reg.name == self.conf['aws']['sqs']['region']:
|
|
39
|
+
region = reg
|
|
40
|
+
break
|
|
41
|
+
except KeyError:
|
|
42
|
+
region = None
|
|
43
|
+
|
|
44
|
+
if internet:
|
|
45
|
+
self.conn = boto.connect_sqs(
|
|
46
|
+
aws_access_key_id=self.conf['aws']['aws_id'],
|
|
47
|
+
aws_secret_access_key=self.conf['aws']['aws_secret'],
|
|
48
|
+
region=region
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
self.q = self.conn.create_queue(queue, timeout)
|
|
52
|
+
self.q.set_message_class(JSONMessage)
|
|
53
|
+
|
|
54
|
+
def send_message(self, _msg):
|
|
55
|
+
'''send message'''
|
|
56
|
+
delay = _msg.get('delay', 0)
|
|
57
|
+
|
|
58
|
+
message = JSONMessage()
|
|
59
|
+
message.set_body(_msg)
|
|
60
|
+
status = self.q.write(message, delay_seconds=delay)
|
|
61
|
+
return status
|
|
62
|
+
|
|
63
|
+
# {u'ApproximateFirstReceiveTimestamp' '1535158416671',
|
|
64
|
+
# u'SenderId': u'',
|
|
65
|
+
# u'ApproximateReceiveCount': u'1
|
|
66
|
+
# u'SentTimestamp': u'1535158416657'}
|
|
67
|
+
def get_messages(self):
|
|
68
|
+
'''get messages'''
|
|
69
|
+
return self.q.get_messages(
|
|
70
|
+
attributes=['All'],
|
|
71
|
+
num_messages=10,
|
|
72
|
+
wait_time_seconds=self.wait_time)
|
|
73
|
+
|
|
74
|
+
def get_message(self):
|
|
75
|
+
'''get a message'''
|
|
76
|
+
return self.q.read(wait_time_seconds=self.wait_time)
|
|
77
|
+
# except socket.gaierror:
|
|
78
|
+
# print >>sys.stderr, 'no connection, sleeping for a minute'
|
|
79
|
+
# time.sleep(60)
|
|
80
|
+
# return None
|
|
81
|
+
|
|
82
|
+
def clear(self, wetrun=False):
|
|
83
|
+
'''clear the queue, delete messages'''
|
|
84
|
+
msgs = self.get_messages()
|
|
85
|
+
print(msgs, file=sys.stderr)
|
|
86
|
+
for msg in msgs:
|
|
87
|
+
print(msg, file=sys.stderr)
|
|
88
|
+
if wetrun:
|
|
89
|
+
self.q.delete_message(msg)
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
def main():
|
|
93
|
+
'''script'''
|
|
94
|
+
args = read_args()
|
|
95
|
+
# test_decider_queue(args)
|
|
96
|
+
# test_instance_queue(args)
|
|
97
|
+
if args.clear:
|
|
98
|
+
sqs = BpSQS(conf=None, config_file=args.config_file)
|
|
99
|
+
sqs.clear()
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
def test_decider_queue(args):
|
|
103
|
+
'''test decider queue'''
|
|
104
|
+
sqs = BpSQS(conf=None, config_file=args.config_file)
|
|
105
|
+
msg = {
|
|
106
|
+
"message": "completed",
|
|
107
|
+
"analysis-id": 1481,
|
|
108
|
+
"data": {},
|
|
109
|
+
"sender": "decider"
|
|
110
|
+
}
|
|
111
|
+
sqs.send_message(msg)
|
|
112
|
+
print(json.dumps(msg, indent=2), file=sys.stderr)
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
def test_instance_queue(args):
|
|
116
|
+
'''test instance queue'''
|
|
117
|
+
analysis_id = int(1000000 * random.random())
|
|
118
|
+
sqs = BpSQS(conf=None, config_file=args.config_file, queue='instance', timeout=600)
|
|
119
|
+
msg = {
|
|
120
|
+
'action': 'start-instance',
|
|
121
|
+
'name': 'bp-%s' % analysis_id,
|
|
122
|
+
'kind': 'spot',
|
|
123
|
+
'mode': 'dev',
|
|
124
|
+
'task_list': 'worker',
|
|
125
|
+
'analysis_id': analysis_id,
|
|
126
|
+
}
|
|
127
|
+
sqs.send_message(msg)
|
|
128
|
+
print(json.dumps(msg, indent=2), file=sys.stderr)
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
def read_args():
|
|
132
|
+
'''user args'''
|
|
133
|
+
parser = argparse.ArgumentParser(description='cmd line instance control')
|
|
134
|
+
parser.add_argument('-a', '--action')
|
|
135
|
+
parser.add_argument('-c', '--config-file')
|
|
136
|
+
parser.add_argument('-C', '--clear')
|
|
137
|
+
parser.set_defaults(clear=False)
|
|
138
|
+
parser.set_defaults(
|
|
139
|
+
config_file='setup/config.dev.json'
|
|
140
|
+
)
|
|
141
|
+
args = parser.parse_args()
|
|
142
|
+
|
|
143
|
+
return args
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
if __name__ == '__main__':
|
|
147
|
+
main()
|
basepair/utils/swf.py
ADDED
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
|
|
3
|
+
from __future__ import print_function
|
|
4
|
+
from builtins import object
|
|
5
|
+
import sys
|
|
6
|
+
import json
|
|
7
|
+
import argparse
|
|
8
|
+
import time
|
|
9
|
+
|
|
10
|
+
import boto.swf
|
|
11
|
+
from boto.swf.exceptions import SWFDomainAlreadyExistsError, \
|
|
12
|
+
SWFTypeAlreadyExistsError
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class SWF(object):
|
|
16
|
+
def __init__(self, config_file):
|
|
17
|
+
self.conf = json.load(open(config_file))
|
|
18
|
+
region = None
|
|
19
|
+
try:
|
|
20
|
+
for reg in boto.swf.regions():
|
|
21
|
+
if reg.name == self.conf['aws']['swf']['region']:
|
|
22
|
+
region = reg
|
|
23
|
+
break
|
|
24
|
+
|
|
25
|
+
except KeyError:
|
|
26
|
+
region = None
|
|
27
|
+
|
|
28
|
+
self.layer = boto.swf.layer1.Layer1(
|
|
29
|
+
aws_access_key_id=self.conf['aws']['aws_id'],
|
|
30
|
+
aws_secret_access_key=self.conf['aws']['aws_secret'],
|
|
31
|
+
region=region
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
# self.s3conn = boto.connect_s3(
|
|
35
|
+
# aws_access_key_id=self.conf['aws']['aws_id'],
|
|
36
|
+
# aws_secret_access_key=self.conf['aws']['aws_secret'],
|
|
37
|
+
# )
|
|
38
|
+
|
|
39
|
+
def terminate(self):
|
|
40
|
+
workflows = self.layer.list_open_workflow_executions(
|
|
41
|
+
self.conf['aws']['swf']['domain'], oldest_date=1
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
for workflow in workflows['executionInfos']:
|
|
45
|
+
workflow_id = workflow['execution']['workflowId']
|
|
46
|
+
self.layer.terminate_workflow_execution(
|
|
47
|
+
self.conf['aws']['swf']['domain'], workflow_id)
|
|
48
|
+
print(workflow_id, file=sys.stderr)
|
|
49
|
+
|
|
50
|
+
def register(self):
|
|
51
|
+
self.register_domain()
|
|
52
|
+
self.register_workflow_type()
|
|
53
|
+
self.register_activity_type()
|
|
54
|
+
|
|
55
|
+
def register_domain(self):
|
|
56
|
+
domain = self.conf['aws']['swf']['domain']
|
|
57
|
+
|
|
58
|
+
try:
|
|
59
|
+
self.layer.register_domain(domain, '7')
|
|
60
|
+
except SWFDomainAlreadyExistsError:
|
|
61
|
+
print('domain', domain, 'exists', file=sys.stderr)
|
|
62
|
+
|
|
63
|
+
# print layer.list_domains('REGISTERED')
|
|
64
|
+
|
|
65
|
+
def register_workflow_type(self):
|
|
66
|
+
domain = self.conf['aws']['swf']['domain']
|
|
67
|
+
workflow = self.conf['aws']['swf']['workflow_type']
|
|
68
|
+
version = '1.0'
|
|
69
|
+
|
|
70
|
+
try:
|
|
71
|
+
self.layer.register_workflow_type(
|
|
72
|
+
domain, workflow, version,
|
|
73
|
+
task_list=self.conf['aws']['swf']['decider_task_list'],
|
|
74
|
+
default_child_policy='REQUEST_CANCEL',
|
|
75
|
+
default_execution_start_to_close_timeout='31536000',
|
|
76
|
+
default_task_start_to_close_timeout='31536000',
|
|
77
|
+
)
|
|
78
|
+
except SWFTypeAlreadyExistsError:
|
|
79
|
+
print('workflow', workflow, 'exists', file=sys.stderr)
|
|
80
|
+
|
|
81
|
+
def register_activity_type(self):
|
|
82
|
+
domain = self.conf['aws']['swf']['domain']
|
|
83
|
+
activity = self.conf['aws']['swf']['activity_type']
|
|
84
|
+
version = '1.0'
|
|
85
|
+
|
|
86
|
+
try:
|
|
87
|
+
self.layer.register_activity_type(
|
|
88
|
+
domain, activity, version,
|
|
89
|
+
default_task_heartbeat_timeout='31536000',
|
|
90
|
+
default_task_schedule_to_close_timeout='31536000',
|
|
91
|
+
default_task_schedule_to_start_timeout='31536000',
|
|
92
|
+
default_task_start_to_close_timeout='31536000',
|
|
93
|
+
task_list=self.conf['aws']['swf']['worker_task_list'],
|
|
94
|
+
)
|
|
95
|
+
except SWFTypeAlreadyExistsError:
|
|
96
|
+
print('activity', activity, 'exists', file=sys.stderr)
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
def main():
|
|
100
|
+
args = read_args()
|
|
101
|
+
swf = SWF(args.config_file)
|
|
102
|
+
|
|
103
|
+
if args.register:
|
|
104
|
+
swf.register()
|
|
105
|
+
|
|
106
|
+
if args.terminate:
|
|
107
|
+
print('terminating ...', file=sys.stderr)
|
|
108
|
+
swf.terminate()
|
|
109
|
+
time.sleep(3)
|
|
110
|
+
swf.terminate()
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
def read_args():
|
|
114
|
+
parser = argparse.ArgumentParser(description='cmd line instance control')
|
|
115
|
+
parser.add_argument('-t', '--terminate', action='store_true',
|
|
116
|
+
help='terminate open workflows')
|
|
117
|
+
parser.add_argument('-r', '--register', action='store_true')
|
|
118
|
+
parser.add_argument('-c', '--config-file')
|
|
119
|
+
parser.set_defaults(
|
|
120
|
+
config_file='setup/config.dev.json'
|
|
121
|
+
)
|
|
122
|
+
|
|
123
|
+
args = parser.parse_args()
|
|
124
|
+
|
|
125
|
+
return args
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
if __name__ == '__main__':
|
|
129
|
+
main()
|