geoseeq 0.2.15__tar.gz → 0.2.17__tar.gz

Sign up to get free protection for your applications and to get access to all the features.
Files changed (82) hide show
  1. {geoseeq-0.2.15 → geoseeq-0.2.17}/PKG-INFO +1 -1
  2. {geoseeq-0.2.15 → geoseeq-0.2.17}/geoseeq/__init__.py +2 -1
  3. geoseeq-0.2.17/geoseeq/blob_constructors.py +6 -0
  4. {geoseeq-0.2.15 → geoseeq-0.2.17}/geoseeq/cli/main.py +1 -1
  5. {geoseeq-0.2.15 → geoseeq-0.2.17}/geoseeq/cli/shared_params/id_handlers.py +1 -1
  6. {geoseeq-0.2.15 → geoseeq-0.2.17}/geoseeq/cli/view.py +34 -2
  7. geoseeq-0.2.17/geoseeq/id_constructors/__init__.py +5 -0
  8. geoseeq-0.2.15/geoseeq/blob_constructors.py → geoseeq-0.2.17/geoseeq/id_constructors/from_blobs.py +12 -76
  9. geoseeq-0.2.17/geoseeq/id_constructors/from_ids.py +87 -0
  10. geoseeq-0.2.17/geoseeq/id_constructors/from_names.py +137 -0
  11. geoseeq-0.2.17/geoseeq/id_constructors/from_uuids.py +82 -0
  12. geoseeq-0.2.17/geoseeq/id_constructors/resolvers.py +73 -0
  13. geoseeq-0.2.15/geoseeq/cli/shared_params/id_utils.py → geoseeq-0.2.17/geoseeq/id_constructors/utils.py +16 -0
  14. {geoseeq-0.2.15 → geoseeq-0.2.17}/geoseeq/plotting/__init__.py +2 -1
  15. geoseeq-0.2.17/geoseeq/plotting/selectable.py +81 -0
  16. {geoseeq-0.2.15 → geoseeq-0.2.17}/geoseeq/vc/cli.py +0 -1
  17. {geoseeq-0.2.15 → geoseeq-0.2.17}/geoseeq/vc/vc_sample.py +0 -1
  18. {geoseeq-0.2.15 → geoseeq-0.2.17}/geoseeq/vc/vc_stub.py +0 -1
  19. {geoseeq-0.2.15 → geoseeq-0.2.17}/geoseeq.egg-info/PKG-INFO +1 -1
  20. {geoseeq-0.2.15 → geoseeq-0.2.17}/geoseeq.egg-info/SOURCES.txt +8 -1
  21. {geoseeq-0.2.15 → geoseeq-0.2.17}/setup.py +1 -1
  22. {geoseeq-0.2.15 → geoseeq-0.2.17}/LICENSE +0 -0
  23. {geoseeq-0.2.15 → geoseeq-0.2.17}/README.md +0 -0
  24. {geoseeq-0.2.15 → geoseeq-0.2.17}/geoseeq/app.py +0 -0
  25. {geoseeq-0.2.15 → geoseeq-0.2.17}/geoseeq/bulk_creators.py +0 -0
  26. {geoseeq-0.2.15 → geoseeq-0.2.17}/geoseeq/cli/__init__.py +0 -0
  27. {geoseeq-0.2.15 → geoseeq-0.2.17}/geoseeq/cli/constants.py +0 -0
  28. {geoseeq-0.2.15 → geoseeq-0.2.17}/geoseeq/cli/copy.py +0 -0
  29. {geoseeq-0.2.15 → geoseeq-0.2.17}/geoseeq/cli/download.py +0 -0
  30. {geoseeq-0.2.15 → geoseeq-0.2.17}/geoseeq/cli/fastq_utils.py +0 -0
  31. {geoseeq-0.2.15 → geoseeq-0.2.17}/geoseeq/cli/manage.py +0 -0
  32. {geoseeq-0.2.15 → geoseeq-0.2.17}/geoseeq/cli/progress_bar.py +0 -0
  33. {geoseeq-0.2.15 → geoseeq-0.2.17}/geoseeq/cli/shared_params/__init__.py +0 -0
  34. {geoseeq-0.2.15 → geoseeq-0.2.17}/geoseeq/cli/shared_params/common_state.py +0 -0
  35. {geoseeq-0.2.15 → geoseeq-0.2.17}/geoseeq/cli/shared_params/obj_getters.py +0 -0
  36. {geoseeq-0.2.15 → geoseeq-0.2.17}/geoseeq/cli/shared_params/opts_and_args.py +0 -0
  37. {geoseeq-0.2.15 → geoseeq-0.2.17}/geoseeq/cli/upload/__init__.py +0 -0
  38. {geoseeq-0.2.15 → geoseeq-0.2.17}/geoseeq/cli/upload/upload.py +0 -0
  39. {geoseeq-0.2.15 → geoseeq-0.2.17}/geoseeq/cli/upload/upload_reads.py +0 -0
  40. {geoseeq-0.2.15 → geoseeq-0.2.17}/geoseeq/cli/user.py +0 -0
  41. {geoseeq-0.2.15 → geoseeq-0.2.17}/geoseeq/cli/utils.py +0 -0
  42. {geoseeq-0.2.15 → geoseeq-0.2.17}/geoseeq/constants.py +0 -0
  43. {geoseeq-0.2.15 → geoseeq-0.2.17}/geoseeq/contrib/__init__.py +0 -0
  44. {geoseeq-0.2.15 → geoseeq-0.2.17}/geoseeq/contrib/ncbi/__init__.py +0 -0
  45. {geoseeq-0.2.15 → geoseeq-0.2.17}/geoseeq/contrib/ncbi/api.py +0 -0
  46. {geoseeq-0.2.15 → geoseeq-0.2.17}/geoseeq/contrib/ncbi/bioproject.py +0 -0
  47. {geoseeq-0.2.15 → geoseeq-0.2.17}/geoseeq/contrib/ncbi/cli.py +0 -0
  48. {geoseeq-0.2.15 → geoseeq-0.2.17}/geoseeq/contrib/ncbi/setup_logging.py +0 -0
  49. {geoseeq-0.2.15 → geoseeq-0.2.17}/geoseeq/file_system_cache.py +0 -0
  50. {geoseeq-0.2.15 → geoseeq-0.2.17}/geoseeq/knex.py +0 -0
  51. {geoseeq-0.2.15 → geoseeq-0.2.17}/geoseeq/organization.py +0 -0
  52. {geoseeq-0.2.15 → geoseeq-0.2.17}/geoseeq/pipeline.py +0 -0
  53. {geoseeq-0.2.15 → geoseeq-0.2.17}/geoseeq/plotting/constants.py +0 -0
  54. {geoseeq-0.2.15 → geoseeq-0.2.17}/geoseeq/plotting/highcharts.py +0 -0
  55. {geoseeq-0.2.15 → geoseeq-0.2.17}/geoseeq/project.py +0 -0
  56. {geoseeq-0.2.15 → geoseeq-0.2.17}/geoseeq/remote_object.py +0 -0
  57. {geoseeq-0.2.15 → geoseeq-0.2.17}/geoseeq/result/__init__.py +0 -0
  58. {geoseeq-0.2.15 → geoseeq-0.2.17}/geoseeq/result/bioinfo.py +0 -0
  59. {geoseeq-0.2.15 → geoseeq-0.2.17}/geoseeq/result/file_download.py +0 -0
  60. {geoseeq-0.2.15 → geoseeq-0.2.17}/geoseeq/result/file_upload.py +0 -0
  61. {geoseeq-0.2.15 → geoseeq-0.2.17}/geoseeq/result/result_file.py +0 -0
  62. {geoseeq-0.2.15 → geoseeq-0.2.17}/geoseeq/result/result_folder.py +0 -0
  63. {geoseeq-0.2.15 → geoseeq-0.2.17}/geoseeq/result/utils.py +0 -0
  64. {geoseeq-0.2.15 → geoseeq-0.2.17}/geoseeq/sample.py +0 -0
  65. {geoseeq-0.2.15 → geoseeq-0.2.17}/geoseeq/user.py +0 -0
  66. {geoseeq-0.2.15 → geoseeq-0.2.17}/geoseeq/utils.py +0 -0
  67. {geoseeq-0.2.15 → geoseeq-0.2.17}/geoseeq/vc/__init__.py +0 -0
  68. {geoseeq-0.2.15 → geoseeq-0.2.17}/geoseeq/vc/checksum.py +0 -0
  69. {geoseeq-0.2.15 → geoseeq-0.2.17}/geoseeq/vc/clone.py +0 -0
  70. {geoseeq-0.2.15 → geoseeq-0.2.17}/geoseeq/vc/constants.py +0 -0
  71. {geoseeq-0.2.15 → geoseeq-0.2.17}/geoseeq/vc/vc_cache.py +0 -0
  72. {geoseeq-0.2.15 → geoseeq-0.2.17}/geoseeq/vc/vc_dir.py +0 -0
  73. {geoseeq-0.2.15 → geoseeq-0.2.17}/geoseeq/work_orders.py +0 -0
  74. {geoseeq-0.2.15 → geoseeq-0.2.17}/geoseeq.egg-info/dependency_links.txt +0 -0
  75. {geoseeq-0.2.15 → geoseeq-0.2.17}/geoseeq.egg-info/entry_points.txt +0 -0
  76. {geoseeq-0.2.15 → geoseeq-0.2.17}/geoseeq.egg-info/requires.txt +0 -0
  77. {geoseeq-0.2.15 → geoseeq-0.2.17}/geoseeq.egg-info/top_level.txt +0 -0
  78. {geoseeq-0.2.15 → geoseeq-0.2.17}/pyproject.toml +0 -0
  79. {geoseeq-0.2.15 → geoseeq-0.2.17}/setup.cfg +0 -0
  80. {geoseeq-0.2.15 → geoseeq-0.2.17}/tests/__init__.py +0 -0
  81. {geoseeq-0.2.15 → geoseeq-0.2.17}/tests/test_api_client.py +0 -0
  82. {geoseeq-0.2.15 → geoseeq-0.2.17}/tests/test_work_orders.py +0 -0
@@ -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
@@ -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 *
@@ -0,0 +1,6 @@
1
+ """Alias for id_constructors.from_blobs and id_constructors.from_uuids
2
+
3
+ For backwards compatibility.
4
+ """
5
+ from .id_constructors.from_blobs import *
6
+ from .id_constructors.from_uuids import *
@@ -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,
@@ -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 *
@@ -1,16 +1,17 @@
1
- from .result import (
1
+ from geoseeq.result import (
2
2
  SampleResultFolder,
3
3
  SampleResultFile,
4
4
  ProjectResultFolder,
5
5
  ProjectResultFile,
6
6
  )
7
- from .organization import Organization
8
- from .sample import Sample
9
- from .project import Project
10
- from .knex import GeoseeqNotFoundError
7
+ from geoseeq.organization import Organization
8
+ from geoseeq.sample import Sample
9
+ from geoseeq.project import Project
10
+ from geoseeq import GeoseeqNotFoundError
11
11
 
12
12
 
13
13
  def org_from_blob(knex, blob, already_fetched=True, modified=False):
14
+ """Return an Organization object from a blob."""
14
15
  org = Organization(knex, blob["name"])
15
16
  org.load_blob(blob)
16
17
  org._already_fetched = already_fetched
@@ -19,6 +20,7 @@ def org_from_blob(knex, blob, already_fetched=True, modified=False):
19
20
 
20
21
 
21
22
  def project_from_blob(knex, blob, already_fetched=True, modified=False):
23
+ """Return a Project object from a blob."""
22
24
  org = org_from_blob(
23
25
  knex, blob["organization_obj"], already_fetched=already_fetched, modified=modified
24
26
  )
@@ -32,6 +34,7 @@ sample_group_from_blob = project_from_blob # Alias
32
34
 
33
35
 
34
36
  def sample_from_blob(knex, blob, already_fetched=True, modified=False):
37
+ """Return a Sample object from a blob."""
35
38
  lib = sample_group_from_blob(
36
39
  knex, blob["library_obj"], already_fetched=already_fetched, modified=modified
37
40
  )
@@ -43,6 +46,7 @@ def sample_from_blob(knex, blob, already_fetched=True, modified=False):
43
46
 
44
47
 
45
48
  def project_result_folder_from_blob(knex, blob, already_fetched=True, modified=False):
49
+ """Return a ProjectResultFolder object from a blob."""
46
50
  group = project_from_blob(
47
51
  knex, blob["sample_group_obj"], already_fetched=already_fetched, modified=modified
48
52
  )
@@ -58,6 +62,7 @@ sample_group_ar_from_blob = project_result_folder_from_blob # Alias
58
62
 
59
63
 
60
64
  def sample_result_folder_from_blob(knex, blob, already_fetched=True, modified=False):
65
+ """Return a SampleResultFolder object from a blob."""
61
66
  sample = sample_from_blob(
62
67
  knex, blob["sample_obj"], already_fetched=already_fetched, modified=modified
63
68
  )
@@ -73,6 +78,7 @@ sample_ar_from_blob = sample_result_folder_from_blob # Alias
73
78
 
74
79
 
75
80
  def sample_result_file_from_blob(knex, blob, already_fetched=True, modified=False):
81
+ """Return a SampleResultFile object from a blob."""
76
82
  ar = sample_result_folder_from_blob(
77
83
  knex, blob["analysis_result_obj"], already_fetched=already_fetched, modified=modified
78
84
  )
@@ -88,6 +94,7 @@ sample_ar_field_from_blob = sample_result_file_from_blob # Alias
88
94
 
89
95
 
90
96
  def project_result_file_from_blob(knex, blob, already_fetched=True, modified=False):
97
+ """Return a ProjectResultFile object from a blob."""
91
98
  ar = project_result_folder_from_blob(
92
99
  knex, blob["analysis_result_obj"], already_fetched=already_fetched, modified=modified
93
100
  )
@@ -100,74 +107,3 @@ def project_result_file_from_blob(knex, blob, already_fetched=True, modified=Fal
100
107
  return arf
101
108
 
102
109
  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')
@@ -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
+ }
@@ -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,
@@ -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
 
@@ -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
@@ -37,7 +37,6 @@ geoseeq/cli/view.py
37
37
  geoseeq/cli/shared_params/__init__.py
38
38
  geoseeq/cli/shared_params/common_state.py
39
39
  geoseeq/cli/shared_params/id_handlers.py
40
- geoseeq/cli/shared_params/id_utils.py
41
40
  geoseeq/cli/shared_params/obj_getters.py
42
41
  geoseeq/cli/shared_params/opts_and_args.py
43
42
  geoseeq/cli/upload/__init__.py
@@ -49,9 +48,17 @@ geoseeq/contrib/ncbi/api.py
49
48
  geoseeq/contrib/ncbi/bioproject.py
50
49
  geoseeq/contrib/ncbi/cli.py
51
50
  geoseeq/contrib/ncbi/setup_logging.py
51
+ geoseeq/id_constructors/__init__.py
52
+ geoseeq/id_constructors/from_blobs.py
53
+ geoseeq/id_constructors/from_ids.py
54
+ geoseeq/id_constructors/from_names.py
55
+ geoseeq/id_constructors/from_uuids.py
56
+ geoseeq/id_constructors/resolvers.py
57
+ geoseeq/id_constructors/utils.py
52
58
  geoseeq/plotting/__init__.py
53
59
  geoseeq/plotting/constants.py
54
60
  geoseeq/plotting/highcharts.py
61
+ geoseeq/plotting/selectable.py
55
62
  geoseeq/result/__init__.py
56
63
  geoseeq/result/bioinfo.py
57
64
  geoseeq/result/file_download.py
@@ -5,7 +5,7 @@ import setuptools
5
5
 
6
6
  setuptools.setup(
7
7
  name='geoseeq',
8
- version='0.2.15', # remember to update version string in CLI as well
8
+ version='0.2.17', # remember to update version string in CLI as well
9
9
  author="David C. Danko",
10
10
  author_email='dcdanko@biotia.io',
11
11
  description=open('README.md').read(),
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes