# # Metrix++, Copyright 2009-2013, Metrix++ Project # Link: http://swi.sourceforge.net # # This file is a part of Metrix++ Tool. # # Metrix++ is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, version 3 of the License. # # Metrix++ is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Metrix++. If not, see . # import re import core.api class Plugin(core.api.Plugin, core.api.IConfigurable): MODE_NEW = 0x01 MODE_TREND = 0x03 MODE_TOUCHED = 0x07 MODE_ALL = 0x15 def declare_configuration(self, parser): self.parser = parser parser.add_option("--general.warn", default='all', choices=['new', 'trend', 'touched', 'all'], help="Defines the warnings mode. " "'off' - no warnings, 'new' - warnings for new regions only, " "'trend' - warnings for new regions and for bad trend of modified regions, " "'touched' - warnings for new regions and modified regions, " "'all' - all warnings active" "[default: %default]") parser.add_option("--general.min-limit", action="multiopt", help='TBD') parser.add_option("--general.max-limit", action="multiopt", help='TBD') def configure(self, options): if options.__dict__['general.warn'] == 'new': self.mode = self.MODE_NEW elif options.__dict__['general.warn'] == 'trend': self.mode = self.MODE_TREND elif options.__dict__['general.warn'] == 'touched': self.mode = self.MODE_TOUCHED elif options.__dict__['general.warn'] == 'all': self.mode = self.MODE_ALL class Limit(object): def __init__(self, limit_type, limit, namespace, field, db_filter): self.type = limit_type self.limit = limit self.namespace = namespace self.field = field self.filter = db_filter def __repr__(self): return "namespace '" + self.namespace + "', filter '" + str(self.filter) + "'" self.limits = [] pattern = re.compile(r'''([^:]+)[:]([^:]+)[:]([-+]?[0-9]+(?:[.][0-9]+)?)''') if options.__dict__['general.max_limit'] != None: for each in options.__dict__['general.max_limit']: match = re.match(pattern, each) if match == None: self.parser.error("Invalid format of the 'general.max-limit' option: " + each) limit = Limit("max", match.group(3), match.group(1), match.group(2), (match.group(2), '>', float(match.group(3)))) self.limits.append(limit) if options.__dict__['general.min_limit'] != None: for each in options.__dict__['general.min_limit']: match = re.match(pattern, each) if match == None: self.parser.error("Invalid format of the 'general.min-limit' option: " + each) limit = Limit("min", match.group(3), match.group(1), match.group(2), (match.group(2), '<', float(match.group(3)))) self.limits.append(limit) def verify_namespaces(self, valid_namespaces): valid = [] for each in valid_namespaces: valid.append(each) for each in self.limits: if each.namespace not in valid: self.parser.error("Invalid limit option (namespace does not exist): " + each.namespace) def verify_fields(self, namespace, valid_fields): valid = [] for each in valid_fields: valid.append(each) for each in self.limits: if each.namespace == namespace: if each.field not in valid: self.parser.error("Invalid limit option (field does not exist): " + each.namespace + ":" + each.field) def iterate_limits(self): for each in self.limits: yield each def is_mode_matched(self, limit, value, diff, is_modified): if is_modified == None: return True if self.mode == self.MODE_ALL: return True if self.mode == self.MODE_TOUCHED and is_modified == True: return True if self.mode == self.MODE_TREND and is_modified == True: if limit < value and diff > 0: return True if limit > value and diff < 0: return True return False