Enable check_untyped_defs and make mypy hook blocking

Fix the 13 errors that surfaced under mypy --check-untyped-defs so the
flag can be turned on permanently in pyproject.toml, and drop the
advisory exit-0 wrapper on the mypy pre-commit hook now that the tree is
clean.

- _plugin_manager: rename colliding loop vars (module/name were reused
  with conflicting types) and guard spec/spec.loader from
  spec_from_file_location; call __init__ via the class in __setstate__.
- __main__: pass Verbosity(options.verbose), not a bare int.
- subprocess/_check: widen package to str | Mapping[str, str] to match
  _error_trailer's existing per-platform handling.
- optimize.main: annotate the standalone PdfContext(..., None, None) that
  only ever reads context.options.
This commit is contained in:
James R. Barlow
2026-07-07 15:02:32 -07:00
parent efebe9ca2e
commit 3d291e72c0
6 changed files with 25 additions and 17 deletions
+1 -1
View File
@@ -49,7 +49,7 @@ def run(args=None):
with suppress(AttributeError, PermissionError):
os.nice(5)
verbosity = options.verbose
verbosity = Verbosity(options.verbose)
if not os.isatty(sys.stderr.fileno()):
options.progress_bar = False
if options.quiet:
+12 -8
View File
@@ -76,7 +76,8 @@ class OcrmypdfPluginManager:
return state
def __setstate__(self, state):
self.__init__(
OcrmypdfPluginManager.__init__(
self,
*state['init_args'],
plugins=state['plugins'],
builtins=state['builtins'],
@@ -88,10 +89,10 @@ class OcrmypdfPluginManager:
# 1. Register builtins
if self._builtins:
for module in sorted(
for module_info in sorted(
pkgutil.iter_modules(ocrmypdf.builtin_plugins.__path__)
):
name = f'ocrmypdf.builtin_plugins.{module.name}'
name = f'ocrmypdf.builtin_plugins.{module_info.name}'
module = importlib.import_module(name)
self._pm.register(module)
@@ -99,17 +100,20 @@ class OcrmypdfPluginManager:
self._pm.load_setuptools_entrypoints('ocrmypdf')
# 3. Register plugins specified on command line
for name in self._plugins:
if isinstance(name, Path) or name.endswith('.py'):
for plugin in self._plugins:
if isinstance(plugin, Path) or plugin.endswith('.py'):
# Import by filename
module_name = Path(name).stem
spec = importlib.util.spec_from_file_location(module_name, name)
plugin_path = Path(plugin)
module_name = plugin_path.stem
spec = importlib.util.spec_from_file_location(module_name, plugin_path)
if spec is None or spec.loader is None:
raise ImportError(f'Could not load plugin from {plugin_path}')
module = importlib.util.module_from_spec(spec)
sys.modules[module_name] = module
spec.loader.exec_module(module)
else:
# Import by dotted module name
module = importlib.import_module(name)
module = importlib.import_module(plugin)
self._pm.register(module)
# =========================================================================
+3 -1
View File
@@ -774,7 +774,9 @@ def main(infile, outfile, level, jobs=1):
)
with TemporaryDirectory() as tmpdir:
context = PdfContext(options, Path(tmpdir), infile, None, None)
# optimize() only reads context.options on this standalone path, so
# pdfinfo and plugin_manager are not needed.
context = PdfContext(options, Path(tmpdir), infile, None, None) # type: ignore[arg-type]
tmpout = Path(tmpdir) / 'out.pdf'
optimize(
infile,
+6 -3
View File
@@ -94,7 +94,10 @@ def _error_trailer(program: str, package: str | Mapping[str, str], **kwargs) ->
def _error_missing_program(
program: str, package: str, required_for: str | None, recommended: bool
program: str,
package: str | Mapping[str, str],
required_for: str | None,
recommended: bool,
) -> None:
# pylint: disable=unused-argument
if recommended:
@@ -108,7 +111,7 @@ def _error_missing_program(
def _error_old_version(
program: str,
package: str,
package: str | Mapping[str, str],
need_version: str,
found_version: str,
required_for: str | None,
@@ -124,7 +127,7 @@ def _error_old_version(
def check_external_program(
*,
program: str,
package: str,
package: str | Mapping[str, str],
version_checker: Callable[[], Version],
need_version: str | Version,
required_for: str | None = None,