Skip to content

Commit

Permalink
fix: make sure code runs with python 3.9
Browse files Browse the repository at this point in the history
To make the installation easier, drop clapper dependency and test against python 3.9
Also point to stable docs.
  • Loading branch information
183amir committed Jul 9, 2024
1 parent ceab541 commit 432e4a3
Show file tree
Hide file tree
Showing 9 changed files with 168 additions and 154 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/pre-commit.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,5 @@ jobs:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.12"
python-version: "3.9"
- uses: pre-commit/[email protected]
2 changes: 1 addition & 1 deletion .github/workflows/publish-pypi.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ jobs:

- uses: actions/setup-python@v5
with:
python-version: "3.12"
python-version: "3.9"

- name: Build release distributions
run: |
Expand Down
10 changes: 4 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ SPDX-FileContributor: Amir Mohammadi <[email protected]>
SPDX-License-Identifier: GPL-3.0-or-later
-->

[![latest-docs](https://img.shields.io/badge/docs-latest-orange.svg)](https://gridtk.readthedocs.io/en/latest/)
[![docs](https://img.shields.io/badge/docs-stable-orange.svg)](https://gridtk.readthedocs.io/en/stable/)
[![build](https://github.com/idiap/gridtk/actions/workflows/build.yml/badge.svg)](https://github.com/idiap/gridtk/actions/workflows/build.yml)
[![coverage](https://raw.githubusercontent.com/idiap/gridtk/python-coverage-comment-action-data/badge.svg)](https://htmlpreview.github.io/?https://github.com/idiap/gridtk/blob/python-coverage-comment-action-data/htmlcov/index.html)
[![repository](https://img.shields.io/badge/github-project-0000c0.svg)](https://github.com/idiap/gridtk)
Expand All @@ -26,22 +26,20 @@ installation, submission, monitoring, and various commands provided by GridTK.
Before diving into GridTK, ensure you have the following prerequisites:

1. A working SLURM setup.
2. [Pixi](https://pixi.sh) installed.
2. [pipx](https://pipx.pypa.io/stable/) installed.
3. GridTK installed (instructions provided below).

## Installation

To install GridTK, open your terminal and run the following command:

```bash
$ pixi global install pipx
$ pixi global install python=3.12
$ pipx install --force --python python3.12 'git+https://github.com/idiap/gridtk.git'
$ pipx install gridtk
```
It is **not recommennded** to install GridTK using `pip install gridtk` in the
same environment as your expeirments. GirdTK does not need to be installed in
the same environment as your experiments and its depencencies may conflict with
your experiments.
your experiments' dependencies.

## Basic Usage

Expand Down
231 changes: 115 additions & 116 deletions pixi.lock

Large diffs are not rendered by default.

16 changes: 7 additions & 9 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ build-backend = "hatchling.build"
[project]
name = "gridtk"
dynamic = ["version"]
requires-python = ">=3.12"
requires-python = ">=3.9"
description = "GridTK: SLURM Job Managetment for Humans"
readme = "README.md"
license = "GPL-3.0-or-later"
Expand All @@ -27,12 +27,7 @@ classifiers = [
"Programming Language :: Python :: 3",
"Topic :: System :: Distributed Computing",
]
dependencies = [
"clapper~=1.1",
"sqlalchemy~=2.0",
"tabulate~=0.9.0",
"click~=8.1",
]
dependencies = ["sqlalchemy~=2.0", "tabulate~=0.9.0", "click~=8.1"]

[project.urls]
documentation = "https://gridtk.readthedocs.io/en/latest/"
Expand Down Expand Up @@ -76,6 +71,9 @@ self = { solve-group = "default" }
test = { features = ["test"], solve-group = "default" }
doc = { features = ["doc"], solve-group = "default" }

[tool.pixi.dependencies]
python = "3.9.*"

[tool.hatch.version]
source = "versioningit"

Expand Down Expand Up @@ -104,7 +102,7 @@ packages = ["src/gridtk"]

[tool.ruff]
line-length = 88
target-version = "py312"
target-version = "py39"

[tool.ruff.format]
docstring-code-format = true
Expand Down Expand Up @@ -170,4 +168,4 @@ junit_log_passing_tests = false
relative_files = true

[tool.mypy]
python_version = "3.12"
python_version = "3.9"
20 changes: 15 additions & 5 deletions src/gridtk/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,27 +8,37 @@

from collections import defaultdict
from pathlib import Path
from typing import Optional

import click

from clapper.click import AliasedGroup


class CustomGroup(AliasedGroup):
class CustomGroup(click.Group):
"""Custom command group that does not sort commands."""

def list_commands(self, ctx: click.Context) -> list[str]:
# do not sort the commands
return self.commands

def get_command(self, ctx, cmd_name):
"""get_command with prefix aliasing and name aliases."""
cmd_name = {
"sbatch": "submit",
"ls": "list",
"rm": "delete",
"remove": "delete",
}.get(cmd_name, cmd_name)
return super().get_command(ctx, cmd_name)
rv = click.Group.get_command(self, ctx, cmd_name)
if rv is not None:
return rv
matches = [x for x in self.list_commands(ctx) if x.startswith(cmd_name)]
if not matches:
return None

if len(matches) == 1:
return click.Group.get_command(self, ctx, matches[0])

ctx.fail(f"Too many matches: {', '.join(sorted(matches))}") # noqa: RET503


@click.group(
Expand Down Expand Up @@ -453,7 +463,7 @@ def report(
states: list[str],
names: list[str],
dependents: bool,
array_idx: str | None,
array_idx: Optional[str],
):
"""Report on jobs in the queue."""
from .manager import JobManager
Expand Down
1 change: 1 addition & 0 deletions src/gridtk/manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
# SPDX-FileContributor: Amir Mohammadi <[email protected]>
#
# SPDX-License-Identifier: GPL-3.0-or-later

"""Implements a Slurm job manager. Jobs are kept track of in an SQL database
and logs are written to a default logs folder.
Expand Down
35 changes: 20 additions & 15 deletions src/gridtk/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
# SPDX-FileContributor: Amir Mohammadi <[email protected]>
#
# SPDX-License-Identifier: GPL-3.0-or-later

import json
import re
import shlex
Expand All @@ -11,6 +12,7 @@

from pathlib import Path
from sqlite3 import Connection as SQLite3Connection
from typing import Optional

from sqlalchemy import Column, ForeignKey, Integer, String, Table, event
from sqlalchemy.engine import Engine
Expand Down Expand Up @@ -80,7 +82,7 @@ class ObjectValue(TypeDecorator):

def process_bind_param(self, value, dialect):
if value is not None:
if isinstance(value, dict | list | tuple):
if isinstance(value, (dict, list, tuple)):
value = json.dumps(value)
elif isinstance(value, Path):
value = str(value.absolute())
Expand Down Expand Up @@ -141,12 +143,12 @@ class Job(Base):
command: Mapped[list] = mapped_column(ObjectValue)
logs_dir: Mapped[Path] = mapped_column(ObjectValue)
is_array_job: Mapped[bool]
dependencies_str: Mapped[str | None] = mapped_column(String(2048))
grid_id: Mapped[int | None]
state: Mapped[str | None] = mapped_column(String(30), default="UNKNOWN")
exit_code: Mapped[str | None]
nodes: Mapped[str | None] # list of node names
array_task_ids: Mapped[list[int] | None] = mapped_column(ObjectValue)
dependencies_str: Mapped[Optional[str]] = mapped_column(String(2048))
grid_id: Mapped[Optional[int]]
state: Mapped[Optional[str]] = mapped_column(String(30), default="UNKNOWN")
exit_code: Mapped[Optional[str]]
nodes: Mapped[Optional[str]] # list of node names
array_task_ids: Mapped[Optional[list[int]]] = mapped_column(ObjectValue)
dependencies_jobdependency: Mapped[list[JobDependency]] = relationship(
JobDependency,
primaryjoin=id == JobDependency.job_id, # type: ignore[attr-defined]
Expand Down Expand Up @@ -237,14 +239,17 @@ def submitted_command(self, fh, session):
] + command

def submit(self, session: Session = None):
with tempfile.NamedTemporaryFile(
mode="w+t", suffix=".sh", delete_on_close=False
) as fh:
command = self.submitted_command(fh=fh, session=session)
output = subprocess.check_output(
command,
text=True,
)
with tempfile.NamedTemporaryFile(mode="w+t", suffix=".sh", delete=False) as fh:
try:
command = self.submitted_command(fh=fh, session=session)
output = subprocess.check_output(
command,
text=True,
)
finally:
# remove the temporary file here because we don't want it
# deleted after fh.close() is called
Path(fh.name).unlink(missing_ok=True)
# find job ID from output
# output is like b'Submitted batch job 123456789\n'
self.grid_id = int(re.search("[0-9]+", output).group())
Expand Down
5 changes: 4 additions & 1 deletion src/gridtk/tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@
# SPDX-FileContributor: Amir Mohammadi <[email protected]>
#
# SPDX-License-Identifier: GPL-3.0-or-later

import re

from typing import Optional


def parse_array_indexes(indexes_str: str) -> list[int]:
"""Pares a string of array indexes to a list of integers."""
Expand Down Expand Up @@ -36,7 +39,7 @@ def parse_segment(segment):
return result


def job_ids_from_dep_str(dependency_string: str | None) -> list[int]:
def job_ids_from_dep_str(dependency_string: Optional[str]) -> list[int]:
"""Extract job IDs from a dependency string."""
if not dependency_string:
return []
Expand Down

0 comments on commit 432e4a3

Please sign in to comment.