[checkers] back to project_path as an attribute of ATest draft
authorDavid Douard <david.douard@logilab.fr>
Sun, 26 Oct 2014 23:30:28 +0100
changeset 1769 8e817371cba1
parent 1768 48066736c862
child 1770 43ee4499b0a2
[checkers] back to project_path as an attribute of ATest instead of an option of the checker. Make also some cleanups in test tools
_apycotlib/__init__.py
_apycotlib/atest.py
_narval/checkers/apycot/__init__.py
_narval/checkers/apycot/jslint.py
_narval/checkers/apycot/python.py
recipes/apycot.python.quick.py
recipes/apycot.python.venv.quick.py
test/unittest_checkers.py
test/unittest_checkers_pyunit.py
testutils.py
--- a/_apycotlib/__init__.py	Sun Oct 26 22:46:44 2014 +0100
+++ b/_apycotlib/__init__.py	Sun Oct 26 23:30:28 2014 +0100
@@ -369,7 +369,7 @@
         try:
             pkginfodir = dirname(test.environ['pkginfo'])
         except KeyError:
-            pkginfodir = config['project_path']
+            pkginfodir = test.project_path()
         try:
             pkginfo = PackageInfo(directory=pkginfodir)
             pyversions = set(pkginfo.pyversions)
--- a/_apycotlib/atest.py	Sun Oct 26 22:46:44 2014 +0100
+++ b/_apycotlib/atest.py	Sun Oct 26 23:30:28 2014 +0100
@@ -62,11 +62,11 @@
         self.texec = texec
         self.tconfig = texec['configuration']
         self.penvironment = texec['environment']
+        self._project_path = None
         # IWriter object
         self.writer = writer
         # local caches
         self._configs_cache = {}
-        self._repositories = {}
         # environment variables as a dictionary
         self.environ = self.tconfig['apycot_process_environment']
         self.environ.update(self.penvironment['apycot_process_environment'])
@@ -83,6 +83,12 @@
         self.options = options
         os.umask(022)
 
+    def project_path(self):
+        return self._project_path
+
+    def set_project_path(self, path):
+        self._project_path = path
+
     def __str__(self):
         return repr(self.apycot_repository())
 
@@ -243,6 +249,7 @@
 
     def run_checker(self, id, displayname=None, nonexecuted=False, **kwargs):
         """run all checks in the test environment"""
+        assert self.project_path() is not None, 'project_path must be set before running any checker'
         options = self.options.copy()
         options.update(kwargs)
         check_writer = self.writer.make_check_writer()
--- a/_narval/checkers/apycot/__init__.py	Sun Oct 26 22:46:44 2014 +0100
+++ b/_narval/checkers/apycot/__init__.py	Sun Oct 26 23:30:28 2014 +0100
@@ -49,12 +49,7 @@
     __type__ = 'checker'
 
     _best_status = None
-    options_def = {
-        'project_path': {
-                'help': 'directory in with to run the checker',
-                'required': True,
-                },
-        }
+    options_def = {}
 
     def check(self, test):
         self.status = None
@@ -63,7 +58,7 @@
             self.set_status(setup_status)
             if setup_status is None or setup_status:
                 self.set_status(self.do_check(test))
-                self.version_info()
+                self.version_info(test)
         finally:
             self.set_status(self.tear_down_check(test))
         # do it last to let checker do whatever they want to do.
@@ -74,10 +69,6 @@
             self.set_status(new_status)
         return self.status
 
-    @property
-    def project_path(self):
-        return self.options['project_path']
-
     def _get_best_status(self):
         best_status = self._best_status
         if best_status is None:
@@ -93,7 +84,7 @@
 
     best_status = property(_get_best_status, _set_best_status)
 
-    def version_info(self):
+    def version_info(self, test):
         """hook for checkers to add their version information"""
 
     def do_check(self, test):
@@ -142,8 +133,8 @@
         self._res = None
         self._safe_dir = set()
 
-    def files_root(self):
-        return join(self.options['project_path'], self.options.get('subpath', ''))
+    def files_root(self, test):
+        return join(test.project_path(), self.options.get('subpath', ''))
 
     def do_check(self, test):
         """run the checker against <path> (usually a directory)
@@ -153,7 +144,7 @@
         self.set_status(SUCCESS)
         self._nbanalyzed = 0
         self.ignored = self.options.get('ignore')
-        files_root = self.files_root()
+        files_root = self.files_root(test)
         self.writer.raw('file root', files_root)
         for dirpath, dirnames, filenames in walk(files_root):
             #inplace pruning of dirnames and filenames
--- a/_narval/checkers/apycot/jslint.py	Sun Oct 26 22:46:44 2014 +0100
+++ b/_narval/checkers/apycot/jslint.py	Sun Oct 26 23:30:28 2014 +0100
@@ -172,8 +172,8 @@
             return ParsedCommand(self.writer, command, parsercls=JsLintParser,
                                  path=path, cwd=os.path.dirname(JSLINT_PATH)).run()
 
-        def version_info(self):
-            super(JsLintChecker, self).version_info()
+        def version_info(self, test):
+            super(JsLintChecker, self).version_info(test)
             self.record_version_info('jslint', '2010-04-06')
 
     register('checker', JsLintChecker)
--- a/_narval/checkers/apycot/python.py	Sun Oct 26 22:46:44 2014 +0100
+++ b/_narval/checkers/apycot/python.py	Sun Oct 26 23:30:28 2014 +0100
@@ -51,7 +51,7 @@
     if 'install_path' in config:
         return config['install_path']
     modname = config.get('python_modname')
-    project_path = config['project_path']
+    project_path = test.project_path()
     if not modname and exists(join(project_path, '__pkginfo__.py')):
         from logilab.devtools.lib.pkginfo import PackageInfo
         pkginfo = PackageInfo(directory=project_path)
@@ -98,7 +98,7 @@
             self.writer.error(error.msg, path=filepath, line=error.lineno)
             return FAILURE
 
-    def version_info(self):
+    def version_info(self, test):
         self.record_version_info('python', sys.version)
 
 register('checker', PythonSyntaxChecker)
@@ -215,15 +215,14 @@
         BaseChecker.__init__(self, writer, options)
         self.coverage_data = None
         self._path = None
-        self.test = None
 
-    def version_info(self):
-        if pyversions(self.test):
-            self.record_version_info('python', ', '.join(pyversions(self.test)))
+    def version_info(self, test):
+        if pyversions(test):
+            self.record_version_info('python', ', '.join(pyversions(test)))
 
-    def enable_coverage(self):
+    def enable_coverage(self, test):
         if self.options.get('pycoverage') and coverage:
-            self.coverage_data = join(self.project_path, '.coverage')
+            self.coverage_data = join(test.project_path(), '.coverage')
             # XXX we need the environment variable to be considered by
             # "python-coverage run"
             os.environ['COVERAGE_FILE'] = self.coverage_data
@@ -233,11 +232,10 @@
     def setup_check(self, test):
         """run the checker against the <project_path> option (usually a directory)"""
         test_support.verbose = 0
-        self.test = test
         return SUCCESS
 
     def do_check(self, test):
-        if self.enable_coverage():
+        if self.enable_coverage(test):
             command = ['-c', 'from logilab.common.pytest import run; import sys; sys.argv=["pytest", "--coverage"]; run()']
         else:
             command = ['-c', 'from logilab.common.pytest import run; run()']
@@ -250,8 +248,8 @@
         testresults = {'success': 0, 'failures': 0,
                        'errors': 0, 'skipped': 0}
         total = 0
-        for python in pyversions(self.test):
-            cmd = self.run_test(command, python)
+        for python in pyversions(test):
+            cmd = self.run_test(test, command, python)
             for rtype in testresults:
                 total += getattr(cmd.parser, rtype)
                 testresults[rtype] += getattr(cmd.parser, rtype)
@@ -266,23 +264,23 @@
         self.writer.raw('error_test_cases', testresults['errors'], 'result')
         self.writer.raw('skipped_test_cases', testresults['skipped'], 'result')
 
-    def get_command(self, command, python):
+    def get_command(self, test, command, python):
         return [python, '-W', 'ignore'] + command
 
-    def run_test(self, command, python='python'):
+    def run_test(self, test, command, python='python'):
         """execute the given test file and parse output to detect failed /
         succeed test cases
         """
         if isinstance(command, basestring):
             command = [command]
-        command = self.get_command(command, python)
+        command = self.get_command(test, command, python)
         self.writer.info(' '.join(command), path=basename(command[-1]))
         self.writer.debug(os.environ['PYTHONPATH'], path='PYTHONPATH')
-        self.writer.debug(self.project_path, path='CWD')
+        self.writer.debug(test.project_path(), path='CWD')
         cmd = ParsedCommand(self.writer, command,
                             parsercls=self.parsercls,
                             parsed_content=self.parsed_content,
-                            path=self._path, cwd=self.project_path)
+                            path=self._path, cwd=test.project_path())
         cmd.run()
         cmd.set_status(cmd.parser.status)
         return cmd
@@ -351,12 +349,12 @@
     def do_check(self, test):
         status = SUCCESS
         testdirs = self.options.get("test_dirs")
-        basepath = self.project_path
+        basepath = test.project_path()
         for testdir in testdirs:
             testdir = join(basepath, testdir)
             if exists(testdir):
                 self._path = testdir
-                _status = self.run_tests(testdir)
+                _status = self.run_tests(test, testdir)
                 status = self.merge_status(status, _status)
                 break
         else:
@@ -364,7 +362,7 @@
             status = NODATA
         return status
 
-    def run_tests(self, testdir):
+    def run_tests(self, test, testdir):
         """run a package test suite
         expect to be in the test directory
         """
@@ -378,9 +376,9 @@
         testresults = {'success': 0, 'failures': 0,
                        'errors': 0, 'skipped': 0}
         total = 0
-        for python in pyversions(self.test):
+        for python in pyversions(test):
             for test_file in tests:
-                cmd = self.run_test(join(testdir, test_file), python)
+                cmd = self.run_test(test, join(testdir, test_file), python)
                 total += cmd.parser.total
                 for rtype in testresults:
                     testresults[rtype] += getattr(cmd.parser, rtype)
@@ -390,11 +388,11 @@
         self.execution_info(total, testresults)
         return status
 
-    def get_command(self, command, python):
+    def get_command(self, test, command, python):
         python = [python, '-W', 'ignore']
-        if self.enable_coverage():
+        if self.enable_coverage(test):
             python += [COVERAGE_CMD, 'run', '-a', '--branch',
-                       '--source=%s' % pyinstall_path(self.test)]
+                       '--source=%s' % pyinstall_path(test)]
         return python + command
 
 register('checker', PyUnitTestChecker)
@@ -439,7 +437,7 @@
     options_def = PyUnitTestChecker.options_def.copy()
     options_def.update(PYVERSIONS_OPTIONS)
 
-    def get_command(self, command, python):
+    def get_command(self, test, command, python):
         # XXX coverage
         return ['py.test', '--exec=%s' % python, '--nomagic', '--tb=no'] + command
 
@@ -481,7 +479,7 @@
             },
         })
 
-    def version_info(self):
+    def version_info(self, test):
         self.record_version_info('pylint', pylint_version)
 
     def do_check(self, test):
@@ -493,7 +491,7 @@
         # register checkers
         pycheckers.initialize(linter)
         # load configuration
-        package_wd_path = self.project_path
+        package_wd_path = test.project_path()
         if exists(join(package_wd_path, 'pylintrc')):
             linter.load_file_configuration(join(package_wd_path, 'pylintrc'))
         else:
@@ -521,7 +519,7 @@
             raise
         except Exception:
             self.writer.error('Error while processing pylint evaluation',
-                              path=self.project_path, tb=True)
+                              path=test.project_path(), tb=True)
             note = 0
         self.writer.raw('statements', '%i' % linter.stats['statement'], 'result')
         if note < threshold:
@@ -596,7 +594,7 @@
         },
     })
 
-    def version_info(self):
+    def version_info(self, test):
         if coverage:
             version = getoutput('%s --version' % COVERAGE_CMD).strip()
             self.record_version_info('python-coverage', version)
@@ -635,7 +633,7 @@
         covertool.use_cache(self.options.get('coverage_data'))
         covertool.load()
         try:
-            report_file = join(self.project_path, "coverage.xml")
+            report_file = join(test.project_path(), "coverage.xml")
             covertool.xml_report(outfile=report_file, ignore_errors=True)
             report = etree.parse(report_file).getroot()
             pc_cover = float(report.attrib.get('line-rate'))
@@ -689,7 +687,7 @@
         command += get_module_files(pyinstall_path(test))
         return ParsedCommand(self.writer, command, parsercls=PyCheckerOutputParser).run()
 
-    def version_info(self):
+    def version_info(self, test):
         self.record_version_info('pychecker', getoutput("pychecker --version").strip())
 
 register('checker', PyCheckerChecker)
--- a/recipes/apycot.python.quick.py	Sun Oct 26 22:46:44 2014 +0100
+++ b/recipes/apycot.python.quick.py	Sun Oct 26 23:30:28 2014 +0100
@@ -27,5 +27,5 @@
                          wdir=src)
     # we can now run the checkers
     repoeid = test.penvironment['repository']['eid']
-    project_path = join(test.tmpdir, 'src', str(repoeid))
-    checker, status = test.run_checker('pyunit', project_path=project_path)
+    test.set_project_path(join(test.tmpdir, 'src', str(repoeid)))
+    checker, status = test.run_checker('pyunit')
--- a/recipes/apycot.python.venv.quick.py	Sun Oct 26 22:46:44 2014 +0100
+++ b/recipes/apycot.python.venv.quick.py	Sun Oct 26 23:30:28 2014 +0100
@@ -30,6 +30,5 @@
                          wdir=src)
     # we can now run the checkers
     repoeid = test.penvironment['repository']['eid']
-    checker, status = test.run_checker('pyunit',
-                                   project_path=join(test.tmpdir, 'src',
-                                                     str(repoeid)))
+    test.set_project_path(join(test.tmpdir, 'src', str(repoeid)))
+    checker, status = test.run_checker('pyunit')
--- a/test/unittest_checkers.py	Sun Oct 26 22:46:44 2014 +0100
+++ b/test/unittest_checkers.py	Sun Oct 26 23:30:28 2014 +0100
@@ -13,7 +13,7 @@
 from logilab.common.testlib import unittest_main, TestCase, TestSuite
 
 import cubicweb.devtools
-from cubes.apycot.testutils import MockTest, MockRepository, MockCheckWriter
+from cubes.apycot.testutils import MockTest, MockCheckWriter
 
 from apycotlib import SUCCESS, FAILURE, PARTIAL, NODATA, ERROR
 
@@ -44,12 +44,10 @@
         TestCase.__init__(self, method_name)
         self.checker = checker
         self.files = [input_path(file) for file in files]
-        self.checker.options['project_path'] = input_path()
         self.set_description('checker: <%s>, files: %s' % (checker.id, files))
 
     def _init_test(self, file):
-        self.checker.options['project_path'] = file
-        atest = MockTest(MockRepository(path=file))
+        atest = MockTest(file)
         atest._apycot_config.update(self.checker.options)
         for k, v in atest._apycot_config.items():
             if isinstance(v, list):
--- a/test/unittest_checkers_pyunit.py	Sun Oct 26 22:46:44 2014 +0100
+++ b/test/unittest_checkers_pyunit.py	Sun Oct 26 23:30:28 2014 +0100
@@ -9,7 +9,7 @@
 from logilab.common.testlib import unittest_main, TestCase, mock_object
 
 import cubicweb.devtools
-from cubes.apycot.testutils import MockCheckWriter
+from cubes.apycot.testutils import MockTest, MockCheckWriter
 
 from apycotlib import SUCCESS, FAILURE, ERROR, PARTIAL, NODATA
 from checkers.apycot import python
@@ -40,35 +40,43 @@
         return join(self.input_dir, path)
 
     def test_run_test_result_empty(self):
-        cmd = self.checker.run_test(self.input_path('unittest_empty.py'))
+        atest = MockTest(self.input_dir)
+        cmd = self.checker.run_test(atest, self.input_path('unittest_empty.py'))
         _test_cmd(self, cmd, NODATA, success=0)
 
     def test_run_test_result_no_main(self):
-        cmd = self.checker.run_test(self.input_path('unittest_no_main.py'))
+        atest = MockTest(self.input_dir)
+        cmd = self.checker.run_test(atest, self.input_path('unittest_no_main.py'))
         _test_cmd(self, cmd, NODATA, success=0)
 
     def test_run_test_result_success(self):
-        cmd = self.checker.run_test(self.input_path('unittest_success.py'))
+        atest = MockTest(self.input_dir)
+        cmd = self.checker.run_test(atest, self.input_path('unittest_success.py'))
         _test_cmd(self, cmd, SUCCESS, success=1)
 
     def test_run_test_result_failure(self):
-        cmd = self.checker.run_test(self.input_path('unittest_failure.py'))
+        atest = MockTest(self.input_dir)
+        cmd = self.checker.run_test(atest, self.input_path('unittest_failure.py'))
         _test_cmd(self, cmd, FAILURE, failures=1)
 
     def test_run_test_result_error(self):
-        cmd = self.checker.run_test(self.input_path('unittest_errors.py'))
+        atest = MockTest(self.input_dir)
+        cmd = self.checker.run_test(atest, self.input_path('unittest_errors.py'))
         _test_cmd(self, cmd, FAILURE, errors=1)
 
     def test_run_test_result_skipped(self):
-        cmd = self.checker.run_test(self.input_path('unittest_skip.py'))
+        atest = MockTest(self.input_dir)
+        cmd = self.checker.run_test(atest, self.input_path('unittest_skip.py'))
         _test_cmd(self, cmd, PARTIAL, skipped=1)
 
     def test_run_test_result_mixed(self):
-        cmd = self.checker.run_test(self.input_path('unittest_mixed.py'))
+        atest = MockTest(self.input_dir)
+        cmd = self.checker.run_test(atest, self.input_path('unittest_mixed.py'))
         _test_cmd(self, cmd, FAILURE, 2, 15, 1, 2)
 
     def test_run_test_result_mixed_std(self):
-        cmd = self.checker.run_test(self.input_path('unittest_mixed_std.py'))
+        atest = MockTest(self.input_dir)
+        cmd = self.checker.run_test(atest, self.input_path('unittest_mixed_std.py'))
         _test_cmd(self, cmd, FAILURE, 2, 15, 1, 0)
 
 
@@ -80,11 +88,11 @@
         self.checker.options['project_path'] = input_path('testcase_pkg')
 
     def _test_cmd(self, *args):
-
+        atest = MockTest(self.input_dir)
         cmd_args = ['-c', 'from logilab.common.pytest '
                   'import run; run()',]
         cmd_args.extend(args)
-        return self.checker.run_test(cmd_args, sys.executable)
+        return self.checker.run_test(atest, cmd_args, sys.executable)
 
     def test_global(self):
         cmd = self._test_cmd()
--- a/testutils.py	Sun Oct 26 22:46:44 2014 +0100
+++ b/testutils.py	Sun Oct 26 23:30:28 2014 +0100
@@ -56,10 +56,10 @@
         self.append = self.msg.append
 
 
-class MockBaseWriter(BaseDataWriter):
+class MockCheckWriter(BaseDataWriter):
 
     def __init__(self):
-        super(MockBaseWriter, self).__init__(MockConnection('narval0'), None)
+        super(MockCheckWriter, self).__init__(None, None)
 
     def skip(self, *args, **kwargs):
         pass
@@ -70,38 +70,30 @@
     def set_exec_status(self, status):
         self._logs.append('<internal> SETTING EXEC STATUS: %s' % status)
 
-    raw = execution_info = skip
-    close = skip
-
-
-class MockTestWriter(MockBaseWriter):
-    """fake apycot.IWriter class, ignore every thing"""
-
-    def make_check_writer(self):
-        return MockCheckWriter()
-
-    link_to_revision = MockBaseWriter.skip
-
-
-class MockCheckWriter(MockBaseWriter):
-    """fake apycot.IWriter class, ignore every thing"""
-
     def start(self, checker):
         self._logs.append('<internal>STARTING %s' % checker.id)
 
     def clear_writer(self):
         self._log_stack = DummyStack()
 
+    raw = execution_info = skip
+    close = skip
+
+
+
 
 class MockTest(object):
     """fake apycot.Test.Test class"""
-    def __init__(self, repo=None):
-        self.repo = repo
+    def __init__(self, project_path=None):
+        self._project_path = project_path
         self.tmpdir = 'data'
         self.environ = {}
         self.checkers = []
         self._apycot_config = {}
 
+    def project_path(self):
+        return self._project_path
+
     @property
     def tconfig(self):
         return mock_object(testconfig={}, name='bob', subpath=None)
@@ -110,47 +102,6 @@
         return self._apycot_config
 
 
-class MockVCSFile(dict):
-    def __init__(self, _type, source_url=None, path=None):
-        super(MockVCSFile, self).__init__(
-                type=_type, source_url=source_url, path=path, local_cache=None)
-
-
-class MockRepository:
-    """fake apycot.IRepository class"""
-    branch = None
-    def __init__(self, attrs=None, **kwargs):
-        self.__dict__.update(kwargs)
-        self.co_path = self.path
-
-    def co_command(self):
-        return self.command
-
-    def co_move_to_branch_command(self):
-        return None
-
-    def __repr__(self):
-        return '<MockRepository %r>' % self.__dict__
-
-    def revision(self):
-        pass
-
-
-class MockConnection(object):
-    """fake HTTP handler"""
-    def __init__(self, instance_id):
-        self.instance_id = instance_id
-        self.instance_url = BASE_URL
-
-    def http_get(self, url, **params):
-        pass
-    def http_post(self, url, **params):
-        pass
-    def pending_plans(self):
-        return ()
-    def plan(self, eid):
-        pass
-
 class ApycotBaseTC(HGRCMixin, NarvalBaseTC):
     _repo_path = ()
     repo_import_revision_content = True