Skip to content

Commit

Permalink
Make linter aware of its own requirements (#4159)
Browse files Browse the repository at this point in the history
  • Loading branch information
ssbarnea authored May 14, 2024
1 parent b77726d commit 492d840
Show file tree
Hide file tree
Showing 10 changed files with 69 additions and 8 deletions.
4 changes: 3 additions & 1 deletion .config/constraints.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
#
# pip-compile --all-extras --no-annotate --output-file=.config/constraints.txt --strip-extras --unsafe-package=resolvelib --unsafe-package=ruamel-yaml-clib --unsafe-package=wcmatch pyproject.toml
#
ansible-compat==24.5.1a0
ansible-compat==24.5.1
ansible-core==2.16.6
astroid==3.1.0
attrs==23.2.0
Expand Down Expand Up @@ -35,6 +35,7 @@ ghp-import==2.1.0
griffe==0.45.0
htmlmin2==0.1.13
idna==3.7
importlib-metadata==7.1.0
iniconfig==2.0.0
isort==5.13.2
jinja2==3.1.4
Expand Down Expand Up @@ -110,6 +111,7 @@ urllib3==2.2.1
watchdog==4.0.0
webencodings==0.5.1
yamllint==1.35.1
zipp==3.18.1

# The following packages are considered to be unsafe in a requirements file:
# resolvelib
Expand Down
2 changes: 1 addition & 1 deletion .config/requirements-lock.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
#
# pip-compile --no-annotate --output-file=.config/requirements-lock.txt --strip-extras --unsafe-package=resolvelib --unsafe-package=ruamel-yaml-clib pyproject.toml
#
ansible-compat==24.5.1a0
ansible-compat==24.5.1
ansible-core==2.16.6
attrs==23.2.0
black==24.4.2
Expand Down
1 change: 1 addition & 0 deletions .config/requirements.in
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ ansible-compat>=24.5.0dev0 # GPLv3
# alphabetically sorted:
black>=24.3.0 # MIT (security)
filelock>=3.3.0 # The Unlicense
importlib-metadata # Apache
jsonschema>=4.10.0 # MIT, version needed for improved errors
packaging>=21.3 # Apache-2.0,BSD-2-Clause
pathspec>=0.10.3 # Mozilla Public License 2.0 (MPL 2.0)
Expand Down
2 changes: 1 addition & 1 deletion .github/lower-constraints.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# automatically updated by dependabot. This should be kept in sync with
# minimal requirements configured inside .config/requirements.in
ansible-core==2.13.0
ansible-compat==24.5.1a0 # GPLv3
ansible-compat==24.5.1 # GPLv3
black==24.3.0 # MIT (security)
filelock==3.3.0 # The Unlicense
jsonschema==4.10.0 # MIT, version needed for improved errors
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/tox.yml
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ jobs:
env:
# Number of expected test passes, safety measure for accidental skip of
# tests. Update value if you add/remove tests.
PYTEST_REQPASS: 869
PYTEST_REQPASS: 870
steps:
- uses: actions/checkout@v4
with:
Expand Down
6 changes: 4 additions & 2 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -153,10 +153,11 @@ repos:
# empty args needed in order to match mypy cli behavior
args: [--strict]
additional_dependencies:
- ansible-compat>=24.5.1a0
- ansible-compat>=24.5.1
- black>=22.10.0
- cryptography>=39.0.1
- filelock>=3.12.2
- importlib_metadata
- jinja2
- license-expression >= 30.3.0
- pytest-mock
Expand All @@ -182,11 +183,12 @@ repos:
args:
- --output-format=colorized
additional_dependencies:
- ansible-compat>=24.5.1a0
- ansible-compat>=24.5.1
- ansible-core>=2.14.0
- black>=22.10.0
- docutils
- filelock>=3.12.2
- importlib_metadata
- jsonschema>=4.20.0
- license-expression >= 30.3.0
- pytest-mock
Expand Down
13 changes: 12 additions & 1 deletion src/ansiblelint/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import itertools
import logging
import os
import sys
from functools import lru_cache
from pathlib import Path
from typing import TYPE_CHECKING, Any
Expand All @@ -21,6 +22,7 @@
from ansiblelint.config import options as default_options
from ansiblelint.constants import RC, RULE_DOC_URL
from ansiblelint.loaders import IGNORE_FILE
from ansiblelint.requirements import Reqs
from ansiblelint.stats import SummarizedResults, TagStats

if TYPE_CHECKING:
Expand Down Expand Up @@ -53,9 +55,18 @@ def __init__(self, options: Options):
require_module=True,
verbosity=options.verbosity,
)
self.reqs = Reqs("ansible-lint")
package = "ansible-core"
if not self.reqs.matches(
package,
str(self.runtime.version),
): # pragma: no cover
msg = f"ansible-lint requires {package}{','.join(str(x) for x in self.reqs[package])} and current version is {self.runtime.version}"
logging.error(msg)
sys.exit(RC.INVALID_CONFIG)

# pylint: disable=import-outside-toplevel
from ansiblelint.yaml_utils import load_yamllint_config # noqa: 811,I001
from ansiblelint.yaml_utils import load_yamllint_config # noqa: 811, I001

self.yamllint_config = load_yamllint_config()

Expand Down
28 changes: 28 additions & 0 deletions src/ansiblelint/requirements.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
"""Utilities for checking python packages requirements."""

import importlib_metadata
from packaging.requirements import Requirement
from packaging.specifiers import SpecifierSet
from packaging.version import Version


class Reqs(dict[str, SpecifierSet]):
"""Utility class for working with package dependencies."""

reqs: dict[str, SpecifierSet]

def __init__(self, name: str = "ansible-lint") -> None:
"""Load linter metadata requirements."""
for req_str in importlib_metadata.metadata(name).json["requires_dist"]:
req = Requirement(req_str)
if req.name:
self[req.name] = req.specifier

def matches(self, req_name: str, req_version: str | Version) -> bool:
"""Verify if given version is matching current metadata dependencies."""
if req_name not in self:
return False
return all(
specifier.contains(str(req_version), prereleases=True)
for specifier in self[req_name]
)
18 changes: 18 additions & 0 deletions test/test_requirements.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
"""Tests requirements module."""

from ansible_compat.runtime import Runtime

from ansiblelint.requirements import Reqs


def test_reqs() -> None:
"""Performs basic testing of Reqs class."""
reqs = Reqs()
runtime = Runtime()
assert "ansible-core" in reqs
# checks that this ansible core version is not supported:
assert reqs.matches("ansible-core", "0.0") is False
# assert that invalid package name
assert reqs.matches("this-package-does-not-exist", "0.0") is False
# check the current ansible core version is supported:
assert reqs.matches("ansible-core", runtime.version)
1 change: 0 additions & 1 deletion test/test_yaml_utils.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
"""Tests for yaml-related utility functions."""

# pylint: disable=too-many-lines
from __future__ import annotations

from io import StringIO
Expand Down

0 comments on commit 492d840

Please sign in to comment.