avkonst 11 éve
szülő
commit
d891fab510

+ 0 - 18
mainline/core/__init__.py

@@ -1,18 +0,0 @@
-#
-#    Metrix++, Copyright 2009-2013, Metrix++ Project
-#    Link: http://metrixplusplus.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 <http://www.gnu.org/licenses/>.
-#

A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 0 - 1225
mainline/core/api.py


+ 0 - 39
mainline/core/cmdparser.py

@@ -1,39 +0,0 @@
-#
-#    Metrix++, Copyright 2009-2013, Metrix++ Project
-#    Link: http://metrixplusplus.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 <http://www.gnu.org/licenses/>.
-#
-
-import optparse
-
-class MultiOptionParser(optparse.OptionParser):
-    
-    class MultipleOption(optparse.Option):
-        ACTIONS = optparse.Option.ACTIONS + ("multiopt",)
-        STORE_ACTIONS = optparse.Option.STORE_ACTIONS + ("multiopt",)
-        TYPED_ACTIONS = optparse.Option.TYPED_ACTIONS + ("multiopt",)
-        ALWAYS_TYPED_ACTIONS = optparse.Option.ALWAYS_TYPED_ACTIONS + ("multiopt",)
-    
-        def take_action(self, action, dest, opt, value, values, parser):
-            if action == "multiopt":
-                values.ensure_value(dest, []).append(value)
-            else:
-                optparse.Option.take_action(self, action, dest, opt, value, values, parser)
-
-    
-    def __init__(self, *args, **kwargs):
-        optparse.OptionParser.__init__(self, *args, option_class=self.MultipleOption, **kwargs)
-        

+ 0 - 40
mainline/core/cout.py

@@ -1,40 +0,0 @@
-#
-#    Metrix++, Copyright 2009-2013, Metrix++ Project
-#    Link: http://metrixplusplus.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 <http://www.gnu.org/licenses/>.
-#
-
-SEVERITY_INFO    = 0x01
-SEVERITY_WARNING = 0x02
-SEVERITY_ERROR   = 0x03
-
-def notify(path, cursor, level, message, details = []):
-    notification = path + ":" + str(cursor) + ": "
-    if level == SEVERITY_INFO:
-        notification += "info: "
-    elif level == SEVERITY_WARNING:
-        notification += "warning: "
-    elif level == SEVERITY_ERROR:
-        notification += "error: "
-    else:
-        assert(len("Invalid message severity level specified") == 0)
-    notification += message + "\n"
-
-    DETAILS_OFFSET = 15
-    for each in details:
-        notification += "\t" + str(each[0]) + (" " * (DETAILS_OFFSET - len(each[0]))) + ": " + str(each[1]) + "\n"
-        
-    print notification

+ 0 - 18
mainline/core/db/__init__.py

@@ -1,18 +0,0 @@
-#
-#    Metrix++, Copyright 2009-2013, Metrix++ Project
-#    Link: http://metrixplusplus.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 <http://www.gnu.org/licenses/>.
-#

+ 0 - 81
mainline/core/db/post.py

@@ -1,81 +0,0 @@
-#
-#    Metrix++, Copyright 2009-2013, Metrix++ Project
-#    Link: http://metrixplusplus.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 <http://www.gnu.org/licenses/>.
-#
-
-import core.api
-
-import os.path
-import re
-
-import logging
-
-class Plugin(core.api.Plugin, core.api.IConfigurable):
-    
-    def declare_configuration(self, parser):
-        parser.add_option("--db-file", "--dbf", default='./metrixpp.db',
-                         help="Primary database file to write (by the collector) and post-process (by other tools) [default: %default]")
-        parser.add_option("--db-file-prev", "--dbfp", default=None,
-                         help="Database file with data collected for the past/previous revision."
-                             " If it is set for the collector tool to perform an incremental/iterative collection,"
-                             " it may reduce the processing time significantly."
-                             " Post-processing tools use it in order to recognise/evaluate change trends. [default: %default].")
-        self.parser = parser
-    
-    def configure(self, options):
-        self.dbfile = options.__dict__['db_file']
-        self.dbfile_prev = options.__dict__['db_file_prev']
-        
-        if self.dbfile_prev != None and os.path.exists(self.dbfile_prev) == False:
-            self.parser.error("File does not exist:" + self.dbfile_prev)
-
-        
-    def initialize(self):
-        
-        if self.get_plugin_loader() != None:
-            if os.path.exists(self.dbfile):
-                logging.warn("Removing existing file: " + self.dbfile)
-                # TODO can reuse existing db file to speed up the processing?
-                # TODO add option to choose to remove or to overwrite?
-                try:
-                    os.unlink(self.dbfile)
-                except:
-                    logging.warn("Failure in removing file: " + self.dbfile)
-    
-            created = self.get_plugin_loader().get_database_loader().create_database(self.dbfile, previous_db = self.dbfile_prev)
-            if created == False:
-                self.parser.error("Failure in creating file: " + self.dbfile)
-            
-            # do not process files dumped by this module
-            self.get_plugin_loader().get_plugin('core.dir').add_exclude_rule(re.compile(r'^' + os.path.basename(self.dbfile) + r'$'))
-            if self.dbfile_prev != None:
-                self.get_plugin_loader().get_plugin('core.dir').add_exclude_rule(re.compile(r'^' + os.path.basename(self.dbfile_prev) + r'$'))
-
-        else:
-            self.loader_prev = core.api.Loader()
-            if self.dbfile_prev != None:
-                if self.loader_prev.open_database(self.dbfile_prev) == False:
-                    self.parser.error("Can not open file: " + self.dbfile_prev)
-            self.loader = core.api.Loader()
-            if self.loader.open_database(self.dbfile) == False:
-                self.parser.error("Can not open file: " + self.dbfile)
-
-    def get_loader(self):
-        return self.loader
-
-    def get_loader_prev(self):
-        return self.loader_prev

+ 0 - 696
mainline/core/db/sqlite.py

@@ -1,696 +0,0 @@
-#
-#    Metrix++, Copyright 2009-2013, Metrix++ Project
-#    Link: http://metrixplusplus.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 <http://www.gnu.org/licenses/>.
-#
-
-import sqlite3
-import re
-import os.path
-import logging
-import itertools 
-import shutil
-import traceback
-
-class Database(object):
-    
-    last_used_id = 0
-    version = "1.0"
-    
-    class TableData(object):
-        def __init__(self, table_id, name, support_regions):
-            self.id = table_id
-            self.name = name
-            self.support_regions = support_regions
-    
-    class ColumnData(object):
-        def __init__(self, column_id, name, sql_type, non_zero):
-            self.id = column_id
-            self.name = name
-            self.sql_type = sql_type
-            self.non_zero = non_zero
-
-    class TagData(object):
-        def __init__(self, tag_id, name):
-            self.id = tag_id
-            self.name = name
-
-    class PropertyData(object):
-        def __init__(self, property_id, name, value):
-            self.id = property_id
-            self.name = name
-            self.value = value
-
-    class FileData(object):
-        def __init__(self, file_id, path, checksum):
-            self.id = file_id
-            self.path = path
-            self.checksum = checksum
-
-    class RegionData(object):
-        def __init__(self, file_id, region_id, name, begin, end, line_begin, line_end, cursor, group, checksum):
-            self.file_id = file_id
-            self.region_id = region_id
-            self.name = name
-            self.begin = begin
-            self.end = end
-            self.line_begin = line_begin
-            self.line_end = line_end
-            self.cursor = cursor
-            self.group = group
-            self.checksum = checksum
-
-    class MarkerData(object):
-        def __init__(self, file_id, begin, end, group):
-            self.file_id = file_id
-            self.begin = begin
-            self.end = end
-            self.group = group
-
-    def __init__(self):
-        self.read_only = False
-        self.conn = None
-        self.dirs = None
-        self.is_cloned = False
-        
-        self.last_used_id += 1
-        self.id = self.last_used_id
-    
-    def __del__(self):
-        if self.conn != None:
-            if self.is_cloned == True:
-                logging.debug("Cleaning up database file")
-                self.InternalCleanUpUtils().clean_up_not_confirmed(self)
-            logging.debug("Committing database file")
-            self.conn.commit()
-    
-    class InternalCleanUpUtils(object):
-        
-        def clean_up_not_confirmed(self, db_loader):
-            sql = "DELETE FROM __info__ WHERE (confirmed = 0)"
-            db_loader.log(sql)
-            db_loader.conn.execute(sql)
-            sql = "DELETE FROM __tags__ WHERE (confirmed = 0)"
-            db_loader.log(sql)
-            db_loader.conn.execute(sql)
-
-            sql = "SELECT * FROM __tables__ WHERE (confirmed = 0)"
-            db_loader.log(sql)
-            for table in db_loader.conn.execute(sql).fetchall():
-                sql = "DELETE FROM __columns__ WHERE table_id = '" + str(table['id']) + "'"
-                db_loader.log(sql)
-                db_loader.conn.execute(sql)
-                sql = "DELETE FROM __tables__ WHERE id = '" + str(table['id']) + "'"
-                db_loader.log(sql)
-                db_loader.conn.execute(sql)
-                sql = "DROP TABLE '" + table['name'] + "'"
-                db_loader.log(sql)
-                db_loader.conn.execute(sql)
-
-            sql = "SELECT __columns__.name AS column_name, __tables__.name AS table_name, __columns__.id AS column_id FROM __columns__, __tables__ WHERE (__columns__.confirmed = 0 AND __columns__.table_id = __tables__.id)"
-            db_loader.log(sql)
-            for column in db_loader.conn.execute(sql).fetchall():
-                logging.info("New database file inherits useless column: '" + column['table_name'] + "'.'" + column['column_name'] + "'")
-                sql = "DELETE FROM __columns__ WHERE id = '" + str(column['column_id']) + "'"
-                db_loader.log(sql)
-                db_loader.conn.execute(sql)
-                sql = "UPDATE '" + column['table_name'] + "' SET '" + column['column_name'] + "' = NULL"
-                db_loader.log(sql)
-                db_loader.conn.execute(sql)
-            
-            self.clean_up_file(db_loader)
-
-        def clean_up_file(self, db_loader, file_id = None):
-            sql = "SELECT * FROM __tables__"
-            db_loader.log(sql)
-            for table in itertools.chain(db_loader.conn.execute(sql).fetchall(), [{'name':'__regions__'}, {'name':'__markers__'}]):
-                sql = ""
-                if file_id == None:
-                    sql = "DELETE FROM '" + table['name'] + "' WHERE file_id IN (SELECT __files__.id FROM __files__ WHERE __files__.confirmed = 0)"
-                else:
-                    sql = "DELETE FROM '" + table['name'] + "' WHERE (file_id = " + str(file_id) + ")"
-                db_loader.log(sql)
-                db_loader.conn.execute(sql)
-            
-    class InternalPathUtils(object):
-        
-        def iterate_heads(self, path):
-            dirs = []
-            head = os.path.dirname(path)
-            last_head = None # to process Windows drives
-            while (head != "" and last_head != head):
-                dirs.append(os.path.basename(head))
-                last_head = head
-                head = os.path.dirname(head)
-            dirs.reverse()
-            for each in dirs:
-                yield each
-                
-        def normalize_path(self, path):
-            if path == None:
-                return None
-            return re.sub(r'''[\\]''', "/", path)
-        
-        def update_dirs(self, db_loader, path = None):
-            if db_loader.dirs == None:
-                if path == None:
-                    db_loader.dirs = {} # initial construction
-                else:
-                    return # avoid useless cache updates 
-            elif path == None:
-                return # avoid multiple initial constructions
-            
-            path = self.normalize_path(path)
-            rows = None
-            if path == None:
-                sql = "SELECT * FROM __files__"
-                db_loader.log(sql)
-                rows = db_loader.conn.execute(sql).fetchall()
-            else:
-                rows = [{"path": path}]
-            for row in rows:
-                cur_head = db_loader.dirs
-                for dir_name in self.iterate_heads(row["path"]):
-                    if dir_name not in cur_head.keys():
-                        cur_head[dir_name] = {}
-                    cur_head = cur_head[dir_name]
-                cur_head[os.path.basename(row["path"])] = None
-
-
-    def create(self, file_name, clone_from = None):
-        if clone_from != None:
-            self.is_cloned = True
-            logging.debug("Cloning database file: " + clone_from)
-            shutil.copy2(clone_from, file_name)
-            logging.debug("Connecting database file: " + file_name)
-            self.conn = sqlite3.connect(file_name)
-            self.conn.row_factory = sqlite3.Row
-            self.read_only = False
-            
-            sql = "UPDATE __tables__ SET confirmed = 0"
-            self.log(sql)
-            self.conn.execute(sql)
-            sql = "UPDATE __columns__ SET confirmed = 0"
-            self.log(sql)
-            self.conn.execute(sql)
-            sql = "UPDATE __tags__ SET confirmed = 0"
-            self.log(sql)
-            self.conn.execute(sql)
-            sql = "UPDATE __files__ SET confirmed = 0"
-            self.log(sql)
-            self.conn.execute(sql)
-                
-        else:
-            self.connect(file_name)
-        
-    def connect(self, file_name, read_only = False):
-        logging.debug("Connecting database file: " + file_name)
-        self.conn = sqlite3.connect(file_name)
-        self.conn.row_factory = sqlite3.Row
-        self.read_only = read_only
-        if self.read_only == False:
-            try:
-                sql = "CREATE TABLE __info__ (id integer NOT NULL PRIMARY KEY AUTOINCREMENT, property text NOT NULL, value text, confirmed integer NOT NULL, UNIQUE (property) ON CONFLICT REPLACE)"
-                self.log(sql)
-                self.conn.execute(sql)
-                sql = "INSERT INTO __info__ (property, value, confirmed) VALUES ('version', '" + self.version + "', 1)"
-                self.log(sql)
-                self.conn.execute(sql)
-                sql = "CREATE TABLE __tables__ (id integer NOT NULL PRIMARY KEY, name text NOT NULL, version text NOT NULL, support_regions integer NOT NULL, confirmed integer NOT NULL, UNIQUE (name))"
-                self.log(sql)
-                self.conn.execute(sql)
-                sql = "CREATE TABLE __columns__ (id integer NOT NULL PRIMARY KEY, name text NOT NULL, type text NOT NULL, table_id integer NOT_NULL, non_zero integer NOT NULL, confirmed integer NOT NULL, UNIQUE (name, table_id))"
-                self.log(sql)
-                self.conn.execute(sql)
-                sql = "CREATE TABLE __tags__ (id integer NOT NULL PRIMARY KEY, name text NOT NULL UNIQUE, confirmed integer NOT NULL)"
-                self.log(sql)
-                self.conn.execute(sql)
-                sql = "CREATE TABLE __files__ (id integer NOT NULL PRIMARY KEY AUTOINCREMENT, path text NOT NULL, checksum integer NOT NULL, tag1 integer, tag2 integer, tag3 integer, confirmed integer NOT NULL, UNIQUE(path))"
-                self.log(sql)
-                self.conn.execute(sql)
-                sql = "CREATE TABLE __regions__ (file_id integer NOT NULL, region_id integer NOT NULL, name text NOT NULL, begin integer NOT NULL, end integer NOT NULL, line_begin integer NOT NULL, line_end integer NOT NULL, cursor integer NOT NULL, group_id integer NOT NULL, checksum integer NOT NULL, PRIMARY KEY (file_id, region_id))"
-                self.log(sql)
-                self.conn.execute(sql)
-                sql = "CREATE TABLE __markers__ (id integer NOT NULL PRIMARY KEY, file_id integer NOT NULL, begin integer NOT NULL, end integer NOT NULL, group_id integer NOT NULL)"
-                self.log(sql)
-                self.conn.execute(sql)
-            except sqlite3.OperationalError as e:
-                logging.debug("sqlite3.OperationalError: " + str(e))
-                
-    def set_property(self, property_name, value):
-        ret_val = None
-        sql = "SELECT * FROM __info__ WHERE (property = '" + property_name + "')"
-        self.log(sql)
-        result = self.conn.execute(sql).fetchall()
-        if len(result) != 0:
-            ret_val = result[0]['value']
-
-        sql = "INSERT INTO __info__ (property, value, confirmed) VALUES ('" + property_name + "', '" + value + "', 1)"
-        self.log(sql)
-        self.conn.execute(sql)
-        return ret_val
-        
-    def get_property(self, property_name):
-        ret_val = None
-        sql = "SELECT * FROM __info__ WHERE (property = '" + property_name + "' AND confirmed = 1)"
-        self.log(sql)
-        result = self.conn.execute(sql).fetchall()
-        if len(result) != 0:
-            ret_val = result[0]['value']
-        return ret_val
-
-    def iterate_properties(self):
-        sql = "SELECT * FROM __info__ WHERE (confirmed = 1)"
-        self.log(sql)
-        for each in self.conn.execute(sql).fetchall():
-            yield self.PropertyData(each['id'], each['property'], each['value'])
-
-    def create_table(self, table_name, support_regions = False, version='1.0'):
-        assert(self.read_only == False)
-
-        sql = "SELECT * FROM __tables__ WHERE (name = '" + table_name + "'AND confirmed == 0)"
-        self.log(sql)
-        result = self.conn.execute(sql).fetchall()
-        if len(result) != 0:
-            if result[0]['version'] != version:
-                # in case of changes in version, drop existing table data
-                sql = "DELETE FROM __columns__ WHERE table_id = '" + str(result[0]['id']) + "'"
-                self.log(sql)
-                self.conn.execute(sql)
-                sql = "DELETE FROM __tables__ WHERE id = '" + str(result[0]['id']) + "'"
-                self.log(sql)
-                self.conn.execute(sql)
-                sql = "DROP TABLE '" + result[0]['name'] + "'"
-                self.log(sql)
-                self.conn.execute(sql)
-            else:                
-                sql = "UPDATE __tables__ SET confirmed = 1 WHERE (name = '" + table_name + "')"
-                self.log(sql)
-                self.conn.execute(sql)
-                return False      
-        
-        sql = "CREATE TABLE '" + table_name + "' (file_id integer NOT NULL PRIMARY KEY)"
-        if support_regions == True:
-            sql = str("CREATE TABLE '" + table_name + "' (file_id integer NOT NULL, region_id integer NOT NULL, "
-                      + "PRIMARY KEY (file_id, region_id))")
-            
-        self.log(sql)
-        self.conn.execute(sql)
-        sql = "INSERT INTO __tables__ (name, version, support_regions, confirmed) VALUES ('" + table_name + "', '" + version + "', '" + str(int(support_regions)) + "', 1)"
-        self.log(sql)
-        self.conn.execute(sql)
-        return True
-
-    def iterate_tables(self):
-        sql = "SELECT * FROM __tables__ WHERE (confirmed = 1)"
-        self.log(sql)
-        result = self.conn.execute(sql).fetchall()
-        for row in result:
-            yield self.TableData(int(row["id"]), str(row["name"]), bool(row["support_regions"]))
-            
-    def check_table(self, table_name):
-        sql = "SELECT * FROM __tables__ WHERE (name = '" + table_name + "' AND confirmed = 1)"
-        self.log(sql)
-        result = self.conn.execute(sql).fetchall()
-        if len(result) == 0:
-            return False
-        return True
-
-    def create_column(self, table_name, column_name, column_type, non_zero=False):
-        assert(self.read_only == False)
-        if column_type == None:
-            logging.debug("Skipping column '" + column_name + "' creation for table '" + table_name + "'")
-            return
-        
-        sql = "SELECT id FROM __tables__ WHERE (name = '" + table_name + "')"
-        self.log(sql)
-        table_id = self.conn.execute(sql).next()['id']
-
-        sql = "SELECT * FROM __columns__ WHERE (table_id = '" + str(table_id) + "' AND name = '" + column_name + "' AND confirmed == 0)"
-        self.log(sql)
-        result = self.conn.execute(sql).fetchall()
-        if len(result) != 0:
-            # Major changes in columns should result in step up of table version,
-            # which causes drop the table in case of database reuse
-            assert(result[0]['type'] == column_type)
-            assert(result[0]['non_zero'] == non_zero)
-            sql = "UPDATE __columns__ SET confirmed = 1 WHERE (table_id = '" + str(table_id) + "' AND name = '" + column_name + "')"
-            self.log(sql)
-            self.conn.execute(sql)
-            return False       
-        
-        sql = "ALTER TABLE '" + table_name + "' ADD COLUMN '" + column_name + "' " + column_type
-        self.log(sql)
-        self.conn.execute(sql)
-        sql = "SELECT id FROM __tables__ WHERE (name = '" + table_name + "')"
-        self.log(sql)
-        table_id = self.conn.execute(sql).next()['id']
-        sql = "INSERT INTO __columns__ (name, type, table_id, non_zero, confirmed) VALUES ('" + column_name + "', '" + column_type + "', '" + str(table_id) + "', '" + str(int(non_zero)) + "', 1)"
-        self.log(sql)
-        self.conn.execute(sql)
-        return True        
-
-    def iterate_columns(self, table_name):
-        sql = "SELECT id FROM __tables__ WHERE (name = '" + table_name + "')"
-        self.log(sql)
-        table_id = self.conn.execute(sql).next()['id']
-        sql = "SELECT * FROM __columns__ WHERE (table_id = '" + str(table_id) + "' AND confirmed = 1)"
-        self.log(sql)
-        result = self.conn.execute(sql).fetchall()
-        for row in result:
-            yield self.ColumnData(int(row["id"]), str(row["name"]), str(row["type"]), bool(row["non_zero"]))
-
-    def check_column(self, table_name, column_name):
-        sql = "SELECT id FROM __tables__ WHERE (name = '" + table_name + "')"
-        self.log(sql)
-        table_id = self.conn.execute(sql).next()['id']
-        sql = "SELECT * FROM __columns__ WHERE (table_id = '" + str(table_id) + "' AND name = '" + column_name + "' AND confirmed = 1)"
-        self.log(sql)
-        result = self.conn.execute(sql).fetchall()
-        if len(result) == 0:
-            return False
-        return True
-    
-    def create_tag(self, tag_name):
-        assert(self.read_only == False)
-        
-        sql = "SELECT * FROM __tags__ WHERE (name = '" + tag_name + "' AND confirmed == 0)"
-        self.log(sql)
-        result = self.conn.execute(sql).fetchall()
-        if len(result) != 0:
-            sql = "UPDATE __tags__ SET confirmed = 1 WHERE (name = '" + tag_name + "')"
-            self.log(sql)
-            self.conn.execute(sql)
-            return        
-        
-        sql = "INSERT INTO __tags__ (name, confirmed) VALUES ('" + tag_name + "', 1)"
-        self.log(sql)
-        self.conn.execute(sql)        
-
-    def iterate_tags(self):
-        sql = "SELECT * FROM __tags__ WHERE (confirmed = 1)"
-        self.log(sql)
-        result = self.conn.execute(sql).fetchall()
-        for row in result:
-            yield self.TagData(int(row["id"]), str(row["name"]))
-
-    def check_tag(self, tag_name):
-        sql = "SELECT * FROM __tags__ WHERE (name = '" + tag_name + "' AND confirmed = 1)"
-        self.log(sql)
-        result = self.conn.execute(sql).fetchall()
-        if len(result) == 0:
-            return False
-        return True
-
-    # TODO activate usage of tags
-    def create_file(self, path, checksum):
-        assert(self.read_only == False)
-        path = self.InternalPathUtils().normalize_path(path)
-
-        if self.is_cloned == True:
-            sql = "SELECT * FROM __files__ WHERE (path = '" + path + "')"
-            self.log(sql)
-            result = self.conn.execute(sql).fetchall()
-            if len(result) != 0:
-                if result[0]['checksum'] == checksum:
-                    old_id = result[0]['id']
-                    sql = "UPDATE __files__ SET confirmed = 1 WHERE (id = " + str(old_id) +")"
-                    self.log(sql)
-                    self.conn.execute(sql)
-                    return (old_id, False)
-                else:
-                    self.InternalCleanUpUtils().clean_up_file(self, result[0]['id'])
-        
-        sql = "INSERT OR REPLACE INTO __files__ (path, checksum, confirmed) VALUES (?, ?, 1)"
-        column_data = [path, checksum]
-        self.log(sql + " /with arguments: " + str(column_data))
-        cur = self.conn.cursor()
-        cur.execute(sql, column_data)
-        self.InternalPathUtils().update_dirs(self, path=path)
-        return (cur.lastrowid, True)
-    
-    def iterate_dircontent(self, path, include_subdirs = True, include_subfiles = True):
-        self.InternalPathUtils().update_dirs(self)
-        path = self.InternalPathUtils().normalize_path(path)
-        cur_head = self.dirs
-        valid = True
-        if path != "":
-            for head in self.InternalPathUtils().iterate_heads(path):
-                if head not in cur_head.keys():
-                    # non existing directory
-                    valid = False
-                else:
-                    cur_head = cur_head[head]
-            basename = os.path.basename(path)
-            if basename not in cur_head.keys() or cur_head[basename] == None:
-                # do not exist or points to the file
-                valid = False
-            else:
-                cur_head = cur_head[basename]
-        if valid == True:
-            for elem in cur_head.keys():
-                if include_subdirs == True and cur_head[elem] != None:
-                    yield elem
-                if include_subfiles == True and cur_head[elem] == None:
-                    yield elem
-
-    def check_file(self, path):
-        return self.get_file(path) != None
-
-    def check_dir(self, path):
-        for each in self.iterate_dircontent(path):
-            each = each # used
-            return True # there is at least one item
-        return False
-
-    def get_file(self, path):
-        path = self.InternalPathUtils().normalize_path(path)
-        result = self.select_rows("__files__", filters = [("path", "=", path), ("confirmed", "=", 1)])
-        if len(result) == 0:
-            return None
-        assert(len(result) == 1)
-        return self.FileData(result[0]['id'], result[0]['path'], result[0]['checksum'])
-
-    def iterate_files(self, path_like = None):
-        for row in self.select_rows('__files__', path_like=path_like, filters=[('confirmed','=','1')]): 
-            yield self.FileData(row['id'], row['path'], row['checksum'])
-
-    def create_region(self, file_id, region_id, name, begin, end, line_begin, line_end, cursor, group, checksum):
-        assert(self.read_only == False)
-        sql = "INSERT OR REPLACE INTO __regions__ (file_id, region_id, name, begin, end, line_begin, line_end, cursor, group_id, checksum) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"
-        column_data = [file_id, region_id, name, begin, end, line_begin, line_end, cursor, group, checksum]
-        self.log(sql + " /with arguments: " + str(column_data))
-        cur = self.conn.cursor()
-        cur.execute(sql, column_data)
-        return cur.lastrowid
-    
-    def get_region(self, file_id, region_id):
-        result = self.select_rows("__regions__", filters = [("file_id", "=", file_id), ("region_id", "=", region_id)])
-        if len(result) == 0:
-            return None
-        return self.RegionData(result[0]['file_id'],
-                               result[0]['region_id'],
-                               result[0]['name'],
-                               result[0]['begin'],
-                               result[0]['end'],
-                               result[0]['line_begin'],
-                               result[0]['line_end'],
-                               result[0]['cursor'],
-                               result[0]['group_id'],
-                               result[0]['checksum'])
-
-    def iterate_regions(self, file_id):
-        for each in self.select_rows("__regions__", filters = [("file_id", "=", file_id)]):
-            yield self.RegionData(each['file_id'],
-                                  each['region_id'],
-                                  each['name'],
-                                  each['begin'],
-                                  each['end'],
-                                  each['line_begin'],
-                                  each['line_end'],
-                                  each['cursor'],
-                                  each['group_id'],
-                                  each['checksum'])
-    
-    def create_marker(self, file_id, begin, end, group):
-        assert(self.read_only == False)
-        sql = "INSERT OR REPLACE INTO __markers__ (file_id, begin, end, group_id) VALUES (?, ?, ?, ?)"
-        column_data = [file_id, begin, end, group]
-        self.log(sql + " /with arguments: " + str(column_data))
-        cur = self.conn.cursor()
-        cur.execute(sql, column_data)
-        return cur.lastrowid
-    
-    def iterate_markers(self, file_id):
-        for each in self.select_rows("__markers__", filters = [("file_id", "=", file_id)]):
-            yield self.MarkerData(each['file_id'],
-                                  each['begin'],
-                                  each['end'],
-                                  each['group_id'])
-
-    def add_row(self, table_name, file_id, region_id, array_data):
-        assert(self.read_only == False)
-        column_names = "'file_id'"
-        column_values = "?"
-        column_data = [file_id]
-        if region_id != None:
-            column_names += ", 'region_id'"
-            column_values += ", ?"
-            column_data.append(region_id)
-        useful_data = 0
-        for each in array_data:
-            column_names +=  ", '" + each[0] + "'"
-            column_values += ", ?"
-            column_data.append(each[1])
-            useful_data += 1
-        if useful_data == 0:
-            return
-        sql = "INSERT OR REPLACE INTO '" + table_name + "' (" + column_names + ") VALUES (" + column_values + ")"
-        self.log(sql + " /with arguments: " + str(column_data))
-        cur = self.conn.cursor()
-        cur.execute(sql, column_data)
-        return cur.lastrowid
-
-    def select_rows(self, table_name, path_like = None, column_names = [], filters = [], order_by = None, limit_by = None):
-        safe_column_names = []
-        for each in column_names:
-            safe_column_names.append("'" + each + "'")
-        return self.select_rows_unsafe(table_name, path_like = path_like,
-                                       column_names = safe_column_names, filters = filters,
-                                       order_by = order_by, limit_by = limit_by)
-
-    def select_rows_unsafe(self, table_name, path_like = None, column_names = [], filters = [], 
-                           group_by = None, order_by = None, limit_by = None):
-        path_like = self.InternalPathUtils().normalize_path(path_like)
-        if self.conn == None:
-            return []
-
-        table_stmt = "'" + table_name + "'"
-
-        what_stmt = ", ".join(column_names)
-        if len(what_stmt) == 0:
-            what_stmt = "*"
-        elif path_like != None and table_name != '__files__' and group_by == None:
-            what_stmt += ", '__files__'.'path', '__files__'.'id'"
-        inner_stmt = ""
-        if path_like != None and table_name != '__files__':
-            inner_stmt = " INNER JOIN '__files__' ON '__files__'.'id' = '" + table_name + "'.'file_id' "
-
-        where_stmt = " "
-        values = ()
-        if len(filters) != 0:
-            if filters[0][1] == 'IN':
-                where_stmt = " WHERE (`" + filters[0][0] + "` " + filters[0][1] + " " + filters[0][2]
-            else:    
-                where_stmt = " WHERE (`" + filters[0][0] + "` " + filters[0][1] + " ?"
-                values = (filters[0][2],)
-            for each in filters[1:]:
-                if each[1] == 'IN':
-                    where_stmt += " AND `" + each[0] + "` " + each[1] + " " + each[2]
-                else:
-                    where_stmt += " AND `" + each[0] + "` " + each[1] + " ?"
-                    values += (each[2], )
-            if path_like != None:
-                where_stmt += " AND '__files__'.'path' LIKE ?"
-                values += (path_like, )
-            where_stmt += ")"
-        elif path_like != None:
-            where_stmt = " WHERE '__files__'.'path' LIKE ?"
-            values += (path_like, )
-        
-        group_stmt = ""
-        if group_by != None:
-            group_stmt = " GROUP BY (`" + group_by + "`)"
-
-        order_stmt = ""
-        if order_by != None:
-            if order_by.startswith("-"):
-                order_stmt = " ORDER BY (`" + order_by[1:] + "`) DESC "
-            else:
-                order_stmt = " ORDER BY (`" + order_by + "`) "
-
-        limit_stmt = ""
-        if limit_by != None:
-            limit_stmt = " LIMIT " + str(limit_by)
-
-        sql = "SELECT " + what_stmt + " FROM " + table_stmt + inner_stmt + where_stmt + group_stmt + order_stmt + limit_stmt
-        self.log(sql + " /with arguments: " + str(values))
-        return self.conn.execute(sql, values).fetchall()
-
-    def get_row(self, table_name, file_id, region_id):
-        selected = self.get_rows(table_name, file_id, region_id)
-        # assures that only one row in database
-        # if assertion happens, caller's intention is not right, use get_rows instead    
-        assert(len(selected) == 0 or len(selected) == 1)
-        if len(selected) == 0:
-            return None
-        return selected[0]
-
-    def get_rows(self, table_name, file_id, region_id):
-        filters = [("file_id", '=', file_id)]
-        if region_id != None:
-            filters.append(("region_id", '=', region_id))
-        return self.select_rows(table_name, filters=filters)
-    
-    def aggregate_rows(self, table_name, path_like = None, column_names = None, filters = []):
-        
-        if column_names == None:
-            column_names = []
-            for column in self.iterate_columns(table_name):
-                column_names.append(column.name)
-                
-        if len(column_names) == 0:
-            # it is possible that a table does not have meanfull columns
-            return {} 
-        
-        total_column_names = []
-        for column_name in column_names:
-            for func in ['max', 'min', 'avg', 'total', 'count']:
-                total_column_names.append(func + "('" + table_name + "'.'" + column_name + "') AS " + "'" + column_name + "_" + func + "'")
-             
-        data = self.select_rows_unsafe(table_name, path_like = path_like, column_names = total_column_names, filters = filters)
-        assert(len(data) == 1)
-        result = {}
-        for column_name in column_names:
-            result[column_name] = {}
-            for func in ['max', 'min', 'avg', 'total', 'count']:
-                result[column_name][func] = data[0][column_name + "_" + func]
-        return result
-    
-    def count_rows(self, table_name, path_like = None, group_by_column = None, filters = []):
-        
-        count_column_names = None
-        
-        if group_by_column != None:
-            for column in self.iterate_columns(table_name):
-                if group_by_column == column.name:
-                    count_column_names = ["`" + group_by_column + "`", "COUNT(`" + group_by_column + "`)"]
-                    break
-        else:
-            count_column_names = ["COUNT(*)"]
-            
-        if count_column_names == None:
-            return []
-             
-        data = self.select_rows_unsafe(table_name, path_like = path_like, column_names = count_column_names,
-                                       filters = filters, group_by = group_by_column)
-        return data
-
-    def log(self, sql):
-        if logging.getLogger().getEffectiveLevel() <= logging.DEBUG:
-            logging.debug("[" + str(self.id) + "] Executing query: " + sql)
-            traceback.print_stack()
-        

+ 0 - 143
mainline/core/dir.py

@@ -1,143 +0,0 @@
-#
-#    Metrix++, Copyright 2009-2013, Metrix++ Project
-#    Link: http://metrixplusplus.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 <http://www.gnu.org/licenses/>.
-#
-
-import core.api
-
-import re
-import os
-import logging
-import time
-import binascii
-
-class Plugin(core.api.Plugin, core.api.Parent, core.api.IConfigurable, core.api.IRunable):
-    
-    def __init__(self):
-        self.reader = DirectoryReader()
-        self.exclude_rules = []
-    
-    def declare_configuration(self, parser):
-        parser.add_option("--non-recursively", "--nr", action="store_true", default=False,
-                         help="If the option is set (True), sub-directories are not processed [default: %default]")
-        parser.add_option("--exclude-files", "--ef", default=r'^[.]',
-                         help="Defines the pattern to exclude files from processing [default: %default]")
-        parser.add_option("--std.general.proctime", "--sgpt", action="store_true", default=False,
-                         help="If the option is set (True), the tool measures processing time per file [default: %default]")
-        parser.add_option("--std.general.procerrors", "--sgpe", action="store_true", default=False,
-                         help="If the option is set (True), the tool counts number of processing/parsing errors per file [default: %default]")
-        parser.add_option("--std.general.size", "--sgs", action="store_true", default=False,
-                         help="If the option is set (True), the tool collects file size metric (in bytes) [default: %default]")
-    
-    def configure(self, options):
-        self.non_recursively = options.__dict__['non_recursively']
-        self.add_exclude_rule(re.compile(options.__dict__['exclude_files']))
-        self.is_proctime_enabled = options.__dict__['std.general.proctime']
-        self.is_procerrors_enabled = options.__dict__['std.general.procerrors']
-        self.is_size_enabled = options.__dict__['std.general.size']
-
-    def initialize(self):
-        fields = []
-        if self.is_proctime_enabled == True:
-            fields.append(self.Field('proctime', float))
-        if self.is_procerrors_enabled == True:
-            fields.append(self.Field('procerrors', int))
-        if self.is_size_enabled == True:
-            fields.append(self.Field('size', int))
-        core.api.Plugin.initialize(self, namespace='std.general', support_regions=False, fields=fields)
-        
-    def run(self, args):
-        if len(args) == 0:
-            return self.reader.run(self, "./")
-        for directory in args:
-            return self.reader.run(self, directory)
-        
-    def add_exclude_rule(self, re_compiled_pattern):
-        # TODO file name may have special regexp symbols what causes an exception
-        # For example try to run a collection with "--db-file=metrix++" option
-        self.exclude_rules.append(re_compiled_pattern)
-        
-    def is_file_excluded(self, file_name):
-        for each in self.exclude_rules:
-            if re.match(each, file_name) != None:
-                return True
-        return False 
-        
-class DirectoryReader():
-    
-    def run(self, plugin, directory):
-        
-        IS_TEST_MODE = False
-        if 'METRIXPLUSPLUS_TEST_MODE' in os.environ.keys():
-            IS_TEST_MODE = True
-        
-        def run_per_file(plugin, fname, full_path):
-            exit_code = 0
-            norm_path = re.sub(r'''[\\]''', "/", full_path)
-            if plugin.is_file_excluded(fname) == False:
-                if os.path.isdir(full_path):
-                    if plugin.non_recursively == False:
-                        exit_code += run_recursively(plugin, full_path)
-                else:
-                    parser = plugin.get_plugin_loader().get_parser(full_path)
-                    if parser == None:
-                        logging.info("Skipping: " + norm_path)
-                    else:
-                        logging.info("Processing: " + norm_path)
-                        ts = time.time()
-                        f = open(full_path, 'r');
-                        text = f.read();
-                        f.close()
-                        checksum = binascii.crc32(text) & 0xffffffff # to match python 3
-
-                        (data, is_updated) = plugin.get_plugin_loader().get_database_loader().create_file_data(norm_path, checksum, text)
-                        procerrors = parser.process(plugin, data, is_updated)
-                        if plugin.is_proctime_enabled == True:
-                            data.set_data('std.general', 'proctime',
-                                          (time.time() - ts) if IS_TEST_MODE == False else 0.01)
-                        if plugin.is_procerrors_enabled == True and procerrors != None and procerrors != 0:
-                            data.set_data('std.general', 'procerrors', procerrors)
-                        if plugin.is_size_enabled == True:
-                            data.set_data('std.general', 'size', len(text))
-                        plugin.get_plugin_loader().get_database_loader().save_file_data(data)
-                        logging.debug("-" * 60)
-                        exit_code += procerrors
-            else:
-                logging.info("Excluding: " + norm_path)
-            return exit_code
-        
-        def run_recursively(plugin, directory):
-            exit_code = 0
-            for fname in os.listdir(directory):
-                full_path = os.path.join(directory, fname)
-                exit_code += run_per_file(plugin, fname, full_path)
-            return exit_code
-        
-        if os.path.exists(directory) == False:
-            logging.error("Skipping (does not exist): " + directory)
-            return 1
-        
-        if os.path.isdir(directory):
-            total_errors = run_recursively(plugin, directory)
-        else:
-            total_errors = run_per_file(plugin, os.path.basename(directory), directory)
-        total_errors = total_errors # used, warnings are per file if not zero
-        return 0 # ignore errors, collection is successful anyway
-    
-
-
-    

+ 0 - 18
mainline/core/export/__init__.py

@@ -1,18 +0,0 @@
-#
-#    Metrix++, Copyright 2009-2013, Metrix++ Project
-#    Link: http://metrixplusplus.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 <http://www.gnu.org/licenses/>.
-#

+ 0 - 38
mainline/core/export/convert.py

@@ -1,38 +0,0 @@
-#
-#    Metrix++, Copyright 2009-2013, Metrix++ Project
-#    Link: http://metrixplusplus.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 <http://www.gnu.org/licenses/>.
-#
-
-
-import core.export.utils.py2xml
-import core.export.utils.py2txt
-
-def to_xml(data, root_name = None):
-    serializer = core.export.utils.py2xml.Py2XML()
-    return serializer.parse(data, objName=root_name)
-
-def to_python(data, root_name = None):
-    prefix = ""
-    postfix = ""
-    if root_name != None:
-        prefix = "{'" + root_name + ": " 
-        postfix = "}"
-    return prefix + data.__repr__() + postfix
-
-def to_txt(data, root_name = None):
-    serializer = core.export.utils.py2txt.Py2TXT()
-    return serializer.parse(data, objName=root_name, indent = -1)

+ 0 - 18
mainline/core/export/utils/__init__.py

@@ -1,18 +0,0 @@
-#
-#    Metrix++, Copyright 2009-2013, Metrix++ Project
-#    Link: http://metrixplusplus.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 <http://www.gnu.org/licenses/>.
-#

+ 0 - 138
mainline/core/export/utils/py2txt.py

@@ -1,138 +0,0 @@
-#
-#    Metrix++, Copyright 2009-2013, Metrix++ Project
-#    Link: http://metrixplusplus.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 <http://www.gnu.org/licenses/>.
-#
-
-# Copied from http://code.activestate.com/recipes/577268-python-data-structure-to-TXT-serialization/ and modified
-
-'''
-Py2TXT - Python to TXT serialization
-
-This code transforms a Python data structures into an TXT document
-
-Usage:
-    serializer = Py2TXT()
-    txt_string = serializer.parse( python_object )
-    print python_object
-    print txt_string
-'''
-
-INDENT_SPACE_SYMBOL = ".   " 
-
-class Py2TXT():
-
-    def __init__( self ):
-
-        self.data = "" # where we store the processed TXT string
-
-    def parse( self, pythonObj, objName=None, indent = 0 ):
-        '''
-        processes Python data structure into TXT string
-        needs objName if pythonObj is a List
-        '''
-        if pythonObj == None:
-            return "\n" + (INDENT_SPACE_SYMBOL * indent) + ""
-
-        if isinstance( pythonObj, dict ):
-            self.data = self._PyDict2TXT( pythonObj, objName, indent = indent + 1 )
-            
-        elif isinstance( pythonObj, list ):
-            # we need name for List object
-            self.data = self._PyList2TXT( pythonObj, objName, indent = indent + 1 )
-            
-        else:
-            self.data = "\n" + (INDENT_SPACE_SYMBOL * indent) + "%(n)s: %(o)s" % { 'n':objName, 'o':str( pythonObj ) }
-            
-        self.data = (INDENT_SPACE_SYMBOL * (indent + 1)) + "-" * 80 + self.data + "\n" + (INDENT_SPACE_SYMBOL * (indent + 1)) + "=" * 80 
-        return self.data
-
-    def _PyDict2TXT( self, pyDictObj, objName=None, indent = 0 ):
-        '''
-        process Python Dict objects
-        They can store TXT attributes and/or children
-        '''
-        tagStr = ""     # TXT string for this level
-        attributes = {} # attribute key/value pairs
-        attrStr = ""    # attribute string of this level
-        childStr = ""   # TXT string of this level's children
-
-        for k, v in pyDictObj.items():
-
-            if isinstance( v, dict ):
-                # child tags, with attributes
-                childStr += self._PyDict2TXT( v, k, indent = indent + 1 )
-
-            elif isinstance( v, list ):
-                # child tags, list of children
-                childStr += self._PyList2TXT( v, k, indent = indent + 1 )
-
-            else:
-                # tag could have many attributes, let's save until later
-                attributes.update( { k:v } )
-
-        if objName == None:
-            return childStr
-
-        # create TXT string for attributes
-        attrStr += ""
-        for k, v in attributes.items():
-            attrStr += "\n" + (INDENT_SPACE_SYMBOL * (indent + 1)) + "%s=\"%s\"" % ( k, v )
-
-        # let's assemble our tag string
-        if childStr == "":
-            tagStr += "\n" + (INDENT_SPACE_SYMBOL * indent) + "%(n)s: %(a)s" % { 'n':objName, 'a':attrStr }
-        else:
-            tagStr += "\n" + (INDENT_SPACE_SYMBOL * indent) + "%(n)s: %(a)s %(c)s" % { 'n':objName, 'a':attrStr, 'c':childStr }
-
-        return tagStr
-
-    def _PyList2TXT( self, pyListObj, objName=None, indent = 0 ):
-        '''
-        process Python List objects
-        They have no attributes, just children
-        Lists only hold Dicts or Strings
-        '''
-        tagStr = ""    # TXT string for this level
-        childStr = ""  # TXT string of children
-
-        for childObj in pyListObj:
-            
-            if isinstance( childObj, dict ):
-                # here's some Magic
-                # we're assuming that List parent has a plural name of child:
-                # eg, persons > person, so cut off last char
-                # name-wise, only really works for one level, however
-                # in practice, this is probably ok
-                childStr += "\n" + (INDENT_SPACE_SYMBOL * indent) + self._PyDict2TXT( childObj, objName[:-1], indent = indent + 1 )
-            elif isinstance( childObj, list ):
-                # here's some Magic
-                # we're assuming that List parent has a plural name of child:
-                # eg, persons > person, so cut off last char
-                # name-wise, only really works for one level, however
-                # in practice, this is probably ok
-                childStr += self._PyList2TXT( childObj, objName[:-1], indent = indent + 1 )
-            else:
-                childStr += "\n" + (INDENT_SPACE_SYMBOL * (indent + 1))
-                for string in childObj:
-                    childStr += str(string);
-
-        if objName == None:
-            return childStr
-
-        tagStr += "\n" + (INDENT_SPACE_SYMBOL * indent) + "%(n)s:%(c)s" % { 'n':objName, 'c':childStr }
-
-        return tagStr

+ 0 - 141
mainline/core/export/utils/py2xml.py

@@ -1,141 +0,0 @@
-#
-#    Metrix++, Copyright 2009-2013, Metrix++ Project
-#    Link: http://metrixplusplus.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 <http://www.gnu.org/licenses/>.
-#
-
-# Copied from http://code.activestate.com/recipes/577268-python-data-structure-to-xml-serialization/
-# - indent feature and better formatting added
-# - fixed handling of lists in lists
-# - fixed root object name for dictionaries
-
-INDENT_SPACE_SYMBOL = "    " 
-
-'''
-Py2XML - Python to XML serialization
-
-This code transforms a Python data structures into an XML document
-
-Usage:
-    serializer = Py2XML()
-    xml_string = serializer.parse( python_object )
-    print python_object
-    print xml_string
-'''
-
-class Py2XML():
-
-    def __init__( self ):
-
-        self.data = "" # where we store the processed XML string
-
-    def parse( self, pythonObj, objName=None, indent = 0 ):
-        '''
-        processes Python data structure into XML string
-        needs objName if pythonObj is a List
-        '''
-        if pythonObj == None:
-            return "\n" + (INDENT_SPACE_SYMBOL * indent) + ""
-
-        if isinstance( pythonObj, dict ):
-            self.data = self._PyDict2XML( pythonObj, objName, indent=indent+1 )
-            
-        elif isinstance( pythonObj, list ):
-            # we need name for List object
-            self.data = self._PyList2XML( pythonObj, objName, indent=indent+1 )
-            
-        else:
-            self.data = "\n" + (INDENT_SPACE_SYMBOL * indent) + "<%(n)s>%(o)s</%(n)s>" % { 'n':objName, 'o':str( pythonObj ) }
-            
-        return self.data
-
-    def _PyDict2XML( self, pyDictObj, objName=None, indent = 0 ):
-        '''
-        process Python Dict objects
-        They can store XML attributes and/or children
-        '''
-        tagStr = ""     # XML string for this level
-        attributes = {} # attribute key/value pairs
-        attrStr = ""    # attribute string of this level
-        childStr = ""   # XML string of this level's children
-
-        for k, v in pyDictObj.items():
-
-            if isinstance( v, dict ):
-                # child tags, with attributes
-                childStr += self._PyDict2XML( v, k, indent=indent+1 )
-
-            elif isinstance( v, list ):
-                # child tags, list of children
-                childStr += self._PyList2XML( v, k, indent=indent+1 )
-
-            else:
-                # tag could have many attributes, let's save until later
-                attributes.update( { k:v } )
-
-        if objName == None:
-            return childStr
-
-        # create XML string for attributes
-        for k, v in attributes.items():
-            attrStr += " %s=\"%s\"" % ( k, v )
-
-        # let's assemble our tag string
-        if childStr == "":
-            tagStr += "\n" + (INDENT_SPACE_SYMBOL * indent) + "<%(n)s%(a)s />" % { 'n':objName, 'a':attrStr }
-        else:
-            tagStr += ("\n" + (INDENT_SPACE_SYMBOL * indent) + "<%(n)s%(a)s>%(c)s" + "\n" + (INDENT_SPACE_SYMBOL * indent) + "</%(n)s>") % { 'n':objName, 'a':attrStr, 'c':childStr }
-
-        return tagStr
-
-    def _PyList2XML( self, pyListObj, objName=None, indent = 0 ):
-        '''
-        process Python List objects
-        They have no attributes, just children
-        Lists only hold Dicts or Strings
-        '''
-        tagStr = ""    # XML string for this level
-        childStr = ""  # XML string of children
-
-        for childObj in pyListObj:
-            
-            if isinstance( childObj, dict ):
-                # here's some Magic
-                # we're assuming that List parent has a plural name of child:
-                # eg, persons > person, so cut off last char
-                # name-wise, only really works for one level, however
-                # in practice, this is probably ok
-                childStr += self._PyDict2XML( childObj, objName[:-1], indent=indent+1 )
-            elif isinstance( childObj, list ):
-                # here's some Magic
-                # we're assuming that List parent has a plural name of child:
-                # eg, persons > person, so cut off last char
-                # name-wise, only really works for one level, however
-                # in practice, this is probably ok
-                childStr += self._PyList2XML( childObj, objName[:-1], indent=indent+1 )
-                pass
-            else:
-                childStr += "\n" + (INDENT_SPACE_SYMBOL * (indent + 1)) + "<" + objName[:-1] + ">"
-                for string in childObj:
-                    childStr += str(string);
-                childStr += "</" + objName[:-1] + ">"
-                
-        if objName == None:
-            return childStr
-
-        tagStr += ("\n" + (INDENT_SPACE_SYMBOL * indent) + "<%(n)s>%(c)s" + "\n" + (INDENT_SPACE_SYMBOL * indent) + "</%(n)s>") % { 'n':objName, 'c':childStr }
-
-        return tagStr

+ 0 - 26
mainline/core/ext-priority/core.db.post.ini

@@ -1,26 +0,0 @@
-;
-;    Metrix++, Copyright 2009-2013, Metrix++ Project
-;    Link: http://metrixplusplus.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 <http://www.gnu.org/licenses/>.
-;
-
-[Plugin]
-version: 1.0
-package: core.db
-module:  post
-class:   Plugin
-depends: None
-enabled: True

+ 0 - 26
mainline/core/ext-priority/core.dir.ini

@@ -1,26 +0,0 @@
-;
-;    Metrix++, Copyright 2009-2013, Metrix++ Project
-;    Link: http://metrixplusplus.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 <http://www.gnu.org/licenses/>.
-;
-
-[Plugin]
-version: 1.0
-package: core
-module:  dir
-class:   Plugin
-depends: None
-enabled: True

+ 0 - 26
mainline/core/ext-priority/core.log.ini

@@ -1,26 +0,0 @@
-;
-;    Metrix++, Copyright 2009-2013, Metrix++ Project
-;    Link: http://metrixplusplus.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 <http://www.gnu.org/licenses/>.
-;
-
-[Plugin]
-version: 1.0
-package: core
-module:  log
-class:   Plugin
-depends: None
-enabled: True

+ 0 - 132
mainline/core/loader.py

@@ -1,132 +0,0 @@
-#
-#    Metrix++, Copyright 2009-2013, Metrix++ Project
-#    Link: http://metrixplusplus.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 <http://www.gnu.org/licenses/>.
-#
-
-import core.api
-
-import os
-import fnmatch
-
-class Loader(object):
-
-    def __init__(self):
-        self.plugins = []
-        self.parsers = []
-        self.hash    = {}
-        self.db = core.api.Loader()
-        
-    def get_database_loader(self):
-        return self.db
-
-    def get_plugin(self, name):
-        return self.hash[name]['instance']
-    
-    def iterate_plugins(self, is_reversed = False):
-        if is_reversed == False:
-            for item in self.plugins:
-                yield item['instance']
-        else:
-            for item in reversed(self.plugins):
-                yield item['instance']
-            
-    def register_parser(self, fnmatch_exp_list, parser):
-        self.parsers.append((fnmatch_exp_list, parser))
-
-    def get_parser(self, file_path):
-        for parser in self.parsers:
-            for fnmatch_exp in parser[0]:
-                if fnmatch.fnmatch(file_path, fnmatch_exp):
-                    return parser[1]
-        return None
-
-    def load(self, directory, optparser, args):
-        import sys
-        sys.path.append(directory)
-        
-        def load_recursively(manager, directory):
-            import ConfigParser
-            import re
-        
-            pattern = re.compile(r'.*[.]ini$', flags=re.IGNORECASE)
-        
-            dirList = os.listdir(directory)
-            for fname in dirList:
-                fname = os.path.join(directory, fname)
-                if os.path.isdir(fname):
-                    load_recursively(manager, fname)
-                elif re.match(pattern, fname):
-                    config = ConfigParser.ConfigParser()
-                    config.read(fname)
-                    item = {'package': config.get('Plugin', 'package'),
-                            'module': config.get('Plugin', 'module'),
-                            'class': config.get('Plugin', 'class'),
-                            'version': config.get('Plugin', 'version'),
-                            'depends': config.get('Plugin', 'depends'),
-                            'enabled': config.getboolean('Plugin', 'enabled')}
-                    if item['enabled']:
-                        manager.plugins.append(item)
-                        manager.hash[item['package'] + '.' + item['module']] = item
-
-        load_recursively(self, os.path.join(os.path.dirname(os.path.abspath(__file__)), 'ext-priority'))
-        load_recursively(self, directory)
-        # TODO check dependencies
-        for item in self.plugins:
-            plugin = __import__(item['package'], globals(), locals(), [item['module']], -1)
-            module_attr = plugin.__getattribute__(item['module'])
-            class_attr = module_attr.__getattribute__(item['class'])
-            item['instance'] = class_attr.__new__(class_attr)
-            item['instance'].__init__()
-            item['instance'].set_name(item['package'] + "." + item['module'])
-            item['instance'].set_version(item['version'])
-            item['instance'].set_plugin_loader(self)
-
-        for item in self.iterate_plugins():
-            if (isinstance(item, core.api.IConfigurable)):
-                item.declare_configuration(optparser)
-
-        (options, args) = optparser.parse_args(args)
-        for item in self.iterate_plugins():
-            if (isinstance(item, core.api.IConfigurable)):
-                item.configure(options)
-
-        for item in self.iterate_plugins():
-            item.initialize()
-            
-        return args
-
-    def unload(self):
-        for item in self.iterate_plugins(is_reversed = True):
-            item.terminate()
-
-    def run(self, args):
-        exit_code = 0
-        for item in self.iterate_plugins():
-            if (isinstance(item, core.api.IRunable)):
-                exit_code += item.run(args)
-        return exit_code
-
-    def __repr__(self):
-        result = object.__repr__(self) + ' with loaded:'
-        for item in self.iterate_plugins():
-            result += '\n\t' + item.__repr__()
-            if isinstance(item, core.api.Parent):
-                result += ' with subscribed:'
-                for child in item.iterate_children():
-                    result += '\n\t\t' + child.__repr__()
-        return result
-

+ 0 - 58
mainline/core/log.py

@@ -1,58 +0,0 @@
-#
-#    Metrix++, Copyright 2009-2013, Metrix++ Project
-#    Link: http://metrixplusplus.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 <http://www.gnu.org/licenses/>.
-#
-
-import core.api
-import logging
-import os
-
-class Plugin(core.api.BasePlugin, core.api.IConfigurable):
-    
-    def declare_configuration(self, parser, default_value='INFO'):
-        allowed_values = ['DEBUG','INFO','WARNING','ERROR']
-        default_value_cur = default_value
-        if os.environ.has_key('METRIXPLUSPLUS_LOG_LEVEL') and os.environ['METRIXPLUSPLUS_LOG_LEVEL'] in allowed_values:
-            default_value_cur = os.environ['METRIXPLUSPLUS_LOG_LEVEL']
-        parser.add_option("--log-level", "--ll", default=default_value_cur, choices=allowed_values,
-                         help="Defines log level. Possible values are 'DEBUG','INFO','WARNING' or 'ERROR'. "
-                         "Default value is inherited from environment variable 'METRIXPLUSPLUS_LOG_LEVEL' if set. "
-                         "[default: " + default_value + "]")
-    
-    def configure(self, options):
-        if options.__dict__['log_level'] == 'ERROR':
-            log_level = logging.ERROR
-        elif options.__dict__['log_level'] == 'WARNING':
-            log_level = logging.WARNING
-        elif options.__dict__['log_level'] == 'INFO':
-            log_level = logging.INFO
-        elif options.__dict__['log_level'] == 'DEBUG':
-            log_level = logging.DEBUG
-        else:
-            raise AssertionError("Unhandled choice of log level")
-        
-        self.level = log_level
-        logging.getLogger().setLevel(self.level)
-        os.environ['METRIXPLUSPLUS_LOG_LEVEL'] = options.__dict__['log_level']
-        logging.warn("Logging enabled with " + options.__dict__['log_level'] + " level")
-
-    def initialize(self):
-        super(Plugin, self).initialize()
-        set_default_format()
-
-def set_default_format():
-    logging.basicConfig(format="[LOG]: %(levelname)s:\t%(message)s", level=logging.WARN)

+ 0 - 114
mainline/core/utils.py

@@ -1,114 +0,0 @@
-#
-#    Metrix++, Copyright 2009-2013, Metrix++ Project
-#    Link: http://metrixplusplus.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 <http://www.gnu.org/licenses/>.
-#
-
-import logging
-import re
-
-class FileRegionsMatcher(object):
-
-    class FileRegionsDisposableGetter(object):
-        
-        def __init__(self, file_data):
-            self.checksums = {}
-            self.names = {}
-            
-            for each in file_data.iterate_regions():
-                if each.get_checksum() not in self.checksums:
-                    self.checksums[each.get_checksum()] = []
-                self.checksums[each.get_checksum()].append((each.get_id(), each.get_name())) 
-                
-                if each.get_name() not in self.names:
-                    self.names[each.get_name()] = []
-                self.names[each.get_name()].append((each.get_id(), each.get_checksum())) 
-            
-        def get_next_id_once_by_checksum(self, checksum):
-            if checksum not in self.checksums.keys():
-                return None
-    
-            if len(self.checksums[checksum]) == 0:
-                return None
-            
-            elem = self.checksums[checksum].pop(0)
-            next_id = elem[0]
-            next_name = elem[1]
-    
-            self.names[next_name].remove((next_id, checksum))
-            return next_id
-    
-        def get_next_id_once_by_name(self, name):
-            if name not in self.names.keys():
-                return None
-            
-            if len(self.names[name]) == 0:
-                return None
-            
-            elem = self.names[name].pop(0)
-            next_id = elem[0]
-            next_checksum = elem[1]
-    
-            self.checksums[next_checksum].remove((next_id, name))
-            return next_id
-    
-    def __init__(self, file_data, prev_file_data):
-        self.ids = [None] # add one to shift id from zero
-        
-        once_filter = self.FileRegionsDisposableGetter(prev_file_data)
-        unmatched_region_ids = []
-        for (ind, region) in enumerate(file_data.iterate_regions()):
-            assert(ind + 1 == region.get_id())
-            # Identify corresponding region in previous database (attempt by checksum)
-            prev_id = once_filter.get_next_id_once_by_checksum(region.checksum)
-            if prev_id != None:
-                self.ids.append((prev_id, False))
-            else:
-                unmatched_region_ids.append(region.get_id())
-                self.ids.append((None, True))
-                            
-        # Identify corresponding region in previous database (attempt by name)
-        for region_id in unmatched_region_ids: 
-            prev_id = once_filter.get_next_id_once_by_name(file_data.get_region(region_id).name)
-            if prev_id != None:
-                self.ids[region_id] = (prev_id, True)
-    
-    def get_prev_id(self, curr_id):
-        return self.ids[curr_id][0]
-
-    def is_matched(self, curr_id):
-        return (self.ids[curr_id][0] != None)
-
-    def is_modified(self, curr_id):
-        return self.ids[curr_id][1]
-
-def check_db_metadata(loader, loader_prev):
-    for each in loader.iterate_properties():
-        prev = loader_prev.get_property(each.name)
-        if prev != each.value:
-            logging.warn("Previous data file has got different metadata:")
-            logging.warn(" - identification of change trends can be not reliable")
-            logging.warn(" - use 'info' tool to view more details")
-            return 1
-    return 0
-
-def preprocess_path(path):
-    path = re.sub(r'''[\\]+''', "/", path)
-    logging.info("Processing: " + path)
-    return path
-
-def report_bad_path(path):
-    logging.error("Specified path '" + path + "' is invalid: not found in the database records.")

+ 0 - 130
mainline/core/warn.py

@@ -1,130 +0,0 @@
-#
-#    Metrix++, Copyright 2009-2013, Metrix++ Project
-#    Link: http://metrixplusplus.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 <http://www.gnu.org/licenses/>.
-#
-
-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("--warn-mode", "--wm", default='all', choices=['new', 'trend', 'touched', 'all'],
-                         help="Defines the warnings mode. "
-                         "'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("--min-limit", "--min", action="multiopt",
-                          help="A threshold per 'namespace:field' metric in order to select regions, "
-                          "which have got metric value less than the specified limit. "
-                          "This option can be specified multiple times, if it is necessary to apply several limits. "
-                          "Should be in the format: <namespace>:<field>:<limit-value>, for example: "
-                          "'std.code.lines:comments:1'.")
-        parser.add_option("--max-limit", "--max", action="multiopt",
-                          help="A threshold per 'namespace:field' metric in order to select regions, "
-                          "which have got metric value more than the specified limit. "
-                          "This option can be specified multiple times, if it is necessary to apply several limits. "
-                          "Should be in the format: <namespace>:<field>:<limit-value>, for example: "
-                          "'std.code.complexity:cyclomatic:7'.")
-        
-    def configure(self, options):
-        if options.__dict__['warn_mode'] == 'new':
-            self.mode = self.MODE_NEW
-        elif options.__dict__['warn_mode'] == 'trend':
-            self.mode = self.MODE_TREND
-        elif options.__dict__['warn_mode'] == 'touched':
-            self.mode = self.MODE_TOUCHED
-        elif options.__dict__['warn_mode'] == 'all':
-            self.mode = self.MODE_ALL
-            
-        if self.mode != self.MODE_ALL and options.__dict__['db_file_prev'] == None:
-            self.parser.error("The mode '" + options.__dict__['warn_mode'] + "' for 'general.warn' option requires '--db-file-prev' option set")
-
-        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__['max_limit'] != None:
-            for each in options.__dict__['max_limit']:
-                match = re.match(pattern, each)
-                if match == None:
-                    self.parser.error("Invalid format of the '--max-limit' option: " + each)
-                limit = Limit("max", float(match.group(3)), match.group(1), match.group(2), (match.group(2), '>', float(match.group(3))))
-                self.limits.append(limit)
-        if options.__dict__['min_limit'] != None:
-            for each in options.__dict__['min_limit']:  
-                match = re.match(pattern, each)
-                if match == None:
-                    self.parser.error("Invalid format of the '--min-limit' option: " + each)
-                limit = Limit("min", float(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
-