Skip to content

Commit

Permalink
Fix mypy violations
Browse files Browse the repository at this point in the history
  • Loading branch information
bartfeenstra committed Jan 6, 2025
1 parent 08ef8ae commit 0ef3112
Show file tree
Hide file tree
Showing 12 changed files with 38 additions and 25 deletions.
2 changes: 1 addition & 1 deletion betty/app/extension/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -442,7 +442,7 @@ async def _dispatch(*args: Any, **kwargs: Any) -> list[Any]:
for target_extension_batch in self._extensions
for result in await gather(
*(
getattr(target_extension, target_method_name)(*args, **kwargs)
getattr(target_extension, target_method_name)(*args, **kwargs) # type: ignore[operator]
for target_extension in target_extension_batch
if isinstance(target_extension, target_type)
)
Expand Down
4 changes: 3 additions & 1 deletion betty/extension/webpack/build.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
from betty.asyncio import gather
from betty.fs import ROOT_DIRECTORY_PATH, iterfiles
from betty.hashid import hashid, hashid_sequence, hashid_file_content
from collections.abc import Mapping

if TYPE_CHECKING:
from betty.app.extension import Extension
Expand Down Expand Up @@ -217,7 +218,8 @@ async def _prepare_npm_project_directory(
npm_project_package_json_path, "r"
) as npm_project_package_json_f:
npm_project_package_json = loads(await npm_project_package_json_f.read())
npm_project_package_json["dependencies"].update(
assert isinstance(npm_project_package_json, Mapping)
npm_project_package_json["dependencies"].update( # type: ignore[union-attr]
npm_project_package_json_dependencies
)
async with aiofiles.open(
Expand Down
2 changes: 1 addition & 1 deletion betty/functools.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ def walk(item: Any, attribute_name: str) -> Iterable[Any]:

# Otherwise loop over the children and yield their attributes.
try:
child_children = iter(child)
child_children = iter(child) # type: ignore[call-overload]
except TypeError:
return
for child_child in child_children:
Expand Down
7 changes: 4 additions & 3 deletions betty/locale.py
Original file line number Diff line number Diff line change
Expand Up @@ -259,10 +259,10 @@ def to_range(self) -> DateRange:

def _compare(self, other: Any, comparator: Callable[[Any, Any], bool]) -> bool:
if not isinstance(other, Date):
return NotImplemented
return NotImplemented # type: ignore[no-any-return]
selfish = self
if not selfish.comparable or not other.comparable:
return NotImplemented
return NotImplemented # type: ignore[no-any-return]
if selfish.complete and other.complete:
return comparator(selfish.parts, other.parts)
if not other.complete:
Expand Down Expand Up @@ -1237,7 +1237,8 @@ def __init__(
@override
def localize(self, localizer: Localizer) -> str:
return cast(
str, getattr(localizer, self._gettext_method_name)(*self._gettext_args)
str,
getattr(localizer, self._gettext_method_name)(*self._gettext_args), # type: ignore[operator]
).format(**self._localize_format_kwargs(localizer, **self._format_kwargs))


Expand Down
4 changes: 2 additions & 2 deletions betty/model/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -505,7 +505,7 @@ def get(self, owner: OwnerT & Entity) -> AssociateT & Entity | None:
"""
Get the associate from the given owner.
"""
return getattr(owner, self._owner_private_attr_name) # type: ignore[no-any-return]
return getattr(owner, self._owner_private_attr_name) # type: ignore[return-value]

def set(
self, owner: OwnerT & Entity, associate: AssociateT & Entity | None
Expand Down Expand Up @@ -895,7 +895,7 @@ def get_associates(
"""
Get the associates for a given owner and association.
"""
associates: AssociateT | None | Iterable[AssociateT] = getattr(
associates: AssociateT | None | Iterable[AssociateT] = getattr( # type: ignore[assignment]
owner, f"_{association.owner_attr_name}"
)
if isinstance(association, ToOneEntityTypeAssociation):
Expand Down
4 changes: 2 additions & 2 deletions betty/model/ancestry.py
Original file line number Diff line number Diff line change
Expand Up @@ -1074,7 +1074,7 @@ async def linked_data_schema(cls, app: App) -> DictDump[Dump]:
f"This class is deprecated as of Betty 0.3.2, and will be removed in Betty 0.4.x. No direct replacement is available. Instead, set the privacy for {Source} entities accordingly."
)
class AnonymousSource(Source): # noqa D101
@property # type: ignore[override]
@property
def name(self) -> str: # noqa D102
return "private"

Expand Down Expand Up @@ -1195,7 +1195,7 @@ async def linked_data_schema(cls, app: App) -> DictDump[Dump]:
f"This class is deprecated as of Betty 0.3.2, and will be removed in Betty 0.4.x. No direct replacement is available. Instead, set the privacy for {Citation} entities accordingly."
)
class AnonymousCitation(Citation): # noqa D101
@property # type: ignore[override]
@property
def location(self) -> Str: # noqa D102
return Str._(
"private (in order to protect people's privacy)"
Expand Down
5 changes: 4 additions & 1 deletion betty/tests/_package/test_license_compatibility.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import io
import json
import sys
from collections.abc import Sequence, Mapping
from importlib.metadata import metadata, PackageNotFoundError
from typing import Iterator, Any

Expand Down Expand Up @@ -43,7 +44,7 @@ class TestPackageLicenses:
"The Unlicense (Unlicense)",
)

def assert_is_compatible(self, package_license: dict[str, Any]) -> None:
def assert_is_compatible(self, package_license: Mapping[str, Any]) -> None:
for compatible_license in self._GPL_V3_COMPATIBLE_LICENSES:
if compatible_license in package_license["License"]:
return
Expand Down Expand Up @@ -105,8 +106,10 @@ def _get_dependency_distribution_names(distribution_name: str) -> Iterator[str]:
sys.stdout = piplicenses_stdout
piplicenses.main()
package_licenses = json.loads(piplicenses_stdout.getvalue())
assert isinstance(package_licenses, Sequence)
assert len(package_licenses) > 1
for package_license in package_licenses:
assert isinstance(package_license, Mapping)
self.assert_is_compatible(package_license)
finally:
sys.argv = argv
Expand Down
19 changes: 10 additions & 9 deletions betty/tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from __future__ import annotations

import logging
from typing import TypeVar, cast, TypeGuard, TYPE_CHECKING
from typing import TypeVar, cast, TypeGuard, TYPE_CHECKING, Any
from warnings import filterwarnings

import pytest
Expand Down Expand Up @@ -115,21 +115,22 @@ def navigate(
"""
Navigate a window's menus and actions.
"""
attribute_item: Any = item
if attributes:
attribute = attributes.pop(0)
item = getattr(item, attribute)
if isinstance(item, QMenu):
self.mouse_click(item)
elif isinstance(item, QAction):
self.assert_interactive(item)
item.trigger()
attribute_item = getattr(attribute_item, attribute)
if isinstance(attribute_item, QMenu):
self.mouse_click(attribute_item)
elif isinstance(attribute_item, QAction):
self.assert_interactive(attribute_item)
attribute_item.trigger()
else:
raise RuntimeError(
'Can only navigate to menus and actions, but attribute "%s" contains %s.'
% (attribute, type(item))
% (attribute, type(attribute_item))
)

self.navigate(item, attributes)
self.navigate(attribute_item, attributes)

def assert_window(
self, window_type: type[QMainWindowT] | QMainWindowT
Expand Down
10 changes: 5 additions & 5 deletions betty/tests/coverage/test_coverage.py
Original file line number Diff line number Diff line change
Expand Up @@ -1023,7 +1023,7 @@ def _get_members(
continue

# Ignore members that are not defined by the module under test (they may have been from other modules).
imported_member = getattr(module, member_name)
imported_member = cast(_Importable, getattr(module, member_name))
if getattr(imported_member, "__module__", None) != module_name:
continue

Expand Down Expand Up @@ -1214,10 +1214,10 @@ class Test_ModuleFunctionCoverageTester:
async def test(
self, errors_expected: bool, module: _Importable, ignore: _ModuleFunctionIgnore
) -> None:
test_class = getattr(module, "TestSrc", None)
test_class = cast(type | None, getattr(module, "TestSrc", None))
sut = _ModuleFunctionCoverageTester(
module.src, # type: ignore[attr-defined]
(test_class,) if test_class else (),
() if test_class is None else (test_class,),
module.__name__,
module.__name__,
ignore,
Expand Down Expand Up @@ -1254,10 +1254,10 @@ class Test_ModuleClassCoverageTester:
async def test(
self, errors_expected: bool, module: _Importable, ignore: _ModuleClassIgnore
) -> None:
test_class = getattr(module, "TestSrc", None)
test_class = cast(type | None, getattr(module, "TestSrc", None))
sut = _ModuleClassCoverageTester(
module.Src, # type: ignore[attr-defined]
(test_class,) if test_class else (),
() if test_class is None else (test_class,),
module.__name__,
module.__name__,
ignore,
Expand Down
2 changes: 2 additions & 0 deletions betty/tests/gui/test_app.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import json
from collections.abc import Mapping
from pathlib import Path

import aiofiles
Expand Down Expand Up @@ -142,5 +143,6 @@ async def test_application_configuration_autowrite(
betty_qtbot.app.configuration.configuration_file_path
) as f:
read_configuration_dump = json.loads(await f.read())
assert isinstance(read_configuration_dump, Mapping)
assert read_configuration_dump == betty_qtbot.app.configuration.dump()
assert read_configuration_dump["locale"] == locale
2 changes: 2 additions & 0 deletions betty/tests/gui/test_project.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import json
from asyncio import sleep
from collections.abc import Mapping
from pathlib import Path
from unittest.mock import AsyncMock

Expand Down Expand Up @@ -74,6 +75,7 @@ async def test_autowrite(self, betty_qtbot: BettyQtBot) -> None:
betty_qtbot.app.project.configuration.configuration_file_path
) as f:
read_configuration_dump = json.loads(await f.read())
assert isinstance(read_configuration_dump, Mapping)
assert read_configuration_dump == betty_qtbot.app.project.configuration.dump()
assert read_configuration_dump["title"] == title

Expand Down
2 changes: 2 additions & 0 deletions betty/tests/test_openapi.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import json as stdjson
from collections.abc import Mapping
from pathlib import Path

import aiofiles
Expand All @@ -22,6 +23,7 @@ async def test_build(self, clean_urls: bool) -> None:
Path(__file__).parent / "test_openapi_assets" / "openapi-schema.json"
) as f:
schema = stdjson.loads(await f.read())
assert isinstance(schema, Mapping)
async with App.new_temporary() as app, app:
app.project.configuration.clean_urls = clean_urls
sut = Specification(app)
Expand Down

0 comments on commit 0ef3112

Please sign in to comment.