Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce use of JSON recursive type #253

Merged
merged 1 commit into from
Apr 30, 2023
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 2 additions & 2 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ repos:
name: Upgrade constraints files and requirements
files: ^(pyproject\.toml|requirements\.txt)$
language: python
entry: python -m piptools compile --resolver=backtracking --upgrade -q --strip-extras --extra docs --extra test --output-file=requirements.txt pyproject.toml --unsafe-package ansible-core --unsafe-package resolvelib
entry: python -m piptools compile --resolver=backtracking --upgrade -q --strip-extras --extra docs --extra test --output-file=requirements.txt pyproject.toml --unsafe-package ansible-core --unsafe-package resolvelib --unsafe-package typing_extensions
pass_filenames: false
stages:
- manual
Expand All @@ -107,7 +107,7 @@ repos:
name: Check constraints files and requirements
files: ^(pyproject\.toml|requirements\.txt)$
language: python
entry: python -m piptools compile --resolver=backtracking -q --strip-extras --extra docs --extra test --output-file=requirements.txt pyproject.toml --unsafe-package ansible-core --unsafe-package resolvelib
entry: python -m piptools compile --resolver=backtracking -q --strip-extras --extra docs --extra test --output-file=requirements.txt pyproject.toml --unsafe-package ansible-core --unsafe-package resolvelib --unsafe-package typing_extensions
pass_filenames: false
additional_dependencies:
- pip-tools>=6.11.0
9 changes: 4 additions & 5 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ dependencies = [
"PyYAML",
"subprocess-tee>=0.4.1",
"jsonschema>=4.6.0",
"typing-extensions>=4.5.0;python_version<'3.10'",
]

[project.urls]
Expand Down Expand Up @@ -117,15 +118,13 @@ filterwarnings = ["error"]
select = ["ALL"]
ignore = [
# Disabled on purpose:
"E501", # we use black
"RET504", # Unnecessary variable assignment before `return` statement
"ANN101", # Missing type annotation for `self` in method
"D203", # incompatible with D211
"D213", # incompatible with D212
"E501", # we use black
"RET504", # Unnecessary variable assignment before `return` statement
# Temporary disabled during adoption:
"A003", # Class attribute `exec` is shadowing a python builtin
"ANN101",
"ANN401",
"ARG",
"S506", # Probable use of unsafe loader `FullLoader`
"S607", # Starting a process with a partial executable path

Expand Down
5 changes: 3 additions & 2 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# This file is autogenerated by pip-compile with Python 3.9
# by the following command:
#
# pip-compile --extra=docs --extra=test --output-file=requirements.txt --resolver=backtracking --strip-extras --unsafe-package=ansible-core --unsafe-package=resolvelib pyproject.toml
# pip-compile --extra=docs --extra=test --output-file=requirements.txt --resolver=backtracking --strip-extras --unsafe-package=ansible-core --unsafe-package=resolvelib --unsafe-package=typing_extensions pyproject.toml
#
argparse-manpage==4.1
# via ansible-compat (pyproject.toml)
Expand Down Expand Up @@ -269,8 +269,9 @@ tomli==2.0.1
# build
# pyproject-hooks
# pytest
typing-extensions==4.5.0
typing-extensions==4.5.0 ; python_version < "3.10"
# via
# ansible-compat (pyproject.toml)
# black
# mkdocs-ansible
# mkdocstrings
Expand Down
2 changes: 1 addition & 1 deletion src/ansible_compat/loaders.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from pathlib import Path


def yaml_from_file(path: Path) -> Any:
def yaml_from_file(path: Path) -> Any: # noqa: ANN401
"""Return a loaded YAML file."""
with path.open(encoding="utf-8") as content:
return yaml.load(content, Loader=yaml.FullLoader)
Expand Down
7 changes: 6 additions & 1 deletion src/ansible_compat/runtime.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,12 @@ def __init__(
from ansible.utils.display import Display

# pylint: disable=unused-argument
def warning(self: Display, msg: str, *, formatted: bool = False) -> None:
def warning(
self: Display, # noqa: ARG001
msg: str,
*,
formatted: bool = False, # noqa: ARG001
) -> None:
"""Override ansible.utils.display.Display.warning to avoid printing warnings."""
warnings.warn(msg, category=AnsibleWarning, stacklevel=2)

Expand Down
8 changes: 5 additions & 3 deletions src/ansible_compat/schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@
import json
from collections.abc import Mapping, Sequence
from dataclasses import dataclass
from typing import Any, Union
from typing import Union

import jsonschema
from jsonschema.validators import validator_for

from ansible_compat.types import JSON


def to_path(schema_path: Sequence[Union[str, int]]) -> str:
"""Flatten a path to a dot delimited string.
Expand Down Expand Up @@ -56,8 +58,8 @@ def to_friendly(self) -> str:


def validate(
schema: Union[str, Mapping[str, Any]],
data: dict[str, Any],
schema: JSON,
data: JSON,
) -> list[JsonSchemaError]:
"""Validate some data against a JSON schema.

Expand Down
23 changes: 23 additions & 0 deletions src/ansible_compat/types.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
"""Custom types."""
from __future__ import annotations

from collections.abc import Mapping, Sequence
from typing import Union

try: # py39 does not have TypeAlias
from typing_extensions import TypeAlias
except ImportError:
from typing import TypeAlias # type: ignore[no-redef,attr-defined]

JSON: TypeAlias = Union[dict[str, "JSON"], list["JSON"], str, int, float, bool, None]
JSON_ro: TypeAlias = Union[
Mapping[str, "JSON_ro"],
Sequence["JSON_ro"],
str,
int,
float,
bool,
None,
]

__all__ = ["JSON", "JSON_ro"]
4 changes: 2 additions & 2 deletions test/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

@pytest.fixture()
# pylint: disable=unused-argument
def runtime(scope: str = "session") -> Generator[Runtime, None, None]:
def runtime(scope: str = "session") -> Generator[Runtime, None, None]: # noqa: ARG001
"""Isolated runtime fixture."""
instance = Runtime(isolated=True)
yield instance
Expand All @@ -20,7 +20,7 @@ def runtime(scope: str = "session") -> Generator[Runtime, None, None]:
# pylint: disable=unused-argument
def runtime_tmp(
tmp_path: pathlib.Path,
scope: str = "session",
scope: str = "session", # noqa: ARG001
) -> Generator[Runtime, None, None]:
"""Isolated runtime fixture using a temp directory."""
instance = Runtime(project_dir=tmp_path, isolated=True)
Expand Down
5 changes: 4 additions & 1 deletion test/test_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,10 @@ def test_ansible_version_missing(monkeypatch: MonkeyPatch) -> None:
"""Validate ansible_version behavior when ansible is missing."""
monkeypatch.setattr(
"subprocess.run",
lambda *args, **kwargs: subprocess.CompletedProcess(args=[], returncode=1),
lambda *args, **kwargs: subprocess.CompletedProcess( # noqa: ARG005
args=[],
returncode=1,
),
)
with pytest.raises(
MissingAnsibleError,
Expand Down
8 changes: 6 additions & 2 deletions test/test_runtime.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,11 @@ def test_runtime_missing_ansible_module(monkeypatch: MonkeyPatch) -> None:
class RaiseException:
"""Class to raise an exception."""

def __init__(self, *args: Any, **kwargs: Any) -> None:
def __init__(
self,
*args: Any, # noqa: ARG002,ANN401
**kwargs: Any, # noqa: ARG002,ANN401
) -> None:
raise ModuleNotFoundError

monkeypatch.setattr("importlib.import_module", RaiseException)
Expand Down Expand Up @@ -362,7 +366,7 @@ def test__update_env_no_default(
def test__update_env(
monkeypatch: MonkeyPatch,
old_value: str,
default: str, # pylint: disable=unused-argument
default: str, # pylint: disable=unused-argument # noqa: ARG001
value: list[str],
result: str,
) -> None:
Expand Down
15 changes: 10 additions & 5 deletions test/test_schema.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
"""Tests for schema utilities."""
from __future__ import annotations

import json
from pathlib import Path
from typing import Any
from typing import TYPE_CHECKING, Any

import pytest

from ansible_compat.schema import JsonSchemaError, json_path, validate

if TYPE_CHECKING:
from ansible_compat.types import JSON

expected_results = [
JsonSchemaError(
message="False is not of type 'string'",
Expand All @@ -31,16 +36,16 @@
]


def json_from_asset(file_name: str) -> Any:
def json_from_asset(file_name: str) -> JSON:
"""Load a json file from disk."""
file = Path(__file__).parent / file_name
with file.open(encoding="utf-8") as f:
return json.load(f)
return json.load(f) # type: ignore[no-any-return]


def jsonify(data: Any) -> Any:
def jsonify(data: Any) -> JSON: # noqa: ANN401
"""Convert object in JSON data structure."""
return json.loads(json.dumps(data, default=vars, sort_keys=True))
return json.loads(json.dumps(data, default=vars, sort_keys=True)) # type: ignore[no-any-return]


@pytest.mark.parametrize("index", range(1))
Expand Down