From 5a2a6f166722285c8234a1e79775229b519d94c2 Mon Sep 17 00:00:00 2001 From: "Druzhkov, Pavel" Date: Fri, 15 Oct 2021 18:18:13 +0300 Subject: [PATCH 1/5] enable mypy checks in precommit (disable all others) --- .mypy.ini | 28 +++++++ .pre-commit-config.yaml | 83 ++++++++++--------- mmdet/apis/ote/apis/detection/__init__.py | 32 +++---- .../apis/ote/apis/detection/inference_task.py | 5 +- mmdet/apis/ote/apis/detection/nncf_task.py | 4 +- .../apis/ote/apis/detection/openvino_task.py | 8 +- mmdet/apis/ote/apis/detection/train_task.py | 10 +-- mmdet/apis/ote/extension/datasets/__init__.py | 2 +- mmdet/apis/ote/extension/utils/__init__.py | 6 +- tests/conftest.py | 2 +- tests/{config.py => e2e_config.py} | 0 tests/test_ote_training.py | 6 +- 12 files changed, 112 insertions(+), 74 deletions(-) create mode 100644 .mypy.ini rename tests/{config.py => e2e_config.py} (100%) diff --git a/.mypy.ini b/.mypy.ini new file mode 100644 index 00000000000..6310db6cb26 --- /dev/null +++ b/.mypy.ini @@ -0,0 +1,28 @@ +[mypy] +python_version = 3.8 +ignore_missing_imports = True +show_error_codes = True + +[mypy-mmdet.apis] +ignore_errors = True + +[mypy-mmdet.core.*] +ignore_errors = True + +[mypy-mmdet.datasets.*] +ignore_errors = True + +[mypy-mmdet.integration.*] +ignore_errors = True + +[mypy-mmdet.models.*] +ignore_errors = True + +[mypy-mmdet.ops.*] +ignore_errors = True + +[mypy-mmdet.parallel.*] +ignore_errors = True + +[mypy-mmdet.utils.*] +ignore_errors = True \ No newline at end of file diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 35566b35337..896613b8891 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,40 +1,47 @@ repos: - - repo: https://gitlab.com/pycqa/flake8.git - rev: 3.8.3 + # - repo: https://gitlab.com/pycqa/flake8.git + # rev: 3.8.3 + # hooks: + # - id: flake8 + # - repo: https://github.com/asottile/seed-isort-config + # rev: v2.2.0 + # hooks: + # - id: seed-isort-config + # - repo: https://github.com/timothycrosley/isort + # rev: 4.3.21 + # hooks: + # - id: isort + # - repo: https://github.com/pre-commit/mirrors-yapf + # rev: v0.30.0 + # hooks: + # - id: yapf + # - repo: https://github.com/pre-commit/pre-commit-hooks + # rev: v3.1.0 + # hooks: + # - id: trailing-whitespace + # - id: check-yaml + # - id: end-of-file-fixer + # - id: requirements-txt-fixer + # - id: double-quote-string-fixer + # - id: check-merge-conflict + # - id: fix-encoding-pragma + # args: ["--remove"] + # - id: mixed-line-ending + # args: ["--fix=lf"] + # - repo: https://github.com/jumanjihouse/pre-commit-hooks + # rev: 2.1.4 + # hooks: + # - id: markdownlint + # args: ["-r", "~MD002,~MD013,~MD024,~MD029,~MD033,~MD034,~MD036"] + # - repo: https://github.com/myint/docformatter + # rev: v1.3.1 + # hooks: + # - id: docformatter + # args: ["--in-place", "--wrap-descriptions", "79"] + - repo: https://github.com/pre-commit/mirrors-mypy + rev: 'v0.812' hooks: - - id: flake8 - - repo: https://github.com/asottile/seed-isort-config - rev: v2.2.0 - hooks: - - id: seed-isort-config - - repo: https://github.com/timothycrosley/isort - rev: 4.3.21 - hooks: - - id: isort - - repo: https://github.com/pre-commit/mirrors-yapf - rev: v0.30.0 - hooks: - - id: yapf - - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v3.1.0 - hooks: - - id: trailing-whitespace - - id: check-yaml - - id: end-of-file-fixer - - id: requirements-txt-fixer - - id: double-quote-string-fixer - - id: check-merge-conflict - - id: fix-encoding-pragma - args: ["--remove"] - - id: mixed-line-ending - args: ["--fix=lf"] - - repo: https://github.com/jumanjihouse/pre-commit-hooks - rev: 2.1.4 - hooks: - - id: markdownlint - args: ["-r", "~MD002,~MD013,~MD024,~MD029,~MD033,~MD034,~MD036"] - - repo: https://github.com/myint/docformatter - rev: v1.3.1 - hooks: - - id: docformatter - args: ["--in-place", "--wrap-descriptions", "79"] + - id: mypy + args: ["--config-file=.mypy.ini"] + additional_dependencies: [numpy==1.19.5, types-PyYAML, attrs==21.2.*, types-requests, types-Deprecated, types-docutils, types_futures, types-python-dateutil] + exclude: "ci|configs|data|demo|docker|docs|experiments|resources|tools" diff --git a/mmdet/apis/ote/apis/detection/__init__.py b/mmdet/apis/ote/apis/detection/__init__.py index f8ab059a759..9c69ddb21fe 100644 --- a/mmdet/apis/ote/apis/detection/__init__.py +++ b/mmdet/apis/ote/apis/detection/__init__.py @@ -25,20 +25,20 @@ from .train_task import OTEDetectionTrainingTask __all__ = [ - config_from_string, - config_to_string, - generate_label_schema, - get_task_class, - load_template, - OpenVINODetectionTask, - OTEDetectionConfig, - OTEDetectionInferenceTask, - OTEDetectionNNCFTask, - OTEDetectionTrainingTask, - patch_config, - prepare_for_testing, - prepare_for_training, - save_config_to_file, - set_hyperparams, - set_values_as_default, + 'config_from_string', + 'config_to_string', + 'generate_label_schema', + 'get_task_class', + 'load_template', + 'OpenVINODetectionTask', + 'OTEDetectionConfig', + 'OTEDetectionInferenceTask', + 'OTEDetectionNNCFTask', + 'OTEDetectionTrainingTask', + 'patch_config', + 'prepare_for_testing', + 'prepare_for_training', + 'save_config_to_file', + 'set_hyperparams', + 'set_values_as_default', ] diff --git a/mmdet/apis/ote/apis/detection/inference_task.py b/mmdet/apis/ote/apis/detection/inference_task.py index 814d0586885..aaf22e20e52 100644 --- a/mmdet/apis/ote/apis/detection/inference_task.py +++ b/mmdet/apis/ote/apis/detection/inference_task.py @@ -205,7 +205,8 @@ def hook(module, input, output): @staticmethod def _infer_detector(model: torch.nn.Module, config: Config, dataset: DatasetEntity, - eval: Optional[bool] = False, metric_name: Optional[str] = 'mAP') -> Tuple[List, float]: + eval: bool = False, + metric_name: str = 'mAP') -> Tuple[List, float]: model.eval() test_config = prepare_for_testing(config, dataset) mm_val_dataset = build_dataset(test_config.data.test) @@ -224,7 +225,7 @@ def _infer_detector(model: torch.nn.Module, config: Config, dataset: DatasetEnti # Use a single gpu for testing. Set in both mm_val_dataloader and eval_model eval_predictions = single_gpu_test(eval_model, mm_val_dataloader, show=False) - metric = None + metric = 0.0 if eval: metric = mm_val_dataset.evaluate(eval_predictions, metric=metric_name)[metric_name] return eval_predictions, metric diff --git a/mmdet/apis/ote/apis/detection/nncf_task.py b/mmdet/apis/ote/apis/detection/nncf_task.py index 84a6f76dfa9..9f00dfd23f7 100644 --- a/mmdet/apis/ote/apis/detection/nncf_task.py +++ b/mmdet/apis/ote/apis/detection/nncf_task.py @@ -17,7 +17,7 @@ import logging import os from collections import defaultdict -from typing import Optional +from typing import DefaultDict, Optional import torch from ote_sdk.configuration import cfg_helper @@ -143,7 +143,7 @@ def optimize( else: update_progress_callback = default_progress_callback time_monitor = TrainingProgressCallback(update_progress_callback) - learning_curves = defaultdict(OTELoggerHook.Curve) + learning_curves: DefaultDict[str, OTELoggerHook.Curve] = defaultdict(OTELoggerHook.Curve) training_config = prepare_for_training(config, train_dataset, val_dataset, time_monitor, learning_curves) mm_train_dataset = build_dataset(training_config.data.train) diff --git a/mmdet/apis/ote/apis/detection/openvino_task.py b/mmdet/apis/ote/apis/detection/openvino_task.py index 5953d6811f3..292d1e14163 100644 --- a/mmdet/apis/ote/apis/detection/openvino_task.py +++ b/mmdet/apis/ote/apis/detection/openvino_task.py @@ -20,6 +20,7 @@ import cv2 import numpy as np from addict import Dict as ADDict +from ie import ExecutableNetwork from compression.api import DataLoader from compression.engines.ie_engine import IEEngine from compression.graph import load_model, save_model @@ -46,7 +47,7 @@ logger = logging.getLogger(__name__) -def get_output(net, outputs, name): +def get_output(net: ExecutableNetwork, outputs: Dict[str, np.ndarray], name: str) -> np.ndarray: try: key = net.get_ov_name_for_tensor(name) assert key in outputs, f'"{key}" is not a valid output identifier' @@ -57,7 +58,8 @@ def get_output(net, outputs, name): return outputs[key] -def extract_detections(output, net, input_size): +def extract_detections(output: Dict[str, np.ndarray], net: ExecutableNetwork, + input_size: Tuple[int, int]) -> Dict[str, np.ndarray]: if 'detection_out' in output: detection_out = output['detection_out'] output['labels'] = detection_out[0, 0, :, 1].astype(np.int32) @@ -106,7 +108,7 @@ def __init__( self.confidence_threshold = float(hparams.postprocessing.confidence_threshold) @staticmethod - def resize_image(image: np.ndarray, size: Tuple[int], keep_aspect_ratio: bool = False) -> np.ndarray: + def resize_image(image: np.ndarray, size: Tuple[int, int], keep_aspect_ratio: bool = False) -> np.ndarray: if not keep_aspect_ratio: resized_frame = cv2.resize(image, size) else: diff --git a/mmdet/apis/ote/apis/detection/train_task.py b/mmdet/apis/ote/apis/detection/train_task.py index 5d22d1a2e34..4422cda5a35 100644 --- a/mmdet/apis/ote/apis/detection/train_task.py +++ b/mmdet/apis/ote/apis/detection/train_task.py @@ -16,7 +16,7 @@ import logging import os from collections import defaultdict -from typing import List, Optional +from typing import DefaultDict, Dict, List, Optional import torch from ote_sdk.entities.datasets import DatasetEntity @@ -40,7 +40,7 @@ class OTEDetectionTrainingTask(OTEDetectionInferenceTask, ITrainingTask): - def _generate_training_metrics_group(self, learning_curves) -> Optional[List[MetricsGroup]]: + def _generate_training_metrics_group(self, learning_curves: Dict[str, OTELoggerHook.Curve]) -> List[MetricsGroup]: """ Parses the mmdetection logs to get metrics from the latest training run @@ -77,7 +77,7 @@ def train(self, dataset: DatasetEntity, output_model: ModelEntity, train_paramet old_model = copy.deepcopy(self._model) # Evaluate model performance before training. - _, initial_performance = self._infer_detector(self._model, config, val_dataset, True) + initial_performance = self._infer_detector(self._model, config, val_dataset, True)[1] logger.info(f'initial_performance = {initial_performance}') # Check for stop signal between pre-eval and training. If training is cancelled at this point, @@ -96,7 +96,7 @@ def train(self, dataset: DatasetEntity, output_model: ModelEntity, train_paramet else: update_progress_callback = default_progress_callback time_monitor = TrainingProgressCallback(update_progress_callback) - learning_curves = defaultdict(OTELoggerHook.Curve) + learning_curves: DefaultDict[str, OTELoggerHook.Curve] = defaultdict(OTELoggerHook.Curve) training_config = prepare_for_training(config, train_dataset, val_dataset, time_monitor, learning_curves) self._training_work_dir = training_config.work_dir mm_train_dataset = build_dataset(training_config.data.train) @@ -120,7 +120,7 @@ def train(self, dataset: DatasetEntity, output_model: ModelEntity, train_paramet self._model.load_state_dict(best_checkpoint['state_dict']) # Evaluate model performance after training. - _, final_performance = self._infer_detector(self._model, config, val_dataset, True) + final_performance = self._infer_detector(self._model, config, val_dataset, True)[1] improved = final_performance > initial_performance # Return a new model if model has improved, or there is no model yet. diff --git a/mmdet/apis/ote/extension/datasets/__init__.py b/mmdet/apis/ote/extension/datasets/__init__.py index 43526acec85..0785abed0da 100644 --- a/mmdet/apis/ote/extension/datasets/__init__.py +++ b/mmdet/apis/ote/extension/datasets/__init__.py @@ -14,4 +14,4 @@ from .mmdataset import OTEDataset, get_annotation_mmdet_format -__all__ = [OTEDataset, get_annotation_mmdet_format] +__all__ = ['OTEDataset', 'get_annotation_mmdet_format'] diff --git a/mmdet/apis/ote/extension/utils/__init__.py b/mmdet/apis/ote/extension/utils/__init__.py index 9cc35e5287d..eb7156da9b9 100644 --- a/mmdet/apis/ote/extension/utils/__init__.py +++ b/mmdet/apis/ote/extension/utils/__init__.py @@ -17,6 +17,6 @@ from .pipelines import LoadImageFromOTEDataset, LoadAnnotationFromOTEDataset from .runner import EpochRunnerWithCancel -__all__ = [CancelTrainingHook, FixedMomentumUpdaterHook, LoadImageFromOTEDataset, EpochRunnerWithCancel, - LoadAnnotationFromOTEDataset, OTELoggerHook, OTEProgressHook, EarlyStoppingHook, - ReduceLROnPlateauLrUpdaterHook] +__all__ = ['CancelTrainingHook', 'FixedMomentumUpdaterHook', 'LoadImageFromOTEDataset', 'EpochRunnerWithCancel', + 'LoadAnnotationFromOTEDataset', 'OTELoggerHook', 'OTEProgressHook', 'EarlyStoppingHook', + 'ReduceLROnPlateauLrUpdaterHook'] diff --git a/tests/conftest.py b/tests/conftest.py index e8207833e78..9a02c64cf1b 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -10,7 +10,7 @@ _e2e_pytest_addoption = None pass -import config +import e2e_config def pytest_addoption(parser): if _e2e_pytest_addoption: diff --git a/tests/config.py b/tests/e2e_config.py similarity index 100% rename from tests/config.py rename to tests/e2e_config.py diff --git a/tests/test_ote_training.py b/tests/test_ote_training.py index c9175a1dad9..c5135106ee7 100644 --- a/tests/test_ote_training.py +++ b/tests/test_ote_training.py @@ -20,7 +20,7 @@ from collections import namedtuple, OrderedDict from copy import deepcopy from pprint import pformat -from typing import Optional, Union +from typing import Optional, Tuple, Union import pytest import yaml @@ -43,7 +43,7 @@ logger = logging.getLogger(__name__) -def DATASET_PARAMETERS_FIELDS(): +def DATASET_PARAMETERS_FIELDS() -> Tuple[str, ...]: return ('annotations_train', 'images_train_dir', 'annotations_val', @@ -53,7 +53,7 @@ def DATASET_PARAMETERS_FIELDS(): ) ROOT_PATH_KEY = '_root_path' -DatasetParameters = namedtuple('DatasetParameters', DATASET_PARAMETERS_FIELDS()) +DatasetParameters = namedtuple('DatasetParameters', DATASET_PARAMETERS_FIELDS()) # type: ignore @pytest.fixture def dataset_definitions_fx(request): From 8540c75666c8d23eda900ba90d96b6103a11c5c2 Mon Sep 17 00:00:00 2001 From: "Druzhkov, Pavel" Date: Mon, 18 Oct 2021 15:21:00 +0300 Subject: [PATCH 2/5] fix import --- mmdet/apis/ote/apis/detection/openvino_task.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mmdet/apis/ote/apis/detection/openvino_task.py b/mmdet/apis/ote/apis/detection/openvino_task.py index 292d1e14163..e59d4f3f5ee 100644 --- a/mmdet/apis/ote/apis/detection/openvino_task.py +++ b/mmdet/apis/ote/apis/detection/openvino_task.py @@ -20,12 +20,12 @@ import cv2 import numpy as np from addict import Dict as ADDict -from ie import ExecutableNetwork from compression.api import DataLoader from compression.engines.ie_engine import IEEngine from compression.graph import load_model, save_model from compression.graph.model_utils import compress_model_weights, get_nodes_by_type from compression.pipeline.initializer import create_pipeline +from openvino.inference_engine import ExecutableNetwork from ote_sdk.entities.annotation import Annotation, AnnotationSceneEntity, AnnotationSceneKind from ote_sdk.entities.datasets import DatasetEntity from ote_sdk.entities.inference_parameters import InferenceParameters From a6da4fb9d998d0b9de72dcfbe2e8c02786a455c9 Mon Sep 17 00:00:00 2001 From: "Druzhkov, Pavel" Date: Mon, 18 Oct 2021 17:45:05 +0300 Subject: [PATCH 3/5] ignore mypy issue in nncf task --- mmdet/apis/ote/apis/detection/nncf_task.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mmdet/apis/ote/apis/detection/nncf_task.py b/mmdet/apis/ote/apis/detection/nncf_task.py index 9f00dfd23f7..9f3fe65cc01 100644 --- a/mmdet/apis/ote/apis/detection/nncf_task.py +++ b/mmdet/apis/ote/apis/detection/nncf_task.py @@ -183,7 +183,7 @@ def save_model(self, output_model: ModelEntity): hyperparams_str = ids_to_strings(cfg_helper.convert(hyperparams, dict, enum_to_str=True)) labels = {label.name: label.color.rgb_tuple for label in self._labels} modelinfo = { - 'compression_state': self._compression_ctrl.get_compression_state(), + 'compression_state': self._compression_ctrl.get_compression_state(), # type: ignore # FIXME. 'meta': { 'config': self._config, 'nncf_enable_compression': True, From b96b9c8ba0257dd7f4358cdbe9e7e573b580938d Mon Sep 17 00:00:00 2001 From: "Druzhkov, Pavel" Date: Tue, 19 Oct 2021 12:18:00 +0300 Subject: [PATCH 4/5] up --- .mypy.ini | 12 +++++++----- mmdet/apis/ote/extension/datasets/mmdataset.py | 7 ++++--- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/.mypy.ini b/.mypy.ini index 6310db6cb26..e0ba677d51c 100644 --- a/.mypy.ini +++ b/.mypy.ini @@ -1,10 +1,9 @@ [mypy] python_version = 3.8 -ignore_missing_imports = True +; ignore_missing_imports = True show_error_codes = True - -[mypy-mmdet.apis] -ignore_errors = True +check_untyped_defs = True +strict = True [mypy-mmdet.core.*] ignore_errors = True @@ -25,4 +24,7 @@ ignore_errors = True ignore_errors = True [mypy-mmdet.utils.*] -ignore_errors = True \ No newline at end of file +ignore_errors = True + +[mypy-mmdet.tests] +ignore_errors = True diff --git a/mmdet/apis/ote/extension/datasets/mmdataset.py b/mmdet/apis/ote/extension/datasets/mmdataset.py index cdbb6921328..cf2cf0e4523 100644 --- a/mmdet/apis/ote/extension/datasets/mmdataset.py +++ b/mmdet/apis/ote/extension/datasets/mmdataset.py @@ -13,7 +13,7 @@ # and limitations under the License. from copy import deepcopy -from typing import List +from typing import List, Sequence, Optional import numpy as np from ote_sdk.entities.dataset_item import DatasetItemEntity @@ -88,7 +88,7 @@ class _DataInfoProxy: forwards data access operations to ote_dataset and converts the dataset items to the view convenient for mmdetection. """ - def __init__(self, ote_dataset, classes): + def __init__(self, ote_dataset: DatasetEntity, classes: Optional[Sequence[str]]): self.ote_dataset = ote_dataset self.CLASSES = classes @@ -113,7 +113,7 @@ def __getitem__(self, index): return data_info def __init__(self, ote_dataset: DatasetEntity, pipeline, classes=None, test_mode: bool = False): - self.ote_dataset = ote_dataset + self.ote_dataset: DatasetEntity = ote_dataset self.test_mode = test_mode self.CLASSES = self.get_classes(classes) @@ -193,4 +193,5 @@ def get_ann_info(self, idx): if label_list is None: # For RepeatDataset wrapper. label_list = self.dataset.CLASSES + self.ote_dataset.project_labels return get_annotation_mmdet_format(dataset_item, label_list) From cc6870bb1adebde89989228a0db5b78892bc0e40 Mon Sep 17 00:00:00 2001 From: "Druzhkov, Pavel" Date: Fri, 12 Nov 2021 18:50:19 +0300 Subject: [PATCH 5/5] update mypy config --- .mypy.ini | 25 +++++++++++++++++++++++-- .pre-commit-config.yaml | 2 +- 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/.mypy.ini b/.mypy.ini index e0ba677d51c..532737e2c07 100644 --- a/.mypy.ini +++ b/.mypy.ini @@ -1,6 +1,6 @@ [mypy] python_version = 3.8 -; ignore_missing_imports = True +ignore_missing_imports = True show_error_codes = True check_untyped_defs = True strict = True @@ -26,5 +26,26 @@ ignore_errors = True [mypy-mmdet.utils.*] ignore_errors = True -[mypy-mmdet.tests] +[mypy-mmdet] +ignore_errors = True + +[mypy-mmdet.version] +ignore_errors = True + +[mypy-mmdet.apis] +ignore_errors = True + +[mypy-mmdet.apis.train] +ignore_errors = True + +[mypy-mmdet.apis.test] +ignore_errors = True + +[mypy-mmdet.apis.export] +ignore_errors = True + +[mypy-mmdet.apis.inference] +ignore_errors = True + +[mypy-mmdet.apis.fake_input] ignore_errors = True diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 896613b8891..5beda0b2ec2 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -44,4 +44,4 @@ repos: - id: mypy args: ["--config-file=.mypy.ini"] additional_dependencies: [numpy==1.19.5, types-PyYAML, attrs==21.2.*, types-requests, types-Deprecated, types-docutils, types_futures, types-python-dateutil] - exclude: "ci|configs|data|demo|docker|docs|experiments|resources|tools" + exclude: "ci|configs|data|demo|docker|docs|experiments|resources|tools|.dev_scripts|tests|setup.py"