summaryrefslogtreecommitdiff
path: root/odoo/addons/test_lint
diff options
context:
space:
mode:
authorChristophe Simonis <chs@odoo.com>2019-06-11 15:20:13 +0200
committerChristophe Simonis <chs@odoo.com>2019-06-11 15:20:13 +0200
commit8853e6b594eb0387939741ec2a8b208593c29646 (patch)
tree2239af0a8a4b4df62b68bf05f8795e35de4f543f /odoo/addons/test_lint
parentbf139f06623916da846ed4776c105cadaee362bf (diff)
parent7ef4ba03c4f8dce42f5a56b64d2374373d13aa8d (diff)
[MERGE] forward port branch 12.0 up to 7ef4ba03c4f
Diffstat (limited to 'odoo/addons/test_lint')
-rw-r--r--odoo/addons/test_lint/__init__.py13
-rw-r--r--odoo/addons/test_lint/__manifest__.py12
-rw-r--r--odoo/addons/test_lint/tests/__init__.py2
-rw-r--r--odoo/addons/test_lint/tests/_odoo_checkers.py44
-rw-r--r--odoo/addons/test_lint/tests/test_ecmascript.py48
-rw-r--r--odoo/addons/test_lint/tests/test_pylint.py90
6 files changed, 209 insertions, 0 deletions
diff --git a/odoo/addons/test_lint/__init__.py b/odoo/addons/test_lint/__init__.py
new file mode 100644
index 00000000000..0e68430dabe
--- /dev/null
+++ b/odoo/addons/test_lint/__init__.py
@@ -0,0 +1,13 @@
+# -*- coding: utf-8 -*-
+# Part of Odoo. See LICENSE file for full copyright and licensing details.
+
+from odoo import api, SUPERUSER_ID
+
+
+# TO REMOVE in master
+def uninstall_test_pylint(cr):
+ env = api.Environment(cr, SUPERUSER_ID, {})
+ env['ir.module.module'].search([
+ ('name', '=', 'test_pylint'),
+ ('state', '=', 'installed')
+ ]).write({'state': 'uninstalled'})
diff --git a/odoo/addons/test_lint/__manifest__.py b/odoo/addons/test_lint/__manifest__.py
new file mode 100644
index 00000000000..554e20ba3b2
--- /dev/null
+++ b/odoo/addons/test_lint/__manifest__.py
@@ -0,0 +1,12 @@
+# -*- coding: utf-8 -*-
+{
+ 'name': 'test-lint',
+ 'version': '0.1',
+ 'category': 'Tests',
+ 'description': """A module to test Odoo code with various linters.""",
+ 'maintainer': 'Odoo SA',
+ 'depends': ['base'],
+ 'installable': True,
+ 'auto_install': False,
+ 'pre_init_hook': 'uninstall_test_pylint'
+}
diff --git a/odoo/addons/test_lint/tests/__init__.py b/odoo/addons/test_lint/tests/__init__.py
new file mode 100644
index 00000000000..d085060f6bf
--- /dev/null
+++ b/odoo/addons/test_lint/tests/__init__.py
@@ -0,0 +1,2 @@
+from . import test_pylint
+from . import test_ecmascript
diff --git a/odoo/addons/test_lint/tests/_odoo_checkers.py b/odoo/addons/test_lint/tests/_odoo_checkers.py
new file mode 100644
index 00000000000..5648ac52219
--- /dev/null
+++ b/odoo/addons/test_lint/tests/_odoo_checkers.py
@@ -0,0 +1,44 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+import tokenize
+
+from pylint import checkers, interfaces
+
+class PEP3110TokenChecker(checkers.BaseTokenChecker):
+ __implements__ = interfaces.ITokenChecker
+ name = 'python3'
+ enabled = False
+
+ msgs = {
+ 'E3110': ('Python 3 uses `as` instead of comma token to catch exceptions',
+ 'no-comma-exception',
+ 'See http://www.python.org/dev/peps/pep-3110/',
+ {'maxversion': (3, 0)}),
+ }
+
+ def process_tokens(self, tokens):
+ comma_found = in_except = False
+ pcount = 0
+ for tok_type, token, start, _, _ in tokens:
+ if tok_type == tokenize.NAME and token == 'except':
+ in_except = True
+ comma_found = False
+ pcount = 0
+
+ elif tok_type == tokenize.OP and in_except:
+ if token == '(':
+ pcount += 1
+ elif token == ')':
+ pcount -= 1
+ elif token == ',' and pcount == 0:
+ comma_found = True
+ if token == ':':
+ if in_except and comma_found:
+ self.add_message('no-comma-exception', line=start[0])
+ comma_found = in_except = False
+ pcount = 0
+
+
+def register(linter):
+ linter.register_checker(PEP3110TokenChecker(linter))
diff --git a/odoo/addons/test_lint/tests/test_ecmascript.py b/odoo/addons/test_lint/tests/test_ecmascript.py
new file mode 100644
index 00000000000..46008b0587d
--- /dev/null
+++ b/odoo/addons/test_lint/tests/test_ecmascript.py
@@ -0,0 +1,48 @@
+# -*- coding: utf-8 -*-
+# Part of Odoo. See LICENSE file for full copyright and licensing details.
+
+import logging
+import os
+import re
+import subprocess
+from unittest import skipIf
+from odoo.tests.common import TransactionCase
+from odoo import tools
+from odoo.modules import get_modules, get_module_path
+
+MAX_ES_VERSION = 'es5'
+
+_logger = logging.getLogger(__name__)
+
+try:
+ es_check = tools.misc.find_in_path('es-check')
+except IOError:
+ es_check = None
+
+
+@skipIf(es_check is None, "es-check tool not found on this system")
+class TestECMAScriptVersion(TransactionCase):
+
+ longMessage = True
+
+ def test_ecmascript_version(self):
+ """ Test that there is no unsupported ecmascript in javascript files """
+
+ black_re = re.compile(r'summernote.+(intro\.js|outro.js)$')
+
+ mod_paths = [get_module_path(m) for m in get_modules()]
+ files_to_check = []
+ for p in mod_paths:
+ for dp, _, file_names in os.walk(p):
+ if 'static/test' in dp:
+ continue
+ for fn in file_names:
+ fullpath_name = os.path.join(dp, fn)
+ if fullpath_name.endswith('.js') and not black_re.search(fullpath_name):
+ files_to_check.append(fullpath_name)
+
+ _logger.info('Testing %s js files', len(files_to_check))
+ cmd = [es_check, MAX_ES_VERSION] + files_to_check
+ process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ out, err = process.communicate()
+ self.assertEqual(process.returncode, 0, msg=out)
diff --git a/odoo/addons/test_lint/tests/test_pylint.py b/odoo/addons/test_lint/tests/test_pylint.py
new file mode 100644
index 00000000000..8e5e69fa351
--- /dev/null
+++ b/odoo/addons/test_lint/tests/test_pylint.py
@@ -0,0 +1,90 @@
+# -*- coding: utf-8 -*-
+# Part of Odoo. See LICENSE file for full copyright and licensing details.
+
+import logging
+try:
+ import pylint
+except ImportError:
+ pylint = None
+import subprocess
+from distutils.version import LooseVersion
+import os
+from os.path import join
+import sys
+
+from odoo.tests.common import TransactionCase
+from odoo import tools
+from odoo.modules import get_modules, get_module_path
+
+HERE = os.path.dirname(os.path.realpath(__file__))
+
+_logger = logging.getLogger(__name__)
+
+
+class TestPyLint(TransactionCase):
+
+ ENABLED_CODES = [
+ 'used-before-assignment',
+ 'undefined-variable',
+ 'eval-used',
+ 'unreachable',
+
+ 'mixed-indentation',
+ ]
+
+ BAD_FUNCTIONS = [
+ 'input',
+ ]
+
+ BAD_MODULES = [
+ 'csv',
+ 'urllib',
+ 'cgi',
+ ] + list(tools.SUPPORTED_DEBUGGER)
+
+ def _skip_test(self, reason):
+ _logger.warn(reason)
+ self.skipTest(reason)
+
+ def test_pylint(self):
+ if pylint is None:
+ self._skip_test('please install pylint')
+ required_pylint_version = LooseVersion('1.6.4')
+ if sys.version_info >= (3, 6):
+ required_pylint_version = LooseVersion('1.7.0')
+ if LooseVersion(getattr(pylint, '__version__', '0.0.1')) < required_pylint_version:
+ self._skip_test('please upgrade pylint to >= %s' % required_pylint_version)
+
+ paths = [tools.config['root_path']]
+ for module in get_modules():
+ module_path = get_module_path(module)
+ if not module_path.startswith(join(tools.config['root_path'], 'addons')):
+ paths.append(module_path)
+
+ options = [
+ '--rcfile=%s' % os.devnull,
+ '--disable=all',
+ '--enable=%s' % ','.join(self.ENABLED_CODES),
+ '--reports=n',
+ "--msg-template='{msg} ({msg_id}) at {path}:{line}'",
+ '--load-plugins=pylint.extensions.bad_builtin,_odoo_checkers',
+ '--bad-functions=%s' % ','.join(self.BAD_FUNCTIONS),
+ '--deprecated-modules=%s' % ','.join(self.BAD_MODULES)
+ ]
+
+ pypath = HERE + os.pathsep + os.environ.get('PYTHONPATH', '')
+ env = dict(os.environ, PYTHONPATH=pypath)
+ try:
+ pylint_bin = tools.which('pylint')
+ process = subprocess.Popen(
+ [pylint_bin] + options + paths,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE,
+ env=env,
+ )
+ except (OSError, IOError):
+ self._skip_test('pylint executable not found in the path')
+ else:
+ out, err = process.communicate()
+ if process.returncode:
+ self.fail("pylint test failed:\n" + (b"\n" + out + b"\n" + err).decode('utf-8').strip())