Skip to content

Commit

Permalink
Make linter aware of its own requirements
Browse files Browse the repository at this point in the history
Related: #4144
  • Loading branch information
ssbarnea committed May 14, 2024
1 parent b77726d commit ebdff8d
Show file tree
Hide file tree
Showing 7 changed files with 58 additions and 1 deletion.
2 changes: 2 additions & 0 deletions .config/constraints.txt
Original file line number Diff line number Diff line change
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
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/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
2 changes: 2 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,7 @@ repos:
- black>=22.10.0
- cryptography>=39.0.1
- filelock>=3.12.2
- importlib_metadata
- jinja2
- license-expression >= 30.3.0
- pytest-mock
Expand Down Expand Up @@ -187,6 +188,7 @@ repos:
- black>=22.10.0
- docutils
- filelock>=3.12.2
- importlib_metadata
- jsonschema>=4.20.0
- license-expression >= 30.3.0
- pytest-mock
Expand Down
8 changes: 8 additions & 0 deletions 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,6 +55,12 @@ 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)):
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)

Check warning on line 63 in src/ansiblelint/app.py

View check run for this annotation

Codecov / codecov/patch

src/ansiblelint/app.py#L61-L63

Added lines #L61 - L63 were not covered by tests

# pylint: disable=import-outside-toplevel
from ansiblelint.yaml_utils import load_yamllint_config # noqa: 811,I001
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

Check warning on line 24 in src/ansiblelint/requirements.py

View check run for this annotation

Codecov / codecov/patch

src/ansiblelint/requirements.py#L24

Added line #L24 was not covered by tests
return all(
specifier.contains(str(req_version), prereleases=True)
for specifier in self[req_name]
)
16 changes: 16 additions & 0 deletions test/test_requirements.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
"""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
# check the current ansible core version is supported:
assert reqs.matches("ansible-core", runtime.version)

0 comments on commit ebdff8d

Please sign in to comment.