Skip to content

Commit

Permalink
#8: Enable flake8 annotations. (#119)
Browse files Browse the repository at this point in the history
* remove unused tools and update pre-commit.

* #8: enable flake8-annotations - still a few mypy issues.

* fix 'need type annotation' issue.

* update lockfile.

* remove unneeded linters from dependencies.

* update lockfile.

* #8: fix typing for ContainsTheEntry.

* add tests directory to mypy and black checks.

* update dependencies.

* fix type error in tests.

* remove isort from makefile.
  • Loading branch information
perrygoy authored Nov 21, 2023
1 parent 370d980 commit aaea650
Show file tree
Hide file tree
Showing 33 changed files with 497 additions and 550 deletions.
3 changes: 0 additions & 3 deletions .flake8

This file was deleted.

2 changes: 2 additions & 0 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,11 @@ jobs:
- name: Lint with black
run: |
black --check --diff screenpy
black --check --diff tests
- name: Lint with mypy
run: |
mypy screenpy
mypy tests
- name: Lint with ruff
run: |
ruff check .
7 changes: 0 additions & 7 deletions .isort.cfg

This file was deleted.

10 changes: 5 additions & 5 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,19 @@ files: '(screenpy|tests)/.*'
fail_fast: false
repos:
- repo: https://github.com/psf/black
rev: 23.10.1
rev: 23.11.0
hooks:
- id: black
language_version: python3.11
language_version: python3.12
- repo: https://github.com/astral-sh/ruff-pre-commit
# Ruff version.
rev: v0.1.2
rev: v0.1.5
hooks:
- id: ruff
- repo: https://github.com/pre-commit/mirrors-mypy
rev: v1.6.1
rev: v1.7.0
hooks:
- id: mypy
language_version: python3.11
language_version: python3.12
additional_dependencies: ["PyHamcrest", "pytest"]

16 changes: 0 additions & 16 deletions .pylintrc

This file was deleted.

12 changes: 3 additions & 9 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,6 @@ black-check:
black:
black .

isort-check:
isort . --check

isort:
isort .

ruff:
ruff check .

Expand All @@ -37,12 +31,12 @@ ruff-fix:
mypy:
mypy .

lint: isort-check ruff mypy
lint: ruff mypy

.PHONY: black-check black isort-check isort ruff ruff-fix mypy lint
.PHONY: black-check black ruff ruff-fix mypy lint

pre-check-in: black-check lint

pre-check-in-fix: black isort ruff-fix mypy
pre-check-in-fix: black ruff-fix mypy

.PHONY: pre-check-in pre-check-in-fix
1 change: 1 addition & 0 deletions mypy.ini
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ exclude = (?x)(
disallow_untyped_defs = True

[mypy-tests.*]
disallow_untyped_defs = True
ignore_missing_imports = True


501 changes: 183 additions & 318 deletions poetry.lock

Large diffs are not rendered by default.

15 changes: 6 additions & 9 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -65,16 +65,14 @@ pydantic = "^1.10.7"
PyHamcrest = ">=2.0.0"
python = "^3.8"
tomli = "^2.0.1"
typing_extensions = ">=4.8.0"

# convenience packages for development of screenpy only
autodoc-pydantic = {version = "*", optional = true}
black = {version = "*", optional = true}
coverage = {version = "*", optional = true}
flake8 = {version = "*", optional = true}
isort = {version = "*", optional = true}
mypy = {version = "*", optional = true}
pre-commit = {version = "*", optional = true}
pylint = {version = "*", optional = true}
pytest = {version = "*", optional = true}
pytest-mock = {version = "*", optional = true}
ruff = {version = "*", optional = true}
Expand All @@ -97,7 +95,6 @@ requests = ["screenpy-requests"]
selenium = ["screenpy-selenium"]
dev = [
"pre-commit",
"pylint",
"pytest-mock",
"pytest",
"tox",
Expand All @@ -106,11 +103,8 @@ dev_all = [
"autodoc-pydantic",
"black",
"coverage",
"flake8",
"isort",
"mypy",
"pre-commit",
"pylint",
"pytest-mock",
"pytest",
"ruff",
Expand All @@ -129,7 +123,7 @@ target-version = "py38" # minimum supported version
line-length = 88 # same as Black.
select = [
"A", # flake8-builtins
# "ANN", # flake8-annotations # coming back to this one later to compare against mypy
"ANN", # flake8-annotations # coming back to this one later to compare against mypy
"ARG", # flake8-unused-arguments
"B", # flake8-bugbear
"BLE", # flake8-blind-except
Expand Down Expand Up @@ -171,7 +165,7 @@ ignore = [
"D203", # one blank line before class docstring, no thanks!
"D212", # multi line summary first line, we want a one line summary.
"ANN101", # missing self annotation, we only annotate self when we return it.
"ANN401", # no `**kwargs: Any` typing; unfortunately we don't have a better way.
"ANN102", # missing cls annotation, we only annotate cls when we return it.
]
exclude = [
"screenpy/__init__.py",
Expand All @@ -186,6 +180,9 @@ exclude = [
"FBT", # using a boolean as a test object is useful!
"PLR", # likewise using specific numbers and strings in tests.
]
"tests/test_pacing.py" = [
"FA100", # we are purposely testing pacing without future annotations.
]


[tool.ruff.isort]
Expand Down
3 changes: 2 additions & 1 deletion screenpy/actions/attach_the_file.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ def perform_as(self, _: Actor) -> None:
"""Direct the Narrator to attach a file."""
the_narrator.attaches_a_file(self.filepath, **self.attach_kwargs)

def __init__(self, filepath: str, **kwargs: Any) -> None:
# ANN401 ignored here to allow for new adapters to use any kwargs.
def __init__(self, filepath: str, **kwargs: Any) -> None: # noqa: ANN401
self.filepath = filepath
self.filename = os.path.basename(filepath)
self.attach_kwargs = kwargs
2 changes: 1 addition & 1 deletion screenpy/actions/eventually.py
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ def perform_as(self, the_actor: Actor) -> None:
)
raise DeliveryError(msg) from self.caught_error

def __init__(self, performable: Performable):
def __init__(self, performable: Performable) -> None:
self.performable = performable
self.performable_to_log = get_additive_description(self.performable)
self.caught_error = None
Expand Down
3 changes: 2 additions & 1 deletion screenpy/actions/silently.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,8 @@ def perform_as(self: Performable, actor: Actor) -> None: # noqa: ARG001
if isinstance(duck, Answerable):
original_answered_by = duck.answered_by

def answered_by(self: Answerable, actor: Actor) -> Any: # noqa: ARG001
# ANN401 ignored here to follow the Answerable protocol.
def answered_by(self: Answerable, actor: Actor) -> Any: # noqa: ARG001, ANN401
"""Direct the Actor to answer the question silently."""
with the_narrator.mic_cable_kinked():
thing = original_answered_by(actor)
Expand Down
3 changes: 2 additions & 1 deletion screenpy/directions.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
from .exceptions import UnableToDirect


def noted_under(key: str) -> Any:
# ANN401 ignored here because the Director can note anything!
def noted_under(key: str) -> Any: # noqa: ANN401
"""Get a noted value from the director.
Examples::
Expand Down
6 changes: 4 additions & 2 deletions screenpy/director.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,12 @@ def __new__(cls: type[SelfDirector]) -> SelfDirector:
cls._instance.notebook = {}
return cls._instance

def notes(self: SelfDirector, key: str, value: Any) -> None:
# ANN401 ignored here because the Director can note anything!
def notes(self: SelfDirector, key: str, value: Any) -> None: # noqa: ANN401
"""Note down a value under the given key."""
self.notebook[key] = value

def looks_up(self: SelfDirector, key: str) -> Any:
# ANN401 ignored here because the Director can note anything!
def looks_up(self: SelfDirector, key: str) -> Any: # noqa: ANN401
"""Look up a noted value by its key."""
return self.notebook[key]
3 changes: 2 additions & 1 deletion screenpy/narration/narrator.py
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,8 @@ def explains_the_error(self, exc: Exception) -> None:
for adapter in self.adapters:
adapter.error(exc)

def attaches_a_file(self, filepath: str, **kwargs: Any) -> None:
# ANN401 ignored here to allow for new adapters to use any kwargs.
def attaches_a_file(self, filepath: str, **kwargs: Any) -> None: # noqa: ANN401
"""Attach a file for the various adapters."""
for adapter in self.adapters:
adapter.attach(filepath, **kwargs)
16 changes: 12 additions & 4 deletions screenpy/narration/stdout_adapter/stdout_adapter.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,20 @@
from contextlib import contextmanager
from functools import wraps
from types import MappingProxyType
from typing import Any, Callable, Generator
from typing import TYPE_CHECKING, Any, Callable, Generator, TypeVar

from ..gravitas import AIRY, EXTREME, HEAVY, LIGHT, NORMAL
from .configuration import settings

# pylint: disable=unused-argument

if TYPE_CHECKING:
from typing_extensions import ParamSpec

P = ParamSpec("P")
T = TypeVar("T")
Function = Callable[P, T]


class StdOutManager:
"""Handle the indentation, formatting, and log action for CLI logging."""
Expand Down Expand Up @@ -83,7 +90,7 @@ def act(self, func: Callable, line: str, gravitas: str | None = None) -> Generat
"""Wrap the act, to log the stylized title."""

@wraps(func)
def func_wrapper(*args: Any, **kwargs: Any) -> Callable:
def func_wrapper(*args: P.args, **kwargs: P.kwargs) -> Function:
"""Wrap the func, so we log at the correct time."""
if gravitas is None:
level = self.GRAVITAS[LIGHT]
Expand All @@ -100,7 +107,7 @@ def scene(
"""Wrap the scene, to log the stylized title."""

@wraps(func)
def func_wrapper(*args: Any, **kwargs: Any) -> Callable:
def func_wrapper(*args: P.args, **kwargs: P.kwargs) -> Function:
"""Wrap the func, so we log at the correct time."""
if gravitas is None:
level = self.GRAVITAS[LIGHT]
Expand Down Expand Up @@ -136,6 +143,7 @@ def error(self, exc: Exception) -> None:
)
self.handled_exception = exc

def attach(self, filepath: str, **__: Any) -> None:
# ANN401 ignored here to allow for new adapters to use any kwargs.
def attach(self, filepath: str, **__: Any) -> None: # noqa: ANN401
"""Log a mention of an attached file."""
self.manager.log(f"See reference file: {filepath}")
30 changes: 20 additions & 10 deletions screenpy/pacing.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,21 @@

import re
from functools import wraps
from typing import Any, Callable
from typing import TYPE_CHECKING, Callable, TypeVar

from screenpy.narration import Narrator, StdOutAdapter
from screenpy.speech_tools import represent_prop

Function = Callable[..., Any]
if TYPE_CHECKING:
from typing_extensions import ParamSpec

P = ParamSpec("P")
T = TypeVar("T")

the_narrator: Narrator = Narrator(adapters=[StdOutAdapter()])


def function_should_log_none(func: Function) -> bool:
def function_should_log_none(func: Callable[P, T]) -> bool:
"""Helper function to decide when to log return values.
Determine if function wrapped in beat should log that it returns None
Expand All @@ -31,7 +35,9 @@ def function_should_log_none(func: Function) -> bool:
return False


def act(title: str, gravitas: str | None = None) -> Callable[[Function], Function]:
def act(
title: str, gravitas: str | None = None
) -> Callable[[Callable[P, T]], Callable[P, T]]:
"""Decorator to mark an "act".
Acts are large groupings of tests, like suites or tests for an epic. You
Expand All @@ -46,14 +52,16 @@ def act(title: str, gravitas: str | None = None) -> Callable[[Function], Functio
The decorated function, which will be narrated when called.
"""

def decorator(func: Function) -> Function:
def decorator(func: Callable[P, T]) -> Callable[P, T]:
with the_narrator.announcing_the_act(func, title, gravitas) as n_func:
return n_func

return decorator


def scene(title: str, gravitas: str | None = None) -> Callable[[Function], Function]:
def scene(
title: str, gravitas: str | None = None
) -> Callable[[Callable[P, T]], Callable[P, T]]:
"""Decorator to mark a "scene".
Scenes are smaller groupings of tests which can transcend a suite's
Expand All @@ -68,14 +76,16 @@ def scene(title: str, gravitas: str | None = None) -> Callable[[Function], Funct
The decorated function, which will be narrated when called.
"""

def decorator(func: Function) -> Function:
def decorator(func: Callable[P, T]) -> Callable[P, T]:
with the_narrator.setting_the_scene(func, title, gravitas) as n_func:
return n_func

return decorator


def beat(line: str, gravitas: str | None = None) -> Callable[[Function], Function]:
def beat(
line: str, gravitas: str | None = None
) -> Callable[[Callable[P, T]], Callable[P, T]]:
"""Decorator to describe a "beat" (a step in a test).
A beat's line can contain markers for replacement via str.format(), which
Expand All @@ -93,9 +103,9 @@ def beat(line: str, gravitas: str | None = None) -> Callable[[Function], Functio
The decorated function, which will be narrated when called.
"""

def decorator(func: Function) -> Function:
def decorator(func: Callable[P, T]) -> Callable[P, T]:
@wraps(func)
def wrapper(*args: Any, **kwargs: Any) -> Any:
def wrapper(*args: P.args, **kwargs: P.kwargs) -> T:
action = args[0] if len(args) > 0 else None
actor = args[1] if len(args) > 1 else ""
markers = re.findall(r"\{([^\}]+)}", line)
Expand Down
6 changes: 4 additions & 2 deletions screenpy/protocols.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@
class Answerable(Protocol):
"""Questions are Answerable."""

def answered_by(self, the_actor: Actor) -> Any:
# ANN401 ignored here so any Question can fulfill this protocol.
def answered_by(self, the_actor: Actor) -> Any: # noqa: ANN401
"""Pose the Question to the Actor, who will attempt to answer.
Args:
Expand Down Expand Up @@ -127,7 +128,8 @@ def aside(
def error(self, exc: Exception) -> None:
"""React to an exception being thrown, probably during a beat."""

def attach(self, filepath: str, **kwargs: Any) -> None:
# ANN401 ignored here to allow for new adapters to use any kwargs.
def attach(self, filepath: str, **kwargs: Any) -> None: # noqa: ANN401
"""Handle attaching a file.
Pass keyword arguments for specific adapters' needs.
Expand Down
Loading

0 comments on commit aaea650

Please sign in to comment.