Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 40 additions & 0 deletions .github/workflows/fmt.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
---
name: Reformat code

on:
push:
branches-ignore:
- main
- master

jobs:
fmt:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Set up ruff
run: curl -LsSf https://astral.sh/ruff/0.15.5/install.sh | sh
- name: Reformat and push
shell: bash
run: |-
ruff check --fix
ruff format
git config user.name "Automated"
git config user.email "actions@users.noreply.github.com"
timestamp=$(date -u)
git commit -am "ruff: ${timestamp}" || exit 0
git push
echo "COMMITTED=1" >> "$GITHUB_ENV"
- name: "Trigger build"
run: |-
if [ -z "$COMMITTED" ]; then
echo "No commit"
exit 0
fi
curl -L \
-X POST \
-H "Accept: application/vnd.github+json" \
-H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" \
-H "X-GitHub-Api-Version: 2022-11-28" \
https://api.github.com/repos/exoscale/python-exoscale/actions/workflows/main.yml/dispatches \
-d '{"ref": "'${{ github.ref }}'"}'
19 changes: 4 additions & 15 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
name: CI

"on":
workflow_dispatch:
push:
branches:
- '**'
Expand All @@ -19,28 +20,16 @@ jobs:
strategy:
fail-fast: false
matrix:
python-version: ['3.9', '3.10', '3.11', '3.12', '3.13']
python-version: ['3.10', '3.11', '3.12', '3.13', '3.14']
steps:
- uses: actions/checkout@v4
- uses: astral-sh/setup-uv@v3
- uses: actions/checkout@v6
- uses: astral-sh/setup-uv@v7
with:
enable-cache: true
cache-dependency-glob: "pyproject.toml"
- name: Tests
run: |
uv --version
uv run --python ${{ matrix.python-version }} pytest
env:
EXOSCALE_API_KEY: ${{ secrets.EXOSCALE_API_KEY }}
EXOSCALE_API_SECRET: ${{ secrets.EXOSCALE_API_SECRET }}
lint:
name: Linting
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up ruff
run: curl -LsSf https://astral.sh/ruff/0.6.9/install.sh | sh
- name: Lint
shell: bash
run: |-
ruff check
6 changes: 1 addition & 5 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,7 @@
# documentation root, use os.path.abspath to make it absolute, like shown here.
#
# import os
import sys
from datetime import datetime
from sphinx_markdown_parser.parser import MarkdownParser # noqa

sys.path.insert(0, "exoscale")


# -- Project information -----------------------------------------------------
Expand All @@ -32,7 +28,7 @@
# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = ["sphinx.ext.autodoc", "sphinx.ext.napoleon", "recommonmark"]
extensions = ["sphinx.ext.autodoc", "sphinx.ext.napoleon", "myst_parser"]

# Add any paths that contain templates here, relative to this directory.
templates_path = ["_templates"]
Expand Down
11 changes: 5 additions & 6 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,18 @@ authors = [{name="Exoscale", email="support@exoscale.com"}]
license = "ISC"
description = "Clients for Exoscale IaaS APIs"
readme = "README.md"
requires-python = ">=3.8"
requires-python = ">=3.10"
classifiers = [
"Intended Audience :: Developers",
"Intended Audience :: System Administrators",
"License :: OSI Approved :: ISC License (ISCL)",
"Operating System :: OS Independent",
"Programming Language :: Python",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
"Programming Language :: Python :: 3.14",
]
dependencies = [
"requests-exoscale-auth>=1.1.2",
Expand Down Expand Up @@ -47,12 +47,11 @@ extend-select = ["B", "Q"]
[tool.black]
line-length = 79

[tool.uv]
dev-dependencies = [
[dependency-groups]
dev = [
"requests-mock>=1.12.1",
"pytest>=5.0.0",
"recommonmark>=0.5.0",
"sphinx-markdown-parser>=0.1.1",
"sphinx-rtd-theme>=0.4.3",
"sphinx>=2.1.2",
"myst-parser",
]
53 changes: 31 additions & 22 deletions tests/test_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -147,14 +147,17 @@ def test_wait_time_success(requests_mock):
"https://api-ch-gva-2.exoscale.com/v2/operation/e2047130-b86e-11ef-83b3-0d8312b2c2d7", # noqa
_mock_poll_response(3),
)
with patch(
"exoscale.api.v2._time",
side_effect=[
0, # start of poll
1, # duration of first loop: 1s
5, # duration of second loop: 4s
],
) as time, patch("exoscale.api.v2._sleep") as sleep:
with (
patch(
"exoscale.api.v2._time",
side_effect=[
0, # start of poll
1, # duration of first loop: 1s
5, # duration of second loop: 4s
],
) as time,
patch("exoscale.api.v2._sleep") as sleep,
):
client = Client(key="EXOtest", secret="sdsd")
client.wait(operation_id="e2047130-b86e-11ef-83b3-0d8312b2c2d7")
assert len(time.call_args_list) == 3
Expand All @@ -166,12 +169,15 @@ def test_wait_time_poll_errors(requests_mock):
"https://api-ch-gva-2.exoscale.com/v2/operation/e2047130-b86e-11ef-83b3-0d8312b2c2d7", # noqa
_mock_poll_response(6, status_code=500),
)
with patch(
"exoscale.api.v2._time",
side_effect=[
0, # start of poll
],
) as time, patch("exoscale.api.v2._sleep") as sleep:
with (
patch(
"exoscale.api.v2._time",
side_effect=[
0, # start of poll
],
) as time,
patch("exoscale.api.v2._sleep") as sleep,
):
client = Client(key="EXOtest", secret="sdsd")
try:
client.wait(operation_id="e2047130-b86e-11ef-83b3-0d8312b2c2d7")
Expand All @@ -188,14 +194,17 @@ def test_wait_time_failure(requests_mock):
"https://api-ch-gva-2.exoscale.com/v2/operation/e2047130-b86e-11ef-83b3-0d8312b2c2d7", # noqa
_mock_poll_response(3, result="failure"),
)
with patch(
"exoscale.api.v2._time",
side_effect=[
0, # start of poll
1, # duration of first loop: 1s
5, # duration of second loop: 4s
],
) as time, patch("exoscale.api.v2._sleep") as sleep:
with (
patch(
"exoscale.api.v2._time",
side_effect=[
0, # start of poll
1, # duration of first loop: 1s
5, # duration of second loop: 4s
],
) as time,
patch("exoscale.api.v2._sleep") as sleep,
):
client = Client(key="EXOtest", secret="sdsd")
try:
client.wait(operation_id="e2047130-b86e-11ef-83b3-0d8312b2c2d7")
Expand Down
Loading