avkonst 11 éve
szülő
commit
86fd90ef1f
37 módosított fájl, 235 hozzáadás és 178 törlés
  1. 1 0
      mainline/ext/std/code/complexity.ini
  2. 1 0
      mainline/ext/std/code/cpp.ini
  3. 1 1
      mainline/ext/std/code/cpp.py
  4. 1 0
      mainline/ext/std/code/cs.ini
  5. 1 1
      mainline/ext/std/code/cs.py
  6. 1 0
      mainline/ext/std/code/java.ini
  7. 1 1
      mainline/ext/std/code/java.py
  8. 1 0
      mainline/ext/std/code/length.ini
  9. 1 0
      mainline/ext/std/code/lines.ini
  10. 1 0
      mainline/ext/std/code/test.ini
  11. 1 0
      mainline/ext/std/suppress.ini
  12. 2 1
      mainline/ext/std/suppress.py
  13. 0 0
      mainline/ext/std/tools/__init__.py
  14. 27 0
      mainline/ext/std/tools/collect.ini
  15. 37 12
      mainline/mpp/dir.py
  16. 6 6
      mainline/mpp/api.py
  17. 2 1
      mainline/mpp/ext-priority/core.dir.ini
  18. 8 8
      mainline/mpp/db/post.py
  19. 0 18
      mainline/mpp/export/__init__.py
  20. 0 38
      mainline/mpp/export/convert.py
  21. 0 18
      mainline/mpp/export/utils/__init__.py
  22. 0 0
      mainline/mpp/internal/__init__.py
  23. 0 0
      mainline/mpp/internal/dbwrap.py
  24. 75 32
      mainline/mpp/loader.py
  25. 0 0
      mainline/mpp/internal/py2txt.py
  26. 0 0
      mainline/mpp/internal/py2xml.py
  27. 1 0
      mainline/mpp/ext-priority/core.log.ini
  28. 19 0
      mainline/mpp/utils.py
  29. 3 2
      mainline/mpp/ext-priority/core.db.post.ini
  30. 8 1
      mainline/mpp/warn.py
  31. 15 15
      mainline/tests/general/test_basic/test_help_collect_default_stdout.gold.txt
  32. 8 6
      mainline/tools/collect.py
  33. 2 2
      mainline/tools/debug.py
  34. 2 2
      mainline/tools/export.py
  35. 2 2
      mainline/tools/info.py
  36. 2 3
      mainline/tools/limit.py
  37. 5 8
      mainline/tools/view.py

+ 1 - 0
mainline/ext/std/code/complexity.ini

@@ -23,4 +23,5 @@ package: std.code
 module:  complexity
 class:   Plugin
 depends: None
+actions: collect
 enabled: True

+ 1 - 0
mainline/ext/std/code/cpp.ini

@@ -23,4 +23,5 @@ package: std.code
 module:  cpp
 class:   Plugin
 depends: None
+actions: collect
 enabled: True

+ 1 - 1
mainline/ext/std/code/cpp.py

@@ -38,7 +38,7 @@ class Plugin(mpp.api.Plugin, mpp.api.Parent, mpp.api.IParser, mpp.api.IConfigura
         mpp.api.Plugin.initialize(self, properties=[
             self.Property('files', ','.join(self.files))
         ])
-        self.get_plugin_loader().register_parser(self.files, self)
+        self.get_plugin_loader().get_plugin('std.tools.collect').register_parser(self.files, self)
         
     def process(self, parent, data, is_updated):
         is_updated = is_updated or self.is_updated

+ 1 - 0
mainline/ext/std/code/cs.ini

@@ -23,4 +23,5 @@ package: std.code
 module:  cs
 class:   Plugin
 depends: None
+actions: collect
 enabled: True

+ 1 - 1
mainline/ext/std/code/cs.py

@@ -38,7 +38,7 @@ class Plugin(mpp.api.Plugin, mpp.api.Parent, mpp.api.IParser, mpp.api.IConfigura
         mpp.api.Plugin.initialize(self, properties=[
             self.Property('files', ','.join(self.files))
         ])
-        self.get_plugin_loader().register_parser(self.files, self)
+        self.get_plugin_loader().get_plugin('std.tools.collect').register_parser(self.files, self)
         
     def process(self, parent, data, is_updated):
         is_updated = is_updated or self.is_updated

+ 1 - 0
mainline/ext/std/code/java.ini

@@ -23,4 +23,5 @@ package: std.code
 module:  java
 class:   Plugin
 depends: None
+actions: collect
 enabled: True

+ 1 - 1
mainline/ext/std/code/java.py

@@ -38,7 +38,7 @@ class Plugin(mpp.api.Plugin, mpp.api.Parent, mpp.api.IParser, mpp.api.IConfigura
         mpp.api.Plugin.initialize(self, properties=[
             self.Property('files', ','.join(self.files))
         ])
-        self.get_plugin_loader().register_parser(self.files, self)
+        self.get_plugin_loader().get_plugin('std.tools.collect').register_parser(self.files, self)
         
     def process(self, parent, data, is_updated):
         is_updated = is_updated or self.is_updated

+ 1 - 0
mainline/ext/std/code/length.ini

@@ -23,4 +23,5 @@ package: std.code
 module:  length
 class:   Plugin
 depends: None
+actions: collect
 enabled: True

+ 1 - 0
mainline/ext/std/code/lines.ini

@@ -23,4 +23,5 @@ package: std.code
 module:  lines
 class:   Plugin
 depends: None
+actions: collect
 enabled: True

+ 1 - 0
mainline/ext/std/code/test.ini

@@ -23,4 +23,5 @@ package: std.code
 module:  test
 class:   Plugin
 depends: None
+actions: collect
 enabled: True

+ 1 - 0
mainline/ext/std/suppress.ini

@@ -23,4 +23,5 @@ package: std
 module:  suppress
 class:   Plugin
 depends: None
+actions: collect
 enabled: True

+ 2 - 1
mainline/ext/std/suppress.py

@@ -79,7 +79,8 @@ class Plugin(mpp.api.Plugin, mpp.api.Child, mpp.api.IConfigurable):
                     matches = self.pattern.findall(text, marker.get_offset_begin(), marker.get_offset_end())
                     for m in matches:
                         namespace_name, field = m.split(':')
-                        namespace = self.get_plugin_loader().get_database_loader().get_namespace(namespace_name)
+                        db_loader = self.get_plugin_loader().get_plugin('mpp.dbf').get_loader()
+                        namespace = db_loader.get_namespace(namespace_name)
                         if namespace == None or namespace.get_field_packager(field) == None:
                             mpp.cout.notify(data.get_path(), region.get_cursor(),
                                                   mpp.cout.SEVERITY_WARNING,

+ 0 - 0
mainline/ext/std/tools/__init__.py


+ 27 - 0
mainline/ext/std/tools/collect.ini

@@ -0,0 +1,27 @@
+;
+;    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: std.tools
+module:  collect
+class:   Plugin
+depends: None
+actions: collect
+enabled: True

+ 37 - 12
mainline/mpp/dir.py

@@ -24,24 +24,37 @@ import os
 import logging
 import time
 import binascii
+import fnmatch
 
 class Plugin(mpp.api.Plugin, mpp.api.Parent, mpp.api.IConfigurable, mpp.api.IRunable):
     
     def __init__(self):
         self.reader = DirectoryReader()
         self.exclude_rules = []
+        self.exclude_files = []
+        self.parsers       = []
+        
+    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 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]")
+        parser.add_option("--exclude-files", "--ef", default=r'^[.]',
+                         help="Defines the pattern to exclude files from processing [default: %default]")
+        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]")
     
     def configure(self, options):
         self.non_recursively = options.__dict__['non_recursively']
@@ -58,7 +71,9 @@ class Plugin(mpp.api.Plugin, mpp.api.Parent, mpp.api.IConfigurable, mpp.api.IRun
             fields.append(self.Field('procerrors', int))
         if self.is_size_enabled == True:
             fields.append(self.Field('size', int))
-        mpp.api.Plugin.initialize(self, namespace='std.general', support_regions=False, fields=fields)
+        super(Plugin, self).initialize(namespace='std.general', support_regions=False, fields=fields)
+        self.add_exclude_file(self.get_plugin_loader().get_plugin('mpp.dbf').get_dbfile_path())
+        self.add_exclude_file(self.get_plugin_loader().get_plugin('mpp.dbf').get_dbfile_prev_path())
         
     def run(self, args):
         if len(args) == 0:
@@ -70,11 +85,20 @@ class Plugin(mpp.api.Plugin, mpp.api.Parent, mpp.api.IConfigurable, mpp.api.IRun
         # 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 add_exclude_file(self, file_path):
+        if file_path == None:
+            return
+        self.exclude_files.append(file_path)
+
     def is_file_excluded(self, file_name):
         for each in self.exclude_rules:
-            if re.match(each, file_name) != None:
+            if re.match(each, os.path.basename(file_name)) != None:
                 return True
+        for each in self.exclude_files:
+            if os.path.basename(each) == os.path.basename(file_name):
+                if os.stat(each) == os.stat(file_name):
+                    return True
         return False 
         
 class DirectoryReader():
@@ -88,12 +112,12 @@ class DirectoryReader():
         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 plugin.is_file_excluded(norm_path) == 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)
+                    parser = plugin.get_parser(full_path)
                     if parser == None:
                         logging.info("Skipping: " + norm_path)
                     else:
@@ -103,8 +127,9 @@ class DirectoryReader():
                         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)
+                        
+                        db_loader = plugin.get_plugin_loader().get_plugin('mpp.dbf').get_loader()
+                        (data, is_updated) = db_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',
@@ -113,7 +138,7 @@ class DirectoryReader():
                             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)
+                        db_loader.save_file_data(data)
                         logging.debug("-" * 60)
                         exit_code += procerrors
             else:

+ 6 - 6
mainline/mpp/api.py

@@ -19,7 +19,7 @@
 
 import logging
 import os.path
-import mpp.db.sqlite
+import mpp.internal.dbwrap
 
 ##############################################################################
 #
@@ -773,7 +773,7 @@ class Loader(object):
         self.last_file_data = None # for performance boost reasons
     
     def create_database(self, dbfile, previous_db = None):
-        self.db = mpp.db.sqlite.Database()
+        self.db = mpp.internal.dbwrap.Database()
         try:
             self.db.create(dbfile, clone_from=previous_db)
         except:
@@ -781,7 +781,7 @@ class Loader(object):
         return True
         
     def open_database(self, dbfile, read_only = True):
-        self.db = mpp.db.sqlite.Database()
+        self.db = mpp.internal.dbwrap.Database()
         if os.path.exists(dbfile) == False:
             return False
         try:
@@ -1059,9 +1059,9 @@ class Plugin(BasePlugin):
         
         if hasattr(self, 'is_updated') == False:
             self.is_updated = False # original initialization
-            
-        db_loader = self.get_plugin_loader().get_database_loader()
-        
+
+        db_loader = self.get_plugin_loader().get_plugin('mpp.dbf').get_loader()
+
         if namespace == None:
             namespace = self.get_name()
 

+ 2 - 1
mainline/mpp/ext-priority/core.dir.ini

@@ -20,7 +20,8 @@
 [Plugin]
 version: 1.0
 package: mpp
-module:  dir
+module:  dbf
 class:   Plugin
 depends: None
+actions: *
 enabled: True

+ 8 - 8
mainline/mpp/db/post.py

@@ -20,8 +20,6 @@
 import mpp.api
 
 import os.path
-import re
-
 import logging
 
 class Plugin(mpp.api.Plugin, mpp.api.IConfigurable):
@@ -56,15 +54,11 @@ class Plugin(mpp.api.Plugin, mpp.api.IConfigurable):
                 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)
+            self.loader = mpp.api.Loader()
+            created = self.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('mpp.dir').add_exclude_rule(re.compile(r'^' + os.path.basename(self.dbfile) + r'$'))
-            if self.dbfile_prev != None:
-                self.get_plugin_loader().get_plugin('mpp.dir').add_exclude_rule(re.compile(r'^' + os.path.basename(self.dbfile_prev) + r'$'))
-
         else:
             self.loader_prev = mpp.api.Loader()
             if self.dbfile_prev != None:
@@ -74,6 +68,12 @@ class Plugin(mpp.api.Plugin, mpp.api.IConfigurable):
             if self.loader.open_database(self.dbfile) == False:
                 self.parser.error("Can not open file: " + self.dbfile)
 
+    def get_dbfile_path(self):
+        return self.dbfile
+
+    def get_dbfile_prev_path(self):
+        return self.dbfile_prev
+
     def get_loader(self):
         return self.loader
 

+ 0 - 18
mainline/mpp/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/mpp/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 mpp.export.utils.py2xml
-import mpp.export.utils.py2txt
-
-def to_xml(data, root_name = None):
-    serializer = mpp.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 = mpp.export.utils.py2txt.Py2TXT()
-    return serializer.parse(data, objName=root_name, indent = -1)

+ 0 - 18
mainline/mpp/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/>.
-#

mainline/mpp/db/__init__.py → mainline/mpp/internal/__init__.py


mainline/mpp/db/sqlite.py → mainline/mpp/internal/dbwrap.py


+ 75 - 32
mainline/mpp/loader.py

@@ -18,21 +18,21 @@
 #
 
 import mpp.api
+import mpp.cmdparser
 
 import os
-import fnmatch
+import sys
+import ConfigParser
+import re
+
+
 
 class Loader(object):
 
     def __init__(self):
         self.plugins = []
-        self.parsers = []
         self.hash    = {}
-        self.db = mpp.api.Loader()
         
-    def get_database_loader(self):
-        return self.db
-
     def get_plugin(self, name):
         return self.hash[name]['instance']
     
@@ -44,31 +44,23 @@ class Loader(object):
             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
-        
+    def load(self, command, directories, args):
+
+        class IniContainer(object):
+            def __init__(self):
+                self.plugins = []
+                self.actions = []
+                self.hash    = {}
+                
+        def load_recursively(inicontainer, directory):
+            active_plugins = []
             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)
+                    active_plugins += load_recursively(inicontainer, fname)
                 elif re.match(pattern, fname):
                     config = ConfigParser.ConfigParser()
                     config.read(fname)
@@ -77,15 +69,58 @@ class Loader(object):
                             'class': config.get('Plugin', 'class'),
                             'version': config.get('Plugin', 'version'),
                             'depends': config.get('Plugin', 'depends'),
-                            'enabled': config.getboolean('Plugin', 'enabled')}
+                            'actions': config.get('Plugin', 'actions'),
+                            'enabled': config.getboolean('Plugin', 'enabled'),
+                            'instance': None}
                     if item['enabled']:
-                        manager.plugins.append(item)
-                        manager.hash[item['package'] + '.' + item['module']] = item
+                        item['actions'] = item['actions'].split(',')
+                        for (ind, action) in enumerate(item['actions']):
+                            action = action.strip()
+                            item['actions'][ind] = action
+                            if action not in inicontainer.actions + ['*', 'None', 'none', 'False', 'false']:
+                                inicontainer.actions.append(action)
+                            if action == '*' or action == command:
+                                active_plugins.append(item['package'] + '.' + item['module'])
+                        inicontainer.plugins.append(item)
+                        inicontainer.hash[item['package'] + '.' + item['module']] = item
+            return active_plugins
+                        
+        def list_dependants_recursively(inicontainer, required_plugin_name):
+            assert required_plugin_name in inicontainer.hash.keys(), \
+                "depends section requires unknown plugin: " + required_plugin_name
+            item = inicontainer.hash[required_plugin_name]
+            if item['depends'] in ('None', 'none', 'False', 'false'):
+                return []
+            result = []
+            for child in item['depends'].split(','):
+                child = child.strip()
+                result += list_dependants_recursively(inicontainer, child)
+                result.append(child)
+            return result
 
-        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:
+        # configure python path for loading
+        std_ext_dir = os.path.join(os.environ['METRIXPLUSPLUS_INSTALL_DIR'], 'ext')
+        std_ext_priority_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
+        for each in [std_ext_dir] + directories:
+            sys.path.append(each)
+
+        inicontainer = IniContainer()
+        # load available plugin ini files
+        required_plugins = []
+        for each in ([std_ext_priority_dir, std_ext_dir] + directories):
+            required_plugins += load_recursively(inicontainer, each)
+            
+        # upgrade the list of required plugins
+        required_and_dependant_plugins = []
+        for name in required_plugins:
+            for each in list_dependants_recursively(inicontainer, name):
+                if each not in required_and_dependant_plugins:
+                    required_and_dependant_plugins.append(each)
+            required_and_dependant_plugins.append(name)
+            
+        # load
+        for plugin_name in required_and_dependant_plugins:
+            item = inicontainer.hash[plugin_name]
             plugin = __import__(item['package'], globals(), locals(), [item['module']], -1)
             module_attr = plugin.__getattribute__(item['module'])
             class_attr = module_attr.__getattribute__(item['class'])
@@ -94,6 +129,14 @@ class Loader(object):
             item['instance'].set_name(item['package'] + "." + item['module'])
             item['instance'].set_version(item['version'])
             item['instance'].set_plugin_loader(self)
+            self.plugins.append(item)
+            self.hash[plugin_name] = item
+
+        optparser =mpp.cmdparser.MultiOptionParser(
+            usage="Usage: %prog {command} [options] -- [path 1] ... [path N]".format(command=command))
+
+        if command not in inicontainer.actions:
+            optparser.error("Unknown action: {action}".format(action={command}))
 
         for item in self.iterate_plugins():
             if (isinstance(item, mpp.api.IConfigurable)):

mainline/mpp/export/utils/py2txt.py → mainline/mpp/internal/py2txt.py


mainline/mpp/export/utils/py2xml.py → mainline/mpp/internal/py2xml.py


+ 1 - 0
mainline/mpp/ext-priority/core.log.ini

@@ -23,4 +23,5 @@ package: mpp
 module:  log
 class:   Plugin
 depends: None
+actions: *
 enabled: True

+ 19 - 0
mainline/mpp/utils.py

@@ -17,6 +17,9 @@
 #    along with Metrix++.  If not, see <http://www.gnu.org/licenses/>.
 #
 
+import mpp.internal.py2xml
+import mpp.internal.py2txt
+
 import logging
 import re
 
@@ -112,3 +115,19 @@ def preprocess_path(path):
 
 def report_bad_path(path):
     logging.error("Specified path '" + path + "' is invalid: not found in the database records.")
+
+def serialize_to_xml(data, root_name = None):
+    serializer = mpp.internal.py2xml.Py2XML()
+    return serializer.parse(data, objName=root_name)
+
+def serialize_to_python(data, root_name = None):
+    prefix = ""
+    postfix = ""
+    if root_name != None:
+        prefix = "{'" + root_name + ": " 
+        postfix = "}"
+    return prefix + data.__repr__() + postfix
+
+def serialize_to_txt(data, root_name = None):
+    serializer = mpp.internal.py2txt.Py2TXT()
+    return serializer.parse(data, objName=root_name, indent = -1)

+ 3 - 2
mainline/mpp/ext-priority/core.db.post.ini

@@ -19,8 +19,9 @@
 
 [Plugin]
 version: 1.0
-package: mpp.db
-module:  post
+package: mpp
+module:  warn
 class:   Plugin
 depends: None
+actions: None
 enabled: True

+ 8 - 1
mainline/mpp/warn.py

@@ -92,7 +92,14 @@ class Plugin(mpp.api.Plugin, mpp.api.IConfigurable):
                     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 initialize(self):
+        super(Plugin, self).initialize()
+        db_loader = self.get_plugin_loader().get_plugin('mpp.dbf').get_loader()
+        self.verify_namespaces(db_loader.iterate_namespace_names())
+        for each in db_loader.iterate_namespace_names():
+            self.verify_fields(each, db_loader.get_namespace(each).iterate_field_names())
+    
     def verify_namespaces(self, valid_namespaces):
         valid = []
         for each in valid_namespaces:

+ 15 - 15
mainline/tests/general/test_basic/test_help_collect_default_stdout.gold.txt

@@ -12,21 +12,6 @@ Options:
                         it may reduce the processing time significantly. Post-
                         processing tools use it in order to recognise/evaluate
                         change trends. [default: none].
-  --non-recursively, --nr
-                        If the option is set (True), sub-directories are not
-                        processed [default: False]
-  --exclude-files=EXCLUDE_FILES, --ef=EXCLUDE_FILES
-                        Defines the pattern to exclude files from processing
-                        [default: ^[.]]
-  --std.general.proctime, --sgpt
-                        If the option is set (True), the tool measures
-                        processing time per file [default: False]
-  --std.general.procerrors, --sgpe
-                        If the option is set (True), the tool counts number of
-                        processing/parsing errors per file [default: False]
-  --std.general.size, --sgs
-                        If the option is set (True), the tool collects file
-                        size metric (in bytes) [default: False]
   --log-level=LOG_LEVEL, --ll=LOG_LEVEL
                         Defines log level. Possible values are
                         'DEBUG','INFO','WARNING' or 'ERROR'. Default value is
@@ -69,3 +54,18 @@ Options:
                         of suppressions: 'metrix++: suppress metric-name'. For
                         example: 'metrix++: suppress
                         std.code.complexity:cyclomatic'.  [default: False]
+  --std.general.proctime, --sgpt
+                        If the option is set (True), the tool measures
+                        processing time per file [default: False]
+  --std.general.procerrors, --sgpe
+                        If the option is set (True), the tool counts number of
+                        processing/parsing errors per file [default: False]
+  --std.general.size, --sgs
+                        If the option is set (True), the tool collects file
+                        size metric (in bytes) [default: False]
+  --exclude-files=EXCLUDE_FILES, --ef=EXCLUDE_FILES
+                        Defines the pattern to exclude files from processing
+                        [default: ^[.]]
+  --non-recursively, --nr
+                        If the option is set (True), sub-directories are not
+                        processed [default: False]

+ 8 - 6
mainline/tools/collect.py

@@ -18,10 +18,9 @@
 #
 
 
-import os.path
+import os
 
-import mpp.loader
-import mpp.cmdparser
+import mpp.internal.loader
 
 import mpp.api
 class Tool(mpp.api.ITool):
@@ -29,9 +28,12 @@ class Tool(mpp.api.ITool):
         return main(tool_args)
 
 def main(tool_args):
-    loader = mpp.loader.Loader()
-    parser =mpp.cmdparser.MultiOptionParser(usage="Usage: %prog collect [options] -- [path 1] ... [path N]")
-    args = loader.load(os.path.join(os.environ['METRIXPLUSPLUS_INSTALL_DIR'], 'ext'), parser, tool_args)
+    loader = mpp.internal.loader.Loader()
+    mpp_paths = []
+    # TODO document this feature
+    if 'METRIXPLUSPLUS_PATH' in os.environ.keys():
+        mpp_paths = os.environ['METRIXPLUSPLUS_PATH'].split(os.pathsep)
+    args = loader.load('collect', mpp_paths, tool_args)
     exit_code = loader.run(args)
     loader.unload()
     return exit_code

+ 2 - 2
mainline/tools/debug.py

@@ -24,7 +24,7 @@ import cgi
 import mpp.api
 import mpp.log
 import mpp.cmdparser
-import mpp.db.post
+import mpp.dbf
 
 import mpp.utils
 
@@ -34,7 +34,7 @@ class Tool(mpp.api.ITool):
 
 def main(tool_args):
     log_plugin = mpp.log.Plugin()
-    db_plugin = mpp.db.post.Plugin()
+    db_plugin = mpp.dbf.Plugin()
 
     parser = mpp.cmdparser.MultiOptionParser(usage="Usage: %prog debug [options] -- [path 1] ... [path N]")
     log_plugin.declare_configuration(parser)

+ 2 - 2
mainline/tools/export.py

@@ -24,7 +24,7 @@ import csv
 
 import mpp.api
 import mpp.log
-import mpp.db.post
+import mpp.dbf
 import mpp.cmdparser
 
 import mpp.utils
@@ -36,7 +36,7 @@ class Tool(mpp.api.ITool):
 def main(tool_args):
     
     log_plugin = mpp.log.Plugin()
-    db_plugin = mpp.db.post.Plugin()
+    db_plugin = mpp.dbf.Plugin()
 
     parser = mpp.cmdparser.MultiOptionParser(usage="Usage: %prog export [options] -- [path 1] ... [path N]")
     log_plugin.declare_configuration(parser)

+ 2 - 2
mainline/tools/info.py

@@ -19,7 +19,7 @@
 
 
 import mpp.api
-import mpp.db.post
+import mpp.dbf
 import mpp.log
 import mpp.cmdparser
 
@@ -32,7 +32,7 @@ class Tool(mpp.api.ITool):
 def main(tool_args):
     exit_code = 0
     log_plugin = mpp.log.Plugin()
-    db_plugin = mpp.db.post.Plugin()
+    db_plugin = mpp.dbf.Plugin()
 
     parser = mpp.cmdparser.MultiOptionParser(usage="Usage: %prog info [options] -- [path 1] ... [path N]")
     log_plugin.declare_configuration(parser)

+ 2 - 3
mainline/tools/limit.py

@@ -20,13 +20,12 @@
 import logging
 
 import mpp.log
-import mpp.db.post
+import mpp.dbf
 import mpp.utils
 import mpp.cout
 import mpp.warn
 import mpp.cmdparser
 
-import mpp.utils
 
 import mpp.api
 class Tool(mpp.api.ITool):
@@ -37,7 +36,7 @@ def main(tool_args):
     
     exit_code = 0
     log_plugin = mpp.log.Plugin()
-    db_plugin = mpp.db.post.Plugin()
+    db_plugin = mpp.dbf.Plugin()
     warn_plugin = mpp.warn.Plugin()
 
     parser = mpp.cmdparser.MultiOptionParser(usage="Usage: %prog limit [options] -- [path 1] ... [path N]")

+ 5 - 8
mainline/tools/view.py

@@ -19,12 +19,9 @@
 
 
 import mpp.log
-import mpp.db.post
+import mpp.dbf
 import mpp.utils
 import mpp.cmdparser
-import mpp.export.convert
-
-import mpp.utils
 
 import mpp.api
 class Tool(mpp.api.ITool):
@@ -34,7 +31,7 @@ class Tool(mpp.api.ITool):
 def main(tool_args):
     
     log_plugin = mpp.log.Plugin()
-    db_plugin = mpp.db.post.Plugin()
+    db_plugin = mpp.dbf.Plugin()
 
     parser = mpp.cmdparser.MultiOptionParser(usage="Usage: %prog view [options] -- [path 1] ... [path N]")
     log_plugin.declare_configuration(parser)
@@ -114,14 +111,14 @@ def export_to_str(out_format, paths, loader, loader_prev, nest_regions):
                 "subfiles": subfiles}
 
         if out_format == 'txt':
-            result += mpp.export.convert.to_txt(data, root_name = "data") + "\n"
+            result += mpp.utils.serialize_to_txt(data, root_name = "data") + "\n"
         elif out_format == 'xml':
-            result += mpp.export.convert.to_xml(data, root_name = "data") + "\n"
+            result += mpp.utils.serialize_to_xml(data, root_name = "data") + "\n"
         elif out_format == 'python':
             postfix = ""
             if ind < len(paths) - 1:
                 postfix = ", "
-            result += mpp.export.convert.to_python(data, root_name = "data") + postfix
+            result += mpp.utils.serialize_to_python(data, root_name = "data") + postfix
 
     if out_format == 'txt':
         result += "\n"