haplohub-cli 0.0.1__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 (59) hide show
  1. haplohub_cli-0.0.1/.env.sample +3 -0
  2. haplohub_cli-0.0.1/.github/workflows/on_pr.yml +27 -0
  3. haplohub_cli-0.0.1/.github/workflows/on_push_main.yml +79 -0
  4. haplohub_cli-0.0.1/.gitignore +18 -0
  5. haplohub_cli-0.0.1/.pre-commit-config.yaml +19 -0
  6. haplohub_cli-0.0.1/PKG-INFO +61 -0
  7. haplohub_cli-0.0.1/README.md +45 -0
  8. haplohub_cli-0.0.1/haplohub_cli/__init__.py +3 -0
  9. haplohub_cli-0.0.1/haplohub_cli/_version.py +21 -0
  10. haplohub_cli-0.0.1/haplohub_cli/auth/__init__.py +0 -0
  11. haplohub_cli-0.0.1/haplohub_cli/auth/auth.py +42 -0
  12. haplohub_cli-0.0.1/haplohub_cli/auth/auth0_client.py +104 -0
  13. haplohub_cli-0.0.1/haplohub_cli/auth/auth_web_server.py +43 -0
  14. haplohub_cli-0.0.1/haplohub_cli/auth/tests/__init__.py +0 -0
  15. haplohub_cli-0.0.1/haplohub_cli/auth/tests/test_auth_web_server.py +22 -0
  16. haplohub_cli-0.0.1/haplohub_cli/auth/tests/test_token_storage.py +43 -0
  17. haplohub_cli-0.0.1/haplohub_cli/auth/token_storage.py +27 -0
  18. haplohub_cli-0.0.1/haplohub_cli/cli.py +35 -0
  19. haplohub_cli-0.0.1/haplohub_cli/commands/__init__.py +0 -0
  20. haplohub_cli-0.0.1/haplohub_cli/commands/cohort.py +33 -0
  21. haplohub_cli-0.0.1/haplohub_cli/commands/config.py +40 -0
  22. haplohub_cli-0.0.1/haplohub_cli/commands/file.py +84 -0
  23. haplohub_cli-0.0.1/haplohub_cli/commands/login.py +17 -0
  24. haplohub_cli-0.0.1/haplohub_cli/commands/model/__init__.py +0 -0
  25. haplohub_cli-0.0.1/haplohub_cli/commands/model/model.py +62 -0
  26. haplohub_cli-0.0.1/haplohub_cli/commands/model/run.py +63 -0
  27. haplohub_cli-0.0.1/haplohub_cli/commands/version.py +11 -0
  28. haplohub_cli-0.0.1/haplohub_cli/config/__init__.py +0 -0
  29. haplohub_cli-0.0.1/haplohub_cli/config/config.py +13 -0
  30. haplohub_cli-0.0.1/haplohub_cli/config/config_manager.py +57 -0
  31. haplohub_cli-0.0.1/haplohub_cli/config/environments.py +20 -0
  32. haplohub_cli-0.0.1/haplohub_cli/core/__init__.py +7 -0
  33. haplohub_cli-0.0.1/haplohub_cli/core/api/__init__.py +0 -0
  34. haplohub_cli-0.0.1/haplohub_cli/core/api/client.py +45 -0
  35. haplohub_cli-0.0.1/haplohub_cli/core/checksum.py +6 -0
  36. haplohub_cli-0.0.1/haplohub_cli/core/network.py +6 -0
  37. haplohub_cli-0.0.1/haplohub_cli/core/slug.py +7 -0
  38. haplohub_cli-0.0.1/haplohub_cli/core/tests/__init__.py +0 -0
  39. haplohub_cli-0.0.1/haplohub_cli/core/tests/test_network.py +20 -0
  40. haplohub_cli-0.0.1/haplohub_cli/core/tests/test_slug.py +20 -0
  41. haplohub_cli-0.0.1/haplohub_cli/formatters/__init__.py +6 -0
  42. haplohub_cli-0.0.1/haplohub_cli/formatters/cohort.py +39 -0
  43. haplohub_cli-0.0.1/haplohub_cli/formatters/config.py +15 -0
  44. haplohub_cli-0.0.1/haplohub_cli/formatters/decorators.py +9 -0
  45. haplohub_cli-0.0.1/haplohub_cli/formatters/file.py +46 -0
  46. haplohub_cli-0.0.1/haplohub_cli/formatters/formatter_registry.py +21 -0
  47. haplohub_cli-0.0.1/haplohub_cli/formatters/generic.py +11 -0
  48. haplohub_cli-0.0.1/haplohub_cli/formatters/model.py +31 -0
  49. haplohub_cli-0.0.1/haplohub_cli/formatters/utils.py +13 -0
  50. haplohub_cli-0.0.1/haplohub_cli/settings.py +24 -0
  51. haplohub_cli-0.0.1/haplohub_cli.egg-info/PKG-INFO +61 -0
  52. haplohub_cli-0.0.1/haplohub_cli.egg-info/SOURCES.txt +57 -0
  53. haplohub_cli-0.0.1/haplohub_cli.egg-info/dependency_links.txt +1 -0
  54. haplohub_cli-0.0.1/haplohub_cli.egg-info/entry_points.txt +2 -0
  55. haplohub_cli-0.0.1/haplohub_cli.egg-info/requires.txt +8 -0
  56. haplohub_cli-0.0.1/haplohub_cli.egg-info/top_level.txt +1 -0
  57. haplohub_cli-0.0.1/pyproject.toml +56 -0
  58. haplohub_cli-0.0.1/setup.cfg +4 -0
  59. haplohub_cli-0.0.1/uv.lock +1538 -0
@@ -0,0 +1,3 @@
1
+ AUTH0_DOMAIN='xxx-yyy.us.auth0.com'
2
+ AUTH0_CLIENT_ID='xxx'
3
+ AUTH0_AUDIENCE='https://xxx/api/'
@@ -0,0 +1,27 @@
1
+ name: On Pull Request
2
+
3
+ on:
4
+ pull_request:
5
+ branches:
6
+ - main
7
+
8
+ jobs:
9
+ lint:
10
+ runs-on: ubuntu-latest
11
+ strategy:
12
+ matrix:
13
+ python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"]
14
+
15
+ steps:
16
+ - uses: actions/checkout@v4
17
+ - uses: astral-sh/setup-uv@v5
18
+ with:
19
+ python-version: ${{ matrix.python-version }}
20
+ - name: Install dependencies
21
+ run: uv sync --dev
22
+ - name: Lint and format with ruff
23
+ run: |
24
+ ruff format --check .
25
+ ruff check .
26
+ - name: Run tests
27
+ run: uv run pytest -v
@@ -0,0 +1,79 @@
1
+ name: On Push to Main
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ tags: ["v[0-9]+.[0-9]+.[0-9]+*"]
7
+
8
+ permissions:
9
+ attestations: write
10
+ contents: write
11
+ id-token: write
12
+
13
+ jobs:
14
+ build:
15
+ name: Build python package
16
+ runs-on: ubuntu-latest
17
+ steps:
18
+ - uses: actions/checkout@v4
19
+ with:
20
+ fetch-depth: 0
21
+ - uses: hynek/build-and-inspect-python-package@v2
22
+ with:
23
+ attest-build-provenance-github: 'true'
24
+
25
+ publish-test-pypi:
26
+ name: Publish to Test PyPI
27
+ runs-on: ubuntu-latest
28
+ needs: build
29
+ environment: testpypi
30
+ steps:
31
+ - uses: actions/download-artifact@v4
32
+ with:
33
+ name: Packages
34
+ path: dist
35
+ - name: Publish to Test PyPI
36
+ uses: pypa/gh-action-pypi-publish@release/v1
37
+ with:
38
+ verbose: true
39
+ repository-url: https://test.pypi.org/legacy/
40
+
41
+ publish-pypi:
42
+ name: Publish to PyPI
43
+ runs-on: ubuntu-latest
44
+ if: startsWith(github.ref, 'refs/tags/v')
45
+ needs: build
46
+ environment: pypi
47
+ steps:
48
+ - uses: actions/download-artifact@v4
49
+ with:
50
+ name: Packages
51
+ path: dist
52
+ - name: Publish to Test PyPI
53
+ uses: pypa/gh-action-pypi-publish@release/v1
54
+ with:
55
+ verbose: true
56
+
57
+ github-release:
58
+ name: Create GitHub Release
59
+ runs-on: ubuntu-latest
60
+ needs: publish-pypi
61
+ steps:
62
+ - uses: actions/download-artifact@v4
63
+ with:
64
+ name: Packages
65
+ path: dist
66
+ - name: Sign the dists with Sigstore
67
+ uses: sigstore/gh-action-sigstore-python@v3.0.0
68
+ with:
69
+ inputs: >-
70
+ ./dist/*.tar.gz
71
+ ./dist/*.whl
72
+ - name: Create GitHub Release
73
+ uses: actions/create-release@v1
74
+ env:
75
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
76
+ with:
77
+ tag_name: ${{ github.ref }}
78
+ release_name: Release ${{ github.ref }}
79
+ body: Release ${{ github.ref }}
@@ -0,0 +1,18 @@
1
+ # Environment variables
2
+ .env
3
+
4
+ # Virtual environment
5
+ .venv/
6
+
7
+ # Python caches, tools caches
8
+ __pycache__/
9
+ .ruff_cache/
10
+ .pytest_cache/
11
+
12
+ # Distribution files
13
+ dist/
14
+ *.egg-info/
15
+ haplohub_cli/_version.py
16
+
17
+ # Mac OS
18
+ .DS_Store
@@ -0,0 +1,19 @@
1
+ repos:
2
+ - repo: https://github.com/astral-sh/ruff-pre-commit
3
+ rev: v0.9.6
4
+ hooks:
5
+ - id: ruff
6
+ args: ["--fix"]
7
+ always_run: true
8
+ - id: ruff-format
9
+ always_run: true
10
+ - repo: local
11
+ hooks:
12
+ - id: tests
13
+ stages: [push]
14
+ name: Run tests
15
+ entry: uv run pytest -v
16
+ language: system
17
+ verbose: true
18
+ pass_filenames: false
19
+ always_run: true
@@ -0,0 +1,61 @@
1
+ Metadata-Version: 2.4
2
+ Name: haplohub-cli
3
+ Version: 0.0.1
4
+ Summary: HaploHub Command Line Interface
5
+ Author-email: Mike Polcari <mike@haplotype-labs.com>, Ilya Khrustalev <ilya@haplotype-labs.com>
6
+ Requires-Python: >=3.8
7
+ Description-Content-Type: text/markdown
8
+ Requires-Dist: auth0-python>=4.8.0
9
+ Requires-Dist: click>=8.1.8
10
+ Requires-Dist: haplohub>=1.0.4
11
+ Requires-Dist: pendulum>=3.0.0
12
+ Requires-Dist: python-dotenv>=1.0.1
13
+ Requires-Dist: requests>=2.32.0
14
+ Requires-Dist: rich>=13.9.4
15
+ Requires-Dist: haplohub
16
+
17
+ # HaploHub CLI
18
+
19
+ HaploHub is a platform for haplotype data storage and analysis. This CLI provides a way to interact with the HaploHub API.
20
+
21
+ ## Installation
22
+
23
+ To install the CLI, run the following command:
24
+
25
+ ```bash
26
+ python -m venv .venv
27
+ source .venv/bin/activate
28
+ pip install --upgrade pip
29
+ pip install haplohub-cli
30
+ ```
31
+
32
+ You can ensure that the CLI is installed correctly by running the following command:
33
+
34
+ ```bash
35
+ haplohub version
36
+
37
+ # HaploHub CLI version 0.1.0
38
+ ```
39
+
40
+ ## Usage
41
+
42
+ ```bash
43
+ haplohub --help
44
+ ```
45
+
46
+ ### Login
47
+
48
+ The first time you run the CLI, you will be prompted to login.
49
+
50
+ ```bash
51
+ haplohub login
52
+ ```
53
+
54
+ This will open a browser window to the HaploHub login page. Once you login, you will be redirected to the CLI.
55
+ ```bash
56
+ Your browser has been opened to authenticate with HaploHub.
57
+
58
+ https://xxx.us.auth0.com/authorize...
59
+
60
+ Successfully authenticated with HaploHub.
61
+ ```
@@ -0,0 +1,45 @@
1
+ # HaploHub CLI
2
+
3
+ HaploHub is a platform for haplotype data storage and analysis. This CLI provides a way to interact with the HaploHub API.
4
+
5
+ ## Installation
6
+
7
+ To install the CLI, run the following command:
8
+
9
+ ```bash
10
+ python -m venv .venv
11
+ source .venv/bin/activate
12
+ pip install --upgrade pip
13
+ pip install haplohub-cli
14
+ ```
15
+
16
+ You can ensure that the CLI is installed correctly by running the following command:
17
+
18
+ ```bash
19
+ haplohub version
20
+
21
+ # HaploHub CLI version 0.1.0
22
+ ```
23
+
24
+ ## Usage
25
+
26
+ ```bash
27
+ haplohub --help
28
+ ```
29
+
30
+ ### Login
31
+
32
+ The first time you run the CLI, you will be prompted to login.
33
+
34
+ ```bash
35
+ haplohub login
36
+ ```
37
+
38
+ This will open a browser window to the HaploHub login page. Once you login, you will be redirected to the CLI.
39
+ ```bash
40
+ Your browser has been opened to authenticate with HaploHub.
41
+
42
+ https://xxx.us.auth0.com/authorize...
43
+
44
+ Successfully authenticated with HaploHub.
45
+ ```
@@ -0,0 +1,3 @@
1
+ from ._version import __version__
2
+
3
+ __all__ = ["__version__"]
@@ -0,0 +1,21 @@
1
+ # file generated by setuptools-scm
2
+ # don't change, don't track in version control
3
+
4
+ __all__ = ["__version__", "__version_tuple__", "version", "version_tuple"]
5
+
6
+ TYPE_CHECKING = False
7
+ if TYPE_CHECKING:
8
+ from typing import Tuple
9
+ from typing import Union
10
+
11
+ VERSION_TUPLE = Tuple[Union[int, str], ...]
12
+ else:
13
+ VERSION_TUPLE = object
14
+
15
+ version: str
16
+ __version__: str
17
+ __version_tuple__: VERSION_TUPLE
18
+ version_tuple: VERSION_TUPLE
19
+
20
+ __version__ = version = '0.0.1'
21
+ __version_tuple__ = version_tuple = (0, 0, 1)
File without changes
@@ -0,0 +1,42 @@
1
+ import webbrowser
2
+
3
+ import click
4
+
5
+ from haplohub_cli.auth.auth0_client import auth0_client
6
+ from haplohub_cli.auth.auth_web_server import AuthWebServer
7
+ from haplohub_cli.config.config_manager import config_manager
8
+ from haplohub_cli.core import ensure_config_dir
9
+ from haplohub_cli.core.network import check_port_available
10
+
11
+
12
+ def token_login(refresh_token: str):
13
+ credentials = auth0_client.exchange_refresh_token(refresh_token)
14
+
15
+ click.echo("Successfully authenticated with HaploHub.")
16
+ auth0_client.token_storage.store_credentials(credentials)
17
+
18
+
19
+ def interactive_login():
20
+ ensure_config_dir()
21
+
22
+ if not check_port_available(config_manager.config.redirect_port):
23
+ click.echo(
24
+ f"Port {config_manager.config.redirect_port} is already in use. Please ensure it is free and try again.\n"
25
+ f"Use `lsof -i4TCP:{config_manager.config.redirect_port} -sTCP:LISTEN -P -n` to find the process using the port."
26
+ )
27
+ exit(1)
28
+
29
+ auth_request = auth0_client.init_auth_request()
30
+ auth_url = auth_request.auth_url
31
+
32
+ click.echo(
33
+ f"Your browser has been opened to authenticate with HaploHub.\n\n {auth_url[0 : auth_url.find('?')] + '...'}\n"
34
+ )
35
+ webbrowser.open(auth_url)
36
+
37
+ auth_web_server = AuthWebServer(config_manager.config.redirect_port)
38
+ auth_code = auth_web_server.handle_request()
39
+ credentials = auth_request.exchange_code(auth_code)
40
+
41
+ click.echo("Successfully authenticated with HaploHub.")
42
+ auth0_client.token_storage.store_credentials(credentials)
@@ -0,0 +1,104 @@
1
+ import base64
2
+ import hashlib
3
+ import os
4
+
5
+ from requests import Session
6
+
7
+ from haplohub_cli.auth.token_storage import TokenStorage, token_storage
8
+ from haplohub_cli.config.config_manager import config_manager
9
+
10
+
11
+ class AuthRequest:
12
+ def __init__(
13
+ self,
14
+ client: "Auth0Client",
15
+ scopes: list[str],
16
+ ):
17
+ self.client = client
18
+ self.scopes = scopes
19
+ self.code_verifier, self.code_challenge = self.generate_code_verifier()
20
+
21
+ @property
22
+ def auth_url(self):
23
+ return (
24
+ f"https://{self.client.domain}/authorize"
25
+ f"?client_id={self.client.client_id}"
26
+ f"&response_type=code"
27
+ f"&redirect_uri={self.client.redirect_uri}"
28
+ f"&scope={' '.join(self.scopes)}"
29
+ f"&code_challenge={self.code_challenge}"
30
+ f"&code_challenge_method=S256"
31
+ f"&audience={self.client.audience}"
32
+ )
33
+
34
+ def generate_code_verifier(self):
35
+ verifier = base64.urlsafe_b64encode(os.urandom(32)).decode("utf-8").rstrip("=")
36
+ challenge = hashlib.sha256(verifier.encode("utf-8")).digest()
37
+ challenge = base64.urlsafe_b64encode(challenge).decode("utf-8").rstrip("=")
38
+ return verifier, challenge
39
+
40
+ def exchange_code(self, code: str):
41
+ return self.client.exchange_code(code, self.code_verifier)
42
+
43
+
44
+ class Auth0Client:
45
+ http = Session()
46
+
47
+ def __init__(self, token_storage: TokenStorage, domain: str, client_id: str, audience: str, redirect_uri: str):
48
+ self.token_storage = token_storage
49
+ self.domain = domain
50
+ self.client_id = client_id
51
+ self.audience = audience
52
+ self.redirect_uri = redirect_uri
53
+
54
+ def init_auth_request(self, scopes: list[str] = ("openid", "profile", "email")):
55
+ return AuthRequest(client=self, scopes=scopes)
56
+
57
+ def exchange_refresh_token(self, refresh_token: str):
58
+ return self._make_request(
59
+ "oauth/token",
60
+ "POST",
61
+ json={
62
+ "grant_type": "refresh_token",
63
+ "client_id": self.client_id,
64
+ "refresh_token": refresh_token,
65
+ "audience": self.audience,
66
+ },
67
+ )
68
+
69
+ def exchange_code(self, code: str, code_verifier: str):
70
+ return self._make_request(
71
+ "oauth/token",
72
+ "POST",
73
+ json={
74
+ "grant_type": "authorization_code",
75
+ "client_id": self.client_id,
76
+ "code": code,
77
+ "redirect_uri": self.redirect_uri,
78
+ "code_verifier": code_verifier,
79
+ "audience": self.audience,
80
+ },
81
+ )
82
+
83
+ def get_user_info(self):
84
+ return self._make_request("userinfo", "GET")
85
+
86
+ def _make_request(self, path: str, method: str, data: dict = None, json: dict = None):
87
+ url = f"https://{self.domain}/{path}"
88
+
89
+ headers = None
90
+ if self.token_storage.credentials_exist:
91
+ headers = {"Authorization": f"Bearer {self.token_storage.get_access_token()}"}
92
+
93
+ response = self.http.request(method, url, headers=headers, data=data, json=json)
94
+ response.raise_for_status()
95
+ return response.json()
96
+
97
+
98
+ auth0_client = Auth0Client(
99
+ token_storage=token_storage,
100
+ domain=config_manager.config.auth0_domain,
101
+ client_id=config_manager.config.auth0_client_id,
102
+ audience=config_manager.config.auth0_audience,
103
+ redirect_uri=config_manager.config.auth0_redirect_uri,
104
+ )
@@ -0,0 +1,43 @@
1
+ from http.server import BaseHTTPRequestHandler, HTTPServer
2
+ from typing import Any
3
+ from urllib.parse import parse_qs, urlparse
4
+
5
+ HTML_SNIPPET = """
6
+ <html>
7
+ <body>
8
+ <h1>Authentication successful!</h1>
9
+ <p>
10
+ You can now close this window.
11
+ </p>
12
+ </body>
13
+ </html>
14
+ """
15
+
16
+
17
+ class AuthHandler(BaseHTTPRequestHandler):
18
+ def log_message(self, format: str, *args: Any) -> None:
19
+ # Suppress logging
20
+ pass
21
+
22
+ def do_GET(self):
23
+ query = urlparse(self.path).query
24
+ params = parse_qs(query)
25
+ if "code" in params:
26
+ self.server.last_auth_code = params["code"][0]
27
+ self.send_response(200)
28
+ self.send_header("Content-Type", "text/html")
29
+ self.end_headers()
30
+ self.wfile.write(HTML_SNIPPET.encode("utf-8"))
31
+
32
+
33
+ class AuthWebServer:
34
+ def __init__(self, port: int):
35
+ self.port = port
36
+ self.server = HTTPServer(
37
+ ("localhost", self.port),
38
+ AuthHandler,
39
+ )
40
+
41
+ def handle_request(self):
42
+ self.server.handle_request()
43
+ return self.server.last_auth_code
File without changes
@@ -0,0 +1,22 @@
1
+ from threading import Timer
2
+ from unittest import TestCase
3
+
4
+ import requests
5
+
6
+ from haplohub_cli.auth.auth_web_server import AuthWebServer
7
+
8
+
9
+ class AuthWebServerTestCase(TestCase):
10
+ @classmethod
11
+ def setUpClass(cls):
12
+ cls.port = 60000
13
+ cls.auth_code = "qwerty123456"
14
+ cls.instance = AuthWebServer(cls.port)
15
+
16
+ def test_auth_web_server_should_return_auth_code_from_redirect_uri(self):
17
+ Timer(0.01, self._send_request).start()
18
+ auth_code = self.instance.handle_request()
19
+ self.assertEqual(auth_code, self.auth_code)
20
+
21
+ def _send_request(self):
22
+ requests.get(f"http://localhost:{self.port}/?code={self.auth_code}")
@@ -0,0 +1,43 @@
1
+ import json
2
+
3
+ from pyfakefs.fake_filesystem_unittest import TestCase
4
+
5
+ from haplohub_cli.auth.token_storage import TokenStorage
6
+
7
+
8
+ class TokenStorageTestCase(TestCase):
9
+ @classmethod
10
+ def setUpClass(cls):
11
+ cls.setUpClassPyfakefs()
12
+ cls.instance = TokenStorage("/tmp/test_token_storage.json")
13
+
14
+ def test_credentials_exist_should_return_false_when_file_does_not_exist(self):
15
+ self.assertFalse(self.instance.credentials_exist)
16
+
17
+ def test_credentials_exist_should_return_true_when_file_exists(self):
18
+ with open(self.instance.token_file, "w"):
19
+ pass
20
+
21
+ self.assertTrue(self.instance.credentials_exist)
22
+
23
+ def test_store_credentials_should_save_credentials_to_file(self):
24
+ creds = {"test": True}
25
+
26
+ self.instance.store_credentials(creds)
27
+
28
+ with open(self.instance.token_file, "r") as f:
29
+ self.assertEqual(json.load(f), creds)
30
+
31
+ def test_get_credentials_should_return_credentials_from_file(self):
32
+ creds = {"test": True}
33
+
34
+ self.instance.store_credentials(creds)
35
+
36
+ self.assertEqual(self.instance.get_credentials(), creds)
37
+
38
+ def test_get_access_token_should_return_access_token_from_credentials(self):
39
+ creds = {"access_token": "123456"}
40
+
41
+ self.instance.store_credentials(creds)
42
+
43
+ self.assertEqual(self.instance.get_access_token(), "123456")
@@ -0,0 +1,27 @@
1
+ import json
2
+ from genericpath import exists
3
+
4
+ from haplohub_cli import settings
5
+
6
+
7
+ class TokenStorage:
8
+ def __init__(self, token_file: str):
9
+ self.token_file = token_file
10
+
11
+ @property
12
+ def credentials_exist(self):
13
+ return exists(self.token_file)
14
+
15
+ def store_credentials(self, credentials: dict):
16
+ with open(self.token_file, "w") as f:
17
+ json.dump(credentials, f)
18
+
19
+ def get_credentials(self):
20
+ with open(self.token_file, "r") as f:
21
+ return json.load(f)
22
+
23
+ def get_access_token(self):
24
+ return self.get_credentials()["access_token"]
25
+
26
+
27
+ token_storage = TokenStorage(settings.CREDENTIALS_FILE)
@@ -0,0 +1,35 @@
1
+ import click
2
+
3
+ from haplohub_cli.commands import cohort, config, file, login, version
4
+ from haplohub_cli.commands.model import model
5
+ from haplohub_cli.formatters.formatter_registry import formatter_registry
6
+
7
+
8
+ @click.group()
9
+ def cli():
10
+ """
11
+ HaploHub CLI
12
+
13
+ To get started, take a look at the documentation:
14
+ https://github.com/haplotypelabs/haplohub-cli
15
+ """
16
+ pass
17
+
18
+
19
+ @cli.result_callback()
20
+ def formatter_callback(result):
21
+ if result is None or not formatter_registry.has_formatter(type(result)):
22
+ return
23
+
24
+ formatter_registry.format(result)
25
+
26
+
27
+ cli.add_command(config.config)
28
+ cli.add_command(login.cmd)
29
+ cli.add_command(version.cmd)
30
+ cli.add_command(cohort.cohort)
31
+ cli.add_command(file.file)
32
+ cli.add_command(model.model)
33
+
34
+ if __name__ == "__main__":
35
+ cli()
File without changes
@@ -0,0 +1,33 @@
1
+ import click
2
+ from haplohub import CreateCohortRequest
3
+
4
+ from haplohub_cli.core.api.client import client
5
+
6
+
7
+ @click.group()
8
+ def cohort():
9
+ """
10
+ Manage cohorts
11
+ """
12
+ pass
13
+
14
+
15
+ @cohort.command()
16
+ def list():
17
+ return client.cohort.list_cohorts()
18
+
19
+
20
+ @cohort.command()
21
+ @click.argument("name")
22
+ @click.option("--description", type=str, required=False)
23
+ def create(name, description=None):
24
+ description = description or ""
25
+
26
+ request = CreateCohortRequest(name=name, description=description)
27
+ return client.cohort.create_cohort(request)
28
+
29
+
30
+ @cohort.command()
31
+ @click.argument("id")
32
+ def delete(id):
33
+ return client.cohort.delete_cohort(id)
@@ -0,0 +1,40 @@
1
+ import click
2
+
3
+ from haplohub_cli.config.config_manager import config_manager
4
+ from haplohub_cli.config.environments import ENVIRONMENTS
5
+
6
+
7
+ @click.group()
8
+ def config():
9
+ """
10
+ Manage configuration
11
+ """
12
+ pass
13
+
14
+
15
+ @config.command()
16
+ def show():
17
+ return config_manager.config
18
+
19
+
20
+ @config.command()
21
+ @click.argument("key")
22
+ @click.argument("value")
23
+ def set(key, value):
24
+ setattr(config_manager.config, key, value)
25
+ config_manager.save()
26
+ return config_manager.config
27
+
28
+
29
+ @config.command()
30
+ @click.argument("environment", type=click.Choice(ENVIRONMENTS.keys()))
31
+ def switch(environment):
32
+ config_manager.switch_environment(environment)
33
+ return config_manager.config
34
+
35
+
36
+ @config.command()
37
+ def reset():
38
+ config_manager.reset()
39
+ config_manager.save()
40
+ return config_manager.config