Skip to content

Commit

Permalink
Add type hints (finally)
Browse files Browse the repository at this point in the history
  • Loading branch information
econchick committed Apr 13, 2024
1 parent 0710ed0 commit 8d9f23c
Show file tree
Hide file tree
Showing 13 changed files with 314 additions and 205 deletions.
4 changes: 4 additions & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,10 @@ jobs:
python -Im pip install --upgrade tox
- name: Run tox targets for ${{ matrix.python-version }}
run: python -Im tox run -f py$(echo ${{ matrix.python-version }} | tr -d .)

- name: Run mypy
run: python -Im tox run -e mypy
if: matrix.python-version == '3.11'

- name: Check MANIFEST.in
run: python -Im tox run -e manifest
Expand Down
8 changes: 5 additions & 3 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,8 @@ fail_under = 95
line-length = 79

[tool.isort]
atomic=true
force_single_line=true
lines_after_imports=2
lines_between_types=1
use_parentheses=true
known_first_party="interrogate"
known_third_party=["attr", "click", "py", "pytest", "setuptools", "tabulate"]

Expand All @@ -53,3 +50,8 @@ quiet = false
whitelist-regex = []
ignore-regex = []
color = true

[tool.mypy]
strict = true
pretty = true
ignore_missing_imports = true
5 changes: 3 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@
import os
import re

from setuptools import find_packages
from setuptools import setup
from setuptools import find_packages, setup


HERE = os.path.abspath(os.path.dirname(__file__))
Expand Down Expand Up @@ -80,11 +79,13 @@ def find_meta(meta):
"png": ["cairosvg"],
"docs": ["sphinx", "sphinx-autobuild"],
"tests": ["pytest", "pytest-cov", "pytest-mock", "coverage[toml]"],
"typing": ["mypy", "types-tabulate"],
}
EXTRAS_REQUIRE["dev"] = (
EXTRAS_REQUIRE["png"]
+ EXTRAS_REQUIRE["docs"]
+ EXTRAS_REQUIRE["tests"]
+ EXTRAS_REQUIRE["typing"]
+ ["wheel", "pre-commit"]
)
URL = find_meta("uri")
Expand Down
53 changes: 35 additions & 18 deletions src/interrogate/badge_gen.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
Inspired by `coverage-badge <https://github.com/dbrgn/coverage-badge>`_.
"""
from __future__ import annotations

import os
import sys
Expand All @@ -16,9 +17,13 @@
except ImportError: # pragma: no cover
cairosvg = None

from interrogate.coverage import InterrogateResults

DEFAULT_FILENAME = "interrogate_badge"
COLORS = {

NumberType = int | float

DEFAULT_FILENAME: str = "interrogate_badge"
COLORS: dict[str, str] = {
"brightgreen": "#4c1",
"green": "#97CA00",
"yellowgreen": "#a4a61d",
Expand All @@ -28,19 +33,19 @@
"lightgrey": "#9f9f9f",
}

COLOR_RANGES = [
COLOR_RANGES: list[tuple[int, str]] = [
(95, "brightgreen"),
(90, "green"),
(75, "yellowgreen"),
(60, "yellow"),
(40, "orange"),
(0, "red"),
]
SUPPORTED_OUTPUT_FORMATS = ["svg", "png"]
SUPPORTED_OUTPUT_FORMATS: list[str] = ["svg", "png"]
# depending on the character length of the result (e.g. 100, 99.9, 9.9)
# a few values in the svg template need to adjust so it's readable.
# Tuple of values: (svg_width, rect_width, text_x, text_length)
SVG_WIDTH_VALUES = {
SVG_WIDTH_VALUES: dict[str, dict[str, tuple[int, int, NumberType, NumberType]]] = {
# integer
"100": {
"plastic": (135, 43, 1140, 330),
Expand Down Expand Up @@ -71,7 +76,9 @@
}


def save_badge(badge, output, output_format=None):
def save_badge(
badge: str, output: str, output_format: str | None = None
) -> str:
"""Save badge to the specified path.
.. versionadded:: 1.4.0 new ``output_format`` keyword argument
Expand Down Expand Up @@ -116,7 +123,7 @@ def save_badge(badge, output, output_format=None):
return output


def _get_badge_measurements(result, style):
def _get_badge_measurements(result: float, style: str) -> dict[str, NumberType]:
"""Lookup templated style values based on result number."""
if result == 100:
width_values = SVG_WIDTH_VALUES["100"]
Expand All @@ -133,15 +140,15 @@ def _get_badge_measurements(result, style):
}


def _format_result(result):
def _format_result(result: float) -> str:
"""Format result into string for templating."""
# do not include decimal if it's 100
if result == 100:
return "100"
return f"{result:.1f}"


def get_badge(result, color, style=None):
def get_badge(result: float, color: str, style: str | None = None) -> str:
"""Generate an SVG from template.
:param float result: coverage % result.
Expand All @@ -154,9 +161,9 @@ def get_badge(result, color, style=None):
style = "flat-square-modified"
template_file = f"{style}-style.svg"
badge_template_values = _get_badge_measurements(result, style)
result = _format_result(result)
badge_template_values["result"] = result
badge_template_values["color"] = color
formatted_result = _format_result(result)
badge_template_values["result"] = formatted_result # type: ignore
badge_template_values["color"] = color # type: ignore

if sys.version_info >= (3, 9):
tmpl = (
Expand All @@ -171,7 +178,7 @@ def get_badge(result, color, style=None):
return tmpl


def should_generate_badge(output, color, result):
def should_generate_badge(output: str, color: str, result: float) -> bool:
"""Detect if existing badge needs updating.
This is to help avoid unnecessary newline updates. See
Expand All @@ -186,8 +193,8 @@ def should_generate_badge(output, color, result):
logo doesn't exist.
:param str output: path to output badge file
:param float result: coverage % result.
:param str color: color of badge.
:param float result: coverage % result.
:return: Whether or not the badge SVG file should be generated.
:rtype: bool
"""
Expand Down Expand Up @@ -228,13 +235,13 @@ def should_generate_badge(output, color, result):
for t in texts
if t.hasAttribute("data-interrogate")
]
result = f"{result:.1f}%"
if result in current_results:
formatted_result = f"{result:.1f}%"
if formatted_result in current_results:
return False
return True


def get_color(result):
def get_color(result: float) -> str:
"""Get color for current doc coverage percent.
:param float result: coverage % result
Expand All @@ -247,7 +254,12 @@ def get_color(result):
return COLORS["lightgrey"]


def create(output, result, output_format=None, output_style=None):
def create(
output: str,
result: InterrogateResults,
output_format: str | None = None,
output_style: str | None = None,
) -> str:
"""Create a status badge.
The badge file will only be written if it doesn't exist, or if the
Expand All @@ -263,6 +275,11 @@ def create(output, result, output_format=None, output_style=None):
:param str output: path to output badge file.
:param coverage.InterrogateResults result: results of coverage
interrogation.
:param str output_format: output format of the badge. Options: "svg", "png".
Default: "svg"
:param str output_style: badge styling. Options: "plastic", "social",
"flat", "flat-square", "flat-square-modified", "for-the-badge".
Default: "flat-square-modified"
:return: path to output badge file.
:rtype: str
"""
Expand Down
Loading

0 comments on commit 8d9f23c

Please sign in to comment.