From 54f6ccdbc2384263129308291b36ff47d55fdd04 Mon Sep 17 00:00:00 2001 From: Charles Langlois Date: Thu, 1 Feb 2024 11:46:45 -0500 Subject: [PATCH 1/2] Added mypy linter --- .pre-commit-config.yaml | 10 ++++++++++ pyproject.toml | 25 ++++++++++++++++++++++++- 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index e10c267b..53a4cc7c 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -10,3 +10,13 @@ repos: rev: 23.10.1 hooks: - id: black + - repo: https://github.com/pre-commit/mirrors-mypy + rev: v1.6.1 + hooks: + - id: mypy + language_version: "3.10" + additional_dependencies: + - "types-requests" + - "types-setuptools" + - "sqlalchemy-stubs" + diff --git a/pyproject.toml b/pyproject.toml index 5bbd102e..e76d260a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -13,4 +13,27 @@ ignore = [ exclude = [ ".tox", ".eggs", -] \ No newline at end of file +] + +[tool.mypy] +python_version = "3.10" +show_error_codes = true + +check_untyped_defs = true +disallow_untyped_calls = false +disallow_untyped_defs = false + +warn_unused_configs = true +warn_unused_ignores = true +warn_redundant_casts = true +no_warn_no_return = true + +# strict_equality = true +# extra_checks = true + +# [[tool.mypy.overrides]] +# module = [ +# "wazo_lib_rest_client.*" +# ] +# ignore_missing_imports = true + From 3a1d0a1de5859906272f5d1443a6f7bf2e5fd373 Mon Sep 17 00:00:00 2001 From: Charles Langlois Date: Thu, 1 Feb 2024 11:50:09 -0500 Subject: [PATCH 2/2] WIP: basic type fixes --- xivo_dao/helpers/asterisk.py | 48 +++++++++++++++++++++++++----------- 1 file changed, 34 insertions(+), 14 deletions(-) diff --git a/xivo_dao/helpers/asterisk.py b/xivo_dao/helpers/asterisk.py index b76a174d..42f2b10f 100644 --- a/xivo_dao/helpers/asterisk.py +++ b/xivo_dao/helpers/asterisk.py @@ -1,8 +1,13 @@ # Copyright 2016-2024 The Wazo Authors (see the AUTHORS file) # SPDX-License-Identifier: GPL-3.0-or-later -from collections.abc import Iterable +from __future__ import annotations + +from collections.abc import Collection, Iterable +from typing import Literal from xivo_dao.helpers import errors +from sqlalchemy import Table + # taken from the definition of the "ast_true" function in Asterisk source code _TRUTH_VALUES = [ @@ -14,37 +19,52 @@ 'on', ] +AST_TRUE = Literal[ + 'yes', + 'true', + 'y', + 't', + '1', + 'on', +] + -def convert_ast_true_to_int(value): +def convert_ast_true_to_int(value: AST_TRUE) -> int: return int(value in _TRUTH_VALUES) -def convert_int_to_ast_true(value): +StrBool = Literal['yes', 'no'] + + +def convert_int_to_ast_true(value: int) -> StrBool: if value: return 'yes' return 'no' class AsteriskOptionsMixin: - EXCLUDE_OPTIONS = set() - EXCLUDE_OPTIONS_CONFD = set() - AST_TRUE_INTEGER_COLUMNS = set() + EXCLUDE_OPTIONS: set[str] = set() + EXCLUDE_OPTIONS_CONFD: set[str] = set() + AST_TRUE_INTEGER_COLUMNS: set[str] = set() + + _options: list[list[str]] + __table__: Table @property - def options(self): + def options(self) -> list[list[str]]: return self.all_options(self.EXCLUDE_OPTIONS_CONFD) - def all_options(self, exclude=None): + def all_options(self, exclude=None) -> list[list[str]]: native_options = list(self.native_options(exclude)) return native_options + self._options - def native_options(self, exclude=None): + def native_options(self, exclude=None) -> Iterable[list[str]]: for column in self.native_option_names(exclude): value = self.native_option(column) if value is not None: yield [column, value] - def native_option(self, column_name): + def native_option(self, column_name: str) -> str | None: value = getattr(self, self._attribute(column_name), None) if value is not None and value != "": if column_name in self.AST_TRUE_INTEGER_COLUMNS: @@ -53,7 +73,7 @@ def native_option(self, column_name): return str(value) return None - @options.setter + @options.setter # type: ignore[attr-defined,no-redef] def options(self, options): option_names = self.native_option_names(self.EXCLUDE_OPTIONS_CONFD) self.reset_options() @@ -82,11 +102,11 @@ def set_options(self, option_names, options): else: self.add_extra_option(column, value) - def validate_options(self, options): + def validate_options(self, options: Iterable[Collection[str]]): if not isinstance(options, Iterable): raise errors.wrong_type('options', 'list of pair of strings') - def validate_option(self, option): + def validate_option(self, option: Collection[str]): if not isinstance(option, Iterable): raise errors.wrong_type('options', 'list of pair of strings') if not len(option) == 2: @@ -95,7 +115,7 @@ def validate_option(self, option): if not isinstance(i, str): raise errors.wrong_type('options', f"value '{i}' is not a string") - def set_native_option(self, column, value): + def set_native_option(self, column: str, value): if column in self.AST_TRUE_INTEGER_COLUMNS: value = convert_ast_true_to_int(value) setattr(self, self._attribute(column), value)