[apycotlib] add ScriptRunner to run custom files as checks, (closes #2882718)
authorPaul Tonelli <paul.tonelli@logilab.fr>
Mon, 07 Oct 2013 11:03:46 +0200
changeset 1428 b60269c2a5c0
parent 1427 c9dd4b0dc364
child 1429 00dced995ee2
[apycotlib] add ScriptRunner to run custom files as checks, (closes #2882718) The new checker can be derived to run any file provided the user writes a custom filename_filter method. The method has three parameters and two roles: - the first parameter (dirpath) is the path being explored; - the second parameter (dirname) is a list of directory names, the function must remove from the list the directories which should not be explored by os.walk; - the third parameter (filenames) is a list of files. The user should yield a list of files which should be run by the checker. This method uses the syntax of os.walk (see python doc). Add corresponding tests and example recipe.
_apycotlib/checkers/scenarios.py
_apycotlib/narvalactions.py
recipes.py
test/unittest_checkers.py
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_apycotlib/checkers/scenarios.py	Mon Oct 07 11:03:46 2013 +0200
@@ -0,0 +1,32 @@
+import os
+from commands import getstatusoutput
+from apycotlib import SUCCESS, FAILURE, ERROR
+from apycotlib.checkers import AbstractFilteredFileChecker
+from apycotlib import register
+
+class ScriptRunner(AbstractFilteredFileChecker):
+    """
+    run files accepted by the filter
+    """
+    id = 'script_runner'
+    def do_check(self, test):
+        if self.options.get('filename_filter') is not None:
+            self.filename_filter = self.options.get('filename_filter')
+        super(ScriptRunner, self).do_check(test)
+
+    def check_file(self, filepath):
+        try:
+            self.writer.debug("running : " + filepath, path=filepath)
+            status, out = getstatusoutput(filepath)
+            if status != 0:
+                self.writer.error(out, path=filepath)
+                return FAILURE
+            self.writer.info(out, path=filepath)
+            return SUCCESS
+        except Exception, error:
+            self.writer.error(error.msg, path=filepath)
+            return ERROR
+
+register('checker', ScriptRunner)
+
+
--- a/_apycotlib/narvalactions.py	Thu Sep 12 11:26:26 2013 +0200
+++ b/_apycotlib/narvalactions.py	Mon Oct 07 11:03:46 2013 +0200
@@ -1,6 +1,6 @@
 from apycotlib import atest, writer, ERROR
 from apycotlib import preprocessors # trigger registration
-from apycotlib.checkers import python # trigger registration
+from apycotlib.checkers import python, scenarios # trigger registration
 
 class apycot_environment(object):
     def __init__(self, plan):
--- a/recipes.py	Thu Sep 12 11:26:26 2013 +0200
+++ b/recipes.py	Mon Oct 07 11:03:46 2013 +0200
@@ -25,3 +25,37 @@
 def create_full_recipe(session):
     return session.create_entity('Recipe', name=u'apycot.recipe.full',
                                  script=full_script)
+
+scenario_runner_script = u'''
+import os
+from apycotlib import narvalactions as na
+from apycotlib.checkers.scenarios import ScriptRunner
+
+class ScenarioChecker(ScriptRunner):
+    id = "scenario_checker"
+    def filename_filter(self, dirpath, dirnames, filenames):
+        """
+        this function takes parameters from os.walk and has two objectives:
+          - from the dirnames, prune folders you do not want to explore
+            using dirnames.remove(x)
+          - remove all the filenames which should not be run from filenames in
+            the same way.
+        """
+        for dirname in dirnames[:]:
+            if dirname in ('.hg', '.git', '.svn'):
+                dirnames.remove(dirname)
+        for filename in filenames[:]:
+            if not (filename.endswith('.py') and filename.startswith('scenario_')):
+                filenames.remove(filename)
+
+register('checker', ScenarioChecker)
+
+with na.apycot_environment(plan) as test:
+    na.install_environment(test)
+    checker, status = test.run_checker('scenario_checker')
+'''
+
+def create_scenrario_filter_recipe(session):
+    return session.create_entity('Recipe', name=u'apycot.recipe.scenario_runner',
+                                 script=scenario_runner_script)
+
--- a/test/unittest_checkers.py	Thu Sep 12 11:26:26 2013 +0200
+++ b/test/unittest_checkers.py	Mon Oct 07 11:03:46 2013 +0200
@@ -39,8 +39,6 @@
         if exists(path):
             shutil.rmtree(path)
 
-
-
 class FileCheckerTest(TestCase):
     def __init__(self, checker, files, method_name):
         TestCase.__init__(self, method_name)
@@ -164,6 +162,53 @@
     python_syntax.best_status = 'partial'
     addTest(FileCheckerTest(python_syntax, ['extentionfilter/'], 'chks_test_dir_partial'))
 
+    # check providing a custom file filter function
+    class CorrectFilter(PythonSyntaxChecker):
+        id = 'correct_filter'
+        def filename_filter(self, dirpath, dirnames, filenames):
+            for filename in filenames:
+                if not filename.endswith('.py'):
+                    filenames.remove(filename)
+
+    python_syntax = CorrectFilter(WRITER)
+    addTest(FileCheckerTest(python_syntax, ['extentionfilter/'], 'chks_test_dir_success'))
+
+    class IncorrectFilter(PythonSyntaxChecker):
+        id = 'incorrect_filter'
+        def filename_filter(self, dirpath, dirnames, filenames):
+            for filename in filenames:
+                if not 'badsyntax' in filename:
+                    filenames.remove(filename)
+
+    python_syntax = IncorrectFilter(WRITER)
+    addTest(FileCheckerTest(python_syntax, ['extentionfilter/'], 'chks_test_dir_failure'))
+
+    class CorrectDirFilter(PythonSyntaxChecker):
+        id = 'correct_dir_filter'
+        def filename_filter(self, dirpath, dirnames, filenames):
+            for dirname in dirnames[:]:
+                if 'bad' in dirname:
+                    dirnames.remove(dirname)
+            for filename in filenames:
+                if 'bad' in filename:
+                    filenames.remove(filename)
+
+    python_syntax = CorrectDirFilter(WRITER)
+    addTest(FileCheckerTest(python_syntax, ['syntax_dir/'], 'chks_test_dir_success'))
+
+    class IncorrectDirFilter(PythonSyntaxChecker):
+        id = 'incorrect_dir_filter'
+        def filename_filter(self, dirpath, dirnames, filenames):
+            for dirname in dirnames[:]:
+                if 'goodsyntax' in dirname:
+                    dirnames.remove(dirname)
+            for filename in filenames:
+                if 'bad' in filename:
+                    filenames.remove(filename)
+
+    python_syntax = IncorrectDirFilter(WRITER)
+    addTest(FileCheckerTest(python_syntax, ['syntax_dir/'], 'chks_test_dir_failure'))
+
     ##### PyUnitTestChecker #####
     python_unit = PyUnitTestChecker(WRITER)
     addTest(ModuleCheckerTest(python_unit, ['goodpkg'], 'chks_test_success'))