firecloud-api-cds 0.2.0__py3-none-any.whl

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.
@@ -0,0 +1,323 @@
1
+ import json
2
+
3
+ import api as fapi
4
+ from .entity import Entity
5
+
6
+ class Workspace(object):
7
+ """A FireCloud Workspace.
8
+
9
+ Attributes:
10
+ api_url (str): API root used to interact with FireCloud,
11
+ normally https://api.firecloud.org/api
12
+ namespace (str): Google project for this workspace
13
+ name (str): Workspace name
14
+ """
15
+
16
+ def __init__(self, namespace, name, api_url=fapi.PROD_API_ROOT):
17
+ """Get an existing workspace from firecloud_api_cds by name.
18
+
19
+ This method assumes that a workspace with the given name and
20
+ namespace is present at the api_url given, and raises an error
21
+ if it does not exist. To create a new workspace, use
22
+ Workspace.new()
23
+
24
+ Raises:
25
+ FireCloudServerError: Workspace does not exist, or
26
+ API call fails
27
+ """
28
+ self.api_url = api_url
29
+ self.namespace = namespace
30
+ self.name = name
31
+
32
+ ## Call out to FireCloud
33
+ r = fapi.get_workspace(namespace, name, api_url)
34
+
35
+ fapi._check_response_code(r, 200)
36
+ self.data = r.json()
37
+
38
+
39
+ @staticmethod
40
+ def new(namespace, name, protected=False,
41
+ attributes=dict(), api_url=fapi.PROD_API_ROOT):
42
+ """Create a new FireCloud workspace.
43
+
44
+ Returns:
45
+ Workspace: A new FireCloud workspace
46
+
47
+ Raises:
48
+ FireCloudServerError: API call failed.
49
+ """
50
+ r = fapi.create_workspace(namespace, name, protected, attributes, api_url)
51
+ fapi._check_response_code(r, 201)
52
+ return Workspace(namespace, name, api_url)
53
+
54
+ def refresh(self):
55
+ """Reload workspace metadata from firecloud_api_cds.
56
+
57
+ Workspace metadata is cached in the data attribute of a Workspace,
58
+ and may become stale, requiring a refresh().
59
+ """
60
+ r = fapi.get_workspace(self.namespace, self.name, self.api_url)
61
+ fapi._check_response_code(r, 200)
62
+ self.data = r.json()
63
+ return self
64
+
65
+ def delete(self):
66
+ """Delete the workspace from firecloud_api_cds.
67
+
68
+ Note:
69
+ This action cannot be undone. Be careful!
70
+ """
71
+ r = fapi.delete_workspace(self.namespace, self.name)
72
+ fapi._check_response_code(r, 202)
73
+
74
+ # Getting useful information out of the bucket
75
+ def __str__(self):
76
+ """Return a JSON representation of the bucket."""
77
+ return json.dumps(self.data, indent=2)
78
+
79
+ def bucket(self):
80
+ """Return google bucket id for this workspace."""
81
+ return str(self.data["workspace"]["bucketName"])
82
+
83
+ def lock(self):
84
+ """Lock this Workspace.
85
+
86
+ This causes the workspace to behave in a read-only way,
87
+ regardless of access permissions.
88
+ """
89
+ r = fapi.lock_workspace(self.namespace, self.name, self.api_url)
90
+ fapi._check_response_code(r, 204)
91
+ self.data['workspace']['isLocked'] = True
92
+ return self
93
+
94
+ def unlock(self):
95
+ """Unlock this Workspace."""
96
+ r = fapi.unlock_workspace(self.namespace, self.name, self.api_url)
97
+ fapi._check_response_code(r, 204)
98
+ self.data['workspace']['isLocked'] = False
99
+ return self
100
+
101
+ def attributes(self):
102
+ """Return a dictionary of workspace attributes"""
103
+ return self.data["workspace"]["attributes"]
104
+
105
+ def get_attribute(self, attr):
106
+ """Return value of workspace attribute.
107
+
108
+ If the attribute does not exist, return None
109
+ """
110
+ return self.data["workspace"]["attributes"].get(attr, None)
111
+
112
+ def update_attribute(self, attr, value):
113
+ """Set the value of a workspace attribute."""
114
+ update = [fapi._attr_up(attr, value)]
115
+ r = fapi.update_workspace_attributes(self.namespace, self.name,
116
+ update, self.api_url)
117
+ fapi._check_response_code(r, 200)
118
+
119
+ def remove_attribute(self, attr):
120
+ """Remove attribute from a workspace.
121
+
122
+ Args:
123
+ attr (str): attribute name
124
+ """
125
+ update = [fapi._attr_rem(attr)]
126
+ r = fapi.update_workspace_attributes(self.namespace, self.name,
127
+ update, self.api_url)
128
+ self.data["workspace"]["attributes"].pop(attr, None)
129
+ fapi._check_response_code(r, 200)
130
+
131
+ def import_tsv(self, tsv_file):
132
+ """Upload entity data to workspace from tsv loadfile.
133
+
134
+ Args:
135
+ tsv_file (file): Tab-delimited file of entity data
136
+ """
137
+ r = fapi.upload_entities_tsv(self.namespace, self.name,
138
+ self.tsv_file, self.api_url)
139
+ fapi._check_response_code(r, 201)
140
+
141
+ def get_entity(self, etype, entity_id):
142
+ """Return entity in this workspace.
143
+
144
+ Args:
145
+ etype (str): Entity type
146
+ entity_id (str): Entity name/unique id
147
+ """
148
+ r = fapi.get_entity(self.namespace, self.name, etype,
149
+ entity_id, self.api_url)
150
+ fapi._check_response_code(r, 200)
151
+ dresp = r.json()
152
+ return Entity(etype, entity_id, dresp['attributes'])
153
+
154
+ def delete_entity(self, etype, entity_id):
155
+ """Delete an entity in this workspace.
156
+
157
+ Args:
158
+ etype (str): Entity type
159
+ entity_id (str): Entity name/unique id
160
+ """
161
+ r = fapi.delete_entity(self.namespace, self.name, etype,
162
+ entity_id, self.api_url)
163
+ fapi._check_response_code(r, 202)
164
+
165
+ def import_entities(self, entities):
166
+ """Upload entity objects.
167
+
168
+ Args:
169
+ entities: iterable of firecloud.Entity objects.
170
+ """
171
+ edata = Entity.create_payload(entities)
172
+ r = fapi.upload_entities(self.namespace, self.name,
173
+ edata, self.api_url)
174
+ fapi._check_response_code(r, 201)
175
+
176
+ def create_set(self, set_id, etype, entities):
177
+ """Create a set of entities and upload to FireCloud.
178
+
179
+ Args
180
+ etype (str): one of {"sample, "pair", "participant"}
181
+ entities: iterable of firecloud.Entity objects.
182
+ """
183
+ if etype not in {"sample", "pair", "participant"}:
184
+ raise ValueError("Unsupported entity type:" + str(etype))
185
+
186
+ payload = "membership:" + etype + "_set_id\t" + etype + "_id\n"
187
+
188
+ for e in entities:
189
+ if e.etype != etype:
190
+ msg = "Entity type '" + e.etype + "' does not match "
191
+ msg += "set type '" + etype + "'"
192
+ raise ValueError(msg)
193
+ payload += set_id + '\t' + e.entity_id + '\n'
194
+
195
+
196
+ r = fapi.upload_entities(self.namespace, self.name,
197
+ payload, self.api_url)
198
+ fapi._check_response_code(r, 201)
199
+
200
+ def create_sample_set(self, sset_id, samples):
201
+ """Create FireCloud sample_set"""
202
+ return self.create_set(sset_id, "sample", samples)
203
+
204
+ def create_pair_set(self, pset_id, pairs):
205
+ """Create FireCloud pair_set"""
206
+ return self.create_set(pset_id, "pair", pairs)
207
+
208
+ def create_participant_set(self, pset_id, participants):
209
+ """Create FireCloud participant_set"""
210
+ return self.create_set(pset_id, "participant", participants)
211
+
212
+ def submissions(self):
213
+ """List job submissions in workspace."""
214
+ r = fapi.get_submissions(self.namespace, self.name, self.api_url)
215
+ fapi._check_response_code(r, 200)
216
+ return r.json()
217
+
218
+ def entity_types(self):
219
+ """List entity types in workspace."""
220
+ r = fapi.get_entity_types(self.namespace, self.name, self.api_url)
221
+ fapi._check_response_code(r, 200)
222
+ return r.json().keys()
223
+
224
+ def entities(self):
225
+ """List all entities in workspace."""
226
+ r = fapi.get_entities_with_type(self.namespace,
227
+ self.name, self.api_url)
228
+ fapi._check_response_code(r, 200)
229
+ edicts = r.json()
230
+ return [Entity(e['entityType'], e['name'], e['attributes'])
231
+ for e in edicts]
232
+
233
+ def __get_entities(self, etype):
234
+ """Helper to get entities for a given type."""
235
+ r = fapi.get_entities(self.namespace, self.name,
236
+ etype, self.api_url)
237
+ fapi._check_response_code(r, 200)
238
+ return [Entity(e['entityType'], e['name'], e['attributes'])
239
+ for e in r.json()]
240
+
241
+ def samples(self):
242
+ """List samples in a workspace."""
243
+ return self.__get_entities("sample")
244
+
245
+ def participants(self):
246
+ """List participants in a workspace."""
247
+ return self.__get_entities("participant")
248
+
249
+ def pairs(self):
250
+ """List pairs in a workspace."""
251
+ return self.__get_entities("pair")
252
+
253
+ def sample_sets(self):
254
+ """List sample sets in a workspace."""
255
+ return self.__get_entities("sample_set")
256
+
257
+ def participant_sets(self):
258
+ """List participant sets in a workspace."""
259
+ return self.__get_entities("participant_set")
260
+
261
+ def pair_sets(self):
262
+ """List pair sets in a workspace."""
263
+ return self.__get_entities("pair_set")
264
+
265
+ def copy_entities(self, from_namespace, from_workspace, etype, enames):
266
+ """Copy entities from another workspace.
267
+
268
+ Args:
269
+ from_namespace (str): Source workspace namespace
270
+ from_workspace (str): Source workspace name
271
+ etype (str): Entity type
272
+ enames (list(str)): List of entity names to copy
273
+ """
274
+ r = fapi.copy_entities(from_namespace, from_workspace,
275
+ self.namespace, self.name, etype, enames,
276
+ self.api_url)
277
+ fapi._check_response_code(r, 201)
278
+
279
+ def configs(self):
280
+ """Get method configurations in a workspace."""
281
+ raise NotImplementedError
282
+ r = fapi.get_configs(self.namespace, self.name, self.api_url)
283
+ fapi._check_response_code(r, 200)
284
+ cdata = r.json()
285
+ configs = []
286
+ for c in cdata:
287
+ cnamespace = c['namespace']
288
+ cname = c['name']
289
+ root_etype = c['rootEntityType']
290
+ method_namespace = c['methodRepoMethod']['methodNamespace']
291
+ method_name = c['methodRepoMethod']['methodName']
292
+ method_version = c['methodRepoMethod']['methodVersion']
293
+
294
+ def acl(self):
295
+ """Get the access control list for this workspace."""
296
+ r = fapi.get_workspace_acl(self.namespace, self.name, self.api_url)
297
+ fapi._check_response_code(r, 200)
298
+ return r.json()
299
+
300
+ def set_acl(self, role, users):
301
+ """Set access permissions for this workspace
302
+
303
+ Args:
304
+ role (str): Access level
305
+ one of {one of "OWNER", "READER", "WRITER", "NO ACCESS"}
306
+ users (list(str)): List of users to give role to
307
+ """
308
+ acl_updates = [{"email": user, "accessLevel": role} for user in users]
309
+ r = fapi.update_workspace_acl(self.namespace, self.name,
310
+ acl_updates, self.api_url)
311
+ fapi._check_response_code(r, 200)
312
+
313
+ def clone(self, to_namespace, to_name):
314
+ """Clone this workspace.
315
+
316
+ Args:
317
+ to_namespace (str): Target workspace namespace
318
+ to_name (str): Target workspace name
319
+ """
320
+ r = fapi.clone_workspace(self.namespace, self.name,
321
+ to_namespace, to_name, self.api_url)
322
+ fapi._check_response_code(r, 201)
323
+ return Workspace(to_namespace, to_name, self.api_url)
@@ -0,0 +1,18 @@
1
+ Metadata-Version: 2.4
2
+ Name: firecloud-api-cds
3
+ Version: 0.2.0
4
+ Summary: Fork of broadinstitute/fiss
5
+ Project-URL: Homepage, https://github.com/broadinstitute/firecloud-api-cds
6
+ License: BSD 3-Clause License
7
+ License-File: LICENSE
8
+ Requires-Python: >=3.9
9
+ Requires-Dist: google-auth!=2.1.*,!=2.2.*,!=2.3.0,!=2.3.1,>=1.6.3
10
+ Requires-Dist: google-cloud-storage>=1.36.1
11
+ Requires-Dist: pydot>=4.0.0
12
+ Requires-Dist: six>=1.17.0
13
+ Description-Content-Type: text/markdown
14
+
15
+ firecloud-api-cds
16
+ ===
17
+
18
+ Fork of [https://github.com/broadinstitute/fiss](https://github.com/broadinstitute/fiss).
@@ -0,0 +1,15 @@
1
+ firecloud_api_cds/__init__.py,sha256=uhUFQxF7jtpCBtdxOkSpOTaSr-h5-fGfWYYknmNxHBE,250
2
+ firecloud_api_cds/api.py,sha256=FOdCgHeygUXl1R6YNXar2z2ljI02K8AC-1WbZgswFew,62555
3
+ firecloud_api_cds/config.py,sha256=B2fmheEVIe-8QSwaItueKceJqD68LB6qfrWSmAz4EW8,729
4
+ firecloud_api_cds/entity.py,sha256=W2vA7Te__HKr_l6IJq-1ThfNLfluCL_HbFPdk_tFCno,2402
5
+ firecloud_api_cds/errors.py,sha256=1vQITDBz3tXOTTH8ptjR26RerIdB3AzEF6An6XF4QhA,470
6
+ firecloud_api_cds/fccore.py,sha256=0KY9wf6LSZVlwBlar7EHKJ66zvbfHLr6RIV8kf3HKg4,7276
7
+ firecloud_api_cds/fiss.py,sha256=TQS8gbWbQ0CYWhqhO85wlUNDE6Rm_KneuF2WX4ZF-8c,127761
8
+ firecloud_api_cds/method.py,sha256=EvfzTUtwfbWKRV22deLhS8zPdNx_7qlSKD7YJM9b1Hs,3055
9
+ firecloud_api_cds/submission.py,sha256=QWXG5Qg8-t3oMOquVnq8Aiq3lfO54LRbZcP_ACYF-aQ,1130
10
+ firecloud_api_cds/supervisor.py,sha256=-z7eTDze4778XC305ndbItjzDCCD2c_KrikPu5At9yg,11982
11
+ firecloud_api_cds/workspace.py,sha256=_SIEQzCZweDPHG6_xGRoJQ0Rg6pHCTT49aKDKAQOwO0,11502
12
+ firecloud_api_cds-0.2.0.dist-info/METADATA,sha256=VjA52NQovI8cZJoG9kWyry0DytjOCqDHW2vPdgi7NCE,567
13
+ firecloud_api_cds-0.2.0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
14
+ firecloud_api_cds-0.2.0.dist-info/licenses/LICENSE,sha256=ZKuWQRVyyGZq9eYztaCgDoPHgnlFv6beDxmHGwcyQtE,1525
15
+ firecloud_api_cds-0.2.0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.28.0
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,30 @@
1
+ BSD 3-Clause License
2
+
3
+ Copyright (c) 2018, Broad Institute, Inc.
4
+ All rights reserved.
5
+
6
+ Redistribution and use in source and binary forms, with or without
7
+ modification, are permitted provided that the following conditions are met:
8
+
9
+ * Redistributions of source code must retain the above copyright notice, this
10
+ list of conditions and the following disclaimer.
11
+
12
+ * Redistributions in binary form must reproduce the above copyright notice,
13
+ this list of conditions and the following disclaimer in the documentation
14
+ and/or other materials provided with the distribution.
15
+
16
+ * Neither the name Broad Institute, Inc. nor the names of its
17
+ contributors may be used to endorse or promote products derived from
18
+ this software without specific prior written permission.
19
+
20
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
24
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
+