Skip to content

Commit 8f505e7

Browse files
Copilotoprypin
andcommitted
Add type annotations to fix mypy --strict errors across all specified files
Agent-Logs-Url: https://github.com/ProperDocs/properdocs/sessions/1095dc3b-4da6-4f7c-bc57-f18d05944c90 Co-authored-by: oprypin <371383+oprypin@users.noreply.github.com>
1 parent 1efcad6 commit 8f505e7

8 files changed

Lines changed: 94 additions & 76 deletions

File tree

properdocs/__main__.py

Lines changed: 29 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@
77
import textwrap
88
import traceback
99
import warnings
10-
from typing import ClassVar
10+
from collections.abc import Callable
11+
from typing import Any, ClassVar
1112

1213
import click
1314

@@ -29,7 +30,14 @@
2930
log = logging.getLogger(__name__)
3031

3132

32-
def _showwarning(message, category, filename, lineno, file=None, line=None):
33+
def _showwarning(
34+
message: Warning | str,
35+
category: type[Warning],
36+
filename: str,
37+
lineno: int,
38+
file: Any = None,
39+
line: str | None = None,
40+
) -> None:
3341
try:
3442
# Last stack frames:
3543
# * ...
@@ -49,7 +57,7 @@ def _showwarning(message, category, filename, lineno, file=None, line=None):
4957
log.info(f'{category.__name__}: {message}\n{tb}')
5058

5159

52-
def _enable_warnings():
60+
def _enable_warnings() -> None:
5361
# When `python -W...` or `PYTHONWARNINGS` are used, `sys.warnoptions` is set.
5462
# In that case, we skip warnings configuration since
5563
# we don't want to overwrite the user configuration.
@@ -79,7 +87,7 @@ class ColorFormatter(logging.Formatter):
7987
subsequent_indent=' ' * 11,
8088
)
8189

82-
def format(self, record):
90+
def format(self, record: logging.LogRecord) -> str:
8391
message = super().format(record)
8492
prefix = f'{record.levelname:<8}- '
8593
if record.levelname in self.colors:
@@ -95,7 +103,7 @@ def format(self, record):
95103
class State:
96104
"""Maintain logging level."""
97105

98-
def __init__(self):
106+
def __init__(self) -> None:
99107
self.logger = logging.getLogger('properdocs')
100108
self.logger.setLevel(logging.INFO)
101109
self.logger.propagate = False
@@ -111,7 +119,7 @@ def __init__(self):
111119
self.stream.name = 'ProperDocsStreamHandler'
112120
self.logger.addHandler(self.stream)
113121

114-
def __del__(self):
122+
def __del__(self) -> None:
115123
self.logger.removeHandler(self.stream)
116124

117125

@@ -158,17 +166,17 @@ def __del__(self):
158166
)
159167

160168

161-
def add_options(*opts):
162-
def inner(f):
169+
def add_options(*opts: Callable[..., Any]) -> Callable[..., Any]:
170+
def inner(f: Callable[..., Any]) -> Callable[..., Any]:
163171
for i in reversed(opts):
164172
f = i(f)
165173
return f
166174

167175
return inner
168176

169177

170-
def verbose_option(f):
171-
def callback(ctx, param, value):
178+
def verbose_option(f: Callable[..., Any]) -> Callable[..., Any]:
179+
def callback(ctx: click.Context, param: click.Parameter, value: Any) -> None:
172180
state = ctx.ensure_object(State)
173181
if value:
174182
state.logger.setLevel(logging.DEBUG)
@@ -183,8 +191,8 @@ def callback(ctx, param, value):
183191
)(f)
184192

185193

186-
def quiet_option(f):
187-
def callback(ctx, param, value):
194+
def quiet_option(f: Callable[..., Any]) -> Callable[..., Any]:
195+
def callback(ctx: click.Context, param: click.Parameter, value: Any) -> None:
188196
state = ctx.ensure_object(State)
189197
if value:
190198
state.logger.setLevel(logging.ERROR)
@@ -199,8 +207,8 @@ def callback(ctx, param, value):
199207
)(f)
200208

201209

202-
def color_option(f):
203-
def callback(ctx, param, value):
210+
def color_option(f: Callable[..., Any]) -> Callable[..., Any]:
211+
def callback(ctx: click.Context, param: click.Parameter, value: Any) -> None:
204212
state = ctx.ensure_object(State)
205213
if value is False or (
206214
value is None
@@ -253,7 +261,7 @@ def callback(ctx, param, value):
253261
)
254262
@common_options
255263
@color_option
256-
def cli():
264+
def cli() -> None:
257265
"""ProperDocs - Project documentation with Markdown."""
258266

259267

@@ -271,7 +279,7 @@ def cli():
271279
)
272280
@common_config_options
273281
@common_options
274-
def serve_command(**kwargs):
282+
def serve_command(**kwargs: Any) -> None:
275283
"""Run the builtin development server."""
276284
from properdocs.commands import serve
277285

@@ -289,7 +297,7 @@ def serve_command(**kwargs):
289297
@common_config_options
290298
@click.option('-d', '--site-dir', type=click.Path(), help=site_dir_help)
291299
@common_options
292-
def build_command(clean, **kwargs):
300+
def build_command(clean: bool, **kwargs: Any) -> None:
293301
"""Build the ProperDocs documentation."""
294302
from properdocs.commands import build
295303

@@ -315,8 +323,8 @@ def build_command(clean, **kwargs):
315323
@click.option('-d', '--site-dir', type=click.Path(), help=site_dir_help)
316324
@common_options
317325
def gh_deploy_command(
318-
clean, message, remote_branch, remote_name, force, no_history, ignore_version, shell, **kwargs
319-
):
326+
clean: bool, message: str | None, remote_branch: str | None, remote_name: str | None, force: bool, no_history: bool, ignore_version: bool, shell: bool, **kwargs: Any
327+
) -> None:
320328
"""Deploy your documentation to GitHub Pages."""
321329
from properdocs.commands import build, gh_deploy
322330

@@ -347,7 +355,7 @@ def gh_deploy_command(
347355
help=projects_file_help,
348356
show_default=True,
349357
)
350-
def get_deps_command(config_file, projects_file):
358+
def get_deps_command(config_file: Any, projects_file: str | None) -> None:
351359
"""Show required PyPI packages inferred from plugins in properdocs.yml."""
352360
from properdocs.commands.get_deps import get_deps, get_projects_file
353361
from properdocs.config.base import _open_config_file
@@ -370,7 +378,7 @@ def get_deps_command(config_file, projects_file):
370378
@cli.command(name="new")
371379
@click.argument("project_directory")
372380
@common_options
373-
def new_command(project_directory):
381+
def new_command(project_directory: str) -> None:
374382
"""Create a new ProperDocs project."""
375383
from properdocs.commands import new
376384

properdocs/contrib/search/__init__.py

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
from properdocs import utils
88
from properdocs.config import base
99
from properdocs.config import config_options as c
10+
from properdocs.config.base import ValidationError
1011
from properdocs.contrib.search.search_index import SearchIndex
1112
from properdocs.plugins import BasePlugin
1213

@@ -23,7 +24,7 @@
2324
class LangOption(c.OptionallyRequired[list[str]]):
2425
"""Validate Language(s) provided in config are known languages."""
2526

26-
def get_lunr_supported_lang(self, lang):
27+
def get_lunr_supported_lang(self, lang: str) -> str | None:
2728
fallback = {'uk': 'ru'}
2829
for lang_part in lang.split("_"):
2930
lang_part = lang_part.lower()
@@ -32,11 +33,11 @@ def get_lunr_supported_lang(self, lang):
3233
return lang_part
3334
return None
3435

35-
def run_validation(self, value: object):
36+
def run_validation(self, value: object) -> list[str]:
3637
if isinstance(value, str):
3738
value = [value]
3839
if not isinstance(value, list):
39-
raise c.ValidationError('Expected a list of language codes.')
40+
raise ValidationError('Expected a list of language codes.')
4041
for lang in value[:]:
4142
if lang != 'en':
4243
lang_detected = self.get_lunr_supported_lang(lang)
@@ -63,7 +64,7 @@ class _PluginConfig(base.Config):
6364
class SearchPlugin(BasePlugin[_PluginConfig]):
6465
"""Add a search feature to ProperDocs."""
6566

66-
def on_config(self, config: ProperDocsConfig, **kwargs) -> ProperDocsConfig:
67+
def on_config(self, config: ProperDocsConfig, **kwargs: object) -> ProperDocsConfig:
6768
"""Add plugin templates and scripts to config."""
6869
if config.theme.get('include_search_page'):
6970
config.theme.static_templates.add('search.html')
@@ -85,15 +86,15 @@ def on_config(self, config: ProperDocsConfig, **kwargs) -> ProperDocsConfig:
8586
)
8687
return config
8788

88-
def on_pre_build(self, config: ProperDocsConfig, **kwargs) -> None:
89+
def on_pre_build(self, config: ProperDocsConfig, **kwargs: object) -> None:
8990
"""Create search index instance for later use."""
9091
self.search_index = SearchIndex(**self.config)
9192

92-
def on_page_context(self, context: TemplateContext, page: Page, **kwargs) -> None:
93+
def on_page_context(self, context: TemplateContext, page: Page, **kwargs: object) -> None:
9394
"""Add page to search index."""
9495
self.search_index.add_entry_from_context(page)
9596

96-
def on_post_build(self, config: ProperDocsConfig, **kwargs) -> None:
97+
def on_post_build(self, config: ProperDocsConfig, **kwargs: object) -> None:
9798
"""Build search index."""
9899
output_base_path = os.path.join(config.site_dir, 'search')
99100
search_index = self.search_index.generate_search_index()

properdocs/contrib/search/search_index.py

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import os
66
import re
77
import subprocess
8+
from collections.abc import Iterable
89
from html.parser import HTMLParser
910
from typing import TYPE_CHECKING
1011

@@ -28,11 +29,11 @@ class SearchIndex:
2829
tags and their following content are sections).
2930
"""
3031

31-
def __init__(self, **config) -> None:
32-
self._entries: list[dict] = []
32+
def __init__(self, **config: object) -> None:
33+
self._entries: list[dict[str, object]] = []
3334
self.config = config
3435

35-
def _find_toc_by_id(self, toc, id_: str | None) -> AnchorLink | None:
36+
def _find_toc_by_id(self, toc: Iterable[AnchorLink], id_: str | None) -> AnchorLink | None:
3637
"""
3738
Given a table of contents and HTML ID, iterate through
3839
and return the matched item in the TOC.
@@ -155,7 +156,9 @@ def __init__(
155156
self.id = id_
156157
self.title = title
157158

158-
def __eq__(self, other):
159+
def __eq__(self, other: object) -> bool:
160+
if not isinstance(other, ContentSection):
161+
return NotImplemented
159162
return self.text == other.text and self.id == other.id and self.title == other.title
160163

161164

@@ -169,8 +172,8 @@ class ContentParser(HTMLParser):
169172
for that section.
170173
"""
171174

172-
def __init__(self, *args, **kwargs) -> None:
173-
super().__init__(*args, **kwargs)
175+
def __init__(self) -> None:
176+
super().__init__()
174177

175178
self.data: list[ContentSection] = []
176179
self.section: ContentSection | None = None

properdocs/localization.py

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,22 +13,25 @@
1313
import jinja2
1414

1515
try:
16-
from babel.core import Locale, UnknownLocaleError
17-
from babel.support import NullTranslations, Translations
16+
from babel.core import Locale, UnknownLocaleError # type: ignore[import-untyped]
17+
from babel.support import NullTranslations, Translations # type: ignore[import-untyped]
1818

1919
has_babel = True
2020
except ImportError: # pragma: no cover
21-
from properdocs.utils.babel_stub import Locale, UnknownLocaleError # type: ignore[assignment]
21+
from properdocs.utils.babel_stub import Locale, UnknownLocaleError
2222

2323
has_babel = False
2424

25+
if TYPE_CHECKING:
26+
from properdocs.utils.babel_stub import Locale as Locale # noqa: F811
27+
2528

2629
log = logging.getLogger(__name__)
2730
base_path = os.path.dirname(os.path.abspath(__file__))
2831

2932

3033
class NoBabelExtension(InternationalizationExtension): # pragma: no cover
31-
def __init__(self, environment):
34+
def __init__(self, environment: jinja2.Environment) -> None:
3235
Extension.__init__(self, environment)
3336
environment.extend(
3437
install_null_translations=self._install_null,

0 commit comments

Comments
 (0)