horus-docker 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.
- horus_docker-0.0.1/.github/workflows/python-ci.yaml +62 -0
- horus_docker-0.0.1/.github/workflows/release.yaml +35 -0
- horus_docker-0.0.1/.gitignore +54 -0
- horus_docker-0.0.1/.mit.tmpl +4 -0
- horus_docker-0.0.1/.pre-commit-config.yaml +43 -0
- horus_docker-0.0.1/Makefile +101 -0
- horus_docker-0.0.1/PKG-INFO +8 -0
- horus_docker-0.0.1/README.md +118 -0
- horus_docker-0.0.1/babel.cfg +2 -0
- horus_docker-0.0.1/pyproject.toml +114 -0
- horus_docker-0.0.1/src/horus_docker/__init__.py +6 -0
- horus_docker-0.0.1/src/horus_docker/executor/__init__.py +6 -0
- horus_docker-0.0.1/src/horus_docker/executor/docker.py +228 -0
- horus_docker-0.0.1/src/horus_docker/i18n.py +22 -0
- horus_docker-0.0.1/src/horus_docker/locale/en/LC_MESSAGES/horus_docker.mo +0 -0
- horus_docker-0.0.1/src/horus_docker/locale/en/LC_MESSAGES/horus_docker.po +62 -0
- horus_docker-0.0.1/src/horus_docker/locale/messages.pot +59 -0
- horus_docker-0.0.1/src/horus_docker/py.typed +0 -0
- horus_docker-0.0.1/tests/__init__.py +6 -0
- horus_docker-0.0.1/tests/conftest.py +55 -0
- horus_docker-0.0.1/tests/unit/__init__.py +6 -0
- horus_docker-0.0.1/tests/unit/test_docker_executor.py +358 -0
- horus_docker-0.0.1/uv.lock +756 -0
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
name: Python CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
pull_request:
|
|
5
|
+
branches: [main]
|
|
6
|
+
|
|
7
|
+
jobs:
|
|
8
|
+
lint:
|
|
9
|
+
runs-on: ubuntu-latest
|
|
10
|
+
steps:
|
|
11
|
+
- uses: actions/checkout@v6
|
|
12
|
+
|
|
13
|
+
- name: Set up Python
|
|
14
|
+
uses: actions/setup-python@v6
|
|
15
|
+
with:
|
|
16
|
+
python-version: "3.13"
|
|
17
|
+
cache: "pip"
|
|
18
|
+
|
|
19
|
+
- name: Install uv
|
|
20
|
+
uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0
|
|
21
|
+
|
|
22
|
+
- name: Sync project dependencies
|
|
23
|
+
run: uv sync --group dev
|
|
24
|
+
|
|
25
|
+
- name: Lint with Ruff and mypy
|
|
26
|
+
run: uv run make lint
|
|
27
|
+
|
|
28
|
+
- name: Check translations
|
|
29
|
+
run: uv run make babel-check
|
|
30
|
+
|
|
31
|
+
test:
|
|
32
|
+
runs-on: ubuntu-latest
|
|
33
|
+
strategy:
|
|
34
|
+
fail-fast: false
|
|
35
|
+
matrix:
|
|
36
|
+
python-version: ["3.13", "3.14"]
|
|
37
|
+
|
|
38
|
+
steps:
|
|
39
|
+
- uses: actions/checkout@v6
|
|
40
|
+
|
|
41
|
+
- name: Set up Python ${{ matrix.python-version }}
|
|
42
|
+
uses: actions/setup-python@v6
|
|
43
|
+
with:
|
|
44
|
+
python-version: ${{ matrix.python-version }}
|
|
45
|
+
cache: "pip"
|
|
46
|
+
|
|
47
|
+
- name: Install uv
|
|
48
|
+
uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0
|
|
49
|
+
|
|
50
|
+
- name: Sync project dependencies
|
|
51
|
+
run: uv sync --group dev
|
|
52
|
+
|
|
53
|
+
- name: Run tests with coverage
|
|
54
|
+
run: uv run make test
|
|
55
|
+
|
|
56
|
+
- name: Upload coverage report
|
|
57
|
+
uses: actions/upload-artifact@v6
|
|
58
|
+
if: matrix.python-version == '3.13'
|
|
59
|
+
with:
|
|
60
|
+
name: coverage-html-report
|
|
61
|
+
path: htmlcov/
|
|
62
|
+
retention-days: 5
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
name: Release
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
release:
|
|
5
|
+
types: [published]
|
|
6
|
+
|
|
7
|
+
jobs:
|
|
8
|
+
release:
|
|
9
|
+
runs-on: ubuntu-latest
|
|
10
|
+
permissions:
|
|
11
|
+
id-token: write
|
|
12
|
+
|
|
13
|
+
steps:
|
|
14
|
+
- uses: actions/checkout@v6
|
|
15
|
+
|
|
16
|
+
- name: Set up Python
|
|
17
|
+
uses: actions/setup-python@v6
|
|
18
|
+
with:
|
|
19
|
+
python-version: "3.13"
|
|
20
|
+
cache: "pip"
|
|
21
|
+
|
|
22
|
+
- name: Install uv
|
|
23
|
+
uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0
|
|
24
|
+
|
|
25
|
+
- name: Sync project dependencies
|
|
26
|
+
run: uv sync --group dev
|
|
27
|
+
|
|
28
|
+
- name: Verify and compile translations
|
|
29
|
+
run: uv run make babel-check
|
|
30
|
+
|
|
31
|
+
- name: Build package
|
|
32
|
+
run: uv run uv build
|
|
33
|
+
|
|
34
|
+
- name: Upload to PyPI
|
|
35
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
*.so
|
|
6
|
+
.Python
|
|
7
|
+
build/
|
|
8
|
+
develop-eggs/
|
|
9
|
+
dist/
|
|
10
|
+
downloads/
|
|
11
|
+
eggs/
|
|
12
|
+
.eggs/
|
|
13
|
+
lib/
|
|
14
|
+
lib64/
|
|
15
|
+
parts/
|
|
16
|
+
sdist/
|
|
17
|
+
var/
|
|
18
|
+
wheels/
|
|
19
|
+
*.egg-info/
|
|
20
|
+
.installed.cfg
|
|
21
|
+
*.egg
|
|
22
|
+
*.ipynb
|
|
23
|
+
|
|
24
|
+
# Virtual environments
|
|
25
|
+
venv/
|
|
26
|
+
.venv/
|
|
27
|
+
ENV/
|
|
28
|
+
env/
|
|
29
|
+
|
|
30
|
+
# IDEs
|
|
31
|
+
.vscode/
|
|
32
|
+
.idea/
|
|
33
|
+
*.swp
|
|
34
|
+
*.swo
|
|
35
|
+
|
|
36
|
+
# Testing
|
|
37
|
+
.pytest_cache/
|
|
38
|
+
.coverage
|
|
39
|
+
htmlcov/
|
|
40
|
+
.tox/
|
|
41
|
+
|
|
42
|
+
# OS
|
|
43
|
+
.DS_Store
|
|
44
|
+
Thumbs.db
|
|
45
|
+
|
|
46
|
+
*.xml
|
|
47
|
+
|
|
48
|
+
# i18n
|
|
49
|
+
*.mo
|
|
50
|
+
|
|
51
|
+
# logs
|
|
52
|
+
logs/
|
|
53
|
+
|
|
54
|
+
no-commit/
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
repos:
|
|
2
|
+
- repo: https://github.com/pre-commit/pre-commit-hooks
|
|
3
|
+
rev: v6.0.0
|
|
4
|
+
hooks:
|
|
5
|
+
- id: trailing-whitespace
|
|
6
|
+
- id: end-of-file-fixer
|
|
7
|
+
- id: check-yaml
|
|
8
|
+
- id: check-added-large-files
|
|
9
|
+
|
|
10
|
+
- repo: local
|
|
11
|
+
hooks:
|
|
12
|
+
- id: ruff-lint
|
|
13
|
+
name: ruff lint
|
|
14
|
+
entry: ruff check --fix
|
|
15
|
+
language: system
|
|
16
|
+
types: [ python ]
|
|
17
|
+
require_serial: true
|
|
18
|
+
|
|
19
|
+
- id: ruff-format
|
|
20
|
+
name: ruff format
|
|
21
|
+
entry: ruff format
|
|
22
|
+
language: system
|
|
23
|
+
types: [ python ]
|
|
24
|
+
|
|
25
|
+
- id: mypy
|
|
26
|
+
name: mypy
|
|
27
|
+
entry: mypy
|
|
28
|
+
language: system
|
|
29
|
+
types: [ python ]
|
|
30
|
+
require_serial: true
|
|
31
|
+
|
|
32
|
+
# If the commit includes changes in translation files,
|
|
33
|
+
# check that all translations are complete.
|
|
34
|
+
- id: babel-check
|
|
35
|
+
name: babel-check
|
|
36
|
+
entry: make babel-check
|
|
37
|
+
language: system
|
|
38
|
+
|
|
39
|
+
- id: add-license-headers
|
|
40
|
+
name: add-license-headers
|
|
41
|
+
entry: make add-license-headers
|
|
42
|
+
language: system
|
|
43
|
+
pass_filenames: false
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
# Makefile for Horus Runtime plugin development
|
|
2
|
+
|
|
3
|
+
# Command definitions (used in CI and locally)
|
|
4
|
+
PYTEST_CMD = pytest --cov=src/horus_docker --cov-report=xml --cov-report=html --cov-report=term --junitxml=test-results.xml
|
|
5
|
+
RUFF_LINT_CMD = ruff check src/ tests/
|
|
6
|
+
RUFF_FORMAT_CHECK_CMD = ruff format --check --diff .
|
|
7
|
+
RUFF_FIX_CMD = ruff check --fix src/ tests/
|
|
8
|
+
RUFF_FORMAT_CMD = ruff format .
|
|
9
|
+
MYPY_CMD = mypy src/ tests/
|
|
10
|
+
|
|
11
|
+
# i18n settings (babel)
|
|
12
|
+
BABEL_CFG = babel.cfg
|
|
13
|
+
LOCALE_DIR = src/horus_docker/locale
|
|
14
|
+
MESSAGES_POT = $(LOCALE_DIR)/messages.pot
|
|
15
|
+
DOMAIN = horus_docker
|
|
16
|
+
SOURCE_DIR = src/horus_docker
|
|
17
|
+
|
|
18
|
+
# Variables used for babel metadata
|
|
19
|
+
PROJECT_NAME = horus_docker
|
|
20
|
+
ORGANIZATION = Temple Compute
|
|
21
|
+
LICENSE_TMPL = .mit.tmpl
|
|
22
|
+
|
|
23
|
+
.PHONY: test lint format type-check clean help ruff-check ruff-format-check mypy-check babel-update babel-check babel-add babel-extract add-license-headers
|
|
24
|
+
|
|
25
|
+
help:
|
|
26
|
+
@echo "Available commands:"
|
|
27
|
+
@echo " test Run all tests with coverage (same as CI)"
|
|
28
|
+
@echo " lint Run all linting tools (same as CI)"
|
|
29
|
+
@echo " ruff-check Check code with ruff linter (used by CI)"
|
|
30
|
+
@echo " ruff-format-check Check code formatting with ruff (used by CI)"
|
|
31
|
+
@echo " mypy-check Check types with mypy (used by CI)"
|
|
32
|
+
@echo " format Format code with ruff"
|
|
33
|
+
@echo " type-check Run type checking"
|
|
34
|
+
@echo " babel-update Update Babel translations"
|
|
35
|
+
@echo " babel-check Check Babel translations (used by CI)"
|
|
36
|
+
@echo " babel-add Add a new language (usage: make babel-add LANG=es)"
|
|
37
|
+
@echo " babel-extract Extract translatable strings to messages.pot"
|
|
38
|
+
@echo " clean Remove cache files"
|
|
39
|
+
|
|
40
|
+
test:
|
|
41
|
+
# Set PYTHONPATH to current directory to ensure tests can find other test modules
|
|
42
|
+
PYTHONPATH=. $(PYTEST_CMD)
|
|
43
|
+
|
|
44
|
+
# Individual check commands
|
|
45
|
+
ruff-check:
|
|
46
|
+
$(RUFF_LINT_CMD)
|
|
47
|
+
|
|
48
|
+
ruff-format-check:
|
|
49
|
+
$(RUFF_FORMAT_CHECK_CMD)
|
|
50
|
+
|
|
51
|
+
mypy-check:
|
|
52
|
+
$(MYPY_CMD)
|
|
53
|
+
|
|
54
|
+
lint:
|
|
55
|
+
$(RUFF_LINT_CMD)
|
|
56
|
+
$(RUFF_FORMAT_CHECK_CMD)
|
|
57
|
+
$(MYPY_CMD)
|
|
58
|
+
|
|
59
|
+
format:
|
|
60
|
+
$(RUFF_FIX_CMD)
|
|
61
|
+
$(RUFF_FORMAT_CMD)
|
|
62
|
+
|
|
63
|
+
type-check:
|
|
64
|
+
$(MYPY_CMD)
|
|
65
|
+
|
|
66
|
+
add-license-headers:
|
|
67
|
+
licenseheaders -t $(LICENSE_TMPL) -cy -o '$(ORGANIZATION)' -n $(PROJECT_NAME) -d src
|
|
68
|
+
licenseheaders -t $(LICENSE_TMPL) -cy -o '$(ORGANIZATION)' -n $(PROJECT_NAME) -d tests
|
|
69
|
+
|
|
70
|
+
clean:
|
|
71
|
+
find . -type d -name "__pycache__" -delete
|
|
72
|
+
find . -type f -name "*.pyc" -delete
|
|
73
|
+
rm -rf .coverage htmlcov/ .pytest_cache/
|
|
74
|
+
rm -rf *.egg-info/ build/ dist/
|
|
75
|
+
|
|
76
|
+
babel-extract:
|
|
77
|
+
pybabel extract -F $(BABEL_CFG) \
|
|
78
|
+
--project=$(PROJECT_NAME) \
|
|
79
|
+
--copyright-holder="$(ORGANIZATION)" \
|
|
80
|
+
-o $(MESSAGES_POT) $(SOURCE_DIR)
|
|
81
|
+
|
|
82
|
+
babel-update:
|
|
83
|
+
pybabel update -i $(MESSAGES_POT) -d $(LOCALE_DIR) -D $(DOMAIN) --no-fuzzy-matching
|
|
84
|
+
|
|
85
|
+
babel-refresh: babel-extract babel-update
|
|
86
|
+
|
|
87
|
+
babel-check:
|
|
88
|
+
@echo "Checking for missing or fuzzy translations..."
|
|
89
|
+
@for file in $(shell find $(LOCALE_DIR) -name "*.po"); do \
|
|
90
|
+
RESULT=$$(msgfmt --statistics -c -o /dev/null $$file 2>&1); \
|
|
91
|
+
echo "$$RESULT"; \
|
|
92
|
+
if echo "$$RESULT" | grep -E "untranslated|fuzzy" > /dev/null; then \
|
|
93
|
+
echo "ERROR: $$file has missing or fuzzy strings!"; \
|
|
94
|
+
exit 1; \
|
|
95
|
+
fi; \
|
|
96
|
+
done
|
|
97
|
+
@echo "Success: All strings are translated."
|
|
98
|
+
pybabel compile -d $(LOCALE_DIR) -D $(DOMAIN) --statistics
|
|
99
|
+
|
|
100
|
+
babel-add:
|
|
101
|
+
pybabel init -i $(MESSAGES_POT) -d $(LOCALE_DIR) -l $(LANG) -D $(DOMAIN)
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: horus_docker
|
|
3
|
+
Version: 0.0.1
|
|
4
|
+
Summary: A custom plugin for the Horus runtime, providing additional functionality and integrations.
|
|
5
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
6
|
+
Classifier: Programming Language :: Python :: 3
|
|
7
|
+
Requires-Python: >=3.13
|
|
8
|
+
Requires-Dist: horus-runtime>=0.1.3
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
# horus-docker
|
|
2
|
+
|
|
3
|
+
[](https://www.python.org/downloads/)
|
|
4
|
+
[](LICENSE)
|
|
5
|
+
|
|
6
|
+
A [horus-runtime](https://github.com/temple-compute/horus-runtime) plugin that runs tasks inside Docker containers.
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## Overview
|
|
11
|
+
|
|
12
|
+
**horus-docker** contributes a `DockerExecutor` to the `horus.executor` entry point group. Once installed, any `HorusContext` that calls `HorusContext.boot()` will automatically discover and register the executor — no manual wiring required.
|
|
13
|
+
|
|
14
|
+
The executor accepts a `CommandRuntime`-produced shell command and runs it via `/bin/sh -c` inside a fresh Docker container, giving you the same shell semantics (pipes, globbing, `&&`, …) as the local shell executor.
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## Repository structure
|
|
19
|
+
|
|
20
|
+
```
|
|
21
|
+
src/
|
|
22
|
+
└── horus_docker/
|
|
23
|
+
├── __init__.py
|
|
24
|
+
├── i18n.py # plugin-scoped gettext wrapper
|
|
25
|
+
├── locale/
|
|
26
|
+
│ └── messages.pot # translatable strings template
|
|
27
|
+
└── executor/
|
|
28
|
+
├── __init__.py
|
|
29
|
+
└── docker.py # DockerExecutor implementation
|
|
30
|
+
tests/
|
|
31
|
+
├── __init__.py
|
|
32
|
+
├── conftest.py # shared fixtures (registry, HorusContext)
|
|
33
|
+
└── unit/
|
|
34
|
+
├── __init__.py
|
|
35
|
+
└── test_docker_executor.py
|
|
36
|
+
babel.cfg
|
|
37
|
+
Makefile
|
|
38
|
+
pyproject.toml
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## DockerExecutor
|
|
44
|
+
|
|
45
|
+
Registered under `kind = "docker_executor"`. Only accepted when the task's runtime is a `CommandRuntime`.
|
|
46
|
+
|
|
47
|
+
### Fields
|
|
48
|
+
|
|
49
|
+
| Field | Type | Default | Description |
|
|
50
|
+
|---|---|---|---|
|
|
51
|
+
| `image` | `str` | required | Docker image to run (e.g. `python:3.13-slim`) |
|
|
52
|
+
| `env` | `dict[str, str]` | `{}` | Environment variables passed into the container |
|
|
53
|
+
| `volumes` | `dict[str, str]` | `{}` | Bind mounts as `host_path → container_path` (read-write) |
|
|
54
|
+
| `ports` | `dict[str, str]` | `{}` | Port mappings as `host_port → container_port` |
|
|
55
|
+
| `working_dir` | `str \| None` | `None` | Working directory inside the container |
|
|
56
|
+
| `network` | `str \| None` | `None` | Docker network to attach the container to |
|
|
57
|
+
| `entrypoint` | `str \| list[str] \| None` | `None` | Override the image's `ENTRYPOINT` |
|
|
58
|
+
| `user` | `str \| None` | `None` | User (`name`/`uid`, optionally `uid:gid`) to run as |
|
|
59
|
+
| `auto_remove` | `bool` | `True` | Remove the container after execution finishes |
|
|
60
|
+
|
|
61
|
+
### Behaviour
|
|
62
|
+
|
|
63
|
+
1. The task's `CommandRuntime` prepares the shell command via `setup_runtime()`.
|
|
64
|
+
2. The command is wrapped as `["/bin/sh", "-c", <command>]` and passed to `docker-py`'s `containers.run()`.
|
|
65
|
+
3. The container runs to completion (blocking, dispatched to a thread with `asyncio.to_thread`).
|
|
66
|
+
4. Container logs are captured and emitted at `DEBUG` level.
|
|
67
|
+
5. If the Docker daemon raises a `DockerException`, or the container exits with a non-zero status code, a `TaskExecutionError` is raised.
|
|
68
|
+
|
|
69
|
+
---
|
|
70
|
+
|
|
71
|
+
## Development
|
|
72
|
+
|
|
73
|
+
### Requirements
|
|
74
|
+
|
|
75
|
+
- Python ≥ 3.13
|
|
76
|
+
- Docker daemon accessible from the host
|
|
77
|
+
- `horus-runtime` ≥ 0.1.1 (install from source or PyPI)
|
|
78
|
+
|
|
79
|
+
### Setup
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
# Install dependencies (creates .venv automatically)
|
|
83
|
+
uv sync
|
|
84
|
+
|
|
85
|
+
# Install pre-commit hooks
|
|
86
|
+
uv run pre-commit install
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### Common commands
|
|
90
|
+
|
|
91
|
+
| Command | Description |
|
|
92
|
+
|---|---|
|
|
93
|
+
| `make test` | Run the full test suite with coverage |
|
|
94
|
+
| `make lint` | ruff + mypy |
|
|
95
|
+
| `make format` | Auto-fix with ruff |
|
|
96
|
+
| `make type-check` | mypy only |
|
|
97
|
+
| `make babel-extract` | Update `messages.pot` |
|
|
98
|
+
| `make babel-add LANG=es` | Add a new language |
|
|
99
|
+
| `make babel-check` | Verify all strings are translated |
|
|
100
|
+
| `make clean` | Remove build artefacts and caches |
|
|
101
|
+
|
|
102
|
+
---
|
|
103
|
+
|
|
104
|
+
## Internationalization (i18n)
|
|
105
|
+
|
|
106
|
+
Each plugin maintains its **own** gettext domain and locale directory, independent of the runtime's translations.
|
|
107
|
+
|
|
108
|
+
`src/horus_docker/i18n.py` wraps Python's `gettext` module, looking for compiled `.mo` files in `src/horus_docker/locale/<lang>/LC_MESSAGES/horus_docker.mo`. If no catalog exists for the detected locale, it falls back to the original string.
|
|
109
|
+
|
|
110
|
+
Import the wrapper as `_` (required by Babel's extractor) in any module with user-visible strings. Use `make babel-extract` → edit `.po` → `make babel-check` to update translations. The pre-commit hook prevents committing incomplete catalogs.
|
|
111
|
+
|
|
112
|
+
> Full i18n workflow and plural-form reference: [docs.templecompute.com](https://docs.templecompute.com/docs/sdk/i18n).
|
|
113
|
+
|
|
114
|
+
---
|
|
115
|
+
|
|
116
|
+
## License
|
|
117
|
+
|
|
118
|
+
MIT — see [LICENSE](LICENSE).
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "horus_docker"
|
|
3
|
+
version = "0.0.1"
|
|
4
|
+
description = "A custom plugin for the Horus runtime, providing additional functionality and integrations."
|
|
5
|
+
requires-python = ">=3.13"
|
|
6
|
+
classifiers = [
|
|
7
|
+
"License :: OSI Approved :: MIT License",
|
|
8
|
+
"Programming Language :: Python :: 3",
|
|
9
|
+
]
|
|
10
|
+
dependencies = ["horus-runtime>=0.1.3"]
|
|
11
|
+
|
|
12
|
+
# ================
|
|
13
|
+
# Plugin entry-points
|
|
14
|
+
# ================
|
|
15
|
+
[project.entry-points."horus.executor"]
|
|
16
|
+
docker = "horus_docker.executor.docker"
|
|
17
|
+
|
|
18
|
+
# ================
|
|
19
|
+
|
|
20
|
+
[dependency-groups]
|
|
21
|
+
dev = [
|
|
22
|
+
"babel~=2.0",
|
|
23
|
+
"licenseheaders~=0.8",
|
|
24
|
+
"mypy~=1.19",
|
|
25
|
+
"pre_commit~=4.0",
|
|
26
|
+
"pytest~=9.0",
|
|
27
|
+
"pytest-asyncio~=1.3.0",
|
|
28
|
+
"pytest-cov~=7.0",
|
|
29
|
+
"ruff~=0.15",
|
|
30
|
+
"types-PyYAML~=6.0",
|
|
31
|
+
]
|
|
32
|
+
|
|
33
|
+
[build-system]
|
|
34
|
+
requires = ["hatchling"]
|
|
35
|
+
build-backend = "hatchling.build"
|
|
36
|
+
|
|
37
|
+
[tool.coverage.run]
|
|
38
|
+
source = ["horus_docker"]
|
|
39
|
+
|
|
40
|
+
[tool.coverage.report]
|
|
41
|
+
omit = ["tests/*"]
|
|
42
|
+
|
|
43
|
+
[tool.hatch.build]
|
|
44
|
+
artifacts = ["src/horus_docker/locale/**/LC_MESSAGES/*.mo"]
|
|
45
|
+
|
|
46
|
+
[tool.hatch.build.targets.wheel]
|
|
47
|
+
packages = ["src/horus_docker"]
|
|
48
|
+
|
|
49
|
+
[tool.mypy]
|
|
50
|
+
python_version = "3.13"
|
|
51
|
+
strict = true
|
|
52
|
+
exclude = ["build", "dist"]
|
|
53
|
+
plugins = ["pydantic.mypy"]
|
|
54
|
+
|
|
55
|
+
[tool.pydantic-mypy]
|
|
56
|
+
init_typed = true
|
|
57
|
+
init_forbid_extra = true
|
|
58
|
+
warn_required_dynamic_aliases = true
|
|
59
|
+
|
|
60
|
+
[tool.pytest.ini_options]
|
|
61
|
+
addopts = """
|
|
62
|
+
--verbose
|
|
63
|
+
--cov=src/horus_docker
|
|
64
|
+
--cov-report=html
|
|
65
|
+
--cov-report=term-missing
|
|
66
|
+
--cov-fail-under=90
|
|
67
|
+
"""
|
|
68
|
+
minversion = "7.0"
|
|
69
|
+
python_classes = ["Test*"]
|
|
70
|
+
python_files = ["test_*.py", "*_test.py"]
|
|
71
|
+
python_functions = ["test_*"]
|
|
72
|
+
testpaths = ["tests"]
|
|
73
|
+
asyncio_mode = "auto"
|
|
74
|
+
|
|
75
|
+
[tool.ruff]
|
|
76
|
+
line-length = 79
|
|
77
|
+
target-version = "py313"
|
|
78
|
+
exclude = [".git", ".venv", "build", "dist", "__pycache__"]
|
|
79
|
+
|
|
80
|
+
[tool.ruff.lint]
|
|
81
|
+
select = [
|
|
82
|
+
"D", # pydocstyle
|
|
83
|
+
"E", # pycodestyle errors
|
|
84
|
+
"W", # pycodestyle warnings
|
|
85
|
+
"F", # pyflakes
|
|
86
|
+
"I", # isort
|
|
87
|
+
"N", # pep8-naming
|
|
88
|
+
"UP", # pyupgrade
|
|
89
|
+
"B", # flake8-bugbear
|
|
90
|
+
"PL", # pylint
|
|
91
|
+
"RUF", # ruff-specific
|
|
92
|
+
"ARG", # ruff-arglint
|
|
93
|
+
"SLF", # ruff-slf
|
|
94
|
+
]
|
|
95
|
+
extend-select = ["T201"] # Prevent use of print()
|
|
96
|
+
|
|
97
|
+
ignore = [
|
|
98
|
+
"E203", # Whitespace before ':', conflicts with formatter
|
|
99
|
+
"D104", # Missing docstring in __init__ (often redundant)
|
|
100
|
+
"D205", # 1 blank line required between summary line and description
|
|
101
|
+
"D212", # Multi-line docstring summary should start at the first line
|
|
102
|
+
"D200", # One-line docstring should fit on one line
|
|
103
|
+
"PLR2004" # Magic numbers are ok
|
|
104
|
+
]
|
|
105
|
+
|
|
106
|
+
[tool.ruff.lint.pydocstyle]
|
|
107
|
+
convention = "google"
|
|
108
|
+
|
|
109
|
+
[tool.ruff.lint.per-file-ignores]
|
|
110
|
+
"tests/**/*.py" = ["SLF001"]
|
|
111
|
+
|
|
112
|
+
[tool.ruff.format]
|
|
113
|
+
quote-style = "double"
|
|
114
|
+
indent-style = "space"
|