seqslab-cli 3.2.1__tar.gz → 3.2.1.post0__tar.gz

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.
Files changed (101) hide show
  1. seqslab-cli-3.2.1.post0/MANIFEST.in +2 -0
  2. seqslab-cli-3.2.1.post0/PKG-INFO +297 -0
  3. seqslab-cli-3.2.1.post0/README.md +277 -0
  4. {seqslab-cli-3.2.1 → seqslab-cli-3.2.1.post0}/python/seqslab/__init__.py +1 -1
  5. {seqslab-cli-3.2.1 → seqslab-cli-3.2.1.post0}/python/seqslab/drs/commands.py +21 -6
  6. {seqslab-cli-3.2.1 → seqslab-cli-3.2.1.post0}/python/seqslab/drs/internal/aiocopy.py +2 -2
  7. {seqslab-cli-3.2.1 → seqslab-cli-3.2.1.post0}/python/seqslab/drs/internal/utils.py +5 -3
  8. seqslab-cli-3.2.1.post0/python/seqslab_cli.egg-info/PKG-INFO +297 -0
  9. {seqslab-cli-3.2.1 → seqslab-cli-3.2.1.post0}/python/seqslab_cli.egg-info/SOURCES.txt +2 -2
  10. {seqslab-cli-3.2.1 → seqslab-cli-3.2.1.post0}/python/seqslab_cli.egg-info/entry_points.txt +1 -0
  11. {seqslab-cli-3.2.1 → seqslab-cli-3.2.1.post0}/python/seqslab_cli.egg-info/requires.txt +2 -0
  12. {seqslab-cli-3.2.1/python → seqslab-cli-3.2.1.post0}/requirements.txt +3 -1
  13. {seqslab-cli-3.2.1 → seqslab-cli-3.2.1.post0}/setup.cfg +2 -2
  14. {seqslab-cli-3.2.1 → seqslab-cli-3.2.1.post0}/setup.py +9 -8
  15. seqslab-cli-3.2.1/MANIFEST.in +0 -3
  16. seqslab-cli-3.2.1/PKG-INFO +0 -272
  17. seqslab-cli-3.2.1/python/seqslab/README.md +0 -252
  18. seqslab-cli-3.2.1/python/seqslab_cli.egg-info/PKG-INFO +0 -272
  19. {seqslab-cli-3.2.1 → seqslab-cli-3.2.1.post0}/LICENSE +0 -0
  20. {seqslab-cli-3.2.1 → seqslab-cli-3.2.1.post0}/python/seqslab/auth/__init__.py +0 -0
  21. {seqslab-cli-3.2.1 → seqslab-cli-3.2.1.post0}/python/seqslab/auth/azuread.py +0 -0
  22. {seqslab-cli-3.2.1 → seqslab-cli-3.2.1.post0}/python/seqslab/auth/commands.py +0 -0
  23. {seqslab-cli-3.2.1 → seqslab-cli-3.2.1.post0}/python/seqslab/cli.py +0 -0
  24. {seqslab-cli-3.2.1 → seqslab-cli-3.2.1.post0}/python/seqslab/context.py +0 -0
  25. {seqslab-cli-3.2.1 → seqslab-cli-3.2.1.post0}/python/seqslab/drs/__init__.py +0 -0
  26. {seqslab-cli-3.2.1 → seqslab-cli-3.2.1.post0}/python/seqslab/drs/api/__init__.py +0 -0
  27. {seqslab-cli-3.2.1 → seqslab-cli-3.2.1.post0}/python/seqslab/drs/api/azure.py +0 -0
  28. {seqslab-cli-3.2.1 → seqslab-cli-3.2.1.post0}/python/seqslab/drs/api/base.py +0 -0
  29. {seqslab-cli-3.2.1 → seqslab-cli-3.2.1.post0}/python/seqslab/drs/api/common.py +0 -0
  30. {seqslab-cli-3.2.1 → seqslab-cli-3.2.1.post0}/python/seqslab/drs/api/template.py +0 -0
  31. {seqslab-cli-3.2.1 → seqslab-cli-3.2.1.post0}/python/seqslab/drs/internal/__init__.py +0 -0
  32. {seqslab-cli-3.2.1 → seqslab-cli-3.2.1.post0}/python/seqslab/drs/internal/common.py +0 -0
  33. {seqslab-cli-3.2.1 → seqslab-cli-3.2.1.post0}/python/seqslab/drs/storage/__init__.py +0 -0
  34. {seqslab-cli-3.2.1 → seqslab-cli-3.2.1.post0}/python/seqslab/drs/storage/azure.py +0 -0
  35. {seqslab-cli-3.2.1 → seqslab-cli-3.2.1.post0}/python/seqslab/drs/storage/base.py +0 -0
  36. {seqslab-cli-3.2.1 → seqslab-cli-3.2.1.post0}/python/seqslab/drs/utils/__init__.py +0 -0
  37. {seqslab-cli-3.2.1 → seqslab-cli-3.2.1.post0}/python/seqslab/drs/utils/biomimetype.py +0 -0
  38. {seqslab-cli-3.2.1 → seqslab-cli-3.2.1.post0}/python/seqslab/drs/utils/progressbar.py +0 -0
  39. {seqslab-cli-3.2.1 → seqslab-cli-3.2.1.post0}/python/seqslab/exceptions.py +0 -0
  40. {seqslab-cli-3.2.1 → seqslab-cli-3.2.1.post0}/python/seqslab/organization/__init__.py +0 -0
  41. {seqslab-cli-3.2.1 → seqslab-cli-3.2.1.post0}/python/seqslab/organization/commands.py +0 -0
  42. {seqslab-cli-3.2.1 → seqslab-cli-3.2.1.post0}/python/seqslab/organization/resource/__init__.py +0 -0
  43. {seqslab-cli-3.2.1 → seqslab-cli-3.2.1.post0}/python/seqslab/organization/resource/base.py +0 -0
  44. {seqslab-cli-3.2.1 → seqslab-cli-3.2.1.post0}/python/seqslab/plugin.py +0 -0
  45. {seqslab-cli-3.2.1 → seqslab-cli-3.2.1.post0}/python/seqslab/role/__init__.py +0 -0
  46. {seqslab-cli-3.2.1 → seqslab-cli-3.2.1.post0}/python/seqslab/role/commands.py +0 -0
  47. {seqslab-cli-3.2.1 → seqslab-cli-3.2.1.post0}/python/seqslab/role/internal/__init__.py +0 -0
  48. {seqslab-cli-3.2.1 → seqslab-cli-3.2.1.post0}/python/seqslab/role/internal/common.py +0 -0
  49. {seqslab-cli-3.2.1 → seqslab-cli-3.2.1.post0}/python/seqslab/role/resource/__init__.py +0 -0
  50. {seqslab-cli-3.2.1 → seqslab-cli-3.2.1.post0}/python/seqslab/role/resource/azure.py +0 -0
  51. {seqslab-cli-3.2.1 → seqslab-cli-3.2.1.post0}/python/seqslab/role/resource/base.py +0 -0
  52. {seqslab-cli-3.2.1 → seqslab-cli-3.2.1.post0}/python/seqslab/runsheet/__init__.py +0 -0
  53. {seqslab-cli-3.2.1 → seqslab-cli-3.2.1.post0}/python/seqslab/runsheet/runsheet.py +0 -0
  54. {seqslab-cli-3.2.1 → seqslab-cli-3.2.1.post0}/python/seqslab/session_logger.py +0 -0
  55. {seqslab-cli-3.2.1 → seqslab-cli-3.2.1.post0}/python/seqslab/settings.py +0 -0
  56. {seqslab-cli-3.2.1 → seqslab-cli-3.2.1.post0}/python/seqslab/statusbar.py +0 -0
  57. {seqslab-cli-3.2.1 → seqslab-cli-3.2.1.post0}/python/seqslab/trs/__init__.py +0 -0
  58. {seqslab-cli-3.2.1 → seqslab-cli-3.2.1.post0}/python/seqslab/trs/commands.py +0 -0
  59. {seqslab-cli-3.2.1 → seqslab-cli-3.2.1.post0}/python/seqslab/trs/internal/__init__.py +0 -0
  60. {seqslab-cli-3.2.1 → seqslab-cli-3.2.1.post0}/python/seqslab/trs/internal/utils.py +0 -0
  61. {seqslab-cli-3.2.1 → seqslab-cli-3.2.1.post0}/python/seqslab/trs/register/__init__.py +0 -0
  62. {seqslab-cli-3.2.1 → seqslab-cli-3.2.1.post0}/python/seqslab/trs/register/azure.py +0 -0
  63. {seqslab-cli-3.2.1 → seqslab-cli-3.2.1.post0}/python/seqslab/trs/register/base.py +0 -0
  64. {seqslab-cli-3.2.1 → seqslab-cli-3.2.1.post0}/python/seqslab/trs/register/common.py +0 -0
  65. {seqslab-cli-3.2.1 → seqslab-cli-3.2.1.post0}/python/seqslab/trs/register/template.py +0 -0
  66. {seqslab-cli-3.2.1 → seqslab-cli-3.2.1.post0}/python/seqslab/trs/resource/__init__.py +0 -0
  67. {seqslab-cli-3.2.1 → seqslab-cli-3.2.1.post0}/python/seqslab/trs/resource/azure.py +0 -0
  68. {seqslab-cli-3.2.1 → seqslab-cli-3.2.1.post0}/python/seqslab/trs/resource/base.py +0 -0
  69. {seqslab-cli-3.2.1 → seqslab-cli-3.2.1.post0}/python/seqslab/trs/resource/common.py +0 -0
  70. {seqslab-cli-3.2.1 → seqslab-cli-3.2.1.post0}/python/seqslab/trs/template/__init__.py +0 -0
  71. {seqslab-cli-3.2.1 → seqslab-cli-3.2.1.post0}/python/seqslab/trs/template/base.py +0 -0
  72. {seqslab-cli-3.2.1 → seqslab-cli-3.2.1.post0}/python/seqslab/trs/template/template.py +0 -0
  73. {seqslab-cli-3.2.1 → seqslab-cli-3.2.1.post0}/python/seqslab/usage_logger.py +0 -0
  74. {seqslab-cli-3.2.1 → seqslab-cli-3.2.1.post0}/python/seqslab/user/__init__.py +0 -0
  75. {seqslab-cli-3.2.1 → seqslab-cli-3.2.1.post0}/python/seqslab/user/commands.py +0 -0
  76. {seqslab-cli-3.2.1 → seqslab-cli-3.2.1.post0}/python/seqslab/user/internal/__init__.py +0 -0
  77. {seqslab-cli-3.2.1 → seqslab-cli-3.2.1.post0}/python/seqslab/user/internal/common.py +0 -0
  78. {seqslab-cli-3.2.1 → seqslab-cli-3.2.1.post0}/python/seqslab/user/resource/__init__.py +0 -0
  79. {seqslab-cli-3.2.1 → seqslab-cli-3.2.1.post0}/python/seqslab/user/resource/azure.py +0 -0
  80. {seqslab-cli-3.2.1 → seqslab-cli-3.2.1.post0}/python/seqslab/user/resource/base.py +0 -0
  81. {seqslab-cli-3.2.1 → seqslab-cli-3.2.1.post0}/python/seqslab/wes/__init__.py +0 -0
  82. {seqslab-cli-3.2.1 → seqslab-cli-3.2.1.post0}/python/seqslab/wes/commands.py +0 -0
  83. {seqslab-cli-3.2.1 → seqslab-cli-3.2.1.post0}/python/seqslab/wes/internal/__init__.py +0 -0
  84. {seqslab-cli-3.2.1 → seqslab-cli-3.2.1.post0}/python/seqslab/wes/internal/common.py +0 -0
  85. {seqslab-cli-3.2.1 → seqslab-cli-3.2.1.post0}/python/seqslab/wes/resource/__init__.py +0 -0
  86. {seqslab-cli-3.2.1 → seqslab-cli-3.2.1.post0}/python/seqslab/wes/resource/azure.py +0 -0
  87. {seqslab-cli-3.2.1 → seqslab-cli-3.2.1.post0}/python/seqslab/wes/resource/base.py +0 -0
  88. {seqslab-cli-3.2.1 → seqslab-cli-3.2.1.post0}/python/seqslab/wes/template/__init__.py +0 -0
  89. {seqslab-cli-3.2.1 → seqslab-cli-3.2.1.post0}/python/seqslab/wes/template/base.py +0 -0
  90. {seqslab-cli-3.2.1 → seqslab-cli-3.2.1.post0}/python/seqslab/wes/template/template.py +0 -0
  91. {seqslab-cli-3.2.1 → seqslab-cli-3.2.1.post0}/python/seqslab/wes/utils.py +0 -0
  92. {seqslab-cli-3.2.1 → seqslab-cli-3.2.1.post0}/python/seqslab/workspace/__init__.py +0 -0
  93. {seqslab-cli-3.2.1 → seqslab-cli-3.2.1.post0}/python/seqslab/workspace/commands.py +0 -0
  94. {seqslab-cli-3.2.1 → seqslab-cli-3.2.1.post0}/python/seqslab/workspace/internal/__init__.py +0 -0
  95. {seqslab-cli-3.2.1 → seqslab-cli-3.2.1.post0}/python/seqslab/workspace/internal/common.py +0 -0
  96. {seqslab-cli-3.2.1 → seqslab-cli-3.2.1.post0}/python/seqslab/workspace/resource/__init__.py +0 -0
  97. {seqslab-cli-3.2.1 → seqslab-cli-3.2.1.post0}/python/seqslab/workspace/resource/azure.py +0 -0
  98. {seqslab-cli-3.2.1 → seqslab-cli-3.2.1.post0}/python/seqslab/workspace/resource/base.py +0 -0
  99. {seqslab-cli-3.2.1 → seqslab-cli-3.2.1.post0}/python/seqslab_cli.egg-info/dependency_links.txt +0 -0
  100. {seqslab-cli-3.2.1 → seqslab-cli-3.2.1.post0}/python/seqslab_cli.egg-info/top_level.txt +0 -0
  101. {seqslab-cli-3.2.1 → seqslab-cli-3.2.1.post0}/python/seqslab_cli.egg-info/zip-safe +0 -0
@@ -0,0 +1,2 @@
1
+ include README.md
2
+ global-exclude **/tests/*
@@ -0,0 +1,297 @@
1
+ Metadata-Version: 2.1
2
+ Name: seqslab-cli
3
+ Version: 3.2.1.post0
4
+ Summary: Atgenomix SeqsLab Command Line Tool
5
+ Home-page: https://github.com/AnomeGAP/seqslab-cli
6
+ Author: Allen Chang
7
+ Author-email: allen.chang@atgenomix.com
8
+ License: MIT license
9
+ Project-URL: Documentation, https://docs.atgenomix.com/
10
+ Project-URL: Repository, https://github.com/AnomeGAP/seqslab-cli
11
+ Description: <!-- PROJECT SHIELDS -->
12
+ <!--
13
+ *** I'm using markdown "reference style" links for readability.
14
+ *** Reference links are enclosed in brackets [ ] instead of parentheses ( ).
15
+ *** See the bottom of this document for the declaration of the reference variables
16
+ *** for contributors-url, forks-url, etc. This is an optional, concise syntax you may use.
17
+ *** https://www.markdownguide.org/basic-syntax/#reference-style-links
18
+ -->
19
+ [Contributors][contributors-url]
20
+ [Stargazers][stars-url]
21
+ [Issues][issues-url]
22
+ [License][license-url]
23
+ [![LinkedIn][linkedin-shield]][linkedin-url]
24
+
25
+ <!-- PROJECT LOGO -->
26
+ <br />
27
+ <p align="center">
28
+ <a href="https://github.com/AnomeGAP/seqslab-cli">
29
+ <img src="https://static.wixstatic.com/media/f7a6a5_1ad70ed05af04d7eb45ee5e2df347a32~mv2_d_4266_4449_s_4_2.gif" alt="Logo" width="80" height="80">
30
+ </a>
31
+
32
+ <h2 align="center">Atgenomix SeqsLab V3 CLI</h2>
33
+ </p>
34
+ <p align="center">
35
+ Command-line interface of Atgenomix SeqsLab, a cloud-native biomedical informatics (BioMed IT) platform
36
+ <br />
37
+ <a href="https://docs.atgenomix.com"><strong>Explore the docs »</strong></a>
38
+ <br />
39
+ <br />
40
+ <a href="https://github.com/AnomeGAP/seqslab-cli/issues">Report issue</a>
41
+ ·
42
+ <a href="https://github.com/AnomeGAP/seqslab-cli/issues">Request feature</a>
43
+ </p>
44
+
45
+ <!-- TABLE OF CONTENTS -->
46
+ <details open="open">
47
+ <summary>Table of Contents</summary>
48
+ <ol>
49
+ <li>
50
+ <a href="#overview">Overview</a>
51
+ <ul>
52
+ <li><a href="#underlying-technology">Underlying Technology</a></li>
53
+ </ul>
54
+ </li>
55
+ <li>
56
+ <a href="#getting-started">Getting Started</a>
57
+ <ul>
58
+ <li><a href="#prerequisites">Prerequisites</a></li>
59
+ <li><a href="#interactive-mode">Interactive Mode</a></li>
60
+ <li><a href="#cli-mode">CLI Mode</a></li>
61
+ </ul>
62
+ </li>
63
+ <li>
64
+ <a href="#development">Development</a>
65
+ <ul>
66
+ <li><a href="#authentication-with-the-seqslab-api">Authentication with the SeqsLab API</a></li>
67
+ </ul>
68
+ </li>
69
+ <li><a href="#roadmap">Roadmap</a></li>
70
+ <li><a href="#contributing">Contributing</a></li>
71
+ <li><a href="#license">License</a></li>
72
+ <li><a href="#contact">Contact</a></li>
73
+ <li><a href="#acknowledgements">Acknowledgements</a></li>
74
+ </ol>
75
+ </details>
76
+
77
+ ## Overview
78
+
79
+ ![Product Screen Shot](https://github.com/AnomeGAP/seqslab-cli/blob/main/Atgenomix%20SeqsLab%20V3.png)
80
+
81
+ Working alongside the web-based SeqsLab Console, the CLI enables bioinformaticians to easily build custom scripts and automate workflows on SeqsLab.
82
+
83
+ Common use cases for the CLI include the following:
84
+
85
+ * Automate processing of sequencing data, including uploading and downloading of datasets to/from the SeqsLab Data Hub
86
+ * Submit workflow run requests on demand via SeqsLab Workflow Execution Service (WES) APIs, and integrate with local downstream analysis tools
87
+ * View records of platform activities for auditing purposes
88
+
89
+ ### Underlying Technology
90
+
91
+ The SeqsLab CLI is built using the following:
92
+
93
+ * [SeqsLab APIs](https://api.seqslab.net/)
94
+ * [Python-Nubia](https://github.com/facebookincubator/python-nubia)
95
+ * [MSAL Python](https://msal-python.readthedocs.io/en/latest/)
96
+ * [Azure SDK](https://github.com/Azure/azure-sdk)
97
+ * [aiohttp](https://docs.aiohttp.org/en/stable/index.html)
98
+
99
+ **Note**: The mechanisms for secure information storage are built around a [keyring](https://pypi.org/project/keyring/) service.
100
+
101
+ ## Getting Started
102
+
103
+ ### Prerequisites
104
+
105
+ * Python 3.8 or later
106
+
107
+ * A Python virtual environment
108
+
109
+ Install the SeqsLab CLI.
110
+ ```bash
111
+ pip3 install seqslab-cli
112
+ ```
113
+ * A keyring backend
114
+
115
+ The SeqsLab CLI supports the following keyring backends:
116
+
117
+ * macOS [Keychain](https://en.wikipedia.org/wiki/Keychain_%28software%29)
118
+ * Freedesktop [Secret Service](http://standards.freedesktop.org/secret-service/) (requires [secretstorage](https://pypi.python.org/pypi/secretstorage))
119
+ * KDE4 & KDE5 [KWallet](https://en.wikipedia.org/wiki/KWallet) (requires [dbus](https://pypi.python.org/pypi/dbus-python))
120
+ * [Windows Credential Locker](https://docs.microsoft.com/en-us/windows/uwp/security/credential-locker)
121
+
122
+ **Note**: See the [Python keyring library documentation](https://pypi.org/project/keyring/) for more information about using keyring on a headless Linux system in a Docker container.
123
+
124
+ * (macOS devices) The following packages:
125
+
126
+ * [pkg-config](https://formulae.brew.sh/formula/pkg-config)
127
+ * [dbus](https://formulae.brew.sh/formula/dbus)
128
+ * [glib](https://formulae.brew.sh/formula/glib)
129
+
130
+ You can install the required packages using Homebrew.
131
+ ```bash
132
+ # install packages:
133
+ brew install dbus
134
+ brew install pkg-config
135
+ brew install glib
136
+ ```
137
+
138
+ ### Interactive Mode
139
+
140
+ This mode provides fish-style auto-completion functionality that is user-friendly, especially for beginners.
141
+
142
+ * Run interactive mode.
143
+ ```bash
144
+ virtualenv .venv
145
+ source .venv/bin/activate
146
+ export PYTHONPATH=$(pwd)
147
+ python3 seqslab/cli.py
148
+ ```
149
+
150
+ * Display the available commands.
151
+ ```bash
152
+ seqslab> help
153
+ ```
154
+
155
+ ### CLI Mode
156
+
157
+ In this mode, the SeqsLab CLI works exactly like any traditional Linux-based command-line utility.
158
+
159
+ ## Development
160
+
161
+ Commands are defined as normal Python functions with `@command` and `@argument` decorators. Super commands are implemented as Python class objects, and instance methods decorated with `@command` are sub-commands. In non-interactive mode, you can set `@command`-decorated functions to return an `int`, which is used as the Linux return code.
162
+
163
+ By default, the framework loads commands from the `python/seqslab/commands` module directory. Atgenomix recommends implementing your program structure under the `commands` directory.
164
+
165
+ ```python
166
+
167
+ from termcolor import cprint
168
+ from nubia import argument, command
169
+ @command("hello")
170
+ @argument("name", type=str, positional=True, description="Your name")
171
+ def hello(name: str) -> int:
172
+ """
173
+ command help, or the command won't be loaded.
174
+ """
175
+ cprint(f"Hello {name}!", "green")
176
+ return 0
177
+ @command
178
+ class SuperCommand:
179
+ """super-command command help"""
180
+
181
+ def __init__(self):
182
+ self._shared = "shared variable value"
183
+
184
+ @property
185
+ def shared(self) -> str:
186
+ return self._shared
187
+
188
+ @command(aliases=["echo"])
189
+ @argument("first",
190
+ type=str,
191
+ positional=False,
192
+ description="firstname",
193
+ aliases=["f"])
194
+ @argument("last",
195
+ type=str,
196
+ positional=False,
197
+ description="lastname",
198
+ aliases=["l"])
199
+ def cprint(self, first: str, last: str) -> int:
200
+ """
201
+ sub-command help message.
202
+ """
203
+ cprint(f"{first} {last}", "red")
204
+ return 0
205
+ ```
206
+
207
+ ### Authentication with the SeqsLab API
208
+
209
+ Regardless of the mode (interactive or non-interactive) that you intend to use, you must sign in to authenticate the session. The SeqsLab CLI follows the OAuth 2.0 Device Authorization Grant (external URL) process.
210
+
211
+ * Specify the platform backend to be used when launching the SeqsLab CLI. The default value is `azure`.
212
+
213
+ ```bash
214
+ seqslab --backend azure
215
+ ```
216
+
217
+ * Sign in to the SeqsLab API and obtain API tokens with a single command. By default, the sign-in command uses the Device Code Flow for browserless systems.
218
+
219
+ ```bash
220
+ auth signin
221
+ ```
222
+
223
+ Set the device-code argument to `True`. By default, the sign-in process uses the Authorization Code Flow.
224
+
225
+ ```bash
226
+ auth signin device-code=True
227
+ ```
228
+
229
+ * Obtain an API access token for interacting with SeqsLab API apps.
230
+
231
+ ```python
232
+ from seqslab.auth.commands import Auth
233
+
234
+ token = Auth.get_token()
235
+ access = token.get("tokens").get("access")
236
+ # use token in your request header, ex: Authorization: Bearer {access}
237
+ attrs = token.get("attrs")
238
+ # attrs is a dictionary containing the information about the signing-in user.
239
+ ```
240
+
241
+ `Auth.get_token()` automatically refreshes the access token upon expiration. When users attempt to sign in to the SeqsLab API before a new access token is generated, the function returns `None`.
242
+
243
+ Access tokens are persistently cached in the system-supported secret service, such as Freedesktop Secret Service and macOS Keychain. As a result, valid access tokens can be used across multiple SeqsLab CLI sessions.
244
+
245
+ ## Roadmap
246
+
247
+ See the [list](https://github.com/AnomeGAP/seqslab-cli/issues) of proposed features and known issues.
248
+
249
+ ## Contributing
250
+
251
+ The repository currently does not accept contributions but will eventually be opened to the community.
252
+
253
+ ## License
254
+
255
+ See `License`.
256
+
257
+ ## Contact
258
+
259
+ Main contact: [Allen Chang](https://www.linkedin.com/in/allen-chang/)
260
+
261
+ Email: allen.chang@atgenomix.com
262
+
263
+ Project repository: [https://github.com/atgenomix](https://github.com/atgenomix)
264
+
265
+ ## Acknowledgements
266
+
267
+ * [Facebook Incubator](https://github.com/facebookincubator)
268
+ * [Microsoft identity platform](https://docs.microsoft.com/en-us/azure/active-directory/develop/active-directory-v2-protocols)
269
+ * [GA4GH](https://www.ga4gh.org/)
270
+ * [Best-README-Template](https://github.com/othneildrew/Best-README-Template)
271
+
272
+ <!-- MARKDOWN LINKS & IMAGES -->
273
+ <!-- https://www.markdownguide.org/basic-syntax/#reference-style-links -->
274
+
275
+ [contributors-url]: https://github.com/AnomeGAP/seqslab-cli/graphs/contributors
276
+
277
+ [stars-url]: https://github.com/AnomeGAP/seqslab-cli/stargazers
278
+
279
+ [issues-url]: https://github.com/AnomeGAP/seqslab-cli/issues
280
+
281
+ [license-url]: https://github.com/AnomeGAP/seqslab-cli/blob/main/LICENSE.txt
282
+
283
+ [linkedin-shield]: https://img.shields.io/badge/-LinkedIn-black.svg?style=for-the-badge&logo=linkedin&colorB=555
284
+
285
+ [linkedin-url]: https://www.linkedin.com/company/atgenomix
286
+
287
+ [product-screenshot]: https://github.com/AnomeGAP/seqslab-cli/blob/main/Atgenomix%20SeqsLab%20V3.png
288
+
289
+ Platform: UNKNOWN
290
+ Classifier: Intended Audience :: Developers
291
+ Classifier: License :: OSI Approved :: MIT License
292
+ Classifier: Operating System :: OS Independent
293
+ Classifier: Programming Language :: Python
294
+ Classifier: Programming Language :: Python :: 3.8
295
+ Classifier: Programming Language :: Python :: 3.9
296
+ Requires-Python: >=3.8
297
+ Description-Content-Type: text/markdown
@@ -0,0 +1,277 @@
1
+ <!-- PROJECT SHIELDS -->
2
+ <!--
3
+ *** I'm using markdown "reference style" links for readability.
4
+ *** Reference links are enclosed in brackets [ ] instead of parentheses ( ).
5
+ *** See the bottom of this document for the declaration of the reference variables
6
+ *** for contributors-url, forks-url, etc. This is an optional, concise syntax you may use.
7
+ *** https://www.markdownguide.org/basic-syntax/#reference-style-links
8
+ -->
9
+ [Contributors][contributors-url]
10
+ [Stargazers][stars-url]
11
+ [Issues][issues-url]
12
+ [License][license-url]
13
+ [![LinkedIn][linkedin-shield]][linkedin-url]
14
+
15
+ <!-- PROJECT LOGO -->
16
+ <br />
17
+ <p align="center">
18
+ <a href="https://github.com/AnomeGAP/seqslab-cli">
19
+ <img src="https://static.wixstatic.com/media/f7a6a5_1ad70ed05af04d7eb45ee5e2df347a32~mv2_d_4266_4449_s_4_2.gif" alt="Logo" width="80" height="80">
20
+ </a>
21
+
22
+ <h2 align="center">Atgenomix SeqsLab V3 CLI</h2>
23
+ </p>
24
+ <p align="center">
25
+ Command-line interface of Atgenomix SeqsLab, a cloud-native biomedical informatics (BioMed IT) platform
26
+ <br />
27
+ <a href="https://docs.atgenomix.com"><strong>Explore the docs »</strong></a>
28
+ <br />
29
+ <br />
30
+ <a href="https://github.com/AnomeGAP/seqslab-cli/issues">Report issue</a>
31
+ ·
32
+ <a href="https://github.com/AnomeGAP/seqslab-cli/issues">Request feature</a>
33
+ </p>
34
+
35
+ <!-- TABLE OF CONTENTS -->
36
+ <details open="open">
37
+ <summary>Table of Contents</summary>
38
+ <ol>
39
+ <li>
40
+ <a href="#overview">Overview</a>
41
+ <ul>
42
+ <li><a href="#underlying-technology">Underlying Technology</a></li>
43
+ </ul>
44
+ </li>
45
+ <li>
46
+ <a href="#getting-started">Getting Started</a>
47
+ <ul>
48
+ <li><a href="#prerequisites">Prerequisites</a></li>
49
+ <li><a href="#interactive-mode">Interactive Mode</a></li>
50
+ <li><a href="#cli-mode">CLI Mode</a></li>
51
+ </ul>
52
+ </li>
53
+ <li>
54
+ <a href="#development">Development</a>
55
+ <ul>
56
+ <li><a href="#authentication-with-the-seqslab-api">Authentication with the SeqsLab API</a></li>
57
+ </ul>
58
+ </li>
59
+ <li><a href="#roadmap">Roadmap</a></li>
60
+ <li><a href="#contributing">Contributing</a></li>
61
+ <li><a href="#license">License</a></li>
62
+ <li><a href="#contact">Contact</a></li>
63
+ <li><a href="#acknowledgements">Acknowledgements</a></li>
64
+ </ol>
65
+ </details>
66
+
67
+ ## Overview
68
+
69
+ ![Product Screen Shot](https://github.com/AnomeGAP/seqslab-cli/blob/main/Atgenomix%20SeqsLab%20V3.png)
70
+
71
+ Working alongside the web-based SeqsLab Console, the CLI enables bioinformaticians to easily build custom scripts and automate workflows on SeqsLab.
72
+
73
+ Common use cases for the CLI include the following:
74
+
75
+ * Automate processing of sequencing data, including uploading and downloading of datasets to/from the SeqsLab Data Hub
76
+ * Submit workflow run requests on demand via SeqsLab Workflow Execution Service (WES) APIs, and integrate with local downstream analysis tools
77
+ * View records of platform activities for auditing purposes
78
+
79
+ ### Underlying Technology
80
+
81
+ The SeqsLab CLI is built using the following:
82
+
83
+ * [SeqsLab APIs](https://api.seqslab.net/)
84
+ * [Python-Nubia](https://github.com/facebookincubator/python-nubia)
85
+ * [MSAL Python](https://msal-python.readthedocs.io/en/latest/)
86
+ * [Azure SDK](https://github.com/Azure/azure-sdk)
87
+ * [aiohttp](https://docs.aiohttp.org/en/stable/index.html)
88
+
89
+ **Note**: The mechanisms for secure information storage are built around a [keyring](https://pypi.org/project/keyring/) service.
90
+
91
+ ## Getting Started
92
+
93
+ ### Prerequisites
94
+
95
+ * Python 3.8 or later
96
+
97
+ * A Python virtual environment
98
+
99
+ Install the SeqsLab CLI.
100
+ ```bash
101
+ pip3 install seqslab-cli
102
+ ```
103
+ * A keyring backend
104
+
105
+ The SeqsLab CLI supports the following keyring backends:
106
+
107
+ * macOS [Keychain](https://en.wikipedia.org/wiki/Keychain_%28software%29)
108
+ * Freedesktop [Secret Service](http://standards.freedesktop.org/secret-service/) (requires [secretstorage](https://pypi.python.org/pypi/secretstorage))
109
+ * KDE4 & KDE5 [KWallet](https://en.wikipedia.org/wiki/KWallet) (requires [dbus](https://pypi.python.org/pypi/dbus-python))
110
+ * [Windows Credential Locker](https://docs.microsoft.com/en-us/windows/uwp/security/credential-locker)
111
+
112
+ **Note**: See the [Python keyring library documentation](https://pypi.org/project/keyring/) for more information about using keyring on a headless Linux system in a Docker container.
113
+
114
+ * (macOS devices) The following packages:
115
+
116
+ * [pkg-config](https://formulae.brew.sh/formula/pkg-config)
117
+ * [dbus](https://formulae.brew.sh/formula/dbus)
118
+ * [glib](https://formulae.brew.sh/formula/glib)
119
+
120
+ You can install the required packages using Homebrew.
121
+ ```bash
122
+ # install packages:
123
+ brew install dbus
124
+ brew install pkg-config
125
+ brew install glib
126
+ ```
127
+
128
+ ### Interactive Mode
129
+
130
+ This mode provides fish-style auto-completion functionality that is user-friendly, especially for beginners.
131
+
132
+ * Run interactive mode.
133
+ ```bash
134
+ virtualenv .venv
135
+ source .venv/bin/activate
136
+ export PYTHONPATH=$(pwd)
137
+ python3 seqslab/cli.py
138
+ ```
139
+
140
+ * Display the available commands.
141
+ ```bash
142
+ seqslab> help
143
+ ```
144
+
145
+ ### CLI Mode
146
+
147
+ In this mode, the SeqsLab CLI works exactly like any traditional Linux-based command-line utility.
148
+
149
+ ## Development
150
+
151
+ Commands are defined as normal Python functions with `@command` and `@argument` decorators. Super commands are implemented as Python class objects, and instance methods decorated with `@command` are sub-commands. In non-interactive mode, you can set `@command`-decorated functions to return an `int`, which is used as the Linux return code.
152
+
153
+ By default, the framework loads commands from the `python/seqslab/commands` module directory. Atgenomix recommends implementing your program structure under the `commands` directory.
154
+
155
+ ```python
156
+
157
+ from termcolor import cprint
158
+ from nubia import argument, command
159
+ @command("hello")
160
+ @argument("name", type=str, positional=True, description="Your name")
161
+ def hello(name: str) -> int:
162
+ """
163
+ command help, or the command won't be loaded.
164
+ """
165
+ cprint(f"Hello {name}!", "green")
166
+ return 0
167
+ @command
168
+ class SuperCommand:
169
+ """super-command command help"""
170
+
171
+ def __init__(self):
172
+ self._shared = "shared variable value"
173
+
174
+ @property
175
+ def shared(self) -> str:
176
+ return self._shared
177
+
178
+ @command(aliases=["echo"])
179
+ @argument("first",
180
+ type=str,
181
+ positional=False,
182
+ description="firstname",
183
+ aliases=["f"])
184
+ @argument("last",
185
+ type=str,
186
+ positional=False,
187
+ description="lastname",
188
+ aliases=["l"])
189
+ def cprint(self, first: str, last: str) -> int:
190
+ """
191
+ sub-command help message.
192
+ """
193
+ cprint(f"{first} {last}", "red")
194
+ return 0
195
+ ```
196
+
197
+ ### Authentication with the SeqsLab API
198
+
199
+ Regardless of the mode (interactive or non-interactive) that you intend to use, you must sign in to authenticate the session. The SeqsLab CLI follows the OAuth 2.0 Device Authorization Grant (external URL) process.
200
+
201
+ * Specify the platform backend to be used when launching the SeqsLab CLI. The default value is `azure`.
202
+
203
+ ```bash
204
+ seqslab --backend azure
205
+ ```
206
+
207
+ * Sign in to the SeqsLab API and obtain API tokens with a single command. By default, the sign-in command uses the Device Code Flow for browserless systems.
208
+
209
+ ```bash
210
+ auth signin
211
+ ```
212
+
213
+ Set the device-code argument to `True`. By default, the sign-in process uses the Authorization Code Flow.
214
+
215
+ ```bash
216
+ auth signin device-code=True
217
+ ```
218
+
219
+ * Obtain an API access token for interacting with SeqsLab API apps.
220
+
221
+ ```python
222
+ from seqslab.auth.commands import Auth
223
+
224
+ token = Auth.get_token()
225
+ access = token.get("tokens").get("access")
226
+ # use token in your request header, ex: Authorization: Bearer {access}
227
+ attrs = token.get("attrs")
228
+ # attrs is a dictionary containing the information about the signing-in user.
229
+ ```
230
+
231
+ `Auth.get_token()` automatically refreshes the access token upon expiration. When users attempt to sign in to the SeqsLab API before a new access token is generated, the function returns `None`.
232
+
233
+ Access tokens are persistently cached in the system-supported secret service, such as Freedesktop Secret Service and macOS Keychain. As a result, valid access tokens can be used across multiple SeqsLab CLI sessions.
234
+
235
+ ## Roadmap
236
+
237
+ See the [list](https://github.com/AnomeGAP/seqslab-cli/issues) of proposed features and known issues.
238
+
239
+ ## Contributing
240
+
241
+ The repository currently does not accept contributions but will eventually be opened to the community.
242
+
243
+ ## License
244
+
245
+ See `License`.
246
+
247
+ ## Contact
248
+
249
+ Main contact: [Allen Chang](https://www.linkedin.com/in/allen-chang/)
250
+
251
+ Email: allen.chang@atgenomix.com
252
+
253
+ Project repository: [https://github.com/atgenomix](https://github.com/atgenomix)
254
+
255
+ ## Acknowledgements
256
+
257
+ * [Facebook Incubator](https://github.com/facebookincubator)
258
+ * [Microsoft identity platform](https://docs.microsoft.com/en-us/azure/active-directory/develop/active-directory-v2-protocols)
259
+ * [GA4GH](https://www.ga4gh.org/)
260
+ * [Best-README-Template](https://github.com/othneildrew/Best-README-Template)
261
+
262
+ <!-- MARKDOWN LINKS & IMAGES -->
263
+ <!-- https://www.markdownguide.org/basic-syntax/#reference-style-links -->
264
+
265
+ [contributors-url]: https://github.com/AnomeGAP/seqslab-cli/graphs/contributors
266
+
267
+ [stars-url]: https://github.com/AnomeGAP/seqslab-cli/stargazers
268
+
269
+ [issues-url]: https://github.com/AnomeGAP/seqslab-cli/issues
270
+
271
+ [license-url]: https://github.com/AnomeGAP/seqslab-cli/blob/main/LICENSE.txt
272
+
273
+ [linkedin-shield]: https://img.shields.io/badge/-LinkedIn-black.svg?style=for-the-badge&logo=linkedin&colorB=555
274
+
275
+ [linkedin-url]: https://www.linkedin.com/company/atgenomix
276
+
277
+ [product-screenshot]: https://github.com/AnomeGAP/seqslab-cli/blob/main/Atgenomix%20SeqsLab%20V3.png
@@ -23,7 +23,7 @@ __all__ = [
23
23
  ]
24
24
 
25
25
 
26
- __version__ = "3.2.1"
26
+ __version__ = "3.2.1.post0"
27
27
 
28
28
  LOGGING = {
29
29
  "DIR_PATH": "/var/log/seqslab"
@@ -584,29 +584,44 @@ class BaseDatahub:
584
584
  return results
585
585
 
586
586
  @command(aliases=["clean"])
587
+ @argument("ids",
588
+ type=List[str],
589
+ positional=False,
590
+ description="Specify the IDs of the DRS object that you want to delete "
591
+ "(optional).")
587
592
  @argument("names",
588
593
  type=List[str],
589
594
  positional=False,
590
- description="Generate a list of DRS object names "
595
+ description="Specify the names of the DRS object that you want to delete "
591
596
  "(optional).")
592
597
  @argument("tags",
593
598
  type=List[str],
594
599
  positional=False,
595
- description="Specify the label of the DRS object that you want to delete "
600
+ description="Specify the labels of the DRS object that you want to delete "
596
601
  "(optional).")
602
+ @argument("backend_resource",
603
+ type=str,
604
+ positional=False,
605
+ description="Specify whether or not you want to delete the associated computing resources (default = true, optional).",
606
+ aliases=["purge"],
607
+ choices=['true', 'false'])
597
608
  def delete(
598
609
  self,
610
+ ids: List[str] = [],
599
611
  tags: List[str] = [],
600
612
  names: List[str] = [],
613
+ backend_resource: str = "true"
601
614
  ) -> int:
602
615
  """
603
- Delete DRS objects either by name or by tag.
616
+ Delete DRS objects by DRS id, by DRS name or by DRS tag.
604
617
  """
605
- if not names and not tags:
606
- cprint("Either give names or tags to do DRS query", "red")
618
+ if not ids and not names and not tags:
619
+ cprint("Must specify one of the ids, names or tags to identify DRS objects for deletion", "red")
607
620
  return errno.ENOENT
608
621
 
609
- asyncio.run(utils.drs_delete(names, tags))
622
+ resps = asyncio.run(utils.drs_delete(ids, names, tags, query_opts=f"?backend_content={backend_resource}"))
623
+ for r in resps:
624
+ print(r)
610
625
 
611
626
  return 0
612
627
 
@@ -54,12 +54,12 @@ class CopyResult(NamedTuple):
54
54
  }
55
55
 
56
56
  @staticmethod
57
- def access_method(access_methods_type, access_tier, dst, region, Authorization=None):
57
+ def access_method(access_methods_type, access_tier, dst, region):
58
58
  return {
59
59
  "type": access_methods_type,
60
60
  "access_url": {
61
61
  "url": dst,
62
- "headers": {"Authorization": Authorization}
62
+ "headers": {}
63
63
  },
64
64
  "access_tier": access_tier,
65
65
  "region": region
@@ -70,9 +70,11 @@ async def drs_crud(drs_id: str, method: str, **kwargs) -> dict:
70
70
  except KeyError:
71
71
  raise KeyError(f"No tokens, Please signin first!")
72
72
 
73
+ query_opts = kwargs.get("query_opts", None)
74
+ url = os.path.join(DRS_OBJECT_URL, drs_id, query_opts) if query_opts else os.path.join(DRS_OBJECT_URL, drs_id)
73
75
  async with RetryClient(client_session=ClientSession(raise_for_status=False),
74
76
  retry_options=RandomRetry(attempts=3)).request(
75
- method=method, url=os.path.join(DRS_OBJECT_URL, drs_id), proxy=kwargs.get("proxy", None),
77
+ method=method, url=url, proxy=kwargs.get("proxy", None),
76
78
  headers={"Authorization": f"Bearer {token}"},
77
79
  ) as response:
78
80
  resp = await response.content.read()
@@ -102,10 +104,10 @@ async def drs_existence(path: URL, label_check: bool = True) -> bool:
102
104
 
103
105
 
104
106
  @async_exception_handler
105
- async def drs_delete(names: List[str], labels: List[str], **kwargs):
107
+ async def drs_delete(ids: List[str], names: List[str], labels: List[str], **kwargs):
106
108
  search = [drs_search(names=names, labels=[]), drs_search(names=[], labels=labels)]
107
109
  resps = await asyncio.gather(*search, return_exceptions=False)
108
- drs_ids = [ob.get('id') for res in resps for ob in res.get('objects')]
110
+ drs_ids = list(set([ob.get('id') for res in resps for ob in res.get('objects')] + ids))
109
111
  if not drs_ids:
110
112
  cprint(f'No object to be delete')
111
113
  else: