Skip to content

Commit

Permalink
More type (3) (#1498)
Browse files Browse the repository at this point in the history
  • Loading branch information
ssbarnea authored Apr 7, 2021
1 parent e83e7e7 commit 4779e5f
Show file tree
Hide file tree
Showing 5 changed files with 35 additions and 36 deletions.
11 changes: 1 addition & 10 deletions mypy.ini
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,12 @@ color_output = True
error_summary = True
disallow_untyped_calls = True
disallow_untyped_defs = True
; disallow_any_generics = True
disallow_any_generics = True
; disallow_any_unimported = True
; warn_redundant_casts = True
; warn_return_any = True
; warn_unused_configs = True

[mypy-ansiblelint.*]
ignore_missing_imports = True

[mypy-ansiblelint.testing.*]
disallow_untyped_defs = False

[mypy-test.*]
disallow_untyped_defs = False


# 3rd party ignores
[mypy-ansible]
Expand Down
6 changes: 3 additions & 3 deletions src/ansiblelint/app.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"""Application."""
import logging
import os
from typing import TYPE_CHECKING, List, Type
from typing import TYPE_CHECKING, Any, List, Type

from ansiblelint import formatters
from ansiblelint.color import console
Expand Down Expand Up @@ -66,9 +66,9 @@ def render_matches(self, matches: List[MatchError]) -> None:

def choose_formatter_factory(
options_list: "Namespace",
) -> Type[formatters.BaseFormatter]:
) -> Type[formatters.BaseFormatter[Any]]:
"""Select an output formatter based on the incoming command line arguments."""
r: Type[formatters.BaseFormatter] = formatters.Formatter
r: Type[formatters.BaseFormatter[Any]] = formatters.Formatter
if options_list.format == 'quiet':
r = formatters.QuietFormatter
elif options_list.parseable or options_list.format == 'pep8':
Expand Down
14 changes: 7 additions & 7 deletions src/ansiblelint/formatters/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
if TYPE_CHECKING:
from ansiblelint.errors import MatchError

T = TypeVar('T', bound='BaseFormatter')
T = TypeVar('T', bound='BaseFormatter') # type: ignore


class BaseFormatter(Generic[T]):
Expand Down Expand Up @@ -56,7 +56,7 @@ def escape(self, text: str) -> str:
return rich.markup.escape(text)


class Formatter(BaseFormatter):
class Formatter(BaseFormatter): # type: ignore
def format(self, match: "MatchError") -> str:
_id = getattr(match.rule, 'id', '000')
result = f"[error_code]{_id}[/][dim]:[/] [error_title]{self.escape(match.message)}[/]"
Expand All @@ -72,15 +72,15 @@ def format(self, match: "MatchError") -> str:
return result


class QuietFormatter(BaseFormatter):
class QuietFormatter(BaseFormatter[Any]):
def format(self, match: "MatchError") -> str:
return (
f"[error_code]{match.rule.id}[/] "
f"[filename]{self._format_path(match.filename or '')}[/]:{match.position}"
)


class ParseableFormatter(BaseFormatter):
class ParseableFormatter(BaseFormatter[Any]):
"""Parseable uses PEP8 compatible format."""

def format(self, match: "MatchError") -> str:
Expand All @@ -97,7 +97,7 @@ def format(self, match: "MatchError") -> str:
return result


class AnnotationsFormatter(BaseFormatter):
class AnnotationsFormatter(BaseFormatter): # type: ignore
# https://docs.github.com/en/actions/reference/workflow-commands-for-github-actions#setting-a-warning-message
"""Formatter for emitting violations as GitHub Workflow Commands.
Expand Down Expand Up @@ -139,7 +139,7 @@ def _severity_to_level(severity: str) -> str:
return 'error'


class ParseableSeverityFormatter(BaseFormatter):
class ParseableSeverityFormatter(BaseFormatter[Any]):
def format(self, match: "MatchError") -> str:

filename = self._format_path(match.filename or "")
Expand All @@ -154,7 +154,7 @@ def format(self, match: "MatchError") -> str:
)


class CodeclimateJSONFormatter(BaseFormatter):
class CodeclimateJSONFormatter(BaseFormatter[Any]):
"""Formatter for emitting violations in Codeclimate JSON report format.
The formatter expects a list of MatchError objects and returns a JSON formatted string.
Expand Down
21 changes: 14 additions & 7 deletions src/ansiblelint/testing/fixtures.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,31 +7,38 @@
"""
import copy
import os
from argparse import Namespace
from pathlib import Path
from typing import Iterator, Union

import pytest
from _pytest.fixtures import SubRequest

from ansiblelint.config import options # noqa: F401
from ansiblelint.constants import DEFAULT_RULESDIR
from ansiblelint.file_utils import Lintable
from ansiblelint.rules import RulesCollection
from ansiblelint.runner import Runner
from ansiblelint.testing import RunFromText


@pytest.fixture
def play_file_path(tmp_path):
def play_file_path(tmp_path: Path) -> str:
"""Fixture to return a playbook path."""
p = tmp_path / 'playbook.yml'
return str(p)


@pytest.fixture
def runner(play_file_path, default_rules_collection):
def runner(
play_file_path: Union[Lintable, str], default_rules_collection: RulesCollection
) -> Runner:
"""Fixture to return a Runner() instance."""
return Runner(play_file_path, rules=default_rules_collection)


@pytest.fixture
def default_rules_collection():
def default_rules_collection() -> RulesCollection:
"""Return default rule collection."""
assert os.path.isdir(DEFAULT_RULESDIR)
# For testing we want to manually enable opt-in rules
Expand All @@ -40,13 +47,13 @@ def default_rules_collection():


@pytest.fixture
def default_text_runner(default_rules_collection):
def default_text_runner(default_rules_collection: RulesCollection) -> RunFromText:
"""Return RunFromText instance for the default set of collections."""
return RunFromText(default_rules_collection)


@pytest.fixture
def rule_runner(request):
def rule_runner(request: SubRequest) -> RunFromText:
"""Return runner for a specific rule class."""
rule_class = request.param
collection = RulesCollection()
Expand All @@ -55,7 +62,7 @@ def rule_runner(request):


@pytest.fixture
def config_options():
def config_options() -> Iterator[Namespace]:
"""Return configuration options that will be restored after testrun."""
global options # pylint: disable=global-statement
original_options = copy.deepcopy(options)
Expand All @@ -64,7 +71,7 @@ def config_options():


@pytest.fixture
def _play_files(tmp_path, request):
def _play_files(tmp_path: Path, request: SubRequest) -> None:
if request.param is None:
return
for play_file in request.param:
Expand Down
19 changes: 10 additions & 9 deletions src/ansiblelint/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@
_logger = logging.getLogger(__name__)


def parse_yaml_from_file(filepath: str) -> Any:
def parse_yaml_from_file(filepath: str) -> AnsibleBaseYAMLObject:
dl = DataLoader()
if hasattr(dl, 'set_vault_password'):
dl.set_vault_password(DEFAULT_VAULT_PASSWORD)
Expand Down Expand Up @@ -166,7 +166,7 @@ def ansible_template(
}


def tokenize(line: str) -> Tuple[str, List[str], Dict]:
def tokenize(line: str) -> Tuple[str, List[str], Dict[str, str]]:
tokens = line.lstrip().split(" ")
if tokens[0] == '-':
tokens = tokens[1:]
Expand All @@ -187,15 +187,16 @@ def tokenize(line: str) -> Tuple[str, List[str], Dict]:
return (command, args, kwargs)


def _playbook_items(pb_data: dict) -> ItemsView:
def _playbook_items(pb_data: AnsibleBaseYAMLObject) -> ItemsView: # type: ignore
if isinstance(pb_data, dict):
return pb_data.items()
if not pb_data:
return []
return [] # type: ignore

# "if play" prevents failure if the play sequence contains None,
# which is weird but currently allowed by Ansible
# https://github.com/ansible-community/ansible-lint/issues/849
return [item for play in pb_data if play for item in play.items()]
return [item for play in pb_data if play for item in play.items()] # type: ignore


def _set_collections_basedir(basedir: str) -> None:
Expand All @@ -221,7 +222,7 @@ def find_children(lintable: Lintable) -> List[Lintable]: # noqa: C901
_set_collections_basedir(playbook_dir or os.path.abspath('.'))
add_all_plugin_dirs(playbook_dir or '.')
if lintable.kind == 'role':
playbook_ds = {'roles': [{'role': str(lintable.path)}]}
playbook_ds = AnsibleMapping({'roles': [{'role': str(lintable.path)}]})
elif lintable.kind not in ("playbook", "tasks"):
return []
else:
Expand All @@ -233,7 +234,7 @@ def find_children(lintable: Lintable) -> List[Lintable]: # noqa: C901
basedir = os.path.dirname(str(lintable.path))
# playbook_ds can be an AnsibleUnicode string, which we consider invalid
if isinstance(playbook_ds, str):
raise MatchError(filename=str(lintable.path), rule=LoadingFailureRule)
raise MatchError(filename=str(lintable.path), rule=LoadingFailureRule())
for item in _playbook_items(playbook_ds):
# if lintable.kind not in ["playbook"]:
# continue
Expand Down Expand Up @@ -413,7 +414,7 @@ def _get_task_handler_children_for_tasks_or_playbooks(
)


def _validate_task_handler_action_for_role(th_action: dict) -> None:
def _validate_task_handler_action_for_role(th_action: Dict[str, Any]) -> None:
"""Verify that the task handler action is valid for role include."""
module = th_action['__ansible_module__']

Expand Down Expand Up @@ -510,7 +511,7 @@ def _kv_to_dict(v: str) -> Dict[str, Any]:
return dict(__ansible_module__=command, __ansible_arguments__=args, **kwargs)


def _sanitize_task(task: dict) -> dict:
def _sanitize_task(task: Dict[str, Any]) -> Dict[str, Any]:
"""Return a stripped-off task structure compatible with new Ansible.
This helper takes a copy of the incoming task and drops
Expand Down

0 comments on commit 4779e5f

Please sign in to comment.