From ee59e3883239c364f5cd2f8b808f0be206f155ce Mon Sep 17 00:00:00 2001 From: Maksim Andrianov Date: Wed, 27 May 2020 14:39:05 +0300 Subject: [PATCH] [python][generator] Added default check sets. --- tools/python/maps_generator/checks/check.py | 27 +++-- .../maps_generator/checks/check_categories.py | 2 +- .../checks/default_check_set.py | 100 ++++++++++++++++++ 3 files changed, 117 insertions(+), 12 deletions(-) create mode 100644 tools/python/maps_generator/checks/default_check_set.py diff --git a/tools/python/maps_generator/checks/check.py b/tools/python/maps_generator/checks/check.py index 5d43c3c5ca..fb04e0119f 100644 --- a/tools/python/maps_generator/checks/check.py +++ b/tools/python/maps_generator/checks/check.py @@ -1,4 +1,5 @@ import os +import sys from abc import ABC from abc import abstractmethod from collections import namedtuple @@ -8,7 +9,6 @@ from typing import Any from typing import Callable from typing import List - ResLine = namedtuple("ResLine", ["previous", "current", "diff", "arrow"]) @@ -35,6 +35,7 @@ class Check(ABC): self.zero: Any = 0 self.diff_format: Callable[[Any], str] = lambda x: str(x) self.format: Callable[[Any], str] = lambda x: str(x) + self.filt: Callable[[Any], bool] = lambda x: True def set_op(self, op: Callable[[Any, Any], Any]): self.op = op @@ -51,10 +52,13 @@ class Check(ABC): def set_format(self, format: Callable[[Any], str]): self.format = format - def print(self, silent_if_no_results=False, filt=lambda x: x, print_=print): - s = self.formatted_string(silent_if_no_results, filt=filt) + def set_filt(self, filt: Callable[[Any], bool]): + self.filt = filt + + def print(self, silent_if_no_results=False, filt=None, file=sys.stdout): + s = self.formatted_string(silent_if_no_results, filt) if s: - print_(s) + print(s, file=file) @abstractmethod def check(self): @@ -65,7 +69,7 @@ class Check(ABC): pass @abstractmethod - def formatted_string(self, silent_if_no_results=False, **kwargs) -> str: + def formatted_string(self, silent_if_no_results=False, *args, **kwargs) -> str: pass @@ -115,7 +119,7 @@ class CompareCheck(Check): ) return True - def formatted_string(self, silent_if_no_results=False, **kwargs) -> str: + def formatted_string(self, silent_if_no_results=False, *args, **kwargs) -> str: assert self.result if silent_if_no_results and self.result.arrow == Arrow.zero: @@ -165,12 +169,13 @@ class CompareCheckSet(Check): def get_result(self,) -> List[ResLine]: return [c.get_result() for c in self._with_result()] - def formatted_string( - self, silent_if_no_results=False, filt=lambda x: True, _offset=0 - ) -> str: + def formatted_string(self, silent_if_no_results=False, filt=None, _offset=0) -> str: sets = filter(lambda c: isinstance(c, CompareCheckSet), self._with_result()) checks = filter(lambda c: isinstance(c, CompareCheck), self._with_result()) - checks = sorted(checks, key=lambda c: c.get_result().diff, reverse=True,) + checks = sorted(checks, key=lambda c: c.get_result().diff, reverse=True) + + if filt is None: + filt = self.filt checks = filter(lambda c: filt(c.get_result()), checks) @@ -190,7 +195,7 @@ class CompareCheckSet(Check): lines.append(f"{' ' * _offset}No results.") for c in checks: - s = c.formatted_string(silent_if_no_results) + s = c.formatted_string(silent_if_no_results, filt, _offset + 1) if s: lines.append(f"{' ' * _offset + ' '}{s}") diff --git a/tools/python/maps_generator/checks/check_categories.py b/tools/python/maps_generator/checks/check_categories.py index a8b87754ff..9a4314da4c 100644 --- a/tools/python/maps_generator/checks/check_categories.py +++ b/tools/python/maps_generator/checks/check_categories.py @@ -29,7 +29,7 @@ def parse_groups(path): return groups -def get_mwm_categories_check_set( +def get_categories_check_set( old_path: str, new_path: str, categories_path: str ) -> check.CompareCheckSet: cs = check.CompareCheckSet("Sections categories check") diff --git a/tools/python/maps_generator/checks/default_check_set.py b/tools/python/maps_generator/checks/default_check_set.py new file mode 100644 index 0000000000..c47e0f36bd --- /dev/null +++ b/tools/python/maps_generator/checks/default_check_set.py @@ -0,0 +1,100 @@ +import os +import sys +from collections import namedtuple +from enum import Enum +from typing import Callable +from typing import Mapping + +from maps_generator.checks import check +from maps_generator.checks.check_categories import get_categories_check_set +from maps_generator.checks.check_mwm_types import count_all_types +from maps_generator.checks.check_mwm_types import get_mwm_all_types_check_set +from maps_generator.checks.check_mwm_types import get_mwm_type_check_set +from maps_generator.checks.check_sections import get_sections_existence_check_set +from maps_generator.checks.check_sections import get_sections_size_check_set +from maps_generator.checks.check_size import get_size_check_set + + +class CheckType(Enum): + low = 1 + medium = 2 + hard = 3 + strict = 4 + + +Threshold = namedtuple("Threshold", ["abs", "rel"]) + +_check_type_map = { + CheckType.low: Threshold(abs=20, rel=20), + CheckType.medium: Threshold(abs=15, rel=15), + CheckType.hard: Threshold(abs=10, rel=10), + CheckType.strict: Threshold(abs=0, rel=0), +} + + +def set_threshold(check_type_map: Mapping[CheckType, Threshold]): + global _check_type_map + _check_type_map = check_type_map + + +def get_threshold(check_type: CheckType) -> Threshold: + return _check_type_map[check_type] + + +def make_default_filter(threshold: Threshold): + def default_filter(r: check.ResLine): + if isinstance(r.diff, (int, float)): + diff = abs(r.diff) + previous = r.previous + current = r.current + else: + assert False, type(r.diff) + + return ( + diff > threshold.abs + and (diff * 100.0 / max(previous, current)) > threshold.rel + ) + + return default_filter + + +def get_mwm_check_sets_and_filters( + old_path: str, new_path: str, categories_path: str +) -> Mapping[check.Check, Callable]: + return { + get_categories_check_set( + old_path, new_path, categories_path + ): make_default_filter, + get_mwm_type_check_set( + old_path, new_path, "sponsored-booking" + ): make_default_filter, + get_mwm_all_types_check_set(old_path, new_path): make_default_filter, + get_size_check_set(old_path, new_path): make_default_filter, + get_sections_size_check_set(old_path, new_path): make_default_filter, + get_sections_existence_check_set(old_path, new_path): None, + } + + +def _print_header(file, header, width=100, s="="): + stars = s * ((width - len(header)) // 2) + rstars = stars + if 2 * len(stars) + len(header) < width: + rstars += s + print(stars, header, rstars, file=file) + + +def run_checks_and_print_results( + checks: Mapping[check.Check, Callable], + check_type: CheckType, + silent_if_no_results: bool = True, + file=sys.stdout, +): + threshold = get_threshold(check_type) + for check, make_filt in checks.items(): + check.check() + _print_header(file, check.name) + check.print( + silent_if_no_results=silent_if_no_results, + filt=None if make_filt is None else make_filt(threshold), + file=file, + )