Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
321a6cc
Bump astral-sh/setup-uv from 4 to 7
dependabot[bot] Dec 10, 2025
f40e467
Bump actions/checkout from 5 to 6
dependabot[bot] Dec 10, 2025
74dabea
Bump actions/cache from 4 to 5
dependabot[bot] Dec 15, 2025
e1458c4
Bump DavidAnson/markdownlint-cli2-action from 21 to 22
dependabot[bot] Dec 15, 2025
07e454c
Merge pull request #695 from opsmill/dependabot/github_actions/stable…
BeArchiTek Dec 16, 2025
335f515
Merge pull request #694 from opsmill/dependabot/github_actions/stable…
BeArchiTek Dec 16, 2025
4c4bc12
fix: py3.14 warnings due to iscoroutinefunction
fatih-acar Dec 11, 2025
6437f03
fix: upgrade pytest-asyncio for py3.14 compat
fatih-acar Dec 11, 2025
24d5fba
chore: add newsfragment
fatih-acar Dec 16, 2025
f01c0c6
Bump astral-sh/setup-uv from 4 to 7
dependabot[bot] Dec 10, 2025
1eae727
Bump actions/checkout from 5 to 6
dependabot[bot] Dec 10, 2025
5b86681
Bump DavidAnson/markdownlint-cli2-action from 21 to 22
dependabot[bot] Dec 15, 2025
ea925fd
Bump actions/cache from 4 to 5
dependabot[bot] Dec 15, 2025
4315fcc
fix: py3.14 warnings due to iscoroutinefunction
fatih-acar Dec 11, 2025
70aefcc
fix: upgrade pytest-asyncio for py3.14 compat
fatih-acar Dec 11, 2025
ef01750
chore: add newsfragment
fatih-acar Dec 16, 2025
af55884
fix(analyzer): allowing passing a parsed query
fatih-acar Nov 14, 2025
8909db5
Add ty as a type checker
ogenstad Dec 19, 2025
eadf3f4
Merge pull request #702 from opsmill/pog-add-ty-typechecker
ogenstad Dec 19, 2025
d215e94
Merge pull request #703 from opsmill/stable
ogenstad Dec 19, 2025
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
8 changes: 5 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ jobs:
timeout-minutes: 5
steps:
- name: "Check out repository code"
uses: "actions/checkout@v5"
uses: "actions/checkout@v6"
- name: Set up Python
uses: actions/setup-python@v6
with:
Expand All @@ -91,6 +91,8 @@ jobs:
run: "uv run ruff check ."
- name: "Linting: ruff format"
run: "uv run ruff format --check --diff ."
- name: "Linting: ty check"
run: "uv run ty check ."


markdown-lint:
Expand All @@ -104,7 +106,7 @@ jobs:
- name: "Check out repository code"
uses: "actions/checkout@v6"
- name: "Linting: markdownlint"
uses: DavidAnson/markdownlint-cli2-action@v21
uses: DavidAnson/markdownlint-cli2-action@v22
with:
config: .markdownlint.yaml
globs: |
Expand Down Expand Up @@ -138,7 +140,7 @@ jobs:
timeout-minutes: 5
steps:
- name: "Check out repository code"
uses: "actions/checkout@v5"
uses: "actions/checkout@v6"
- name: "Set up Python"
uses: "actions/setup-python@v6"
with:
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/publish-pypi.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ jobs:
python-version: "3.12"

- name: Install UV
uses: astral-sh/setup-uv@v4
uses: astral-sh/setup-uv@v7
with:
version: ${{ needs.prepare-environment.outputs.UV_VERSION }}

Expand All @@ -52,7 +52,7 @@ jobs:
submodules: true

- name: Cache UV dependencies
uses: "actions/cache@v4"
uses: "actions/cache@v5"
id: "cached-uv-dependencies"
with:
path: ".venv"
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ jobs:
python-version: "3.12"

- name: Install UV
uses: astral-sh/setup-uv@v4
uses: astral-sh/setup-uv@v7
with:
version: "${{ needs.prepare-environment.outputs.UV_VERSION }}"

Expand Down
1 change: 1 addition & 0 deletions changelog/+1b40f022.housekeeping.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fixed Python 3.14 compatibility warnings. Testing now requires pytest>=9.
4 changes: 2 additions & 2 deletions infrahub_sdk/analyzer.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,10 @@ class GraphQLOperation(BaseModel):


class GraphQLQueryAnalyzer:
def __init__(self, query: str, schema: GraphQLSchema | None = None) -> None:
def __init__(self, query: str, schema: GraphQLSchema | None = None, document: DocumentNode | None = None) -> None:
self.query: str = query
self.schema: GraphQLSchema | None = schema
self.document: DocumentNode = parse(self.query)
self.document: DocumentNode = document or parse(self.query)
self._fields: dict | None = None

@property
Expand Down
4 changes: 2 additions & 2 deletions infrahub_sdk/checks.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from __future__ import annotations

import asyncio
import importlib
import inspect
import os
import warnings
from abc import abstractmethod
Expand Down Expand Up @@ -160,7 +160,7 @@ async def run(self, data: dict | None = None) -> bool:
data = await self.collect_data()
unpacked = data.get("data") or data

if asyncio.iscoroutinefunction(self.validate):
if inspect.iscoroutinefunction(self.validate):
await self.validate(data=unpacked)
else:
self.validate(data=unpacked)
Expand Down
3 changes: 2 additions & 1 deletion infrahub_sdk/ctl/cli_commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import asyncio
import functools
import importlib
import inspect
import logging
import platform
import sys
Expand Down Expand Up @@ -240,7 +241,7 @@ async def _run_transform(
console.print("[yellow] you can specify a different branch with --branch")
raise typer.Abort()

if asyncio.iscoroutinefunction(transform_func):
if inspect.iscoroutinefunction(transform_func):
output = await transform_func(response)
else:
output = transform_func(response)
Expand Down
4 changes: 2 additions & 2 deletions infrahub_sdk/ctl/utils.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from __future__ import annotations

import asyncio
import inspect
import logging
import traceback
from collections.abc import Callable, Coroutine
Expand Down Expand Up @@ -83,7 +83,7 @@ def catch_exception(
console = Console()

def decorator(func: Callable[..., T]) -> Callable[..., T | Coroutine[Any, Any, T]]:
if asyncio.iscoroutinefunction(func):
if inspect.iscoroutinefunction(func):

@wraps(func)
async def async_wrapper(*args: Any, **kwargs: Any) -> T:
Expand Down
4 changes: 2 additions & 2 deletions infrahub_sdk/transforms.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from __future__ import annotations

import asyncio
import inspect
import os
from abc import abstractmethod
from typing import TYPE_CHECKING, Any
Expand Down Expand Up @@ -75,7 +75,7 @@ async def run(self, data: dict | None = None) -> Any:
unpacked = data.get("data") or data
await self.process_nodes(data=unpacked)

if asyncio.iscoroutinefunction(self.transform):
if inspect.iscoroutinefunction(self.transform):
return await self.transform(data=unpacked)

return self.transform(data=unpacked)
68 changes: 66 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,8 @@ all = [
# Core optional dependencies
tests = [
"infrahub-testcontainers>=1.5.1",
"pytest",
"pytest-asyncio<0.23",
"pytest>=9.0,<9.1",
"pytest-asyncio>=1.3,<1.4",
"pytest-clarity>=1.0.1",
"pytest-cov>=4.0.0",
"pytest-httpx>=0.30",
Expand All @@ -82,6 +82,7 @@ lint = [
"mypy==1.11.2",
"ruff==0.14.5",
"astroid>=3.1,<4.0",
"ty==0.0.4",
]
types = [
"types-ujson",
Expand All @@ -108,13 +109,76 @@ exclude_lines = ["if TYPE_CHECKING:", "raise NotImplementedError()"]

[tool.pytest.ini_options]
asyncio_mode = "auto"
asyncio_default_fixture_loop_scope = "session"
testpaths = ["tests"]
filterwarnings = [
"ignore:Module already imported so cannot be rewritten",
"ignore:Deprecated call to",
]
addopts = "-vs --cov-report term-missing --cov-report xml --dist loadscope"

[tool.ty]

[tool.ty.environment]
python-version = "3.10"

[[tool.ty.overrides]]
include = ["infrahub_sdk/**"]

[tool.ty.overrides.rules]
##################################################################################################
# The ignored rules below should be removed once the code has been updated, they are included #
# like this so that we can reactivate them one by one. #
##################################################################################################
division-by-zero = "ignore"
invalid-argument-type = "ignore"
invalid-assignment = "ignore"
invalid-await = "ignore"
invalid-return-type = "ignore"
invalid-type-form = "ignore"
missing-argument = "ignore"
no-matching-overload = "ignore"
possibly-unresolved-reference = "ignore"
redundant-cast = "ignore"
too-many-positional-arguments = "ignore"
type-assertion-failure = "ignore"
unknown-argument = "ignore"
unresolved-attribute = "ignore"
unresolved-import = "ignore"
unsupported-operator = "ignore"


[[tool.ty.overrides]]
include = ["tests/**"]

[tool.ty.overrides.rules]
##################################################################################################
# The ignored rules below should be removed once the code has been updated, they are included #
# like this so that we can reactivate them one by one. #
##################################################################################################
invalid-argument-type = "ignore"
invalid-assignment = "ignore"
invalid-method-override = "ignore"
invalid-return-type = "ignore"
no-matching-overload = "ignore"
non-subscriptable = "ignore"
not-iterable = "ignore"
possibly-missing-attribute = "ignore"
unresolved-attribute = "ignore"
unresolved-import = "ignore"


[[tool.ty.overrides]]
include = ["docs/**"]

[tool.ty.overrides.rules]
##################################################################################################
# The ignored rules below should be removed once the code has been updated, they are included #
# like this so that we can reactivate them one by one. #
##################################################################################################
invalid-assignment = "ignore"


[tool.mypy]
pretty = true
ignore_missing_imports = true
Expand Down
10 changes: 10 additions & 0 deletions tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,15 @@ def lint_mypy(context: Context) -> None:
context.run(exec_cmd)


@task
def lint_ty(context: Context) -> None:
"""Run ty type checker against all Python files."""
print(" - Check code with ty")
exec_cmd = "uv run ty check ."
with context.cd(MAIN_DIRECTORY_PATH):
context.run(exec_cmd)


@task
def lint_ruff(context: Context) -> None:
"""Run Linter to check all Python files."""
Expand Down Expand Up @@ -220,6 +229,7 @@ def lint_all(context: Context) -> None:
"""Run all linters."""
lint_yaml(context)
lint_ruff(context)
lint_ty(context)
lint_mypy(context)
lint_docs(context)

Expand Down
14 changes: 6 additions & 8 deletions tests/conftest.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import asyncio
import os
from collections.abc import Generator

import pytest
import pytest_asyncio

from infrahub_sdk.ctl import config

Expand All @@ -11,13 +11,11 @@
ENV_VARS_TO_CLEAN = ["INFRAHUB_ADDRESS", "INFRAHUB_TOKEN", "INFRAHUB_BRANCH", "INFRAHUB_USERNAME", "INFRAHUB_PASSWORD"]


@pytest.fixture(scope="session")
def event_loop() -> Generator[asyncio.AbstractEventLoop]:
"""Overrides pytest default function scoped event loop"""
policy = asyncio.get_event_loop_policy()
loop = policy.new_event_loop()
yield loop
loop.close()
def pytest_collection_modifyitems(items) -> None:
pytest_asyncio_tests = (item for item in items if pytest_asyncio.is_async_test(item))
session_scope_marker = pytest.mark.asyncio(loop_scope="session")
for async_test in pytest_asyncio_tests:
async_test.add_marker(session_scope_marker, append=False)


@pytest.fixture(scope="session", autouse=True)
Expand Down
Loading