Skip to content

Commit 5a22acb

Browse files
authored
Merge pull request #178 from econchick/type-hints
Add type hints (finally)
2 parents 73128e3 + 68193e3 commit 5a22acb

27 files changed

+382
-228
lines changed

.github/workflows/main.yml

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ on:
1010
branches: [ master ]
1111
# Allow rebuilds via API.
1212
repository_dispatch:
13-
types: rebuild
13+
types: [rebuild]
1414

1515
env:
1616
FORCE_COLOR: "1"
@@ -51,6 +51,14 @@ jobs:
5151
- name: Run tox targets for ${{ matrix.python-version }}
5252
run: python -Im tox run -f py$(echo ${{ matrix.python-version }} | tr -d .)
5353

54+
- name: Run mypy
55+
run: python -Im tox run -e mypy
56+
if: matrix.python-version == '3.11'
57+
58+
- name: Run mypy
59+
run: python -Im tox run -e mypy
60+
if: matrix.python-version == '3.11'
61+
5462
- name: Check MANIFEST.in
5563
run: python -Im tox run -e manifest
5664
if: matrix.python-version == '3.11'
@@ -127,6 +135,9 @@ jobs:
127135
- name: "Create a badge"
128136
run: interrogate --config pyproject.toml --generate-badge . src tests
129137
if: runner.os != 'Windows'
138+
env:
139+
# TODO: set for only macos
140+
DYLD_FALLBACK_LIBRARY_PATH: "/opt/homebrew/lib"
130141

131142
docs:
132143
name: Check docs

README.rst

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,11 +74,31 @@ To generate a **PNG file** instead, install ``interrogate`` with the extras ``[p
7474
**NOTICE:** Additional system libraries/tools may be required in order to generate a PNG file of the coverage badge:
7575

7676
* on Windows, install Visual C++ compiler for Cairo;
77-
* on macOS, install ``cairo`` and ``libffi`` (with Homebrew for example);
77+
* on macOS, install ``cairo`` and ``libffi`` (with Homebrew for example - `see note below <#macos-and-cairo>`_);
7878
* on Linux, install the ``cairo``, ``python3-dev`` and ``libffi-dev`` packages (names may vary depending on distribution).
7979

8080
Refer to the ``cairosvg`` `documentation <https://cairosvg.org/documentation/>`_ for more information.
8181

82+
MacOS and Cairo
83+
^^^^^^^^^^^^^^^
84+
85+
If you get an error when trying to generate a badge like so:
86+
87+
.. code-block:: console
88+
89+
OSError: no library called "cairo-2" was found
90+
no library called "cairo" was found
91+
no library called "libcairo-2" was found
92+
93+
94+
Then first try:
95+
96+
.. code-block:: console
97+
98+
export DYLD_FALLBACK_LIBRARY_PATH=/opt/homebrew/lib
99+
100+
And rerun the command.
101+
82102
Usage
83103
=====
84104

@@ -373,7 +393,7 @@ Configure within your ``pyproject.toml`` (``interrogate`` will automatically det
373393
ignore-regex = ["^get$", "^mock_.*", ".*BaseClass.*"]
374394
ext = []
375395
# possible values: sphinx (default), google
376-
style = sphinx
396+
style = "sphinx"
377397
# possible values: 0 (minimal output), 1 (-v), 2 (-vv)
378398
verbose = 0
379399
quiet = false

docs/Makefile

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1)
1010
$(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/)
1111
endif
1212

13+
# Internal variables
14+
ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(SPHINXOPTS) .
15+
1316
.PHONY: help clean html livehtml linkcheck
1417

1518
help:

docs/changelog.rst

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,14 @@
11
Changelog
22
=========
33

4+
1.8.0 (UNRELEASED)
5+
------------------
6+
7+
Added
8+
^^^^^
9+
10+
* Finally added type hints
11+
412
.. short-log
513
614
1.7.0 (2024-04-07)

pyproject.toml

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,8 @@ fail_under = 95
2929
line-length = 79
3030

3131
[tool.isort]
32-
atomic=true
33-
force_single_line=true
3432
lines_after_imports=2
3533
lines_between_types=1
36-
use_parentheses=true
3734
known_first_party="interrogate"
3835
known_third_party=["attr", "click", "py", "pytest", "setuptools", "tabulate"]
3936

@@ -53,3 +50,8 @@ quiet = false
5350
whitelist-regex = []
5451
ignore-regex = []
5552
color = true
53+
54+
[tool.mypy]
55+
strict = true
56+
pretty = true
57+
ignore_missing_imports = true

setup.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,7 @@
55
import os
66
import re
77

8-
from setuptools import find_packages
9-
from setuptools import setup
8+
from setuptools import find_packages, setup
109

1110

1211
HERE = os.path.abspath(os.path.dirname(__file__))
@@ -80,11 +79,13 @@ def find_meta(meta):
8079
"png": ["cairosvg"],
8180
"docs": ["sphinx", "sphinx-autobuild"],
8281
"tests": ["pytest", "pytest-cov", "pytest-mock", "coverage[toml]"],
82+
"typing": ["mypy", "types-tabulate"],
8383
}
8484
EXTRAS_REQUIRE["dev"] = (
8585
EXTRAS_REQUIRE["png"]
8686
+ EXTRAS_REQUIRE["docs"]
8787
+ EXTRAS_REQUIRE["tests"]
88+
+ EXTRAS_REQUIRE["typing"]
8889
+ ["wheel", "pre-commit"]
8990
)
9091
URL = find_meta("uri")

src/interrogate/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright 2020-2021 Lynn Root
1+
# Copyright 2020-2024 Lynn Root
22
"""Explain yourself! Interrogate a codebase for docstring coverage."""
33
__author__ = "Lynn Root"
44
__version__ = "1.7.0"

src/interrogate/__main__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright 2020 Lynn Root
1+
# Copyright 2020-2024 Lynn Root
22
"""interrogate entrypoint"""
33

44
from interrogate import cli

src/interrogate/badge_gen.py

Lines changed: 41 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
1-
# Copyright 2020 Lynn Root
1+
# Copyright 2020-2024 Lynn Root
22
"""Module for generating an SVG badge.
33
44
Inspired by `coverage-badge <https://github.com/dbrgn/coverage-badge>`_.
55
"""
6+
from __future__ import annotations
67

78
import os
89
import sys
910

1011
from importlib import resources
12+
from typing import Union
1113
from xml.dom import minidom
1214

1315

@@ -16,9 +18,13 @@
1618
except ImportError: # pragma: no cover
1719
cairosvg = None
1820

21+
from interrogate.coverage import InterrogateResults
1922

20-
DEFAULT_FILENAME = "interrogate_badge"
21-
COLORS = {
23+
24+
NumberType = Union[int, float]
25+
26+
DEFAULT_FILENAME: str = "interrogate_badge"
27+
COLORS: dict[str, str] = {
2228
"brightgreen": "#4c1",
2329
"green": "#97CA00",
2430
"yellowgreen": "#a4a61d",
@@ -28,19 +34,21 @@
2834
"lightgrey": "#9f9f9f",
2935
}
3036

31-
COLOR_RANGES = [
37+
COLOR_RANGES: list[tuple[int, str]] = [
3238
(95, "brightgreen"),
3339
(90, "green"),
3440
(75, "yellowgreen"),
3541
(60, "yellow"),
3642
(40, "orange"),
3743
(0, "red"),
3844
]
39-
SUPPORTED_OUTPUT_FORMATS = ["svg", "png"]
45+
SUPPORTED_OUTPUT_FORMATS: list[str] = ["svg", "png"]
4046
# depending on the character length of the result (e.g. 100, 99.9, 9.9)
4147
# a few values in the svg template need to adjust so it's readable.
4248
# Tuple of values: (svg_width, rect_width, text_x, text_length)
43-
SVG_WIDTH_VALUES = {
49+
SVG_WIDTH_VALUES: dict[
50+
str, dict[str, tuple[int, int, NumberType, NumberType]]
51+
] = {
4452
# integer
4553
"100": {
4654
"plastic": (135, 43, 1140, 330),
@@ -71,7 +79,9 @@
7179
}
7280

7381

74-
def save_badge(badge, output, output_format=None):
82+
def save_badge(
83+
badge: str, output: str, output_format: str | None = None
84+
) -> str:
7585
"""Save badge to the specified path.
7686
7787
.. versionadded:: 1.4.0 new ``output_format`` keyword argument
@@ -116,7 +126,9 @@ def save_badge(badge, output, output_format=None):
116126
return output
117127

118128

119-
def _get_badge_measurements(result, style):
129+
def _get_badge_measurements(
130+
result: float, style: str
131+
) -> dict[str, NumberType]:
120132
"""Lookup templated style values based on result number."""
121133
if result == 100:
122134
width_values = SVG_WIDTH_VALUES["100"]
@@ -133,15 +145,15 @@ def _get_badge_measurements(result, style):
133145
}
134146

135147

136-
def _format_result(result):
148+
def _format_result(result: float) -> str:
137149
"""Format result into string for templating."""
138150
# do not include decimal if it's 100
139151
if result == 100:
140152
return "100"
141153
return f"{result:.1f}"
142154

143155

144-
def get_badge(result, color, style=None):
156+
def get_badge(result: float, color: str, style: str | None = None) -> str:
145157
"""Generate an SVG from template.
146158
147159
:param float result: coverage % result.
@@ -154,9 +166,9 @@ def get_badge(result, color, style=None):
154166
style = "flat-square-modified"
155167
template_file = f"{style}-style.svg"
156168
badge_template_values = _get_badge_measurements(result, style)
157-
result = _format_result(result)
158-
badge_template_values["result"] = result
159-
badge_template_values["color"] = color
169+
formatted_result = _format_result(result)
170+
badge_template_values["result"] = formatted_result # type: ignore
171+
badge_template_values["color"] = color # type: ignore
160172

161173
if sys.version_info >= (3, 9):
162174
tmpl = (
@@ -171,7 +183,7 @@ def get_badge(result, color, style=None):
171183
return tmpl
172184

173185

174-
def should_generate_badge(output, color, result):
186+
def should_generate_badge(output: str, color: str, result: float) -> bool:
175187
"""Detect if existing badge needs updating.
176188
177189
This is to help avoid unnecessary newline updates. See
@@ -186,8 +198,8 @@ def should_generate_badge(output, color, result):
186198
logo doesn't exist.
187199
188200
:param str output: path to output badge file
189-
:param float result: coverage % result.
190201
:param str color: color of badge.
202+
:param float result: coverage % result.
191203
:return: Whether or not the badge SVG file should be generated.
192204
:rtype: bool
193205
"""
@@ -228,13 +240,13 @@ def should_generate_badge(output, color, result):
228240
for t in texts
229241
if t.hasAttribute("data-interrogate")
230242
]
231-
result = f"{result:.1f}%"
232-
if result in current_results:
243+
formatted_result = f"{result:.1f}%"
244+
if formatted_result in current_results:
233245
return False
234246
return True
235247

236248

237-
def get_color(result):
249+
def get_color(result: float) -> str:
238250
"""Get color for current doc coverage percent.
239251
240252
:param float result: coverage % result
@@ -247,7 +259,12 @@ def get_color(result):
247259
return COLORS["lightgrey"]
248260

249261

250-
def create(output, result, output_format=None, output_style=None):
262+
def create(
263+
output: str,
264+
result: InterrogateResults,
265+
output_format: str | None = None,
266+
output_style: str | None = None,
267+
) -> str:
251268
"""Create a status badge.
252269
253270
The badge file will only be written if it doesn't exist, or if the
@@ -263,6 +280,11 @@ def create(output, result, output_format=None, output_style=None):
263280
:param str output: path to output badge file.
264281
:param coverage.InterrogateResults result: results of coverage
265282
interrogation.
283+
:param str output_format: output format of the badge. Options: "svg", "png".
284+
Default: "svg"
285+
:param str output_style: badge styling. Options: "plastic", "social",
286+
"flat", "flat-square", "flat-square-modified", "for-the-badge".
287+
Default: "flat-square-modified"
266288
:return: path to output badge file.
267289
:rtype: str
268290
"""

0 commit comments

Comments
 (0)