aiida-hyperqueue 0.1.1__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.1.1 → aiida_hyperqueue-0.2.0}/.github/workflows/cd.yml +3 -4
  2. aiida_hyperqueue-0.2.0/.github/workflows/ci.yml +30 -0
  3. {aiida-hyperqueue-0.1.1 → aiida_hyperqueue-0.2.0}/.github/workflows/validate_release_tag.py +12 -11
  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.1 → aiida_hyperqueue-0.2.0}/LICENSE +1 -1
  8. {aiida-hyperqueue-0.1.1 → aiida_hyperqueue-0.2.0}/PKG-INFO +28 -12
  9. aiida_hyperqueue-0.2.0/README.md +31 -0
  10. {aiida-hyperqueue-0.1.1 → 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.1 → aiida_hyperqueue-0.2.0}/docs/source/conf.py +41 -37
  21. {aiida-hyperqueue-0.1.1 → aiida_hyperqueue-0.2.0}/docs/source/get_started.md +25 -27
  22. {aiida-hyperqueue-0.1.1 → aiida_hyperqueue-0.2.0}/docs/source/index.md +1 -1
  23. {aiida-hyperqueue-0.1.1 → 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.1 → 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.1/.github/workflows/ci.yml +0 -86
  40. aiida-hyperqueue-0.1.1/.pre-commit-config.yaml +0 -33
  41. aiida-hyperqueue-0.1.1/.readthedocs.yml +0 -9
  42. aiida-hyperqueue-0.1.1/CHANGELOG.md +0 -7
  43. aiida-hyperqueue-0.1.1/README.md +0 -15
  44. aiida-hyperqueue-0.1.1/aiida_hyperqueue/cli.py +0 -149
  45. aiida-hyperqueue-0.1.1/aiida_hyperqueue/scheduler.py +0 -289
  46. aiida-hyperqueue-0.1.1/tests/conftest.py +0 -11
  47. aiida-hyperqueue-0.1.1/tests/test_scheduler.py +0 -18
  48. {aiida-hyperqueue-0.1.1 → aiida_hyperqueue-0.2.0}/.gitignore +0 -0
  49. {aiida-hyperqueue-0.1.1 → aiida_hyperqueue-0.2.0}/docs/.gitignore +0 -0
  50. {aiida-hyperqueue-0.1.1 → aiida_hyperqueue-0.2.0}/docs/Makefile +0 -0
  51. {aiida-hyperqueue-0.1.1 → aiida_hyperqueue-0.2.0}/docs/source/developer_guide/index.md +0 -0
  52. {aiida-hyperqueue-0.1.1 → aiida_hyperqueue-0.2.0}/docs/source/img/AiiDA_transparent_logo.png +0 -0
@@ -29,11 +29,10 @@ jobs:
29
29
  name: Publish to PyPI
30
30
  needs: [validate-release-tag]
31
31
  runs-on: ubuntu-latest
32
- environment:
33
- name: deployment
34
- url: https://pypi.org/project/aiida-hyperqueue/
32
+ environment: deployment
35
33
  permissions:
36
34
  id-token: write
35
+
37
36
  steps:
38
37
  - name: Checkout source
39
38
  uses: actions/checkout@v3
@@ -49,5 +48,5 @@ jobs:
49
48
  - name: Build with flit
50
49
  run: flit build
51
50
 
52
- - name: Publish package distributions to PyPI
51
+ - name: Publish to PyPI using Trusted Publishing
53
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 .
@@ -1,5 +1,6 @@
1
1
  # -*- coding: utf-8 -*-
2
2
  """Validate that the version in the tag label matches the version of the package."""
3
+
3
4
  import argparse
4
5
  import ast
5
6
  from pathlib import Path
@@ -13,32 +14,32 @@ def get_version_from_module(content: str) -> str:
13
14
  try:
14
15
  module = ast.parse(content)
15
16
  except SyntaxError as exception:
16
- raise OSError('Unable to parse module.') from exception
17
+ raise OSError("Unable to parse module.") from exception
17
18
 
18
19
  try:
19
20
  return next(
20
- ast.literal_eval(statement.value) for statement in module.body
21
+ ast.literal_eval(statement.value)
22
+ for statement in module.body
21
23
  if isinstance(statement, ast.Assign)
22
24
  for target in statement.targets
23
- if isinstance(target, ast.Name) and target.id == '__version__')
25
+ if isinstance(target, ast.Name) and target.id == "__version__"
26
+ )
24
27
  except StopIteration as exception:
25
28
  raise OSError(
26
- 'Unable to find the `__version__` attribute in the module.'
29
+ "Unable to find the `__version__` attribute in the module."
27
30
  ) from exception
28
31
 
29
32
 
30
- if __name__ == '__main__':
33
+ if __name__ == "__main__":
31
34
  parser = argparse.ArgumentParser()
32
- parser.add_argument('GITHUB_REF',
33
- help='The GITHUB_REF environmental variable')
35
+ parser.add_argument("GITHUB_REF", help="The GITHUB_REF environmental variable")
34
36
  args = parser.parse_args()
35
37
  assert args.GITHUB_REF.startswith(
36
- 'refs/tags/v'
38
+ "refs/tags/v"
37
39
  ), f'GITHUB_REF should start with "refs/tags/v": {args.GITHUB_REF}'
38
40
  tag_version = args.GITHUB_REF[11:]
39
41
  package_version = get_version_from_module(
40
- Path('aiida_hyperqueue/__init__.py').read_text(encoding='utf-8'))
41
- error_message = (
42
- f'The tag version `{tag_version}` is different from the package version `{package_version}`'
42
+ Path("aiida_hyperqueue/__init__.py").read_text(encoding="utf-8")
43
43
  )
44
+ error_message = f"The tag version `{tag_version}` is different from the package version `{package_version}`"
44
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
@@ -1,9 +1,9 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.4
2
2
  Name: aiida-hyperqueue
3
- Version: 0.1.1
3
+ Version: 0.2.0
4
4
  Summary: AiiDA plugin for the HyperQueue metascheduler
5
- Author: Marnik Bercx
6
- Requires-Python: >=3.6
5
+ Author: Marnik Bercx, Jusong Yu
6
+ Requires-Python: >=3.9
7
7
  Description-Content-Type: text/markdown
8
8
  Classifier: Framework :: AiiDA
9
9
  Classifier: Development Status :: 3 - Alpha
@@ -12,31 +12,31 @@ Classifier: Operating System :: POSIX :: Linux
12
12
  Classifier: Operating System :: MacOS :: MacOS X
13
13
  Classifier: Natural Language :: English
14
14
  Classifier: Programming Language :: Python
15
+ License-File: LICENSE
15
16
  Requires-Dist: aiida-core~=2.0
16
17
  Requires-Dist: sphinx ; extra == "docs"
17
18
  Requires-Dist: myst-parser ; extra == "docs"
18
19
  Requires-Dist: sphinx-design ; extra == "docs"
19
20
  Requires-Dist: sphinx-book-theme ; extra == "docs"
20
21
  Requires-Dist: sphinxcontrib-details-directive~=0.1.0 ; extra == "docs"
21
- Requires-Dist: pre-commit~=2.2 ; extra == "pre-commit"
22
- Requires-Dist: pylint>=2.5.0,<2.9 ; extra == "pre-commit"
22
+ Requires-Dist: pre-commit~=3.5 ; extra == "pre-commit"
23
+ Requires-Dist: mypy~=1.10.0 ; extra == "pre-commit"
23
24
  Requires-Dist: pgtest~=1.3.1 ; extra == "tests"
24
- Requires-Dist: wheel~=0.31 ; extra == "tests"
25
- Requires-Dist: coverage ; extra == "tests"
26
- Requires-Dist: pytest~=6.0 ; extra == "tests"
27
- Requires-Dist: pytest-cov ; 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
28
  Project-URL: Source, https://github.com/aiidateam/aiida-hyperqueue
29
29
  Provides-Extra: docs
30
30
  Provides-Extra: pre-commit
31
31
  Provides-Extra: tests
32
32
 
33
- [![Build Status](https://github.com/aiidateam/aiida-hyperqueue/workflows/ci/badge.svg?branch=main)](https://github.com/aiidateam/aiida-hyperqueue/actions)
33
+ [![Build Status](https://github.com/aiidateam/aiida-hyperqueue/workflows/ci/badge.svg)](https://github.com/aiidateam/aiida-hyperqueue/actions)
34
34
  [![Docs status](https://readthedocs.org/projects/aiida-hyperqueue/badge)](http://aiida-hyperqueue.readthedocs.io/)
35
35
  [![PyPI version](https://badge.fury.io/py/aiida-hyperqueue.svg)](https://badge.fury.io/py/aiida-hyperqueue)
36
36
 
37
37
  # AiiDA HyperQueue plugin
38
38
 
39
- AiiDA plugin for the [HyperQueue](https://github.com/It4innovations/hyperqueue) metascheduler.
39
+ AiiDA plugin for the [HyperQueue](https://it4innovations.github.io/hyperqueue/stable/) metascheduler.
40
40
 
41
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
42
  |---|
@@ -46,3 +46,19 @@ AiiDA plugin for the [HyperQueue](https://github.com/It4innovations/hyperqueue)
46
46
  Allows task farming on Slurm machines through the submission of AiiDA calculations to the [HyperQueue](https://github.com/It4innovations/hyperqueue) metascheduler.
47
47
  See the [Documentation](http://aiida-hyperqueue.readthedocs.io/) for more information on how to install and use the plugin.
48
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.1'
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."""