geoseeq 0.2.15__py3-none-any.whl → 0.2.17__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
geoseeq/__init__.py CHANGED
@@ -30,4 +30,5 @@ from .work_orders import (
30
30
  WorkOrder,
31
31
  WorkOrderProto,
32
32
  )
33
- from .app import App
33
+ from .app import App
34
+ from .id_constructors import *
@@ -1,173 +1,6 @@
1
- from .result import (
2
- SampleResultFolder,
3
- SampleResultFile,
4
- ProjectResultFolder,
5
- ProjectResultFile,
6
- )
7
- from .organization import Organization
8
- from .sample import Sample
9
- from .project import Project
10
- from .knex import GeoseeqNotFoundError
1
+ """Alias for id_constructors.from_blobs and id_constructors.from_uuids
11
2
 
12
-
13
- def org_from_blob(knex, blob, already_fetched=True, modified=False):
14
- org = Organization(knex, blob["name"])
15
- org.load_blob(blob)
16
- org._already_fetched = already_fetched
17
- org._modified = modified
18
- return org
19
-
20
-
21
- def project_from_blob(knex, blob, already_fetched=True, modified=False):
22
- org = org_from_blob(
23
- knex, blob["organization_obj"], already_fetched=already_fetched, modified=modified
24
- )
25
- grp = Project(knex, org, blob["name"], is_library=blob["is_library"])
26
- grp.load_blob(blob)
27
- grp._already_fetched = already_fetched
28
- grp._modified = modified
29
- return grp
30
-
31
- sample_group_from_blob = project_from_blob # Alias
32
-
33
-
34
- def sample_from_blob(knex, blob, already_fetched=True, modified=False):
35
- lib = sample_group_from_blob(
36
- knex, blob["library_obj"], already_fetched=already_fetched, modified=modified
37
- )
38
- sample = Sample(knex, lib, blob["name"], metadata=blob["metadata"])
39
- sample.load_blob(blob)
40
- sample._already_fetched = already_fetched
41
- sample._modified = modified
42
- return sample
43
-
44
-
45
- def project_result_folder_from_blob(knex, blob, already_fetched=True, modified=False):
46
- group = project_from_blob(
47
- knex, blob["sample_group_obj"], already_fetched=already_fetched, modified=modified
48
- )
49
- ar = ProjectResultFolder(
50
- knex, group, blob["module_name"], replicate=blob["replicate"], metadata=blob["metadata"]
51
- )
52
- ar.load_blob(blob)
53
- ar._already_fetched = already_fetched
54
- ar._modified = modified
55
- return ar
56
-
57
- sample_group_ar_from_blob = project_result_folder_from_blob # Alias
58
-
59
-
60
- def sample_result_folder_from_blob(knex, blob, already_fetched=True, modified=False):
61
- sample = sample_from_blob(
62
- knex, blob["sample_obj"], already_fetched=already_fetched, modified=modified
63
- )
64
- ar = SampleResultFolder(
65
- knex, sample, blob["module_name"], replicate=blob["replicate"], metadata=blob["metadata"]
66
- )
67
- ar.load_blob(blob)
68
- ar._already_fetched = already_fetched
69
- ar._modified = modified
70
- return ar
71
-
72
- sample_ar_from_blob = sample_result_folder_from_blob # Alias
73
-
74
-
75
- def sample_result_file_from_blob(knex, blob, already_fetched=True, modified=False):
76
- ar = sample_result_folder_from_blob(
77
- knex, blob["analysis_result_obj"], already_fetched=already_fetched, modified=modified
78
- )
79
- arf = SampleResultFile(
80
- knex, ar, blob["name"], data=blob["stored_data"]
81
- )
82
- arf.load_blob(blob)
83
- ar._already_fetched = already_fetched
84
- ar._modified = modified
85
- return arf
86
-
87
- sample_ar_field_from_blob = sample_result_file_from_blob # Alias
88
-
89
-
90
- def project_result_file_from_blob(knex, blob, already_fetched=True, modified=False):
91
- ar = project_result_folder_from_blob(
92
- knex, blob["analysis_result_obj"], already_fetched=already_fetched, modified=modified
93
- )
94
- arf = ProjectResultFile(
95
- knex, ar, blob["name"], data=blob["stored_data"]
96
- )
97
- arf.load_blob(blob)
98
- ar._already_fetched = already_fetched
99
- ar._modified = modified
100
- return arf
101
-
102
- sample_group_ar_field_from_blob = project_result_file_from_blob # Alias
103
-
104
- def org_from_uuid(knex, uuid):
105
- """Return the organization object which the uuid points to."""
106
- blob = knex.get(f"organizations/{uuid}")
107
- org = org_from_blob(knex, blob)
108
- return org
109
-
110
- def project_from_uuid(knex, uuid):
111
- """Return the project object which the uuid points to."""
112
- blob = knex.get(f"sample_groups/{uuid}")
113
- project = project_from_blob(knex, blob)
114
- return project
115
-
116
- sample_group_from_uuid = project_from_uuid # Alias
117
-
118
-
119
- def sample_from_uuid(knex, uuid):
120
- blob = knex.get(f"samples/{uuid}")
121
- sample = sample_from_blob(knex, blob)
122
- return sample
123
-
124
-
125
- def sample_result_folder_from_uuid(knex, uuid):
126
- blob = knex.get(f"sample_ars/{uuid}")
127
- ar = sample_result_folder_from_blob(knex, blob)
128
- return ar
129
-
130
- sample_ar_from_uuid = sample_result_folder_from_uuid # Alias
131
-
132
-
133
- def project_result_folder_from_uuid(knex, uuid):
134
- blob = knex.get(f"sample_group_ars/{uuid}")
135
- ar = project_result_folder_from_blob(knex, blob)
136
- return ar
137
-
138
- sample_group_ar_from_uuid = project_result_folder_from_uuid # Alias
139
-
140
-
141
- def sample_result_file_from_uuid(knex, uuid):
142
- blob = knex.get(f"sample_ar_fields/{uuid}")
143
- ar = sample_result_file_from_blob(knex, blob)
144
- return ar
145
-
146
- sample_ar_field_from_uuid = sample_result_file_from_uuid # Alias
147
-
148
-
149
- def project_result_file_from_uuid(knex, uuid):
150
- blob = knex.get(f"sample_group_ar_fields/{uuid}")
151
- ar = project_result_file_from_blob(knex, blob)
152
- return ar
153
-
154
- sample_group_ar_field_from_uuid = project_result_file_from_uuid # Alias
155
-
156
-
157
- def resolve_brn(knex, brn):
158
- """Return the object which the brn points to."""
159
- assert brn.startswith(f'brn:{knex.instance_code()}:')
160
- _, _, object_type, uuid = brn.split(':')
161
- if object_type == 'project':
162
- return object_type, sample_group_from_uuid(knex, uuid)
163
- if object_type == 'sample':
164
- return object_type, sample_from_uuid(knex, uuid)
165
- if object_type == 'sample_result':
166
- return object_type, sample_ar_from_uuid(knex, uuid)
167
- if object_type == 'sample_result_field':
168
- return object_type, sample_ar_field_from_uuid(knex, uuid)
169
- if object_type == 'project_result':
170
- return object_type, sample_group_ar_from_uuid(knex, uuid)
171
- if object_type == 'project_result_field':
172
- return object_type, sample_group_ar_field_from_uuid(knex, uuid)
173
- raise GeoseeqNotFoundError(f'Type "{object_type}" not found')
3
+ For backwards compatibility.
4
+ """
5
+ from .id_constructors.from_blobs import *
6
+ from .id_constructors.from_uuids import *
geoseeq/cli/main.py CHANGED
@@ -30,7 +30,7 @@ main.add_command(cli_view)
30
30
  @main.command()
31
31
  def version():
32
32
  """Print the version of the Geoseeq API being used."""
33
- click.echo('0.2.15') # remember to update setup
33
+ click.echo('0.2.17') # remember to update setup
34
34
 
35
35
 
36
36
  @main.group('advanced')
@@ -9,7 +9,7 @@ from geoseeq.blob_constructors import (
9
9
  )
10
10
  from geoseeq.knex import GeoseeqNotFoundError
11
11
  from os.path import isfile
12
- from .id_utils import *
12
+ from geoseeq.id_constructors.utils import is_grn, is_uuid, is_grn_or_uuid
13
13
  from .obj_getters import (
14
14
  _get_org,
15
15
  _get_org_and_proj,
geoseeq/cli/view.py CHANGED
@@ -1,7 +1,7 @@
1
1
  import click
2
2
 
3
3
  from geoseeq import Organization, App
4
- from geoseeq.utils import paginated_iterator
4
+ from geoseeq.id_constructors import resolve_id
5
5
  from .shared_params import (
6
6
  use_common_state,
7
7
  project_id_arg,
@@ -210,4 +210,36 @@ def cli_view_sample(state, project_id, sample_ids):
210
210
  print(sample)
211
211
  for field_name, field_value, optional in sample.get_remote_fields():
212
212
  optional = "Optional" if optional else "Required"
213
- print(f'\t{field_name} :: "{field_value}" ({optional})')
213
+ print(f'\t{field_name} :: "{field_value}" ({optional})')
214
+
215
+
216
+ @cli_view.command('object')
217
+ @use_common_state
218
+ @click.argument('ids', nargs=-1)
219
+ def cli_view_object(state, ids):
220
+ """Print the specified object as well as its type.
221
+
222
+ ---
223
+
224
+ Example Usage:
225
+
226
+ \b
227
+ # Print the object with name "My Org/My Project/My Sample/My Result Folder"
228
+ $ geoseeq view object "My Org/My Project/My Sample/My Result Folder"
229
+
230
+ \b
231
+ # Print the object with GRN "grn:geoseeq:sample::d051ce05-f799-4aa7-8d8f-5cbf99136543"
232
+ $ geoseeq view object "grn:geoseeq:sample::d051ce05-f799-4aa7-8d8f-5cbf99136543"
233
+
234
+ ---
235
+
236
+ Command Arguments:
237
+
238
+ [ID] is the name or GRN of the object to print. UUIDs cannot be resolved without a type.
239
+
240
+ ---
241
+ """
242
+ knex = state.get_knex()
243
+ for id in ids:
244
+ obj_type, obj = resolve_id(knex, id)
245
+ print(f'{obj_type}:\t{obj}', file=state.outfile)
@@ -0,0 +1,5 @@
1
+ from .from_blobs import *
2
+ from .from_ids import *
3
+ from .from_names import *
4
+ from .from_uuids import *
5
+ from .resolvers import *
@@ -0,0 +1,109 @@
1
+ from geoseeq.result import (
2
+ SampleResultFolder,
3
+ SampleResultFile,
4
+ ProjectResultFolder,
5
+ ProjectResultFile,
6
+ )
7
+ from geoseeq.organization import Organization
8
+ from geoseeq.sample import Sample
9
+ from geoseeq.project import Project
10
+ from geoseeq import GeoseeqNotFoundError
11
+
12
+
13
+ def org_from_blob(knex, blob, already_fetched=True, modified=False):
14
+ """Return an Organization object from a blob."""
15
+ org = Organization(knex, blob["name"])
16
+ org.load_blob(blob)
17
+ org._already_fetched = already_fetched
18
+ org._modified = modified
19
+ return org
20
+
21
+
22
+ def project_from_blob(knex, blob, already_fetched=True, modified=False):
23
+ """Return a Project object from a blob."""
24
+ org = org_from_blob(
25
+ knex, blob["organization_obj"], already_fetched=already_fetched, modified=modified
26
+ )
27
+ grp = Project(knex, org, blob["name"], is_library=blob["is_library"])
28
+ grp.load_blob(blob)
29
+ grp._already_fetched = already_fetched
30
+ grp._modified = modified
31
+ return grp
32
+
33
+ sample_group_from_blob = project_from_blob # Alias
34
+
35
+
36
+ def sample_from_blob(knex, blob, already_fetched=True, modified=False):
37
+ """Return a Sample object from a blob."""
38
+ lib = sample_group_from_blob(
39
+ knex, blob["library_obj"], already_fetched=already_fetched, modified=modified
40
+ )
41
+ sample = Sample(knex, lib, blob["name"], metadata=blob["metadata"])
42
+ sample.load_blob(blob)
43
+ sample._already_fetched = already_fetched
44
+ sample._modified = modified
45
+ return sample
46
+
47
+
48
+ def project_result_folder_from_blob(knex, blob, already_fetched=True, modified=False):
49
+ """Return a ProjectResultFolder object from a blob."""
50
+ group = project_from_blob(
51
+ knex, blob["sample_group_obj"], already_fetched=already_fetched, modified=modified
52
+ )
53
+ ar = ProjectResultFolder(
54
+ knex, group, blob["module_name"], replicate=blob["replicate"], metadata=blob["metadata"]
55
+ )
56
+ ar.load_blob(blob)
57
+ ar._already_fetched = already_fetched
58
+ ar._modified = modified
59
+ return ar
60
+
61
+ sample_group_ar_from_blob = project_result_folder_from_blob # Alias
62
+
63
+
64
+ def sample_result_folder_from_blob(knex, blob, already_fetched=True, modified=False):
65
+ """Return a SampleResultFolder object from a blob."""
66
+ sample = sample_from_blob(
67
+ knex, blob["sample_obj"], already_fetched=already_fetched, modified=modified
68
+ )
69
+ ar = SampleResultFolder(
70
+ knex, sample, blob["module_name"], replicate=blob["replicate"], metadata=blob["metadata"]
71
+ )
72
+ ar.load_blob(blob)
73
+ ar._already_fetched = already_fetched
74
+ ar._modified = modified
75
+ return ar
76
+
77
+ sample_ar_from_blob = sample_result_folder_from_blob # Alias
78
+
79
+
80
+ def sample_result_file_from_blob(knex, blob, already_fetched=True, modified=False):
81
+ """Return a SampleResultFile object from a blob."""
82
+ ar = sample_result_folder_from_blob(
83
+ knex, blob["analysis_result_obj"], already_fetched=already_fetched, modified=modified
84
+ )
85
+ arf = SampleResultFile(
86
+ knex, ar, blob["name"], data=blob["stored_data"]
87
+ )
88
+ arf.load_blob(blob)
89
+ ar._already_fetched = already_fetched
90
+ ar._modified = modified
91
+ return arf
92
+
93
+ sample_ar_field_from_blob = sample_result_file_from_blob # Alias
94
+
95
+
96
+ def project_result_file_from_blob(knex, blob, already_fetched=True, modified=False):
97
+ """Return a ProjectResultFile object from a blob."""
98
+ ar = project_result_folder_from_blob(
99
+ knex, blob["analysis_result_obj"], already_fetched=already_fetched, modified=modified
100
+ )
101
+ arf = ProjectResultFile(
102
+ knex, ar, blob["name"], data=blob["stored_data"]
103
+ )
104
+ arf.load_blob(blob)
105
+ ar._already_fetched = already_fetched
106
+ ar._modified = modified
107
+ return arf
108
+
109
+ sample_group_ar_field_from_blob = project_result_file_from_blob # Alias
@@ -0,0 +1,87 @@
1
+ from geoseeq import GeoseeqNotFoundError
2
+ from .from_uuids import (
3
+ org_from_uuid,
4
+ project_from_uuid,
5
+ sample_from_uuid,
6
+ sample_result_folder_from_uuid,
7
+ project_result_folder_from_uuid,
8
+ result_folder_from_uuid,
9
+ sample_result_file_from_uuid,
10
+ project_result_file_from_uuid,
11
+ result_file_from_uuid,
12
+ )
13
+ from .from_names import (
14
+ org_from_name,
15
+ project_from_name,
16
+ sample_from_name,
17
+ sample_result_folder_from_name,
18
+ project_result_folder_from_name,
19
+ result_folder_from_name,
20
+ sample_result_file_from_name,
21
+ project_result_file_from_name,
22
+ result_file_from_name,
23
+ )
24
+ from .utils import is_grn_or_uuid, is_name
25
+
26
+
27
+ def _generic_from_id(knex, id, from_uuid_func, from_name_func):
28
+ """Return the object which the id points to."""
29
+ if is_grn_or_uuid(id):
30
+ return from_uuid_func(knex, id)
31
+ if is_name(id):
32
+ return from_name_func(knex, id)
33
+ raise ValueError(f'"{id}" is not a GRN, UUID, or name')
34
+
35
+
36
+ def org_from_id(knex, id):
37
+ """Return the organization object which the id points to."""
38
+ return _generic_from_id(knex, id, org_from_uuid, org_from_name)
39
+
40
+
41
+ def project_from_id(knex, id):
42
+ """Return the project object which the id points to."""
43
+ return _generic_from_id(knex, id, project_from_uuid, project_from_name)
44
+
45
+
46
+ def sample_from_id(knex, id):
47
+ """Return the sample object which the id points to."""
48
+ return _generic_from_id(knex, id, sample_from_uuid, sample_from_name)
49
+
50
+
51
+ def sample_result_folder_from_id(knex, id):
52
+ """Return the sample result folder object which the id points to."""
53
+ return _generic_from_id(knex, id, sample_result_folder_from_uuid, sample_result_folder_from_name)
54
+
55
+
56
+ def project_result_folder_from_id(knex, id):
57
+ """Return the project result folder object which the id points to."""
58
+ return _generic_from_id(knex, id, project_result_folder_from_uuid, project_result_folder_from_name)
59
+
60
+
61
+ def result_folder_from_id(knex, id):
62
+ """Return a result folder object which the id points to.
63
+
64
+ Guess the result folder is a sample result folder. If not, try a project result folder.
65
+ """
66
+ return _generic_from_id(knex, id, result_folder_from_uuid, result_folder_from_name)
67
+
68
+
69
+ def sample_result_file_from_id(knex, id):
70
+ """Return the sample result file object which the id points to."""
71
+ return _generic_from_id(knex, id, sample_result_file_from_uuid, sample_result_file_from_name)
72
+
73
+
74
+ def project_result_file_from_id(knex, id):
75
+ """Return the project result file object which the id points to."""
76
+ return _generic_from_id(knex, id, project_result_file_from_uuid, project_result_file_from_name)
77
+
78
+
79
+ def result_file_from_id(knex, id):
80
+ """Return a result file object which the id points to.
81
+
82
+ Guess the result file is a sample result file. If not, try a project result file.
83
+ """
84
+ return _generic_from_id(knex, id, result_file_from_uuid, result_file_from_name)
85
+
86
+
87
+
@@ -0,0 +1,137 @@
1
+ """Construct objects from names.
2
+
3
+ This module is used to construct objects from names. It is used by the
4
+
5
+ Names are human-readable ids that are used to identify objects in GeoSeeq.
6
+ They similar to file paths, e.g.:
7
+ - "My Org"
8
+ - "My Org/My Project"
9
+ - "My Org/My Project/My Sample/My Result Folder/My Result File"
10
+ - "My Org/My Project/My Result Folder/My Result File"
11
+
12
+ Unlike UUIDs or GRNs names can be changed by the user.
13
+ This makes them more human-readable, but not reliable for permanent references.
14
+ """
15
+ from geoseeq.organization import Organization
16
+ from geoseeq import GeoseeqNotFoundError
17
+
18
+
19
+ def org_from_name(knex, name):
20
+ """Return the organization object which the name points to.
21
+
22
+ e.g. "My Org"
23
+ """
24
+ tkns = name.split("/")
25
+ org_name = tkns[0]
26
+ org = Organization(knex, org_name)
27
+ org.get()
28
+ return org
29
+
30
+
31
+ def project_from_name(knex, name):
32
+ """Return the project object which the name points to.
33
+
34
+ e.g. "My Org/My Project"
35
+ """
36
+ tkns = name.split("/")
37
+ proj_name = tkns[1]
38
+ org = org_from_name(knex, name)
39
+ proj = org.project(proj_name)
40
+ proj.get()
41
+ return proj
42
+
43
+
44
+ def sample_from_name(knex, name):
45
+ """Return the sample object which the name points to.
46
+
47
+ e.g. "My Org/My Project/My Sample"
48
+ """
49
+ tkns = name.split("/")
50
+ sample_name = tkns[2]
51
+ proj = project_from_name(knex, name)
52
+ sample = proj.sample(sample_name)
53
+ sample.get()
54
+ return sample
55
+
56
+
57
+ def sample_result_folder_from_name(knex, name):
58
+ """Return the sample result folder object which the name points to.
59
+
60
+ e.g. "My Org/My Project/My Sample/My Result Folder"
61
+ """
62
+ tkns = name.split("/")
63
+ result_folder_name = tkns[3]
64
+ sample = sample_from_name(knex, name)
65
+ ar = sample.result_folder(result_folder_name)
66
+ ar.get()
67
+ return ar
68
+
69
+
70
+ def project_result_folder_from_name(knex, name):
71
+ """Return the project result folder object which the name points to.
72
+
73
+ e.g. "My Org/My Project/My Result Folder"
74
+ """
75
+ tkns = name.split("/")
76
+ result_folder_name = tkns[2]
77
+ proj = project_from_name(knex, name)
78
+ rf = proj.result_folder(result_folder_name)
79
+ rf.get()
80
+ return rf
81
+
82
+
83
+ def result_folder_from_name(knex, name):
84
+ """Return a result folder object which the name points to.
85
+
86
+ Guess the result folder is a sample result folder. If not, try a project result folder.
87
+ """
88
+ tkns = name.split("/")
89
+ if len(tkns) >= 4:
90
+ try:
91
+ return sample_result_folder_from_name(knex, name)
92
+ except GeoseeqNotFoundError:
93
+ return project_result_folder_from_name(knex, name)
94
+ else: # can't be a sample result folder
95
+ return project_result_folder_from_name(knex, name)
96
+
97
+
98
+ def sample_result_file_from_name(knex, name):
99
+ """Return the sample result file object which the name points to.
100
+
101
+ e.g. "My Org/My Project/My Sample/My Result Folder/My Result File"
102
+ """
103
+ tkns = name.split("/")
104
+ result_file_name = tkns[4]
105
+ r_folder = sample_result_folder_from_name(knex, name)
106
+ r_file = r_folder.result_file(result_file_name)
107
+ r_file.get()
108
+ return r_file
109
+
110
+
111
+ def project_result_file_from_name(knex, name):
112
+ """Return the project result file object which the name points to.
113
+
114
+ e.g. "My Org/My Project/My Result Folder/My Result File"
115
+ """
116
+ tkns = name.split("/")
117
+ result_file_name = tkns[3]
118
+ r_folder = project_result_folder_from_name(knex, name)
119
+ r_file = r_folder.result_file(result_file_name)
120
+ r_file.get()
121
+ return r_file
122
+
123
+
124
+ def result_file_from_name(knex, name):
125
+ """Return a result file object which the name points to.
126
+
127
+ Guess the result file is a sample result file. If not, try a project result file.
128
+ """
129
+ tkns = name.split("/")
130
+ if len(tkns) >= 5:
131
+ try:
132
+ return sample_result_file_from_name(knex, name)
133
+ except GeoseeqNotFoundError:
134
+ return project_result_file_from_name(knex, name)
135
+ else: # can't be a sample result file
136
+ return project_result_file_from_name(knex, name)
137
+
@@ -0,0 +1,82 @@
1
+ from .from_blobs import *
2
+ from geoseeq import GeoseeqNotFoundError
3
+
4
+
5
+ def org_from_uuid(knex, uuid):
6
+ """Return the organization object which the uuid points to."""
7
+ blob = knex.get(f"organizations/{uuid}")
8
+ org = org_from_blob(knex, blob)
9
+ return org
10
+
11
+ def project_from_uuid(knex, uuid):
12
+ """Return the project object which the uuid points to."""
13
+ blob = knex.get(f"sample_groups/{uuid}")
14
+ project = project_from_blob(knex, blob)
15
+ return project
16
+
17
+ sample_group_from_uuid = project_from_uuid # Alias
18
+
19
+
20
+ def sample_from_uuid(knex, uuid):
21
+ """Return the sample object which the uuid points to."""
22
+ blob = knex.get(f"samples/{uuid}")
23
+ sample = sample_from_blob(knex, blob)
24
+ return sample
25
+
26
+
27
+ def sample_result_folder_from_uuid(knex, uuid):
28
+ """Return the sample result folder object which the uuid points to."""
29
+ blob = knex.get(f"sample_ars/{uuid}")
30
+ ar = sample_result_folder_from_blob(knex, blob)
31
+ return ar
32
+
33
+ sample_ar_from_uuid = sample_result_folder_from_uuid # Alias
34
+
35
+
36
+ def project_result_folder_from_uuid(knex, uuid):
37
+ """Return the project result folder object which the uuid points to."""
38
+ blob = knex.get(f"sample_group_ars/{uuid}")
39
+ ar = project_result_folder_from_blob(knex, blob)
40
+ return ar
41
+
42
+ sample_group_ar_from_uuid = project_result_folder_from_uuid # Alias
43
+
44
+
45
+ def result_folder_from_uuid(knex, uuid):
46
+ """Return a result folder object which the uuid points to.
47
+
48
+ Guess the result folder is a sample result folder. If not, try a project result folder.
49
+ """
50
+ try:
51
+ return sample_result_folder_from_uuid(knex, uuid)
52
+ except GeoseeqNotFoundError:
53
+ return project_result_folder_from_uuid(knex, uuid)
54
+
55
+
56
+ def sample_result_file_from_uuid(knex, uuid):
57
+ """Return the sample result file object which the uuid points to."""
58
+ blob = knex.get(f"sample_ar_fields/{uuid}")
59
+ ar = sample_result_file_from_blob(knex, blob)
60
+ return ar
61
+
62
+ sample_ar_field_from_uuid = sample_result_file_from_uuid # Alias
63
+
64
+
65
+ def project_result_file_from_uuid(knex, uuid):
66
+ """Return the project result file object which the uuid points to."""
67
+ blob = knex.get(f"sample_group_ar_fields/{uuid}")
68
+ ar = project_result_file_from_blob(knex, blob)
69
+ return ar
70
+
71
+ sample_group_ar_field_from_uuid = project_result_file_from_uuid # Alias
72
+
73
+
74
+ def result_file_from_uuid(knex, uuid):
75
+ """Return a result file object which the uuid points to.
76
+
77
+ Guess the result file is a sample result file. If not, try a project result file.
78
+ """
79
+ try:
80
+ return sample_result_file_from_uuid(knex, uuid)
81
+ except GeoseeqNotFoundError:
82
+ return project_result_file_from_uuid(knex, uuid)
@@ -0,0 +1,73 @@
1
+ from geoseeq import GeoseeqNotFoundError
2
+ from .from_uuids import (
3
+ org_from_uuid,
4
+ project_from_uuid,
5
+ sample_from_uuid,
6
+ sample_result_folder_from_uuid,
7
+ project_result_folder_from_uuid,
8
+ result_folder_from_uuid,
9
+ sample_result_file_from_uuid,
10
+ project_result_file_from_uuid,
11
+ result_file_from_uuid,
12
+ )
13
+ from .from_names import (
14
+ org_from_name,
15
+ project_from_name,
16
+ sample_from_name,
17
+ sample_result_folder_from_name,
18
+ project_result_folder_from_name,
19
+ result_folder_from_name,
20
+ sample_result_file_from_name,
21
+ project_result_file_from_name,
22
+ result_file_from_name,
23
+ )
24
+ from .utils import is_name, is_grn
25
+
26
+
27
+ def resolve_id(knex, id):
28
+ """Return the object which the id points to."""
29
+ if is_grn(id):
30
+ return resolve_grn(knex, id)
31
+ if is_name(id):
32
+ return resolve_name(knex, id)
33
+ raise ValueError(f'"{id}" is not a GRN, or name. UUIDs cannot be resolved without a type')
34
+
35
+
36
+ def resolve_name(knex, name):
37
+ """Return the object which the name points to."""
38
+ assert is_name(name), f'"{name}" is not a name'
39
+ tkns = name.split("/")
40
+ if len(tkns) == 1: # org
41
+ return "org", org_from_name(knex, name)
42
+ if len(tkns) == 2: # project
43
+ return "project", project_from_name(knex, name)
44
+ if len(tkns) == 3: # sample or project result folder
45
+ try:
46
+ return "sample", sample_from_name(knex, name)
47
+ except GeoseeqNotFoundError:
48
+ return "folder", result_folder_from_name(knex, name)
49
+ if len(tkns) == 4: # sample result folder or project result file
50
+ try:
51
+ return "folder", result_folder_from_name(knex, name)
52
+ except GeoseeqNotFoundError:
53
+ return "file", result_file_from_name(knex, name)
54
+ if len(tkns) == 5: # sample result file
55
+ return "file", result_file_from_name(knex, name)
56
+ raise GeoseeqNotFoundError(f'Name "{name}" not found')
57
+
58
+
59
+ def resolve_grn(knex, grn):
60
+ """Return the object which the grn points to."""
61
+ assert is_grn(grn), f'"{grn}" is not a GRN'
62
+ _, _, object_type, uuid = grn.split(':')
63
+ if object_type == 'org':
64
+ return object_type, org_from_uuid(knex, uuid)
65
+ if object_type == 'project':
66
+ return object_type, project_from_uuid(knex, uuid)
67
+ if object_type == 'sample':
68
+ return object_type, sample_from_uuid(knex, uuid)
69
+ if object_type == 'folder':
70
+ return object_type, result_folder_from_uuid(knex, uuid)
71
+ if object_type == 'file':
72
+ return object_type, result_file_from_uuid(knex, uuid)
73
+ raise GeoseeqNotFoundError(f'Type "{object_type}" not found')
@@ -5,6 +5,7 @@ def is_grn(el):
5
5
  """Return True if `el` is a GeoSeeq Resource Number (GRN)"""
6
6
  return el.startswith('grn:')
7
7
 
8
+
8
9
  def is_uuid(el):
9
10
  """Return True if `el` is a UUID"""
10
11
  try:
@@ -13,6 +14,21 @@ def is_uuid(el):
13
14
  except ValueError:
14
15
  return False
15
16
 
17
+
18
+ def is_name(el):
19
+ """Return True if `el` is a name.
20
+
21
+ e.g. "My Org/My Project"
22
+ """
23
+ if "/" in el:
24
+ # every name except org names have a slash
25
+ return True
26
+ if not is_grn_or_uuid(el):
27
+ # if the name has no slash and is not a grn or uuid, it's a name
28
+ return True
29
+ return False
30
+
31
+
16
32
  def is_grn_or_uuid(el):
17
33
  """Return True if `el` is a GRN or a UUID"""
18
34
  return is_grn(el) or is_uuid(el)
@@ -1,2 +1,3 @@
1
1
  from .constants import COLORS
2
- from .highcharts import series_is_categorical, series_is_numeric, scatter_plot_config
2
+ from .highcharts import series_is_categorical, series_is_numeric, scatter_plot_config
3
+ from .selectable import SelectablePlot
@@ -0,0 +1,81 @@
1
+
2
+ class PlotSelector:
3
+
4
+ def __init__(self, title, kind='dropdown', options=None):
5
+ self.title = title
6
+ assert kind in ['dropdown', 'radio']
7
+ self.kind = kind
8
+ self.options = options or []
9
+
10
+ def __iter__(self):
11
+ return iter(self.options)
12
+
13
+ def add_option(self, option):
14
+ if option not in self.options:
15
+ self.options.append(option)
16
+
17
+ def to_dict(self):
18
+ assert self.options
19
+ return {
20
+ 'title': self.title,
21
+ 'kind': self.kind,
22
+ 'options': self.options,
23
+ }
24
+
25
+
26
+ class SelectablePlot:
27
+ VERSION = 'v0'
28
+
29
+ def __init__(self):
30
+ self.selectors = []
31
+ self.data = {}
32
+
33
+ def add_selector(self, title, kind='dropdown', options=None):
34
+ """Add a selector to the selectable plot. Return the selectable plot for chaining."""
35
+ self.selectors.append(PlotSelector(title, kind=kind, options=options))
36
+ return self
37
+
38
+ def _add_keys(self, *keys):
39
+ """Add keys to the data structure."""
40
+ assert self.selectors
41
+ assert len(keys) == len(self.selectors)
42
+ subdata = self.data
43
+ for i, key in enumerate(keys):
44
+ if key not in subdata:
45
+ subdata[key] = {}
46
+ self.selectors[i].add_option(key)
47
+ subdata = subdata[key]
48
+
49
+ def add_plot(self, plot, *keys):
50
+ """Add a plot to the selectable plot. Return the selectable plot for chaining."""
51
+ self._add_keys(*keys)
52
+ subdata = self.data
53
+ for key in keys:
54
+ if key == keys[-1]:
55
+ subdata[key] = plot
56
+ subdata = subdata[key]
57
+ return self
58
+
59
+ def _check_invariants(self):
60
+ """Ensure we have plots for each key combo."""
61
+ assert self.selectors
62
+
63
+ def check_subdata(i, subdata, key_chain):
64
+ if i == len(self.selectors):
65
+ assert subdata, f"subdata does not exist or is empty. Key Chain: {key_chain}"
66
+ return
67
+ for key in self.selectors[i]:
68
+ if key not in subdata:
69
+ assert False, f'key: "{key}" is missing in `data`'
70
+ check_subdata(i + 1, subdata[key], key_chain + [key])
71
+
72
+ check_subdata(0, self.data, [])
73
+
74
+ def to_dict(self):
75
+ """Return the selectable plot as a dictionary."""
76
+ self._check_invariants()
77
+ return {
78
+ 'version': self.VERSION,
79
+ 'selectors': [s.to_dict() for s in self.selectors],
80
+ 'data': self.data,
81
+ }
geoseeq/vc/cli.py CHANGED
@@ -2,7 +2,6 @@ import logging
2
2
  import click
3
3
  from os.path import isfile
4
4
  from geoseeq.cli.utils import use_common_state
5
- from geoseeq.blob_constructors import resolve_brn
6
5
  from .vc_dir import VCDir
7
6
  from .clone import (
8
7
  clone_project,
geoseeq/vc/vc_sample.py CHANGED
@@ -4,7 +4,6 @@ from glob import glob
4
4
  from string import Template
5
5
  from os.path import join
6
6
 
7
- from geoseeq.blob_constructors import resolve_brn
8
7
  from .vc_stub import VCStub
9
8
 
10
9
 
geoseeq/vc/vc_stub.py CHANGED
@@ -1,6 +1,5 @@
1
1
 
2
2
  import json
3
- from geoseeq.blob_constructors import resolve_brn
4
3
  from os.path import join, dirname
5
4
  from .checksum import Checksum
6
5
  from os import environ, symlink, makedirs
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: geoseeq
3
- Version: 0.2.15
3
+ Version: 0.2.17
4
4
  Summary: # Geoseeq API Client
5
5
  Author: David C. Danko
6
6
  Author-email: dcdanko@biotia.io
@@ -1,6 +1,6 @@
1
- geoseeq/__init__.py,sha256=pOUrWGCAMEA-cJN9is2qkmUy_dceZcYdzlDsf1X4O9A,833
1
+ geoseeq/__init__.py,sha256=FxA5ioZVxUR3XAjllE5F2mtcUk8NDSBD-VYmMp6U254,864
2
2
  geoseeq/app.py,sha256=Y6d1UzxFLfE3RNccATbFCVi6kH3eFmzwoUbeR2Ry09A,2387
3
- geoseeq/blob_constructors.py,sha256=20seQXgsr5COJb6HhV1eBpBzYQlGgS7eqRq3eElPbEI,5732
3
+ geoseeq/blob_constructors.py,sha256=AkWpDQY0EdGMxF1p6eRspyHKubcUdiW4it-_Q7S2QWk,188
4
4
  geoseeq/bulk_creators.py,sha256=pdn-Dv7yv5SFv-PfDuQbuOnw2W4-BfIfRJVRAhM8U6s,2115
5
5
  geoseeq/constants.py,sha256=2sO50sItJsBCHFvfUCvB2NziQnJKG6lFOFDMu3IHzaw,122
6
6
  geoseeq/file_system_cache.py,sha256=7pdM-1VncOvjkYv2pOocPHOXnEWz0jKhH6sm1LaXtoU,3405
@@ -18,16 +18,15 @@ geoseeq/cli/constants.py,sha256=Do5AUf9lMO9_P8KpFJ3XwwFBAWsxSjZ6sx9_QEGyC_c,176
18
18
  geoseeq/cli/copy.py,sha256=ocJ-T6vZBTPELUSBA65KndzAugrBWMq-3ux0dbffacE,1997
19
19
  geoseeq/cli/download.py,sha256=N4eEUiQIiqpFMXOnhkMBCRCKlYyKi0QtRJk5HBEAHkA,10807
20
20
  geoseeq/cli/fastq_utils.py,sha256=-bmeQLaiMBm57zWOF0R5OlWTU0_3sh1JBC1RYw2BOFM,3083
21
- geoseeq/cli/main.py,sha256=s9QZ9bNpU9RPnK5ypDFT-3lL3VAmSKE5NThrV1BL5gA,1027
21
+ geoseeq/cli/main.py,sha256=pY8P-GsO5Rc5wAWsAg5qKzYN76rXjPOIoXSt6tfuPG0,1027
22
22
  geoseeq/cli/manage.py,sha256=xy_iMfqSSMaSTQNYiTw2xEWpH4mpTAq4Cf_6QemEMnI,5409
23
23
  geoseeq/cli/progress_bar.py,sha256=p1Xl01nkYxSBZCB30ue2verIIi22W93m3ZAMAxipD0g,738
24
24
  geoseeq/cli/user.py,sha256=fARv_5vx-QYT765Hsjgwr6J5ddA_viCPQdv9iUoVX6w,925
25
25
  geoseeq/cli/utils.py,sha256=f0wX5-19uDrYZ8d-aBLplqfbGOkr5BH8x3AMSAyPCes,2873
26
- geoseeq/cli/view.py,sha256=I29klmNPn0x1QjoMueXO76-BawV6CbbeEEXboXp066E,4913
26
+ geoseeq/cli/view.py,sha256=R5lW7Bg3oQwmzTyd_g9dssY6LDw5kemP3XpkhzZfOGo,5751
27
27
  geoseeq/cli/shared_params/__init__.py,sha256=j8RjuTB7AoEvEDczNJjyAfizrT0Rv0-eAowAPAbaVLo,231
28
28
  geoseeq/cli/shared_params/common_state.py,sha256=TQK0UXvaH5k4W6XKbaug1bdoWbD3sTcJTRoJTtUmgSQ,2569
29
- geoseeq/cli/shared_params/id_handlers.py,sha256=7VGM_tdKUYNCjrb7HBAhW2z3_2WuZrfsJhD3GKLdt5I,6443
30
- geoseeq/cli/shared_params/id_utils.py,sha256=XEQxv13fRCZxA2OHG0O3nVQYCI29YzSsz8eZs79UqFI,392
29
+ geoseeq/cli/shared_params/id_handlers.py,sha256=7s2g-UfKoTfwmDX_FI96-M_g_U1yYBUEj-8yy8NC_c8,6493
31
30
  geoseeq/cli/shared_params/obj_getters.py,sha256=ZSkt6LnDkVFlNVYKgLrjzg60-6BthZMr3eeD3HNqzac,2741
32
31
  geoseeq/cli/shared_params/opts_and_args.py,sha256=Jy2rVQydlvkgjoA_BYjSNuI-wUSPmE2S1C1rN6bycBI,1399
33
32
  geoseeq/cli/upload/__init__.py,sha256=QqBh0WXD9BaEDcKsKpb-WgWwQ0WzZdQUgYXYwyowW_c,340
@@ -39,9 +38,17 @@ geoseeq/contrib/ncbi/api.py,sha256=WQeLoGA_-Zha-QeSO8_i7HpvXyD8UkV0qc5okm11KiA,1
39
38
  geoseeq/contrib/ncbi/bioproject.py,sha256=_oThTd_iLDOC8cLOlJKAatSr362OBYZCEV3YrqodhFg,4341
40
39
  geoseeq/contrib/ncbi/cli.py,sha256=j9zEcaZPTryK3a4xluRxigcJKDhRpRxbp3KZSx-Bfhk,2400
41
40
  geoseeq/contrib/ncbi/setup_logging.py,sha256=Tp1bY1U0f-o739aHpvVYriG2qdd1lFvCYBXZeXQgt-w,175
42
- geoseeq/plotting/__init__.py,sha256=XTl5y488a9Ib6Et_kSluScMr9OPYiPByoNXHfjuZFeM,115
41
+ geoseeq/id_constructors/__init__.py,sha256=w5E0PNQ9UuAxBeZbDI7KBnUoERd85gGz3nScz45bd2o,126
42
+ geoseeq/id_constructors/from_blobs.py,sha256=WljFMY-VHLLp0tABE0Mu5b2UXMSvD8bcHmMFfwlgpHg,3752
43
+ geoseeq/id_constructors/from_ids.py,sha256=xFv_TeXpN03ajQTSUVeaiXQFoB5M_QIf0SlX09rW3sM,2916
44
+ geoseeq/id_constructors/from_names.py,sha256=RMKEzpmEZKfPWQ2sMUUqao3j5NPq9-T9DnprLScUI-8,4041
45
+ geoseeq/id_constructors/from_uuids.py,sha256=d61azvpP22a57Z-kYXLwxmIUTWB25pwqWlwnRgPXHxw,2667
46
+ geoseeq/id_constructors/resolvers.py,sha256=zTp4uWFkThj4GhlPVnFTt7JQ7dmmUD9vRyIbTJpPcRU,2608
47
+ geoseeq/id_constructors/utils.py,sha256=CKlZHGMiqi1b6r1KtgD3czSAomH99Gdfx5ziqaahz-0,723
48
+ geoseeq/plotting/__init__.py,sha256=RkGoXxgu7jEfK0B7NmdalPS2AbU7I7dZwDbi4rn9CKM,154
43
49
  geoseeq/plotting/constants.py,sha256=CGUlm8WAFG3YRKdicc9Rcy5hFxUdUm2RgK0iXZWLuX8,285
44
50
  geoseeq/plotting/highcharts.py,sha256=AGzdW4VSUsL_rfEI-RiVbbtaTLFMARvzLzVUDrKTlnU,4096
51
+ geoseeq/plotting/selectable.py,sha256=hFbVlSgklR8tkLt9H1Fi-EwjXhV72YDdkkZMoReeBbI,2554
45
52
  geoseeq/result/__init__.py,sha256=IFHIyRV8ZzuKIfwfze1SXgcKwNMcSgMAknLHMkwjXIU,356
46
53
  geoseeq/result/bioinfo.py,sha256=QQtbyogrdro9avJSN0713sxLVnVeA24mFw3hWtKDKyw,1782
47
54
  geoseeq/result/file_download.py,sha256=R087ypOAu2pMZ9vXvkO9babPBNtRXTF3ZhpPldcT_jM,4593
@@ -51,19 +58,19 @@ geoseeq/result/result_folder.py,sha256=r3r1lQx_EkN9w5e0l0DmHS2IwNZxt0Zzs2lJvEdOC
51
58
  geoseeq/result/utils.py,sha256=C-CxGzB3WddlnRiqFSkrY78I_m0yFgNqsTBRzGU-y8Q,2772
52
59
  geoseeq/vc/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
53
60
  geoseeq/vc/checksum.py,sha256=y8rh1asUZNbE_NLiFO0-9hImLNiTOc2YXQBRKORWK7k,710
54
- geoseeq/vc/cli.py,sha256=VlAvBoXckENKAvREZ5nKXl2F6Z6Glh_mKBDiSfaT_lQ,2853
61
+ geoseeq/vc/cli.py,sha256=rUspr6FUJiUWIVMvf-pmyC5psKfufN45alk8392fAfA,2803
55
62
  geoseeq/vc/clone.py,sha256=G5IUMg5QASJ5c2ii9i54DX2eVpv55rBvgYjqlayZmuU,2486
56
63
  geoseeq/vc/constants.py,sha256=b91uugHPKC3OJhCKXkL55YghzUYhY5jS15EHHqaKPKE,19
57
64
  geoseeq/vc/vc_cache.py,sha256=P4LXTbq2zOIv1OhP7Iw5MmypR2vXuy29Pq5K6gRvi-M,730
58
65
  geoseeq/vc/vc_dir.py,sha256=A9CLTh2wWCRzZjiLyqXD1vhtsWZGD3OjaMT5KqlfAXI,457
59
- geoseeq/vc/vc_sample.py,sha256=a15sKcPRYPO772l-kThO13J03zAmDvj9pnYGCrudoFg,3900
60
- geoseeq/vc/vc_stub.py,sha256=BNFr7CZtpvLPe0MOqgB0zYL037vRCSwd2A_Fcy9UTKA,3160
66
+ geoseeq/vc/vc_sample.py,sha256=qZeioWydXvfu4rGMs20nICfNcp46y_XkND-bHdV6P5M,3850
67
+ geoseeq/vc/vc_stub.py,sha256=IQr8dI0zsWKVAeY_5ybDD6n49_3othcgfHS3P0O9tuY,3110
61
68
  tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
62
69
  tests/test_api_client.py,sha256=DDhnNJBJgz-LAmpRzVvvfjdcm_t4meQhZLUuS7XP7fE,14452
63
70
  tests/test_work_orders.py,sha256=CB6QbGGMNeEePZiOVioiSQP2dQsyMnsy4L31AQMRs3A,498
64
- geoseeq-0.2.15.dist-info/LICENSE,sha256=IuhIl1XCxXLPLJT_coN1CNqQU4Khlq7x4IdW7ioOJD8,1067
65
- geoseeq-0.2.15.dist-info/METADATA,sha256=-cUN6cXta3rtlVdiVaYyna1HkacL97paA4hHjfMx6pw,455
66
- geoseeq-0.2.15.dist-info/WHEEL,sha256=yQN5g4mg4AybRjkgi-9yy4iQEFibGQmlz78Pik5Or-A,92
67
- geoseeq-0.2.15.dist-info/entry_points.txt,sha256=yF-6KDM8zXib4Al0qn49TX-qM7PUkWUIcYtsgt36rjM,45
68
- geoseeq-0.2.15.dist-info/top_level.txt,sha256=zZk7mmeaqAYqFJG8nq2DTgSQPbflRjJwkDIhNURPDEU,14
69
- geoseeq-0.2.15.dist-info/RECORD,,
71
+ geoseeq-0.2.17.dist-info/LICENSE,sha256=IuhIl1XCxXLPLJT_coN1CNqQU4Khlq7x4IdW7ioOJD8,1067
72
+ geoseeq-0.2.17.dist-info/METADATA,sha256=MhD15WS-G8qtqJtYghJ3SiU-bJN_tIMn99z8dl5pQzA,455
73
+ geoseeq-0.2.17.dist-info/WHEEL,sha256=yQN5g4mg4AybRjkgi-9yy4iQEFibGQmlz78Pik5Or-A,92
74
+ geoseeq-0.2.17.dist-info/entry_points.txt,sha256=yF-6KDM8zXib4Al0qn49TX-qM7PUkWUIcYtsgt36rjM,45
75
+ geoseeq-0.2.17.dist-info/top_level.txt,sha256=zZk7mmeaqAYqFJG8nq2DTgSQPbflRjJwkDIhNURPDEU,14
76
+ geoseeq-0.2.17.dist-info/RECORD,,