From 20f804586a4df5c3d860ac338cb8ec4744cc4cee Mon Sep 17 00:00:00 2001 From: Moises Lopez Date: Sat, 22 Aug 2015 04:58:15 +0000 Subject: [PATCH 1/3] [ADD] pylint_oca: Enable pylint plugin script to check OCA guidelines --- .travis.yml | 5 +- tests/test_repo/broken_lint/__init__.py | 3 ++ tests/test_repo/broken_lint/__openerp__.py | 11 ++++ tests/test_repo/broken_lint/case_import.py | 49 ++++++++++++++++++ tests/test_repo/broken_module/README.rst | 4 ++ tests/test_repo/broken_module/__init__.py | 5 +- tests/test_repo/broken_module/__openerp__.py | 7 ++- tests/test_repo/broken_module/doc/index.rst | 4 ++ .../broken_module/interpreter_wox.py | 5 ++ tests/test_repo/broken_module/ipdb.py | 1 + tests/test_repo/broken_module/model.py | 2 +- tests/test_repo/broken_module/model_view.xml | 33 ++++++++++++ tests/test_repo/broken_module/pdb.py | 1 + tests/test_repo/broken_module/pudb.py | 1 + .../test_repo/broken_module/tests/__init__.py | 2 + .../broken_module/tests/dummy_test.py | 13 +++++ tests/test_repo/second_module/__openerp__.py | 4 +- tests/test_repo/test_module/README.rst | 9 ++++ tests/test_repo/test_module/__openerp__.py | 2 + tests/test_repo/test_module/doc/index.rst | 9 ++++ .../test_module/static/description/icon.png | Bin 0 -> 9455 bytes travis/cfg/travis_run_pylint.cfg | 2 +- travis/cfg/travis_run_pylint_pr.cfg | 40 ++++++++++++-- travis/self_tests | 2 +- travis/test_pylint | 40 +++++++++++++- travis/travis_install_nightly | 2 +- 26 files changed, 241 insertions(+), 15 deletions(-) create mode 100644 tests/test_repo/broken_lint/__init__.py create mode 100644 tests/test_repo/broken_lint/__openerp__.py create mode 100644 tests/test_repo/broken_lint/case_import.py create mode 100644 tests/test_repo/broken_module/README.rst create mode 100644 tests/test_repo/broken_module/doc/index.rst create mode 100755 tests/test_repo/broken_module/interpreter_wox.py mode change 100644 => 100755 tests/test_repo/broken_module/model.py create mode 100644 tests/test_repo/broken_module/model_view.xml create mode 100644 tests/test_repo/broken_module/tests/__init__.py create mode 100644 tests/test_repo/broken_module/tests/dummy_test.py create mode 100644 tests/test_repo/test_module/README.rst create mode 100644 tests/test_repo/test_module/doc/index.rst create mode 100644 tests/test_repo/test_module/static/description/icon.png diff --git a/.travis.yml b/.travis.yml index 6f3b974b7..6f97f911a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -31,8 +31,9 @@ env: - INCLUDE="test_module,second_module" UNIT_TEST="1" - VERSION="7.0" INCLUDE="test_module,second_module" ODOO_REPO="OCA/OCB" # ODOO_REPO usage example - VERSION="6.1" INCLUDE="test_module,second_module" - - LINT_CHECK="1" TESTS="0" PYLINT_EXPECTED_ERRORS="17" TRAVIS_PULL_REQUEST="false" # Use main pylint config file - - LINT_CHECK="1" TESTS="0" PYLINT_EXPECTED_ERRORS="18" TRAVIS_PULL_REQUEST="true" # Use PR pylint config file + - LINT_CHECK="1" TESTS="0" PYLINT_EXPECTED_ERRORS="18" TRAVIS_PULL_REQUEST="false" # Use main pylint config file + - VERSION=master LINT_CHECK="1" TESTS="0" PYLINT_EXPECTED_ERRORS="40" TRAVIS_PULL_REQUEST="true" # Use PR pylint config file + - VERSION="7.0" LINT_CHECK="1" TESTS="0" PYLINT_EXPECTED_ERRORS="34" TRAVIS_PULL_REQUEST="true" # To check pylint_conf of PR's with old api install: - cp -r ../maintainer-quality-tools/ $HOME diff --git a/tests/test_repo/broken_lint/__init__.py b/tests/test_repo/broken_lint/__init__.py new file mode 100644 index 000000000..dbba1fc56 --- /dev/null +++ b/tests/test_repo/broken_lint/__init__.py @@ -0,0 +1,3 @@ +# -*- coding: utf-8 -*- + +from . import case_import diff --git a/tests/test_repo/broken_lint/__openerp__.py b/tests/test_repo/broken_lint/__openerp__.py new file mode 100644 index 000000000..0cfd8f089 --- /dev/null +++ b/tests/test_repo/broken_lint/__openerp__.py @@ -0,0 +1,11 @@ +# -*- coding: utf-8 -*- +{ + 'name': 'Broken module for lint tests', + 'license': 'AGPL-3', + 'author': 'Odoo Community Association (OCA)', + 'version': '1.0', + 'depends': [], + 'data': [], + 'test': [], + 'installable': False, +} diff --git a/tests/test_repo/broken_lint/case_import.py b/tests/test_repo/broken_lint/case_import.py new file mode 100644 index 000000000..e553aca8d --- /dev/null +++ b/tests/test_repo/broken_lint/case_import.py @@ -0,0 +1,49 @@ +# -*- coding: utf-8 -*- + +import openerp + +from openerp import api +from openerp.api import one + +from openerp.exceptions import Warning as UserError +from openerp.exceptions import Warning as OtherName +from openerp.exceptions import Warning +from openerp.exceptions import AccessError as AE, \ + ValidationError, Warning as UserError2 + + +class UseUnusedImport(object): + def method1(self): + return UserError, OtherName, Warning, AE, ValidationError, UserError2 + + +class ApiOne(object): + @api.one + def copy(): + pass + + +class One(object): + @one + def copy(): + pass + + +class OpenerpApiOne(object): + @openerp.api.one + def copy(): + pass + + +class WOApiOne(object): + # copy without api.one decorator + def copy(): + pass + + +class ApiOneMultiTogether(object): + + @api.multi + @api.one + def copy(): + pass diff --git a/tests/test_repo/broken_module/README.rst b/tests/test_repo/broken_module/README.rst new file mode 100644 index 000000000..caf2e50c7 --- /dev/null +++ b/tests/test_repo/broken_module/README.rst @@ -0,0 +1,4 @@ +Module broken +=============== +`````````` +syntax error diff --git a/tests/test_repo/broken_module/__init__.py b/tests/test_repo/broken_module/__init__.py index f3fc39f79..efcda3c3b 100644 --- a/tests/test_repo/broken_module/__init__.py +++ b/tests/test_repo/broken_module/__init__.py @@ -1,2 +1,5 @@ -# -*- coding: utf-8 -*- +#!/usr/bin/python +# -*- coding: latin-1 -*- from . import model +from . import interpreter_wox +# execution permission and interpreter done diff --git a/tests/test_repo/broken_module/__openerp__.py b/tests/test_repo/broken_module/__openerp__.py index 4930c48d3..663d793cf 100644 --- a/tests/test_repo/broken_module/__openerp__.py +++ b/tests/test_repo/broken_module/__openerp__.py @@ -1,9 +1,14 @@ # -*- coding: utf-8 -*- { 'name': 'Broken module for tests', + # missing license + 'author': 'Many People', # Missing oca author + 'description': 'Should be a README.rst file', 'version': '1.0', 'depends': ['base'], - 'data': [], + 'data': ['model_view.xml'], 'test': ['test.yml'], 'installable': True, + 'name': 'Duplicated value', + 'active': True, # Deprecated active key } diff --git a/tests/test_repo/broken_module/doc/index.rst b/tests/test_repo/broken_module/doc/index.rst new file mode 100644 index 000000000..caf2e50c7 --- /dev/null +++ b/tests/test_repo/broken_module/doc/index.rst @@ -0,0 +1,4 @@ +Module broken +=============== +`````````` +syntax error diff --git a/tests/test_repo/broken_module/interpreter_wox.py b/tests/test_repo/broken_module/interpreter_wox.py new file mode 100755 index 000000000..188711aa1 --- /dev/null +++ b/tests/test_repo/broken_module/interpreter_wox.py @@ -0,0 +1,5 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + + +"Module python with interpreter but without execute permission." diff --git a/tests/test_repo/broken_module/ipdb.py b/tests/test_repo/broken_module/ipdb.py index 919b22fe9..e99e5319d 100644 --- a/tests/test_repo/broken_module/ipdb.py +++ b/tests/test_repo/broken_module/ipdb.py @@ -1 +1,2 @@ +# -*- coding: utf-8 -*- # W0402(deprecated-module) require module present diff --git a/tests/test_repo/broken_module/model.py b/tests/test_repo/broken_module/model.py old mode 100644 new mode 100755 index dd1fac83b..cc833bc22 --- a/tests/test_repo/broken_module/model.py +++ b/tests/test_repo/broken_module/model.py @@ -1,4 +1,4 @@ - +# missing coding from openerp.osv import orm, fields import os diff --git a/tests/test_repo/broken_module/model_view.xml b/tests/test_repo/broken_module/model_view.xml new file mode 100644 index 000000000..1b85c1db0 --- /dev/null +++ b/tests/test_repo/broken_module/model_view.xml @@ -0,0 +1,33 @@ + + + + + + view.model.form + test.model + +
+ + +
+
+ + + view.model.form + test.model + + + + + + + + + + By name + test.model + {'group_by': ['name']} + + +
+
diff --git a/tests/test_repo/broken_module/pdb.py b/tests/test_repo/broken_module/pdb.py index 919b22fe9..e99e5319d 100644 --- a/tests/test_repo/broken_module/pdb.py +++ b/tests/test_repo/broken_module/pdb.py @@ -1 +1,2 @@ +# -*- coding: utf-8 -*- # W0402(deprecated-module) require module present diff --git a/tests/test_repo/broken_module/pudb.py b/tests/test_repo/broken_module/pudb.py index 919b22fe9..e99e5319d 100644 --- a/tests/test_repo/broken_module/pudb.py +++ b/tests/test_repo/broken_module/pudb.py @@ -1 +1,2 @@ +# -*- coding: utf-8 -*- # W0402(deprecated-module) require module present diff --git a/tests/test_repo/broken_module/tests/__init__.py b/tests/test_repo/broken_module/tests/__init__.py new file mode 100644 index 000000000..e0bb3a28b --- /dev/null +++ b/tests/test_repo/broken_module/tests/__init__.py @@ -0,0 +1,2 @@ +# -*- coding: utf-8 -*- +from . import dummy_test diff --git a/tests/test_repo/broken_module/tests/dummy_test.py b/tests/test_repo/broken_module/tests/dummy_test.py new file mode 100644 index 000000000..273bb8738 --- /dev/null +++ b/tests/test_repo/broken_module/tests/dummy_test.py @@ -0,0 +1,13 @@ +# -*- coding: utf-8 -*- +# missing coding +"""This file is not added to main __init__ +We need to validate that check py errors""" + +try: + from openerp.exceptions import Warning +except ImportError: + pass + + +def using_imported(): + return Warning diff --git a/tests/test_repo/second_module/__openerp__.py b/tests/test_repo/second_module/__openerp__.py index a0652d4f3..4af221b52 100644 --- a/tests/test_repo/second_module/__openerp__.py +++ b/tests/test_repo/second_module/__openerp__.py @@ -1,7 +1,9 @@ # -*- coding: utf-8 -*- { 'name': 'Second empty module for tests', - 'version': '1.0', + 'version': '8.0.1.0.0', + 'author': 'Odoo Community Association (OCA)', + 'license': 'AGPL-3', 'depends': [ 'base', 'test_module', diff --git a/tests/test_repo/test_module/README.rst b/tests/test_repo/test_module/README.rst new file mode 100644 index 000000000..d00cd1be4 --- /dev/null +++ b/tests/test_repo/test_module/README.rst @@ -0,0 +1,9 @@ +.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg + :alt: License: AGPL-3 + +Test module +=========== + +This module was written to check the test of rst syntax. +This is a rst file without syntax error. + diff --git a/tests/test_repo/test_module/__openerp__.py b/tests/test_repo/test_module/__openerp__.py index 27124ec04..1656d77fa 100644 --- a/tests/test_repo/test_module/__openerp__.py +++ b/tests/test_repo/test_module/__openerp__.py @@ -1,6 +1,8 @@ # -*- coding: utf-8 -*- { 'name': 'Empty module for tests', + 'license': 'AGPL-3', + 'author': 'Odoo Community Association (OCA)', 'version': '1.0', 'depends': [ 'base', diff --git a/tests/test_repo/test_module/doc/index.rst b/tests/test_repo/test_module/doc/index.rst new file mode 100644 index 000000000..d00cd1be4 --- /dev/null +++ b/tests/test_repo/test_module/doc/index.rst @@ -0,0 +1,9 @@ +.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg + :alt: License: AGPL-3 + +Test module +=========== + +This module was written to check the test of rst syntax. +This is a rst file without syntax error. + diff --git a/tests/test_repo/test_module/static/description/icon.png b/tests/test_repo/test_module/static/description/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..3a0328b516c4980e8e44cdb63fd945757ddd132d GIT binary patch literal 9455 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 z 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 Xviia!U7SGha1wx#SCgwmn*{w2TRX*I literal 0 HcmV?d00001 diff --git a/travis/cfg/travis_run_pylint.cfg b/travis/cfg/travis_run_pylint.cfg index 1caa9cd0d..a68ec2567 100644 --- a/travis/cfg/travis_run_pylint.cfg +++ b/travis/cfg/travis_run_pylint.cfg @@ -1,6 +1,6 @@ [MASTER] profile=no -ignore=CVS,.git,scenarios,.bzr,__openerp__.py,__odoo__.py,__terp__.py +ignore=CVS,.git,scenarios,.bzr persistent=yes cache-size=500 diff --git a/travis/cfg/travis_run_pylint_pr.cfg b/travis/cfg/travis_run_pylint_pr.cfg index 1f32c3a44..33dd3223c 100644 --- a/travis/cfg/travis_run_pylint_pr.cfg +++ b/travis/cfg/travis_run_pylint_pr.cfg @@ -1,14 +1,46 @@ [MASTER] profile=no -ignore=CVS,.git,scenarios,.bzr,__openerp__.py,__odoo__.py,__terp__.py +ignore=CVS,.git,scenarios,.bzr persistent=yes cache-size=500 +[ODOOLINT] +readme_template_url="https://github.com/OCA/maintainer-tools/blob/master/template/module/README.rst" +manifest_required_author="Odoo Community Association (OCA)" +manifest_required_keys=license +manifest_deprecated_keys=description,active + [MESSAGES CONTROL] disable=all -# This change don't add new checks. -# Adding one exits check to test the pr-diff feature -enable=W0403 + +# Enable message and code: +# api-one-multi-together - W8101 +# class-camelcase - C8104 +# copy-wo-api-one - W8102 +# dangerous-filter-wo-user - W7901 +# duplicate-xml-record-id - W7902 +# incoherent-interpreter-exec-perm - W8201 +# manifest-deprecated-key - C8103 +# manifest-required-author - C8101 +# manifest-required-key - C8102 +# missing-readme - C7902 +# no-utf8-coding-comment - C8201 +# openerp-exception-warning - R8101 +# rst-syntax-error - E7901 + +enable=api-one-multi-together, + class-camelcase, + copy-wo-api-one, + dangerous-filter-wo-user, + duplicate-xml-record-id, + incoherent-interpreter-exec-perm, + manifest-deprecated-key, + manifest-required-author, + manifest-required-key, + missing-readme, + no-utf8-coding-comment, + openerp-exception-warning, + rst-syntax-error [REPORTS] msg-template={path}:{line}: [{msg_id}({symbol}), {obj}] {msg} diff --git a/travis/self_tests b/travis/self_tests index 1832359cb..ca954f22e 100755 --- a/travis/self_tests +++ b/travis/self_tests @@ -44,7 +44,7 @@ if os.environ.get('LINT_CHECK', 0) == '1': "--extra-params", "-d", "--extra-params", "all", "--extra-params", "-e", "--extra-params", "F0010,duplicate-key", "--path", repo_dir], standalone_mode=False) - assert 1 == count_errors + assert 2 == count_errors empty_path = os.path.join(repo_dir, 'empty_path') if not os.path.exists(empty_path): diff --git a/travis/test_pylint b/travis/test_pylint index 967373b86..67020bca7 100755 --- a/travis/test_pylint +++ b/travis/test_pylint @@ -12,13 +12,49 @@ import travis_helpers from getaddons import get_modules_changed + +def get_extra_params(odoo_version): + ''' + Get extra pylint params by odoo version + :param version: String with name of version of odoo + :return: List of extra pylint params + ''' + params = ["--load-plugins=pylint_oca"] + try: + version_f = float(odoo_version) + except ValueError: + # master case + version_f = -1 + if version_f != -1 and version_f < 8: + # Class name snake_case style to version < 8 + params.append( + '--class-rgx=' + '([a-z_][a-z0-9_]{2,45})|([A-Z_][a-zA-Z0-9]{2,45})$' + ) + params.append( + '--disable=' + 'missing-readme,manifest-deprecated-key,copy-wo-api-one' + ) + return params + + +version = os.environ.get('VERSION', False) +extra_params_cmd = [] +if version: + extra_params = get_extra_params(version) + for extra_param in extra_params: + extra_params_cmd.extend([ + '--extra-params', extra_param + ]) + + pylint_rcfile = os.path.join( os.path.dirname(os.path.realpath(__file__)), 'cfg', "travis_run_pylint.cfg") count_errors = run_pylint.main([ "--config-file=" + pylint_rcfile, -], standalone_mode=False) + ] + extra_params_cmd, standalone_mode=False) pylint_rcfile_pr = os.path.join( @@ -42,7 +78,7 @@ if is_pull_request and branch_base and git_work_dir: ]) count_errors += run_pylint.main([ "--config-file=" + pylint_rcfile_pr, - ] + modules_changed_cmd, standalone_mode=False) + ] + modules_changed_cmd + extra_params_cmd, standalone_mode=False) else: # TODO: Add git hook case in other PR pass diff --git a/travis/travis_install_nightly b/travis/travis_install_nightly index 28c8f55bf..5bbed9e4a 100755 --- a/travis/travis_install_nightly +++ b/travis/travis_install_nightly @@ -1,6 +1,6 @@ #!/bin/bash -pip install -q QUnitSuite flake8 coveralls pylint Click > /dev/null 2>&1 +pip install -q QUnitSuite flake8 coveralls Click git+https://github.com/moylop260/pylint_oca.git > /dev/null 2>&1 # We can exit here and do nothing if this only a LINT check if [ "${LINT_CHECK}" == "1" ] ; then From ae9719a0fe1e66989ca583a496201bfefd3f5f66 Mon Sep 17 00:00:00 2001 From: Moises Lopez Date: Fri, 4 Sep 2015 22:23:38 +0000 Subject: [PATCH 2/3] [REF] test_pylint: Add cfg file by version --- .travis.yml | 2 +- travis/cfg/travis_run_pylint_61.cfg | 21 +++++++++++++++++++++ travis/cfg/travis_run_pylint_70.cfg | 21 +++++++++++++++++++++ travis/test_pylint | 29 ++++++++++++++--------------- travis/travis_install_nightly | 2 +- 5 files changed, 58 insertions(+), 17 deletions(-) create mode 100644 travis/cfg/travis_run_pylint_61.cfg create mode 100644 travis/cfg/travis_run_pylint_70.cfg diff --git a/.travis.yml b/.travis.yml index 6f97f911a..5c9c9ca10 100644 --- a/.travis.yml +++ b/.travis.yml @@ -33,7 +33,7 @@ env: - VERSION="6.1" INCLUDE="test_module,second_module" - LINT_CHECK="1" TESTS="0" PYLINT_EXPECTED_ERRORS="18" TRAVIS_PULL_REQUEST="false" # Use main pylint config file - VERSION=master LINT_CHECK="1" TESTS="0" PYLINT_EXPECTED_ERRORS="40" TRAVIS_PULL_REQUEST="true" # Use PR pylint config file - - VERSION="7.0" LINT_CHECK="1" TESTS="0" PYLINT_EXPECTED_ERRORS="34" TRAVIS_PULL_REQUEST="true" # To check pylint_conf of PR's with old api + - VERSION="7.0" LINT_CHECK="1" TESTS="0" PYLINT_EXPECTED_ERRORS="29" TRAVIS_PULL_REQUEST="true" # To check pylint_conf of PR's with old api install: - cp -r ../maintainer-quality-tools/ $HOME diff --git a/travis/cfg/travis_run_pylint_61.cfg b/travis/cfg/travis_run_pylint_61.cfg new file mode 100644 index 000000000..6784e2433 --- /dev/null +++ b/travis/cfg/travis_run_pylint_61.cfg @@ -0,0 +1,21 @@ +# This config file not is a real pylint config file. +# This file overwrite params of base template. + +[ODOOLINT] +manifest_deprecated_keys= + +[MESSAGES CONTROL] +# Disable message and code: +# copy-wo-api-one - W8102 +# class-camelcase - C8104 +# missing-readme - C7902 +# openerp-exception-warning - R8101 + +disable=copy-wo-api-one, + class-camelcase, + missing-readme, + openerp-exception-warning, + +[IMPORTS] +deprecated-modules=pdb,pudb,ipdb + diff --git a/travis/cfg/travis_run_pylint_70.cfg b/travis/cfg/travis_run_pylint_70.cfg new file mode 100644 index 000000000..6784e2433 --- /dev/null +++ b/travis/cfg/travis_run_pylint_70.cfg @@ -0,0 +1,21 @@ +# This config file not is a real pylint config file. +# This file overwrite params of base template. + +[ODOOLINT] +manifest_deprecated_keys= + +[MESSAGES CONTROL] +# Disable message and code: +# copy-wo-api-one - W8102 +# class-camelcase - C8104 +# missing-readme - C7902 +# openerp-exception-warning - R8101 + +disable=copy-wo-api-one, + class-camelcase, + missing-readme, + openerp-exception-warning, + +[IMPORTS] +deprecated-modules=pdb,pudb,ipdb + diff --git a/travis/test_pylint b/travis/test_pylint index 67020bca7..a02bd72e7 100755 --- a/travis/test_pylint +++ b/travis/test_pylint @@ -6,6 +6,7 @@ Script to process pylint run and exit with result. """ import os +import ConfigParser import run_pylint import travis_helpers @@ -16,25 +17,23 @@ from getaddons import get_modules_changed def get_extra_params(odoo_version): ''' Get extra pylint params by odoo version + Transform a seudo-pylint-conf to params, + it to overwrite base-pylint-conf values. :param version: String with name of version of odoo :return: List of extra pylint params ''' params = ["--load-plugins=pylint_oca"] - try: - version_f = float(odoo_version) - except ValueError: - # master case - version_f = -1 - if version_f != -1 and version_f < 8: - # Class name snake_case style to version < 8 - params.append( - '--class-rgx=' - '([a-z_][a-z0-9_]{2,45})|([A-Z_][a-zA-Z0-9]{2,45})$' - ) - params.append( - '--disable=' - 'missing-readme,manifest-deprecated-key,copy-wo-api-one' - ) + odoo_version = odoo_version.replace('.', '') + custom_cfg = os.path.join( + os.path.dirname(os.path.realpath(__file__)), + 'cfg/travis_run_pylint_{odoo_version}.cfg'.format( + odoo_version=odoo_version)) + if os.path.isfile(custom_cfg): + config = ConfigParser.ConfigParser() + config.readfp(open(custom_cfg)) + for section in config.sections(): + for option, value in config.items(section): + params.extend(['--' + option, value]) return params diff --git a/travis/travis_install_nightly b/travis/travis_install_nightly index 5bbed9e4a..0fd8a4460 100755 --- a/travis/travis_install_nightly +++ b/travis/travis_install_nightly @@ -1,6 +1,6 @@ #!/bin/bash -pip install -q QUnitSuite flake8 coveralls Click git+https://github.com/moylop260/pylint_oca.git > /dev/null 2>&1 +pip install -q QUnitSuite flake8 coveralls Click oca-pylint-plugin > /dev/null 2>&1 # We can exit here and do nothing if this only a LINT check if [ "${LINT_CHECK}" == "1" ] ; then From cbcf946813c089d2bf17b7fc6acbf40ee6a7534b Mon Sep 17 00:00:00 2001 From: Moises Lopez Date: Sun, 6 Sep 2015 22:22:49 -0500 Subject: [PATCH 3/3] [REF] pylint: Add use-vim-comment, disable red in checks of modules changed and small fixes [REF] pylint: Add use-vim-comment [REF] test_pylint: Avoid run pylint without modules changed [REF] Change generic exception [REF] .travis.yml: Identify all modules as changed [REF] pylint: Disable red in checks of modules changed [REF] pylint: Print warning messages --- .travis.yml | 5 +- tests/test_repo/broken_module/model.py | 2 + travis/cfg/travis_run_pylint_pr.cfg | 4 +- travis/run_pylint.py | 6 +-- travis/test_pylint | 71 +++++++++++++++++++++----- 5 files changed, 69 insertions(+), 19 deletions(-) diff --git a/.travis.yml b/.travis.yml index 5c9c9ca10..1bb3814df 100644 --- a/.travis.yml +++ b/.travis.yml @@ -32,14 +32,15 @@ env: - VERSION="7.0" INCLUDE="test_module,second_module" ODOO_REPO="OCA/OCB" # ODOO_REPO usage example - VERSION="6.1" INCLUDE="test_module,second_module" - LINT_CHECK="1" TESTS="0" PYLINT_EXPECTED_ERRORS="18" TRAVIS_PULL_REQUEST="false" # Use main pylint config file - - VERSION=master LINT_CHECK="1" TESTS="0" PYLINT_EXPECTED_ERRORS="40" TRAVIS_PULL_REQUEST="true" # Use PR pylint config file - - VERSION="7.0" LINT_CHECK="1" TESTS="0" PYLINT_EXPECTED_ERRORS="29" TRAVIS_PULL_REQUEST="true" # To check pylint_conf of PR's with old api + - VERSION=master LINT_CHECK="1" TESTS="0" PYLINT_EXPECTED_ERRORS="18" TRAVIS_PULL_REQUEST="true" # Use PR pylint config file + - VERSION="7.0" LINT_CHECK="1" TESTS="0" PYLINT_EXPECTED_ERRORS="18" TRAVIS_PULL_REQUEST="true" # To check pylint_conf of PR's with old api install: - cp -r ../maintainer-quality-tools/ $HOME - mv tests/test_repo/* ./ - export PATH=$HOME/maintainer-quality-tools/travis:$PATH - travis_install_nightly 8.0 # only used if VERSION not set in env + - git --git-dir=${TRAVIS_BUILD_DIR}/.git add --all # All modules moved are modules changed to test PR changes script: - coverage run --append ./travis/self_tests diff --git a/tests/test_repo/broken_module/model.py b/tests/test_repo/broken_module/model.py index cc833bc22..2118418a3 100755 --- a/tests/test_repo/broken_module/model.py +++ b/tests/test_repo/broken_module/model.py @@ -70,3 +70,5 @@ def method_w1111(): class E0101(object): def __init__(self): return 'E0101' + +# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/travis/cfg/travis_run_pylint_pr.cfg b/travis/cfg/travis_run_pylint_pr.cfg index 33dd3223c..187db292c 100644 --- a/travis/cfg/travis_run_pylint_pr.cfg +++ b/travis/cfg/travis_run_pylint_pr.cfg @@ -27,6 +27,7 @@ disable=all # no-utf8-coding-comment - C8201 # openerp-exception-warning - R8101 # rst-syntax-error - E7901 +# use-vim-comment - W8202 enable=api-one-multi-together, class-camelcase, @@ -40,7 +41,8 @@ enable=api-one-multi-together, missing-readme, no-utf8-coding-comment, openerp-exception-warning, - rst-syntax-error + rst-syntax-error, + use-vim-comment, [REPORTS] msg-template={path}:{line}: [{msg_id}({symbol}), {obj}] {msg} diff --git a/travis/run_pylint.py b/travis/run_pylint.py index b20629eec..d07f94e2d 100755 --- a/travis/run_pylint.py +++ b/travis/run_pylint.py @@ -62,8 +62,8 @@ def run_pylint(paths, cfg, sys_paths=None, extra_params=None): cmd.extend(extra_params) subpaths = get_subpaths(paths) if not subpaths: - raise ValueError("Python modules not found in paths" - " {paths}".format(paths=paths)) + raise UserWarning("Python modules not found in paths" + " {paths}".format(paths=paths)) cmd.extend(subpaths) pylint_res = pylint.lint.Run(cmd, exit=False) return pylint_res.linter.stats @@ -92,7 +92,7 @@ def main(paths, config_file, sys_paths=None, extra_params=None): list(paths), config_file.name, sys_paths=sys_paths, extra_params=extra_params) count_fails = get_count_fails(stats) - except ValueError: + except UserWarning: count_fails = -1 return count_fails diff --git a/travis/test_pylint b/travis/test_pylint index a02bd72e7..aca2ca005 100755 --- a/travis/test_pylint +++ b/travis/test_pylint @@ -15,10 +15,39 @@ from getaddons import get_modules_changed def get_extra_params(odoo_version): - ''' - Get extra pylint params by odoo version + '''Get extra pylint params by odoo version Transform a seudo-pylint-conf to params, it to overwrite base-pylint-conf values. + Use a seudo-inherit of configuration file. + To avoid have a 2 config files (stable and pr-conf) by each odoo-version + Example: + + pylint_master.conf + pylint_master_pr.conf + pylint_90.conf + pylint_90_pr.conf + pylint_80.conf + pylint_80_pr.conf + pylint_70.conf + pylint_70_pr.conf + pylint_61.conf + pylint_61_pr.conf + ... and new future versions. + + If you need add a new conventions in all versions + you will need change all pr files or stables files. + + + With this method you can use: + + pylint_lastest.conf + pylint_lastest_pr.conf + pylint_disabling_70.conf <- Overwrite params of pylint_lastest*.conf + pylint_disabling_61.conf <- Overwrite params of pylint_lastest*.conf + + If you need add a new conventions in all versions you will need change just + pylint_lastest_pr.conf or pylint_lastest.conf, similar to inherit. + :param version: String with name of version of odoo :return: List of extra pylint params ''' @@ -55,7 +84,6 @@ count_errors = run_pylint.main([ "--config-file=" + pylint_rcfile, ] + extra_params_cmd, standalone_mode=False) - pylint_rcfile_pr = os.path.join( os.path.dirname(os.path.realpath(__file__)), 'cfg', @@ -65,23 +93,40 @@ is_pull_request = os.environ.get( 'TRAVIS_PULL_REQUEST', 'false') != 'false' branch_base = os.environ.get('TRAVIS_BRANCH', False) git_work_dir = os.environ.get('TRAVIS_BUILD_DIR', False) + + if is_pull_request and branch_base and git_work_dir: modules_changed = get_modules_changed( git_work_dir, 'origin/' + branch_base) - modules_changed_cmd = [] - for module_changed in modules_changed: - modules_changed_cmd.extend([ - '--path', - module_changed, - ]) - count_errors += run_pylint.main([ - "--config-file=" + pylint_rcfile_pr, - ] + modules_changed_cmd + extra_params_cmd, standalone_mode=False) + if modules_changed and count_errors >= 0: + print(travis_helpers.green( + 'Start lint check just in modules changed')) + modules_changed_cmd = [] + for module_changed in modules_changed: + modules_changed_cmd.extend([ + '--path', + module_changed, + ]) + pr_errors = run_pylint.main([ + "--config-file=" + pylint_rcfile_pr, + ] + modules_changed_cmd + extra_params_cmd, standalone_mode=False) + if pr_errors: + print(travis_helpers.yellow( + "Found {pr_errors} errors".format(pr_errors=pr_errors) + + " in modules changed." + "\nThese checks are still in beta:" + " they won't affect your build status for now." + )) + pr_errors = 0 + # TODO: Enable next code when change of beta to stable version + # if pr_errors < 0: + # count_errors = pr_errors + # else: + # count_errors += pr_errors else: # TODO: Add git hook case in other PR pass - expected_errors = int( os.environ.get('PYLINT_EXPECTED_ERRORS', 0))