aiida-hyperqueue 0.1.0__tar.gz → 0.2.0__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 (52) hide show
  1. aiida_hyperqueue-0.2.0/.github/workflows/cd.yml +52 -0
  2. aiida_hyperqueue-0.2.0/.github/workflows/ci.yml +30 -0
  3. aiida_hyperqueue-0.2.0/.github/workflows/validate_release_tag.py +45 -0
  4. aiida_hyperqueue-0.2.0/.pre-commit-config.yaml +17 -0
  5. aiida_hyperqueue-0.2.0/.readthedocs.yml +26 -0
  6. aiida_hyperqueue-0.2.0/CHANGELOG.md +21 -0
  7. {aiida-hyperqueue-0.1.0 → aiida_hyperqueue-0.2.0}/LICENSE +1 -1
  8. aiida_hyperqueue-0.2.0/PKG-INFO +64 -0
  9. aiida_hyperqueue-0.2.0/README.md +31 -0
  10. {aiida-hyperqueue-0.1.0 → aiida_hyperqueue-0.2.0}/aiida_hyperqueue/__init__.py +1 -1
  11. aiida_hyperqueue-0.2.0/aiida_hyperqueue/cli/__init__.py +5 -0
  12. aiida_hyperqueue-0.2.0/aiida_hyperqueue/cli/alloc.py +99 -0
  13. aiida_hyperqueue-0.2.0/aiida_hyperqueue/cli/install.py +120 -0
  14. aiida_hyperqueue-0.2.0/aiida_hyperqueue/cli/params/__init__.py +0 -0
  15. aiida_hyperqueue-0.2.0/aiida_hyperqueue/cli/params/arguments.py +4 -0
  16. aiida_hyperqueue-0.2.0/aiida_hyperqueue/cli/params/options.py +33 -0
  17. aiida_hyperqueue-0.2.0/aiida_hyperqueue/cli/root.py +37 -0
  18. aiida_hyperqueue-0.2.0/aiida_hyperqueue/cli/server.py +121 -0
  19. aiida_hyperqueue-0.2.0/aiida_hyperqueue/scheduler.py +312 -0
  20. {aiida-hyperqueue-0.1.0 → aiida_hyperqueue-0.2.0}/docs/source/conf.py +41 -37
  21. {aiida-hyperqueue-0.1.0 → aiida_hyperqueue-0.2.0}/docs/source/get_started.md +25 -27
  22. {aiida-hyperqueue-0.1.0 → aiida_hyperqueue-0.2.0}/docs/source/index.md +1 -1
  23. {aiida-hyperqueue-0.1.0 → aiida_hyperqueue-0.2.0}/pyproject.toml +12 -27
  24. aiida_hyperqueue-0.2.0/tests/README.md +5 -0
  25. {aiida-hyperqueue-0.1.0 → aiida_hyperqueue-0.2.0}/tests/__init__.py +2 -1
  26. aiida_hyperqueue-0.2.0/tests/conftest.py +387 -0
  27. aiida_hyperqueue-0.2.0/tests/target/hq +0 -0
  28. aiida_hyperqueue-0.2.0/tests/test_cli_alloc.py +16 -0
  29. aiida_hyperqueue-0.2.0/tests/test_cli_install.py +30 -0
  30. aiida_hyperqueue-0.2.0/tests/test_cli_server.py +152 -0
  31. aiida_hyperqueue-0.2.0/tests/test_scheduler.py +215 -0
  32. aiida_hyperqueue-0.2.0/tests/utils/__init__.py +11 -0
  33. aiida_hyperqueue-0.2.0/tests/utils/cmd.py +16 -0
  34. aiida_hyperqueue-0.2.0/tests/utils/io.py +28 -0
  35. aiida_hyperqueue-0.2.0/tests/utils/job.py +24 -0
  36. aiida_hyperqueue-0.2.0/tests/utils/mock.py +43 -0
  37. aiida_hyperqueue-0.2.0/tests/utils/table.py +151 -0
  38. aiida_hyperqueue-0.2.0/tests/utils/wait.py +85 -0
  39. aiida-hyperqueue-0.1.0/.github/workflows/ci.yml +0 -86
  40. aiida-hyperqueue-0.1.0/.pre-commit-config.yaml +0 -33
  41. aiida-hyperqueue-0.1.0/.readthedocs.yml +0 -9
  42. aiida-hyperqueue-0.1.0/PKG-INFO +0 -48
  43. aiida-hyperqueue-0.1.0/README.md +0 -15
  44. aiida-hyperqueue-0.1.0/aiida_hyperqueue/cli.py +0 -149
  45. aiida-hyperqueue-0.1.0/aiida_hyperqueue/scheduler.py +0 -289
  46. aiida-hyperqueue-0.1.0/tests/conftest.py +0 -11
  47. aiida-hyperqueue-0.1.0/tests/test_scheduler.py +0 -18
  48. {aiida-hyperqueue-0.1.0 → aiida_hyperqueue-0.2.0}/.gitignore +0 -0
  49. {aiida-hyperqueue-0.1.0 → aiida_hyperqueue-0.2.0}/docs/.gitignore +0 -0
  50. {aiida-hyperqueue-0.1.0 → aiida_hyperqueue-0.2.0}/docs/Makefile +0 -0
  51. {aiida-hyperqueue-0.1.0 → aiida_hyperqueue-0.2.0}/docs/source/developer_guide/index.md +0 -0
  52. {aiida-hyperqueue-0.1.0 → aiida_hyperqueue-0.2.0}/docs/source/img/AiiDA_transparent_logo.png +0 -0
@@ -0,0 +1,52 @@
1
+ name: cd
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - 'v[0-9]+.[0-9]+.[0-9]+*'
7
+
8
+ jobs:
9
+
10
+ validate-release-tag:
11
+
12
+ if: github.repository == 'aiidateam/aiida-hyperqueue'
13
+ runs-on: ubuntu-latest
14
+
15
+ steps:
16
+ - name: Checkout source
17
+ uses: actions/checkout@v3
18
+
19
+ - name: Set up Python 3.10
20
+ uses: actions/setup-python@v4
21
+ with:
22
+ python-version: '3.10'
23
+
24
+ - name: Validate the tag version against the package version
25
+ run: python .github/workflows/validate_release_tag.py $GITHUB_REF
26
+
27
+ publish:
28
+
29
+ name: Publish to PyPI
30
+ needs: [validate-release-tag]
31
+ runs-on: ubuntu-latest
32
+ environment: deployment
33
+ permissions:
34
+ id-token: write
35
+
36
+ steps:
37
+ - name: Checkout source
38
+ uses: actions/checkout@v3
39
+
40
+ - name: Set up Python 3.10
41
+ uses: actions/setup-python@v4
42
+ with:
43
+ python-version: '3.10'
44
+
45
+ - name: Install flit
46
+ run: pip install flit~=3.8
47
+
48
+ - name: Build with flit
49
+ run: flit build
50
+
51
+ - name: Publish to PyPI using Trusted Publishing
52
+ uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,30 @@
1
+ name: ci
2
+
3
+ on: [push, pull_request]
4
+
5
+ jobs:
6
+
7
+ tests:
8
+ runs-on: ubuntu-latest
9
+ timeout-minutes: 30
10
+ strategy:
11
+ matrix:
12
+ python-version: ["3.10"]
13
+
14
+ steps:
15
+ - uses: actions/checkout@v3
16
+
17
+ - name: Set up Python ${{ matrix.python-version }}
18
+ uses: actions/setup-python@v4
19
+ with:
20
+ python-version: ${{ matrix.python-version }}
21
+
22
+ - name: Install python dependencies
23
+ run: |
24
+ pip install --upgrade pip
25
+ pip install .[tests]
26
+
27
+ - name: Run test suite
28
+ run: |
29
+ chmod og-rw ~
30
+ pytest --cov aiida_hyperqueue --cov-append .
@@ -0,0 +1,45 @@
1
+ # -*- coding: utf-8 -*-
2
+ """Validate that the version in the tag label matches the version of the package."""
3
+
4
+ import argparse
5
+ import ast
6
+ from pathlib import Path
7
+
8
+
9
+ def get_version_from_module(content: str) -> str:
10
+ """Get the ``__version__`` attribute from a module.
11
+
12
+ .. note:: This has been adapted from :mod:`setuptools.config`.
13
+ """
14
+ try:
15
+ module = ast.parse(content)
16
+ except SyntaxError as exception:
17
+ raise OSError("Unable to parse module.") from exception
18
+
19
+ try:
20
+ return next(
21
+ ast.literal_eval(statement.value)
22
+ for statement in module.body
23
+ if isinstance(statement, ast.Assign)
24
+ for target in statement.targets
25
+ if isinstance(target, ast.Name) and target.id == "__version__"
26
+ )
27
+ except StopIteration as exception:
28
+ raise OSError(
29
+ "Unable to find the `__version__` attribute in the module."
30
+ ) from exception
31
+
32
+
33
+ if __name__ == "__main__":
34
+ parser = argparse.ArgumentParser()
35
+ parser.add_argument("GITHUB_REF", help="The GITHUB_REF environmental variable")
36
+ args = parser.parse_args()
37
+ assert args.GITHUB_REF.startswith(
38
+ "refs/tags/v"
39
+ ), f'GITHUB_REF should start with "refs/tags/v": {args.GITHUB_REF}'
40
+ tag_version = args.GITHUB_REF[11:]
41
+ package_version = get_version_from_module(
42
+ Path("aiida_hyperqueue/__init__.py").read_text(encoding="utf-8")
43
+ )
44
+ error_message = f"The tag version `{tag_version}` is different from the package version `{package_version}`"
45
+ assert tag_version == package_version, error_message
@@ -0,0 +1,17 @@
1
+ # Install pre-commit hooks via:
2
+ # pre-commit install
3
+ repos:
4
+ - repo: https://github.com/pre-commit/pre-commit-hooks
5
+ rev: v4.6.0
6
+ hooks:
7
+ - id: end-of-file-fixer
8
+ - id: fix-encoding-pragma
9
+ - id: mixed-line-ending
10
+ - id: trailing-whitespace
11
+ - id: check-json
12
+
13
+ - repo: https://github.com/astral-sh/ruff-pre-commit
14
+ rev: v0.6.5
15
+ hooks:
16
+ - id: ruff-format
17
+ - id: ruff
@@ -0,0 +1,26 @@
1
+ version: 2
2
+
3
+ # YAML adapted from aiida-core .readthedocs.yml
4
+
5
+ # Disable all unneeded formats
6
+ formats: []
7
+
8
+ build:
9
+ os: ubuntu-22.04
10
+ tools:
11
+ python: '3.11'
12
+ jobs:
13
+ # Use uv to speed up the build
14
+ # https://docs.readthedocs.io/en/stable/build-customization.html#install-dependencies-with-uv
15
+ post_create_environment:
16
+ - asdf plugin add uv
17
+ - asdf install uv 0.2.9
18
+ - asdf global uv 0.2.9
19
+ post_install:
20
+ - VIRTUAL_ENV=$READTHEDOCS_VIRTUALENV_PATH uv pip install .[docs]
21
+
22
+ # Let the build fail if there are any warnings
23
+ sphinx:
24
+ builder: html
25
+ configuration: docs/source/conf.py
26
+ fail_on_warning: true
@@ -0,0 +1,21 @@
1
+ ## v0.2.0
2
+
3
+ - [#18](https://github.com/aiidateam/aiida-hyperqueue/pull/18) A large refactoring with following changes:
4
+
5
+ - correctly support memory setup for resources.
6
+ - support turn on hyperthreading with latest version of hyperqueue.
7
+ - Support install hq to remote computer over CLI.
8
+ - adding unit tests with submit to real hq using the fixture from hyperqueue repo.
9
+ - Fix the submit bug for hq > 0.12 that resources are configured twice in job script and submit command.
10
+
11
+ - [#26](https://github.com/aiidateam/aiida-hyperqueue/pull/26) Change alloc add worker name (name appear in slurm queue) `aiida` -> `ahq`
12
+ - [#24](https://github.com/aiidateam/aiida-hyperqueue/pull/24) Use JSON format as output for hq job list and hq submit
13
+
14
+
15
+ ## v0.1.1
16
+
17
+ Only a small fix to the `README.md` was added here, this release is mainly to test the automated deployment to PyPI.
18
+
19
+ ## v0.1.0
20
+
21
+ First release on PyPI, tested with HyperQueue v0.15.0.
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2021 The AiiDA Team.
3
+ Copyright (c) 2023 The AiiDA Team.
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
@@ -0,0 +1,64 @@
1
+ Metadata-Version: 2.4
2
+ Name: aiida-hyperqueue
3
+ Version: 0.2.0
4
+ Summary: AiiDA plugin for the HyperQueue metascheduler
5
+ Author: Marnik Bercx, Jusong Yu
6
+ Requires-Python: >=3.9
7
+ Description-Content-Type: text/markdown
8
+ Classifier: Framework :: AiiDA
9
+ Classifier: Development Status :: 3 - Alpha
10
+ Classifier: License :: OSI Approved :: MIT License
11
+ Classifier: Operating System :: POSIX :: Linux
12
+ Classifier: Operating System :: MacOS :: MacOS X
13
+ Classifier: Natural Language :: English
14
+ Classifier: Programming Language :: Python
15
+ License-File: LICENSE
16
+ Requires-Dist: aiida-core~=2.0
17
+ Requires-Dist: sphinx ; extra == "docs"
18
+ Requires-Dist: myst-parser ; extra == "docs"
19
+ Requires-Dist: sphinx-design ; extra == "docs"
20
+ Requires-Dist: sphinx-book-theme ; extra == "docs"
21
+ Requires-Dist: sphinxcontrib-details-directive~=0.1.0 ; extra == "docs"
22
+ Requires-Dist: pre-commit~=3.5 ; extra == "pre-commit"
23
+ Requires-Dist: mypy~=1.10.0 ; extra == "pre-commit"
24
+ Requires-Dist: pgtest~=1.3.1 ; extra == "tests"
25
+ Requires-Dist: coverage~=7.0 ; extra == "tests"
26
+ Requires-Dist: pytest~=7.0 ; extra == "tests"
27
+ Requires-Dist: pytest-cov~=4.1 ; extra == "tests"
28
+ Project-URL: Source, https://github.com/aiidateam/aiida-hyperqueue
29
+ Provides-Extra: docs
30
+ Provides-Extra: pre-commit
31
+ Provides-Extra: tests
32
+
33
+ [![Build Status](https://github.com/aiidateam/aiida-hyperqueue/workflows/ci/badge.svg)](https://github.com/aiidateam/aiida-hyperqueue/actions)
34
+ [![Docs status](https://readthedocs.org/projects/aiida-hyperqueue/badge)](http://aiida-hyperqueue.readthedocs.io/)
35
+ [![PyPI version](https://badge.fury.io/py/aiida-hyperqueue.svg)](https://badge.fury.io/py/aiida-hyperqueue)
36
+
37
+ # AiiDA HyperQueue plugin
38
+
39
+ AiiDA plugin for the [HyperQueue](https://it4innovations.github.io/hyperqueue/stable/) metascheduler.
40
+
41
+ | ❗️ This package is still in the early stages of development and we will most likely break the API regularly in new 0.X versions. Be sure to pin the version when installing this package in scripts.|
42
+ |---|
43
+
44
+ ## Features
45
+
46
+ Allows task farming on Slurm machines through the submission of AiiDA calculations to the [HyperQueue](https://github.com/It4innovations/hyperqueue) metascheduler.
47
+ See the [Documentation](http://aiida-hyperqueue.readthedocs.io/) for more information on how to install and use the plugin.
48
+
49
+ ## For developers
50
+
51
+ To control the loglevel of command, since we use the `echo` module from aiida, the CLI loglever can be set through `logging.verdi_loglevel`.
52
+
53
+ ## Acknowledgenement
54
+ If you use this plugin for your research, please cite the following work:
55
+
56
+ #### HyperQueue
57
+
58
+ * J. Beránek *et al.*, *HyperQueue: Efficient and ergonomic task graphs on HPC clusters*, SoftwareX **27**, 101814 (2024); DOI: [10.1016/j.softx.2024.101814](https://doi.org/10.1016/j.softx.2024.101814)
59
+
60
+ #### AiiDA
61
+
62
+ * S. P. Huber *et al.*, *AiiDA 1.0, a scalable computational infrastructure for automated reproducible workflows and data provenance*, Scientific Data **7**, 300 (2020); DOI: [10.1038/s41597-020-00638-4](https://doi.org/10.1038/s41597-020-00638-4)
63
+ * M. Uhrin *et al.*, *Workflows in AiiDA: Engineering a high-throughput, event-based engine for robust and modular computational workflows*, Computational Materials Science **187**, 110086 (2021); DOI: [10.1016/j.commatsci.2020.110086](https://doi.org/10.1016/j.commatsci.2020.110086)
64
+
@@ -0,0 +1,31 @@
1
+ [![Build Status](https://github.com/aiidateam/aiida-hyperqueue/workflows/ci/badge.svg)](https://github.com/aiidateam/aiida-hyperqueue/actions)
2
+ [![Docs status](https://readthedocs.org/projects/aiida-hyperqueue/badge)](http://aiida-hyperqueue.readthedocs.io/)
3
+ [![PyPI version](https://badge.fury.io/py/aiida-hyperqueue.svg)](https://badge.fury.io/py/aiida-hyperqueue)
4
+
5
+ # AiiDA HyperQueue plugin
6
+
7
+ AiiDA plugin for the [HyperQueue](https://it4innovations.github.io/hyperqueue/stable/) metascheduler.
8
+
9
+ | ❗️ This package is still in the early stages of development and we will most likely break the API regularly in new 0.X versions. Be sure to pin the version when installing this package in scripts.|
10
+ |---|
11
+
12
+ ## Features
13
+
14
+ Allows task farming on Slurm machines through the submission of AiiDA calculations to the [HyperQueue](https://github.com/It4innovations/hyperqueue) metascheduler.
15
+ See the [Documentation](http://aiida-hyperqueue.readthedocs.io/) for more information on how to install and use the plugin.
16
+
17
+ ## For developers
18
+
19
+ To control the loglevel of command, since we use the `echo` module from aiida, the CLI loglever can be set through `logging.verdi_loglevel`.
20
+
21
+ ## Acknowledgenement
22
+ If you use this plugin for your research, please cite the following work:
23
+
24
+ #### HyperQueue
25
+
26
+ * J. Beránek *et al.*, *HyperQueue: Efficient and ergonomic task graphs on HPC clusters*, SoftwareX **27**, 101814 (2024); DOI: [10.1016/j.softx.2024.101814](https://doi.org/10.1016/j.softx.2024.101814)
27
+
28
+ #### AiiDA
29
+
30
+ * S. P. Huber *et al.*, *AiiDA 1.0, a scalable computational infrastructure for automated reproducible workflows and data provenance*, Scientific Data **7**, 300 (2020); DOI: [10.1038/s41597-020-00638-4](https://doi.org/10.1038/s41597-020-00638-4)
31
+ * M. Uhrin *et al.*, *Workflows in AiiDA: Engineering a high-throughput, event-based engine for robust and modular computational workflows*, Computational Materials Science **187**, 110086 (2021); DOI: [10.1016/j.commatsci.2020.110086](https://doi.org/10.1016/j.commatsci.2020.110086)
@@ -5,4 +5,4 @@ aiida_hyperqueue
5
5
  AiiDA plugin for the HyperQueue metascheduler
6
6
  """
7
7
 
8
- __version__ = '0.1.0'
8
+ __version__ = "0.2.0"
@@ -0,0 +1,5 @@
1
+ # -*- coding: utf-8 -*-
2
+ from .root import cmd_root # noqa: F401
3
+ from .install import cmd_install # noqa: F401
4
+ from .server import cmd_info, cmd_start, cmd_stop # noqa: F401
5
+ from .alloc import cmd_list, cmd_add, cmd_remove # noqa: F401
@@ -0,0 +1,99 @@
1
+ # -*- coding: utf-8 -*-
2
+ import click
3
+
4
+ from aiida.cmdline.params import options, arguments
5
+ from aiida.cmdline.utils import echo
6
+
7
+ from .root import cmd_root
8
+
9
+
10
+ @cmd_root.group("alloc")
11
+ def alloc_group():
12
+ """Commands to configure HQ allocations."""
13
+
14
+
15
+ @alloc_group.command("add")
16
+ @click.argument("slurm-options", nargs=-1)
17
+ @options.COMPUTER(required=True)
18
+ @click.option(
19
+ "-t",
20
+ "--time-limit",
21
+ type=str,
22
+ required=True,
23
+ help=(
24
+ "Time limit for each job run by the allocation. The duration can be expressed using various shortcuts "
25
+ "recognised by HyperQueue, e.g. 30m, 2h, ... For the full list, see https://tinyurl.com/hq-duration."
26
+ ),
27
+ )
28
+ @click.option(
29
+ "--hyper-threading/--no-hyper-threading",
30
+ default=True,
31
+ type=click.BOOL,
32
+ help=("Allow HyperQueue to consider hyperthreads when assigning resources."),
33
+ )
34
+ @click.option(
35
+ "-b",
36
+ "--backlog",
37
+ type=click.INT,
38
+ required=False,
39
+ default=1,
40
+ help=(
41
+ "Set the backlog for the allocator. This is the number of allocations HyperQueue will make sure is waiting with"
42
+ " the job manager."
43
+ ),
44
+ )
45
+ @click.option(
46
+ "-w",
47
+ "--workers-per-alloc",
48
+ type=click.INT,
49
+ required=False,
50
+ default=1,
51
+ help=("Option to allow pooled jobs to launch on multiple nodes."),
52
+ )
53
+ def cmd_add(
54
+ slurm_options, computer, time_limit, hyper_threading, backlog, workers_per_alloc
55
+ ):
56
+ """Add a new allocation to the HQ server."""
57
+
58
+ # from hq==0.13.0: ``--cpus=no-ht`` is now changed to a flag ``--no-hyper-threading``
59
+ hyper = "" if hyper_threading else "--no-hyper-threading"
60
+
61
+ with computer.get_transport() as transport:
62
+ retval, _, stderr = transport.exec_command_wait(
63
+ f'hq alloc add slurm --backlog {backlog} --time-limit {time_limit} --name ahq {hyper} '
64
+ f'--workers-per-alloc {workers_per_alloc} -- {" ".join(slurm_options)}'
65
+ )
66
+
67
+ if retval != 0:
68
+ echo.echo_critical(f"failed to create new allocation: {stderr}\n")
69
+
70
+ echo.echo_success(f"{stderr}")
71
+
72
+
73
+ @alloc_group.command("list")
74
+ @arguments.COMPUTER()
75
+ def cmd_list(computer):
76
+ """List the allocations on the HQ server."""
77
+
78
+ with computer.get_transport() as transport:
79
+ retval, stdout, stderr = transport.exec_command_wait("hq alloc list")
80
+
81
+ if retval != 0:
82
+ echo.echo_critical(f"failed to list allocations: {stderr}\n")
83
+
84
+ echo.echo(stdout)
85
+
86
+
87
+ @alloc_group.command("remove")
88
+ @click.argument("alloc_id")
89
+ @options.COMPUTER(required=True)
90
+ def cmd_remove(alloc_id, computer):
91
+ """Remove an allocation from the HQ server."""
92
+
93
+ with computer.get_transport() as transport:
94
+ retval, _, stderr = transport.exec_command_wait(f"hq alloc remove {alloc_id}")
95
+
96
+ if retval != 0:
97
+ echo.echo_critical(f"failed to remove allocation: {stderr}\n")
98
+
99
+ echo.echo_success(f"{stderr}")
@@ -0,0 +1,120 @@
1
+ # -*- coding: utf-8 -*-
2
+ import click
3
+ import tempfile
4
+ import requests
5
+ import tarfile
6
+ from pathlib import Path
7
+
8
+ from aiida import orm
9
+ from aiida.cmdline.utils import echo
10
+
11
+ from .params import arguments
12
+ from .root import cmd_root
13
+
14
+
15
+ @cmd_root.command("install")
16
+ @arguments.COMPUTER()
17
+ @click.option(
18
+ "-p",
19
+ "--remote-bin-dir",
20
+ type=click.Path(),
21
+ default=Path("$HOME/bin/"),
22
+ help="remote bin path hq will stored.",
23
+ )
24
+ @click.option(
25
+ "--write-bashrc/--no-write-bashrc",
26
+ default=True,
27
+ help="write the bin path to bashrc.",
28
+ )
29
+ @click.option(
30
+ "--hq-version", type=str, default="0.19.0", help="the hq version will be installed."
31
+ )
32
+ # TODO: should also support different arch binary??
33
+ def cmd_install(
34
+ computer: orm.Computer, remote_bin_dir: Path, hq_version: str, write_bashrc: bool
35
+ ):
36
+ """Install the hq binary to the computer through the transport"""
37
+
38
+ # The minimal hq version we support is 0.13.0, check the minor version
39
+ try:
40
+ _, minor, _ = hq_version.split(".")
41
+ except ValueError as e:
42
+ echo.echo_critical(f"Cannot parse the version {hq_version}: {e}")
43
+ else:
44
+ if int(minor) < 13:
45
+ # `--no-hyper-threading` replace `--cpus=no-ht` from 0.13.0
46
+ # If older version installed, try to not use `--no-hyper-threading` for `aiida-hq alloc add`.
47
+ echo.echo_warning(
48
+ f"You are installing hq version {hq_version}, please do not use `--no-hyper-threading` for `aiida-hq alloc add`."
49
+ " Or install version >= 0.13.0"
50
+ )
51
+
52
+ # Download the hq binary with specific version to local temp folder
53
+ # raise if the version not found
54
+ # Then upload to the remote using opened transport of computer
55
+ with tempfile.TemporaryDirectory() as temp_dir:
56
+ url = f"https://github.com/It4innovations/hyperqueue/releases/download/v{hq_version}/hq-v{hq_version}-linux-x64.tar.gz"
57
+ response = requests.get(url, stream=True)
58
+ rcode = response.status_code
59
+
60
+ if rcode != 200:
61
+ echo.echo_error(
62
+ "Cannot download the hq, please check the version is exist."
63
+ )
64
+
65
+ temp_dir = Path(temp_dir)
66
+ tar_path = temp_dir / "hq.tar.gz"
67
+
68
+ with open(tar_path, "wb") as f:
69
+ for chunk in response.iter_content(chunk_size=8192):
70
+ f.write(chunk)
71
+
72
+ with tarfile.open(tar_path, "r") as tar:
73
+ tar.extractall(path=temp_dir)
74
+
75
+ echo.echo_success(f"The hq version {hq_version} binary downloaded.")
76
+
77
+ bin_path = temp_dir / "hq"
78
+
79
+ # upload the binary to remote
80
+ # TODO: try not override if the binary exist, put has overwrite=True as default
81
+ with computer.get_transport() as transport:
82
+ # Get the abs path of remote bin dir
83
+ retval, stdout, stderr = transport.exec_command_wait(
84
+ f"echo {str(remote_bin_dir)}"
85
+ )
86
+ if retval != 0:
87
+ echo.echo_critical(
88
+ f"Not able to parse remote bin dir {remote_bin_dir}, exit_code={retval}"
89
+ )
90
+ else:
91
+ remote_bin_dir = Path(stdout.strip())
92
+
93
+ # first check if the hq exist in the target folder
94
+ if transport.isfile(str(remote_bin_dir / "hq")):
95
+ echo.echo_info(
96
+ f"hq exist in the {remote_bin_dir} on remote, will override it."
97
+ )
98
+
99
+ transport.makedirs(path=remote_bin_dir, ignore_existing=True)
100
+ transport.put(
101
+ localpath=str(bin_path.resolve()), remotepath=str(remote_bin_dir)
102
+ )
103
+
104
+ # XXX: should transport.put take care of this already??
105
+ transport.exec_command_wait(f"chmod +x {str(remote_bin_dir / 'hq')}")
106
+
107
+ # write to bashrc
108
+ if write_bashrc:
109
+ identity_str = "by aiida-hq"
110
+ retval, _, stderr = transport.exec_command_wait(
111
+ f"grep -q '# {identity_str}' ~/.bashrc || echo '# {identity_str}\nexport PATH=$HOME/bin:$PATH' >> ~/.bashrc"
112
+ )
113
+
114
+ if retval != 0:
115
+ echo.echo_critical(
116
+ f"Not able to set set the path $HOME/bin to your remote bashrc, try to do it manually.\n"
117
+ f"Info: {stderr}"
118
+ )
119
+
120
+ echo.echo_success(f"The hq binary installed into remote {remote_bin_dir}")
@@ -0,0 +1,4 @@
1
+ # -*- coding: utf-8 -*-
2
+ from aiida.cmdline.params import arguments as core_arguments
3
+
4
+ COMPUTER = core_arguments.COMPUTER
@@ -0,0 +1,33 @@
1
+ # -*- coding: utf-8 -*-
2
+ """Reusable options for CLI commands."""
3
+
4
+ import functools
5
+
6
+ import click
7
+ from aiida.cmdline.params import options as core_options
8
+ from aiida.cmdline.params import types as core_types
9
+
10
+ __all__ = (
11
+ "PROFILE",
12
+ "VERBOSITY",
13
+ "VERSION",
14
+ )
15
+
16
+ PROFILE = functools.partial(
17
+ core_options.PROFILE,
18
+ type=core_types.ProfileParamType(load_profile=True),
19
+ expose_value=False,
20
+ )
21
+
22
+ # Clone the ``VERBOSITY`` option from ``aiida-core`` so the ``-v`` short flag can be removed, since that overlaps with
23
+ # the flag of the ``VERSION`` option of this CLI.
24
+ VERBOSITY = core_options.VERBOSITY.clone()
25
+ VERBOSITY.args = ("--verbosity",)
26
+
27
+ VERSION = core_options.OverridableOption(
28
+ "-v",
29
+ "--version",
30
+ type=click.STRING,
31
+ required=False,
32
+ help="Select the version of the installed configuration.",
33
+ )
@@ -0,0 +1,37 @@
1
+ # -*- coding: utf-8 -*-
2
+ """Command line interface `aiida-hq` for aiida-hyperqueue.
3
+ The CLI implementation prototype from `aiida-pseudo`.
4
+ """
5
+
6
+ import click
7
+
8
+ from aiida.cmdline.groups.verdi import VerdiCommandGroup
9
+
10
+ from .params import options
11
+
12
+
13
+ class CustomVerdiCommandGroup(VerdiCommandGroup):
14
+ """Subclass of :class:`aiida.cmdline.groups.verdi.VerdiCommandGroup` for the CLI.
15
+
16
+ This subclass overrides the verbosity option to use a custom one that removes the ``-v`` short version of the option
17
+ since that is used by other options in this CLI and so would clash.
18
+ """
19
+
20
+ @staticmethod
21
+ def add_verbosity_option(cmd):
22
+ """Apply the ``verbosity`` option to the command, which is common to all subcommands."""
23
+ if cmd is not None and "verbosity" not in [param.name for param in cmd.params]:
24
+ cmd = options.VERBOSITY()(cmd)
25
+
26
+ return cmd
27
+
28
+
29
+ @click.group(
30
+ "aiida-hq",
31
+ cls=CustomVerdiCommandGroup,
32
+ context_settings={"help_option_names": ["-h", "--help"]},
33
+ )
34
+ @options.VERBOSITY()
35
+ @options.PROFILE()
36
+ def cmd_root():
37
+ """CLI for the ``aiida-hyperqueue`` plugin."""