├── test_repo ├── broken_module │ ├── xml_empty.xml │ ├── report │ │ ├── manual.xml │ │ └── test_report.xml │ ├── xml_semi_empty.po │ ├── xml_wo_header.xml │ ├── coding_latin.py │ ├── encoding_utf8.py │ ├── tests │ │ ├── __init__.py │ │ ├── xml_not_important.xml │ │ ├── xml_not_important_0.xml │ │ ├── xml_not_important_1.xml │ │ ├── xml_not_important_4.xml │ │ ├── xml_not_important_3.xml │ │ └── test_model.py │ ├── xml_syntax_error.XML │ ├── doc │ │ └── index.rst │ ├── rst_syntax.rst │ ├── wointerpreter_wx.py │ ├── xml_special_char.xml │ ├── interpreter_wx.py │ ├── models │ │ ├── __init__.py │ │ ├── model_inhe1.py │ │ └── model_inhe2.py │ ├── skip_file_no_used.xml │ ├── skip_file_not_used.xml │ ├── __init__.py │ ├── interpreter_wox.py │ ├── lib │ │ ├── tab_no_check.js │ │ └── broken_example.js │ ├── skip_xml_check_2.xml │ ├── broken_example2.js │ ├── broken_example.js │ ├── report.xml │ ├── deprecated_disable.xml │ ├── demo │ │ └── duplicated_id_demo.xml │ ├── skip_xml_check.xml │ ├── i18n │ │ ├── broken_module.pot │ │ ├── es.po │ │ └── ar_unicode.po │ ├── ir.model.access.csv │ ├── i18n_extra │ │ └── es.po │ ├── skip_xml_check_3.xml │ ├── template1_disable.xml │ ├── model_view.xml │ ├── __openerp__.py │ ├── template1_copy.xml │ ├── template1_copy2.xml │ ├── template1.xml │ ├── model_view_odoo.xml │ ├── pylint_oca_broken.py │ ├── model_view2.xml │ └── model_view_odoo2.xml ├── broken_module3 │ ├── __init__.py │ ├── README.rst │ ├── __openerp__.py │ └── ir.model.access.csv ├── manifest_werror │ ├── __init__.py │ └── __manifest__.py ├── odoo18_module │ ├── __init__.py │ ├── __manifest__.py │ └── views │ │ └── deprecated_chatter.xml ├── woversion_module │ ├── __init__.py │ └── __manifest__.py ├── pylint_deprecated_modules │ ├── ipdb.py │ ├── pdb.py │ ├── pudb.py │ ├── __init__.py │ ├── openerp │ │ ├── osv │ │ │ └── __init__.py │ │ └── __init__.py │ └── README.md ├── syntax_err_module │ ├── __init__.py │ ├── ir.model.access.csv │ ├── __manifest__.py │ └── i18n │ │ └── es.po ├── woinit_module │ ├── __manifest__.py │ ├── ir.model.access.csv │ └── doc │ │ └── index.rst ├── womanifest_module │ ├── ir.model.access.csv │ ├── __init__.py │ └── doc │ │ └── index.rst ├── test_module │ ├── samples │ │ └── my_no_odoo_file.csv │ ├── __init__.py │ ├── static │ │ └── src │ │ │ └── xml │ │ │ └── widget.xml │ ├── absolute_import.py │ ├── test_example.js │ ├── README.rst │ ├── migrations │ │ └── 10.0.1.0.0 │ │ │ └── pre-migration.py │ ├── osv_expression.py │ ├── res_users.xml │ ├── i18n_extra │ │ └── fr.po │ ├── __openerp__.py │ ├── security │ │ └── ir.model.access.csv │ ├── model_view.xml │ ├── except_pass.py │ ├── website_templates_disable.xml │ ├── website_templates.xml │ └── i18n │ │ └── fr.po ├── broken_module2 │ ├── i18n │ │ └── en.po │ ├── __init__.py │ ├── tests │ │ └── data │ │ │ ├── help_test_data.xml │ │ │ ├── odoo_data_noupdate_0.xml │ │ │ └── odoo_data_noupdate_1.xml │ ├── __openerp__.py │ ├── README.rst │ └── ir.model.access.csv ├── eleven_module │ ├── README.rst │ ├── tests │ │ ├── __init__.py │ │ └── test_model1.py │ ├── __init__.py │ ├── utf8_models.py │ ├── migrations │ │ └── 11.0.1.0.0 │ │ │ └── not_used_from_manifest.xml │ ├── __manifest__.py │ ├── models.py │ ├── security │ │ └── ir.model.access.csv │ └── i18n │ │ ├── pretty.po │ │ ├── ugly.po │ │ └── autofixed_ugly.po ├── twelve_module │ ├── README.rst │ ├── __init__.py │ ├── models.py │ ├── utf8_models.py │ ├── __manifest__.py │ └── security │ │ └── ir.model.access.csv └── no_odoo_module │ ├── __init__.py │ ├── myfile.py │ └── eval_used.py ├── src └── oca_pre_commit_hooks │ ├── __init__.py │ ├── checks_odoo_module_fixit │ ├── __init__.py │ ├── manifest_superfluous_key_rule.py │ └── prefer_env_translation.py │ ├── __main__.py │ ├── checks_odoo_module_fixit_common.py │ ├── cli_po.py │ ├── cli.py │ ├── checks_odoo_module_csv.py │ ├── base_checker.py │ ├── global_parser.py │ └── utils.py ├── tests ├── __init__.py ├── test_fixit.py ├── test_profiling.py ├── test_pre_commit_hook.py ├── test_checks_po.py ├── test_checks.py └── common.py ├── docs ├── conf.py ├── messages │ ├── xml │ │ ├── index.rst │ │ └── oe-structure-missing-id.rst │ └── index.rst ├── index.rst └── dev.md ├── pyproject.toml ├── requirements.txt ├── test-requirements.txt ├── .prettierrc.yml ├── .isort.cfg ├── .coveragerc ├── .flake8 ├── .editorconfig ├── .bumpversion.cfg ├── .pre-commit-hooks.yaml ├── .gitignore ├── .pylintrc ├── pytest.ini ├── tox.ini ├── .github └── workflows │ ├── stale.yml │ └── test.yml ├── .pre-commit-config.yaml ├── setup.py └── .eslintrc.yml /test_repo/broken_module/xml_empty.xml: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test_repo/broken_module3/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test_repo/manifest_werror/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test_repo/odoo18_module/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test_repo/woversion_module/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test_repo/broken_module/report/manual.xml: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test_repo/pylint_deprecated_modules/ipdb.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test_repo/pylint_deprecated_modules/pdb.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test_repo/pylint_deprecated_modules/pudb.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test_repo/syntax_err_module/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test_repo/woinit_module/__manifest__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test_repo/woinit_module/ir.model.access.csv: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test_repo/broken_module/xml_semi_empty.po: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /test_repo/manifest_werror/__manifest__.py: -------------------------------------------------------------------------------- 1 | error -------------------------------------------------------------------------------- /test_repo/pylint_deprecated_modules/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test_repo/womanifest_module/ir.model.access.csv: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test_repo/test_module/samples/my_no_odoo_file.csv: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test_repo/broken_module2/i18n/en.po: -------------------------------------------------------------------------------- 1 | PO syntax error 2 | -------------------------------------------------------------------------------- /src/oca_pre_commit_hooks/__init__.py: -------------------------------------------------------------------------------- 1 | __version__ = "0.2.2" 2 | -------------------------------------------------------------------------------- /test_repo/pylint_deprecated_modules/openerp/osv/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test_repo/broken_module/xml_wo_header.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /test_repo/test_module/__init__.py: -------------------------------------------------------------------------------- 1 | from . import osv_expression 2 | -------------------------------------------------------------------------------- /test_repo/womanifest_module/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | -------------------------------------------------------------------------------- /test_repo/broken_module/coding_latin.py: -------------------------------------------------------------------------------- 1 | # -*- coding: latin-1 -*- 2 | -------------------------------------------------------------------------------- /test_repo/broken_module/encoding_utf8.py: -------------------------------------------------------------------------------- 1 | # -*- encoding: utf-8 -*- 2 | -------------------------------------------------------------------------------- /test_repo/broken_module/tests/__init__.py: -------------------------------------------------------------------------------- 1 | from . import test_model 2 | -------------------------------------------------------------------------------- /test_repo/eleven_module/README.rst: -------------------------------------------------------------------------------- 1 | # Eleven module module for tests 2 | -------------------------------------------------------------------------------- /test_repo/twelve_module/README.rst: -------------------------------------------------------------------------------- 1 | # Eleven module module for tests 2 | -------------------------------------------------------------------------------- /tests/__init__.py: -------------------------------------------------------------------------------- 1 | from . import common 2 | from . import test_fixit 3 | -------------------------------------------------------------------------------- /test_repo/eleven_module/tests/__init__.py: -------------------------------------------------------------------------------- 1 | 2 | from . import test_model1 3 | -------------------------------------------------------------------------------- /test_repo/broken_module2/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | from . import tests 4 | -------------------------------------------------------------------------------- /test_repo/no_odoo_module/__init__.py: -------------------------------------------------------------------------------- 1 | from . import myfile 2 | from . import eval_used 3 | -------------------------------------------------------------------------------- /test_repo/twelve_module/__init__.py: -------------------------------------------------------------------------------- 1 | from . import models 2 | from . import utf8_models 3 | -------------------------------------------------------------------------------- /docs/conf.py: -------------------------------------------------------------------------------- 1 | # pylint: skip-file 2 | project = "Odoo Hooks Documentation" 3 | root_doc = "index" 4 | -------------------------------------------------------------------------------- /test_repo/broken_module/xml_syntax_error.XML: -------------------------------------------------------------------------------- 1 | 2 | <{xml-syntax-error}> -------------------------------------------------------------------------------- /test_repo/woinit_module/doc/index.rst: -------------------------------------------------------------------------------- 1 | Module broken 2 | =============== 3 | `````````` 4 | syntax error 5 | -------------------------------------------------------------------------------- /docs/messages/xml/index.rst: -------------------------------------------------------------------------------- 1 | XML Messages 2 | ############ 3 | 4 | .. toctree:: 5 | :glob: 6 | 7 | * 8 | -------------------------------------------------------------------------------- /test_repo/broken_module/report/test_report.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /test_repo/womanifest_module/doc/index.rst: -------------------------------------------------------------------------------- 1 | Module broken 2 | =============== 3 | `````````` 4 | syntax error 5 | -------------------------------------------------------------------------------- /test_repo/broken_module/tests/xml_not_important.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /test_repo/test_module/static/src/xml/widget.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /test_repo/broken_module/doc/index.rst: -------------------------------------------------------------------------------- 1 | Module broken 2 | ====================== 3 | 4 | 5 | `````````` 6 | syntax error 7 | -------------------------------------------------------------------------------- /test_repo/broken_module/rst_syntax.rst: -------------------------------------------------------------------------------- 1 | Module broken 2 | ====================== 3 | 4 | 5 | `````````` 6 | syntax error 7 | -------------------------------------------------------------------------------- /test_repo/broken_module3/README.rst: -------------------------------------------------------------------------------- 1 | Test module 3 2 | ============= 3 | 4 | This module was written to check the test lint 5 | -------------------------------------------------------------------------------- /test_repo/eleven_module/__init__.py: -------------------------------------------------------------------------------- 1 | from . import models 2 | from . import utf8_models 3 | from .tests import test_model1 4 | -------------------------------------------------------------------------------- /test_repo/broken_module/tests/xml_not_important_0.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /test_repo/broken_module/tests/xml_not_important_1.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /test_repo/twelve_module/models.py: -------------------------------------------------------------------------------- 1 | from odoo import models 2 | 3 | 4 | class TwelveModel(models.Model): 5 | _name = 'twelve.model' 6 | -------------------------------------------------------------------------------- /test_repo/broken_module/tests/xml_not_important_4.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /test_repo/pylint_deprecated_modules/openerp/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | from . import osv # pylint: disable=W0402 4 | _ = str 5 | -------------------------------------------------------------------------------- /src/oca_pre_commit_hooks/checks_odoo_module_fixit/__init__.py: -------------------------------------------------------------------------------- 1 | from . import manifest_superfluous_key_rule 2 | from . import prefer_env_translation 3 | -------------------------------------------------------------------------------- /test_repo/broken_module/wointerpreter_wx.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | 4 | "Module python without interpreter but with execute permission." 5 | -------------------------------------------------------------------------------- /test_repo/broken_module/xml_special_char.xml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OCA/odoo-pre-commit-hooks/HEAD/test_repo/broken_module/xml_special_char.xml -------------------------------------------------------------------------------- /test_repo/broken_module2/tests/data/help_test_data.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /test_repo/no_odoo_module/myfile.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | import other_package 3 | 4 | if __name__ == '__main__': 5 | var = other_package 6 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.black] 2 | line-length=119 3 | 4 | [build-system] 5 | requires = ["setuptools >=42"] 6 | build-backend = "setuptools.build_meta" 7 | -------------------------------------------------------------------------------- /test_repo/broken_module/interpreter_wx.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # !/usr/bin/python 3 | 4 | "Module python with interpreter and execute permission." 5 | -------------------------------------------------------------------------------- /test_repo/broken_module/models/__init__.py: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | 3 | from . import broken_model 4 | from . import model_inhe1 5 | from . import model_inhe2 6 | -------------------------------------------------------------------------------- /test_repo/broken_module/skip_file_no_used.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /test_repo/broken_module/skip_file_not_used.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /test_repo/syntax_err_module/ir.model.access.csv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OCA/odoo-pre-commit-hooks/HEAD/test_repo/syntax_err_module/ir.model.access.csv -------------------------------------------------------------------------------- /test_repo/test_module/absolute_import.py: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | try: 3 | import uninstalled_module 4 | except ImportError: 5 | uninstalled_module = None 6 | -------------------------------------------------------------------------------- /test_repo/broken_module/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | from . import models 4 | from .models import broken_model 5 | from .tests import test_model 6 | -------------------------------------------------------------------------------- /test_repo/eleven_module/utf8_models.py: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | 3 | from odoo import models 4 | 5 | 6 | class EleveModel(models.Model): 7 | _name = 'eleve.model' 8 | -------------------------------------------------------------------------------- /test_repo/broken_module/interpreter_wox.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | 4 | 5 | "Module python with interpreter but without execute permission." 6 | -------------------------------------------------------------------------------- /test_repo/broken_module/lib/tab_no_check.js: -------------------------------------------------------------------------------- 1 | $(document).ready(function () { 2 | $('.example').each(function () { 3 | var oe_website_sale = this; 4 | }); 5 | }); 6 | -------------------------------------------------------------------------------- /test_repo/broken_module2/tests/data/odoo_data_noupdate_0.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /test_repo/twelve_module/utf8_models.py: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | 3 | from odoo import models 4 | 5 | 6 | class TwelveModel(models.Model): 7 | _name = 'twelve.model' 8 | -------------------------------------------------------------------------------- /test_repo/test_module/test_example.js: -------------------------------------------------------------------------------- 1 | $(document).ready(function () { 2 | $('.example').each(function () { 3 | var oe_website_sale = this; 4 | }); 5 | }); 6 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | colorama 2 | fixit @ git+https://github.com/Instagram/Fixit.git@ab5dea2 # py autofixes 3 | lxml>=4.2.3 # xml checks 4 | packaging 5 | polib==1.2.* # po checks 6 | -------------------------------------------------------------------------------- /test-requirements.txt: -------------------------------------------------------------------------------- 1 | build 2 | bump2version 3 | coverage 4 | pbr 5 | pre-commit 6 | pytest 7 | pytest-cov 8 | pytest-xdist 9 | tox 10 | twine 11 | wheel 12 | setuptools >=42 13 | -------------------------------------------------------------------------------- /test_repo/broken_module/skip_xml_check_2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /test_repo/broken_module2/tests/data/odoo_data_noupdate_1.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /test_repo/broken_module/lib/broken_example.js: -------------------------------------------------------------------------------- 1 | $(document).ready(function () { 2 | $('.example').each(function () { 3 | var oe_website_sale = this; 4 | }) /*missing semicolon*/ 5 | }) /*missing semicolon*/ 6 | -------------------------------------------------------------------------------- /test_repo/broken_module/tests/xml_not_important_3.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /test_repo/pylint_deprecated_modules/README.md: -------------------------------------------------------------------------------- 1 | Pylint has next issue: 2 | 3 | https://bitbucket.org/logilab/pylint/issues/362/bug-w0402-not-show-fails-if-module-not-is 4 | 5 | This folder add all packages deprecated to show the error. 6 | -------------------------------------------------------------------------------- /docs/messages/index.rst: -------------------------------------------------------------------------------- 1 | Messages 2 | ######## 3 | Most hooks provide messages with all the data required to fix the offending code. Messages which grant 4 | a deeper explanation are found here. 5 | 6 | .. toctree:: 7 | 8 | xml/index.rst 9 | -------------------------------------------------------------------------------- /test_repo/broken_module/broken_example2.js: -------------------------------------------------------------------------------- 1 | /*Use of "+function" instead of "Number(function" */ 2 | +function ($) { 3 | 'use strict'; 4 | var var_1 = "value1"; 5 | var var_2 = "value2"; 6 | }; 7 | /* Newline required at end of file but not found */ -------------------------------------------------------------------------------- /test_repo/woversion_module/__manifest__.py: -------------------------------------------------------------------------------- 1 | { 2 | 'name': 'Manifest without version', 3 | 'license': 'AGPL-3', 4 | 'author': 'Odoo Community Association (OCA)', 5 | 'depends': [ 6 | 'base', 7 | ], 8 | 'data': [], 9 | } 10 | -------------------------------------------------------------------------------- /test_repo/syntax_err_module/__manifest__.py: -------------------------------------------------------------------------------- 1 | { 2 | 'name': 'Syntax error module', 3 | 'version': '16.0.1.0.0', 4 | 'website': 'https://odoo-community.org', 5 | 'depends': ['base'], 6 | 'data': [ 7 | 'ir.model.access.csv', 8 | ], 9 | } 10 | -------------------------------------------------------------------------------- /.prettierrc.yml: -------------------------------------------------------------------------------- 1 | # Defaults for all prettier-supported languages. 2 | # Prettier will complete this with settings from .editorconfig file. 3 | bracketSpacing: false 4 | printWidth: 119 5 | proseWrap: always 6 | semi: true 7 | trailingComma: "es5" 8 | xmlWhitespaceSensitivity: "strict" 9 | -------------------------------------------------------------------------------- /test_repo/eleven_module/migrations/11.0.1.0.0/not_used_from_manifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | -------------------------------------------------------------------------------- /test_repo/broken_module/broken_example.js: -------------------------------------------------------------------------------- 1 | $(document).ready(function () { 2 | $('.example').each(function () { 3 | var oe_website_sale = this; 4 | }) /*missing semicolon*/ 5 | /*Use of console log*/ 6 | console.log("This is similar to a print"); 7 | }) /*missing semicolon*/ 8 | -------------------------------------------------------------------------------- /test_repo/broken_module/report.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 10 | 11 | -------------------------------------------------------------------------------- /test_repo/odoo18_module/__manifest__.py: -------------------------------------------------------------------------------- 1 | { 2 | 'name': 'Odoo 18 Module For Tests', 3 | 'license': 'AGPL-3', 4 | 'author': 'Odoo Community Association (OCA)', 5 | 'version': '18.0.1.0.0', 6 | 'depends': [ 7 | 'base', 8 | ], 9 | 'data': [ 10 | 'views/deprecated_chatter.xml', 11 | ], 12 | } 13 | -------------------------------------------------------------------------------- /test_repo/eleven_module/__manifest__.py: -------------------------------------------------------------------------------- 1 | { 2 | 'name': 'Eleven module for tests', 3 | 'license': 'AGPL-3', 4 | 'author': u'Jesus, Odoo Community Association (OCA)', 5 | 'version': '11.0.1.0.0', 6 | 'depends': [ 7 | 'base', 8 | ], 9 | 'data': [ 10 | 'security/ir.model.access.csv', 11 | ], 12 | } 13 | -------------------------------------------------------------------------------- /test_repo/twelve_module/__manifest__.py: -------------------------------------------------------------------------------- 1 | { 2 | 'name': 'Twelve module for tests', 3 | 'license': 'AGPL-3', 4 | 'author': u'Jesus, Odoo Community Association (OCA)', 5 | 'version': '12.0.1.0.0', 6 | 'depends': [ 7 | 'base', 8 | ], 9 | 'data': [ 10 | 'security/ir.model.access.csv', 11 | ], 12 | } 13 | -------------------------------------------------------------------------------- /docs/index.rst: -------------------------------------------------------------------------------- 1 | Odoo pre-commit hooks 2 | ##################### 3 | The documentation provides in-depth information about several topics, with the section on messages perhaps being 4 | the most useful to users. It explains the rational behind more nuanced, not so obvious messages and provides tips 5 | on how to fix your code. 6 | 7 | .. toctree:: 8 | 9 | messages/index 10 | -------------------------------------------------------------------------------- /test_repo/test_module/README.rst: -------------------------------------------------------------------------------- 1 | .. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg 2 | :alt: License: AGPL-3 3 | 4 | Test module 5 | =========== 6 | 7 | This module was written to check the test of rst syntax. 8 | This is a rst file without syntax error. 9 | 10 | Pygments test 11 | 12 | .. code-block:: python 13 | 14 | if True: 15 | pass 16 | -------------------------------------------------------------------------------- /test_repo/broken_module/deprecated_disable.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | hello 6 | 7 | 8 | 9 | hello from duplicate 10 | 11 | 12 | -------------------------------------------------------------------------------- /test_repo/test_module/migrations/10.0.1.0.0/pre-migration.py: -------------------------------------------------------------------------------- 1 | from odoo import SUPERUSER_ID, api 2 | 3 | 4 | def method(cr, unused): 5 | # invalid-name cr and unused-argument unused 6 | return cr 7 | 8 | 9 | def migrate(cr, version): 10 | # suppressed invalid-name cr and unused-argument version 11 | with api.Environment.manage(): 12 | env = api.Environment(cr, SUPERUSER_ID, {}) 13 | env.ref('xmlid').unlink() 14 | -------------------------------------------------------------------------------- /.isort.cfg: -------------------------------------------------------------------------------- 1 | [settings] 2 | ; see https://github.com/psf/black 3 | multi_line_output=3 4 | include_trailing_comma=True 5 | force_grid_wrap=0 6 | combine_as_imports=True 7 | use_parentheses=True 8 | line_length=119 9 | known_odoo=odoo 10 | known_odoo_addons=odoo.addons 11 | sections=FUTURE,STDLIB,THIRDPARTY,ODOO,ODOO_ADDONS,FIRSTPARTY,LOCALFOLDER 12 | default_section=THIRDPARTY 13 | ensure_newline_before_comments = True 14 | known_local_folder = oca_pre_commit_hooks 15 | -------------------------------------------------------------------------------- /test_repo/broken_module/tests/test_model.py: -------------------------------------------------------------------------------- 1 | from odoo.tests.common import TransactionCase 2 | 3 | 4 | class TestModel(TransactionCase): 5 | def setUp(self): 6 | super(TestModel, self).setUp() 7 | 8 | def method1(self, example_var): 9 | return example_var 10 | 11 | def test_1(self): 12 | self.partner.message_post(body="Test", subtype="mail.mt_comment") 13 | self.partner.message_post("Test", subtype="mail.mt_comment") 14 | -------------------------------------------------------------------------------- /src/oca_pre_commit_hooks/__main__.py: -------------------------------------------------------------------------------- 1 | """Entrypoint module, in case you use `python -mpre_commit_vauxoo`. 2 | 3 | 4 | Why does this file exist, and why __main__? For more info, read: 5 | 6 | - https://www.python.org/dev/peps/pep-0338/ 7 | - https://docs.python.org/2/using/cmdline.html#cmdoption-m 8 | - https://docs.python.org/3/using/cmdline.html#cmdoption-m 9 | """ 10 | 11 | from oca_pre_commit_hooks.cli import main 12 | 13 | if __name__ == "__main__": 14 | main() 15 | -------------------------------------------------------------------------------- /src/oca_pre_commit_hooks/checks_odoo_module_fixit_common.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | from fixit import LintRule 4 | 5 | 6 | class Common(LintRule): 7 | def report(self, *args, **kwargs) -> None: 8 | if os.environ.get("FIXIT_AUTOFIX") != "True": 9 | # skip replacement to improve performance skipping the diff process 10 | # if autofix is not enabled 11 | kwargs["replacement"] = None 12 | return super().report(*args, **kwargs) 13 | -------------------------------------------------------------------------------- /test_repo/broken_module3/__openerp__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | { 3 | 'name': 'Broken module 3 for tests', 4 | 'license': 'AGPL-3', 5 | 'author': ['Other', 'Odoo Community Association (OCA)'], # expected string 6 | 'maintainers': 'Others, Many people', # expected a list of strings 7 | 'website': 'htt://odoo-community.com', 8 | 'version': '8.0.1.0.0foo', 9 | 'depends': ['base'], 10 | 'data': [], 11 | 'test': [], 12 | 'installable': False, 13 | } 14 | -------------------------------------------------------------------------------- /test_repo/eleven_module/models.py: -------------------------------------------------------------------------------- 1 | from odoo import models 2 | 3 | # astroid is not set as an external Python dependency in the manifest, 4 | # so all of the following imports should fail 5 | import astroid 6 | from astroid import Const 7 | from astroid import BinOp as bo 8 | 9 | 10 | class EleveModel(models.Model): 11 | _name = 'eleve.model' 12 | 13 | def method1(self): 14 | self.const = isinstance(astroid.Const, Const) 15 | self.bo = isinstance(astroid.BinOp, bo) 16 | -------------------------------------------------------------------------------- /test_repo/broken_module2/__openerp__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | { 3 | 'name': 'Broken module 2 for tests', 4 | 'license': 'unknow license', # unknow license 5 | 'author': 'Other,Odoo Community Association (OCA)', # Missing oca author 6 | 'development_status': 'InvalidDevStatus', 7 | 'website': 'https://odoo-community.org,https://odoo.com', 8 | 'version': '1.0', 9 | 'depends': ['base'], 10 | 'data': [], 11 | 'test': [], 12 | 'installable': False, 13 | } 14 | -------------------------------------------------------------------------------- /test_repo/odoo18_module/views/deprecated_chatter.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | deprecated.chatter.view 4 | random.model 5 | 6 |
7 | 8 | 9 |
10 |
11 |
12 | -------------------------------------------------------------------------------- /test_repo/broken_module3/ir.model.access.csv: -------------------------------------------------------------------------------- 1 | name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink 2 | product.product.account.user,product.model_product_product,group_account_user,1,0,0,0 3 | account.payment.term,model_account_payment_term,account.group_account_user,1,0,0,0 4 | account.account.type,model_account_account_type,account.group_account_user,1,0,0,0 5 | account.tax internal user,model_account_tax,base.group_user,1,0,0,0 6 | account.account,model_account_account,account.group_account_user,1,0,0,0 7 | -------------------------------------------------------------------------------- /test_repo/no_odoo_module/eval_used.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | 4 | def eval_from_param(param): 5 | """eval used from param""" 6 | param("c = 2") 7 | 8 | 9 | def eval_from_other(): 10 | """eval used from many ways""" 11 | my_dict = { 12 | 'my_eval': eval, # [eval-used] 13 | } 14 | my_list = [eval] # [eval-used] 15 | 16 | my_var = eval # [eval-used] 17 | # inferred case 18 | my_var('d = 3') # [eval-used] 19 | eval_from_param(eval) # [eval-used] 20 | return my_dict, my_list 21 | -------------------------------------------------------------------------------- /.coveragerc: -------------------------------------------------------------------------------- 1 | [paths] 2 | source = src 3 | 4 | [run] 5 | source = src 6 | parallel = true 7 | context = ${{COVERAGE_CONTEXT}} 8 | 9 | [report] 10 | show_missing = true 11 | precision = 2 12 | fail_under = 98 13 | omit = 14 | *__init__.py 15 | */tests/* 16 | *__main__.py 17 | 18 | # Regexes for lines to exclude from consideration 19 | exclude_lines = 20 | # Have to re-enable the standard pragma 21 | pragma: no cover 22 | # tests import the package instead 23 | if __name__ == "__main__": 24 | 25 | [html] 26 | show_contexts=True 27 | -------------------------------------------------------------------------------- /test_repo/broken_module/demo/duplicated_id_demo.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | view.model.form 7 | test.model 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /.flake8: -------------------------------------------------------------------------------- 1 | [flake8] 2 | max-line-length = 119 3 | max-complexity = 16 4 | # B = bugbear 5 | # B9 = bugbear opinionated (incl line length) 6 | select = C,E,F,W,B,B9 7 | # B036: Don't except `BaseException` unless you plan to re-raise it. (we use a lot) 8 | # B907: '...' is manually surrounded by quotes, consider using the `!r` conversion flag. (I don't care) 9 | # E203: whitespace before ':' (black behaviour) 10 | # E501: flake8 line length (covered by bugbear B950) 11 | # W503: line break before binary operator (black behaviour) 12 | ignore = B036,B907,E203,E501,W503 13 | per-file-ignores= 14 | __init__.py:F401 15 | -------------------------------------------------------------------------------- /test_repo/twelve_module/security/ir.model.access.csv: -------------------------------------------------------------------------------- 1 | name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink 2 | product.product.account.user,product.model_product_product,group_account_user,1,0,0,0 3 | account.payment.term,model_account_payment_term,account.group_account_user,1,0,0,0 4 | account.payment.term.line,model_account_payment_term_line,account.group_account_user,1,0,0,0 5 | account.account.type,model_account_account_type,account.group_account_user,1,0,0,0 6 | account.tax internal user,model_account_tax,base.group_user,1,0,0,0 7 | account.account,model_account_account,account.group_account_user,1,0,0,0 8 | -------------------------------------------------------------------------------- /test_repo/syntax_err_module/i18n/es.po: -------------------------------------------------------------------------------- 1 | msgid "" 2 | msgstr "" 3 | "Project-Id-Version: Odoo Server\n" 4 | "Report-Msgid-Bugs-To: \n" 5 | "POT-Creation-Date: 1985-04-14 17:12+0000\n" 6 | "PO-Revision-Date: 1985-04-14 02:03+0000\n" 7 | "Last-Translator: Moisés López \n" 8 | "Language-Team: \n" 9 | "MIME-Version: 1.0\n" 10 | "Content-Type: text/plain; charset=UTF-8\n" 11 | "Content-Transfer-Encoding: \n" 12 | "Plural-Forms: \n" 13 | 14 | #. module: broken_module 15 | #: model:ir.model.fields,field_description:broken_module.field_wizard_description 16 | #, python-format 17 | msgid "Branch" 18 | msgstr "syntax 19 | error" 20 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # Configuration for known file extensions 2 | [*.{css,js,json,less,md,py,rst,sass,scss,xml,yaml,yml}] 3 | charset = utf-8 4 | end_of_line = lf 5 | indent_size = 4 6 | indent_style = space 7 | insert_final_newline = true 8 | trim_trailing_whitespace = true 9 | 10 | [*.{json,yml,yaml,rst,md}] 11 | indent_size = 2 12 | 13 | # Do not configure editor for libs and autogenerated content 14 | [{*/static/{lib,src/lib}/**,*/static/description/index.html,*/readme/../README.rst}] 15 | charset = unset 16 | end_of_line = unset 17 | indent_size = unset 18 | indent_style = unset 19 | insert_final_newline = false 20 | trim_trailing_whitespace = false 21 | -------------------------------------------------------------------------------- /test_repo/broken_module/skip_xml_check.xml: -------------------------------------------------------------------------------- 1 | 3 | 5 | 6 | 7 | 8 | view.model.form80 9 | test.model 10 | 11 | 12 | view.model.form80 13 | test.model 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /test_repo/test_module/osv_expression.py: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | 3 | from __future__ import absolute_import 4 | import expression 5 | import expression as expr4 6 | import manifest_lib 7 | import openerp.osv 8 | import openerp.osv.expression 9 | 10 | from openerp.osv import expression as expr2 11 | from openerp.osv import osv as osv2 12 | from openerp.osv import osv, expression # noqa 13 | from openerp.osv import osv, expression as expr3 # noqa 14 | from openerp.osv.expression import is_operator # noqa 15 | 16 | 17 | def dummy(): 18 | return (expression, osv, osv2, expr2, openerp.osv.expression, openerp.osv, 19 | expr4, expr3, absolute_import, manifest_lib) 20 | -------------------------------------------------------------------------------- /test_repo/broken_module/models/model_inhe1.py: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | 3 | from openerp import models 4 | from .no_exists import dot_package 5 | 6 | # to tests a suppression of a import-error 7 | from odoo import tools 8 | import odoo 9 | import odoo.addons as addons 10 | from odoo.addons.module.models import partner 11 | 12 | import no_exists 13 | from no_exists import package 14 | 15 | 16 | class TestModel(models.Model): 17 | _inherit = 'res.company' 18 | 19 | def method(self): 20 | return (tools, odoo, addons, partner, no_exists, package, 21 | dot_package) 22 | 23 | 24 | class TestModel2(models.Model): 25 | _inherit = 'model.no.duplicated' 26 | -------------------------------------------------------------------------------- /test_repo/broken_module2/README.rst: -------------------------------------------------------------------------------- 1 | Test module 2 2 | ============= 3 | 4 | This module was written to check the test lint 5 | 6 | 7 | ******* 8 | Project 9 | ******* 10 | 11 | .. toctree:: 12 | :maxdepth: 1 13 | 14 | project/contribute 15 | project/contributors 16 | project/license 17 | project/changes 18 | project/roadmap 19 | 20 | ***************** 21 | Developer's guide 22 | ***************** 23 | 24 | .. toctree:: 25 | :maxdepth: 2 26 | 27 | guides/concepts.rst 28 | guides/code_overview.rst 29 | 30 | ****************** 31 | Indices and tables 32 | ****************** 33 | 34 | * :ref:`genindex` 35 | * :ref:`modindex` 36 | * :ref:`search` 37 | -------------------------------------------------------------------------------- /test_repo/test_module/res_users.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Moy6 7 | moylop260 8 | 9 | 10 | 11 | Admin 2 12 | admin_2 13 | 14 | 15 | 16 | 17 | 18 | 19 | change_password 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /test_repo/broken_module/i18n/broken_module.pot: -------------------------------------------------------------------------------- 1 | msgid "" 2 | msgstr "" 3 | "Project-Id-Version: Odoo Server\n" 4 | "Report-Msgid-Bugs-To: \n" 5 | "POT-Creation-Date: 1985-04-14 17:12+0000\n" 6 | "PO-Revision-Date: 1985-04-14 02:03+0000\n" 7 | "Last-Translator: Moisés López \n" 8 | "Language-Team: \n" 9 | "MIME-Version: 1.0\n" 10 | "Content-Type: text/plain; charset=UTF-8\n" 11 | "Content-Transfer-Encoding: \n" 12 | "Plural-Forms: \n" 13 | 14 | # Missing module: comment 15 | #: model:ir.model.fields,field_description:broken_module.field_description 16 | #: model:ir.model.fields,field_description:broken_module.field_wizard_description 17 | #, python-format 18 | msgid "Branch" 19 | msgstr "" 20 | -------------------------------------------------------------------------------- /test_repo/test_module/i18n_extra/fr.po: -------------------------------------------------------------------------------- 1 | # Translation of Odoo Server. 2 | msgid "" 3 | msgstr "" 4 | "Project-Id-Version: Odoo Server\n" 5 | "Report-Msgid-Bugs-To: \n" 6 | "POT-Creation-Date: 1985-04-14 17:12+0000\n" 7 | "PO-Revision-Date: 1985-04-14 02:03+0000\n" 8 | "Last-Translator: Moisés López \n" 9 | "Language-Team: \n" 10 | "MIME-Version: 1.0\n" 11 | "Content-Type: text/plain; charset=UTF-8\n" 12 | "Content-Transfer-Encoding: \n" 13 | "Plural-Forms: \n" 14 | 15 | #. module: test_module 16 | #: model:ir.model.fields,field_description:test_module.field_description 17 | #, python-format 18 | msgid "same msgid msgstr allowed for i18n_extra" 19 | msgstr "same msgid msgstr allowed for i18n_extra" 20 | -------------------------------------------------------------------------------- /test_repo/test_module/__openerp__.py: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | { 3 | 'name': 'Empty module for tests', 4 | 'license': 'AGPL-3', 5 | 'author': u'Moisés, Odoo Community Association (OCA), author2', 6 | 'version': '10.0.1.0.0', 7 | 'depends': [ 8 | 'base', 9 | ], 10 | 'data': [ 11 | 'security/ir.model.access.csv', 12 | 'res_users.xml', 13 | 'model_view.xml', 14 | 'model_view.xml', 15 | 'website_templates.xml', 16 | 'website_templates_disable.xml', 17 | ], 18 | 'external_dependencies': { 19 | 'bin': [ 20 | 'sh', 21 | ], 22 | 'python': [ 23 | 'os', 24 | 'manifest_lib', 25 | ], 26 | }, 27 | } 28 | -------------------------------------------------------------------------------- /test_repo/eleven_module/tests/test_model1.py: -------------------------------------------------------------------------------- 1 | 2 | from odoo.tests.common import TransactionCase 3 | from odoo.addons.eleven_module.models import EleveModel 4 | from .no_exists import package 5 | 6 | # Even though astroid is not set as an external dependency, it should not fail, 7 | # because this is a test file 8 | import astroid 9 | from astroid import Const 10 | from astroid import BinOp as bo 11 | 12 | 13 | class TestModel(TransactionCase): 14 | def setUp(self): 15 | super(TestModel, self).setUp() 16 | self.const = isinstance(astroid.Const, Const) 17 | self.bo = isinstance(astroid.BinOp, bo) 18 | 19 | def method(self): 20 | return package 21 | 22 | def methodModel(self): 23 | return EleveModel 24 | -------------------------------------------------------------------------------- /test_repo/broken_module/ir.model.access.csv: -------------------------------------------------------------------------------- 1 | id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink 2 | access_product_product_account_user,product.product.account.user,product.model_product_product,group_account_user,1,0,0,0 3 | access_account_payment_term,account.payment.term,model_account_payment_term,account.group_account_user,1,0,0,0 4 | access_account_payment_term_line,account.payment.term.line,model_account_payment_term_line,account.group_account_user,1,0,0,0 5 | access_account_account_type,account.account.type,model_account_account_type,account.group_account_user,1,0,0,0 6 | access_account_account_type,account.tax internal user,model_account_tax,base.group_user,1,0,0,0 7 | access_account_account,account.account,model_account_account,account.group_account_user,1,0,0,0 8 | -------------------------------------------------------------------------------- /test_repo/broken_module2/ir.model.access.csv: -------------------------------------------------------------------------------- 1 | id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink 2 | access_product_product_account_user,product.product.account.user,product.model_product_product,group_account_user,1,0,0,0 3 | access_account_payment_term,account.payment.term,model_account_payment_term,account.group_account_user,1,0,0,0 4 | access_account_payment_term_line,account.payment.term.line,model_account_payment_term_line,account.group_account_user,1,0,0,0 5 | access_account_account_tax,account.account.type,model_account_account_type,account.group_account_user,1,0,0,0 6 | access_account_account_tax,account.tax internal user,model_account_tax,base.group_user,1,0,0,0 7 | access_account_account,account.account,model_account_account,account.group_account_user,1,0,0,0 8 | -------------------------------------------------------------------------------- /test_repo/eleven_module/security/ir.model.access.csv: -------------------------------------------------------------------------------- 1 | id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink 2 | access_product_product_account_user,product.product.account.user,product.model_product_product,group_account_user,1,0,0,0 3 | access_account_payment_term,account.payment.term,model_account_payment_term,account.group_account_user,1,0,0,0 4 | access_account_payment_term_line,account.payment.term.line,model_account_payment_term_line,account.group_account_user,1,0,0,0 5 | access_account_account_type,account.account.type,model_account_account_type,account.group_account_user,1,0,0,0 6 | access_account_account_tax,account.tax internal user,model_account_tax,base.group_user,1,0,0,0 7 | access_account_account,account.account,model_account_account,account.group_account_user,1,0,0,0 8 | -------------------------------------------------------------------------------- /test_repo/test_module/security/ir.model.access.csv: -------------------------------------------------------------------------------- 1 | id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink 2 | access_product_product_account_user,product.product.account.user,product.model_product_product,group_account_user,1,0,0,0 3 | access_account_payment_term,account.payment.term,model_account_payment_term,account.group_account_user,1,0,0,0 4 | access_account_payment_term_line,account.payment.term.line,model_account_payment_term_line,account.group_account_user,1,0,0,0 5 | access_account_account_type,account.account.type,model_account_account_type,account.group_account_user,1,0,0,0 6 | access_account_account_tax,account.tax internal user,model_account_tax,base.group_user,1,0,0,0 7 | access_account_account,account.account,model_account_account,account.group_account_user,1,0,0,0 8 | -------------------------------------------------------------------------------- /.bumpversion.cfg: -------------------------------------------------------------------------------- 1 | [bumpversion] 2 | current_version = 0.2.2 3 | commit = True 4 | tag = True 5 | sign_tags = True 6 | 7 | [bumpversion:file:setup.py] 8 | search = version="{current_version}" 9 | replace = version="{new_version}" 10 | 11 | [bumpversion:file (badge):README.md] 12 | search = /v{current_version}.svg 13 | replace = /v{new_version}.svg 14 | 15 | [bumpversion:file (link):README.md] 16 | search = /v{current_version}...main 17 | replace = /v{new_version}...main 18 | 19 | [bumpversion:file (github link):README.md] 20 | search = /blob/v{current_version}/ 21 | replace = /blob/v{new_version}/ 22 | 23 | [bumpversion:file:README.md] 24 | search = rev: v{current_version} 25 | replace = rev: v{new_version} 26 | 27 | [bumpversion:file:src/oca_pre_commit_hooks/__init__.py] 28 | search = __version__ = "{current_version}" 29 | replace = __version__ = "{new_version}" 30 | -------------------------------------------------------------------------------- /test_repo/broken_module/i18n_extra/es.po: -------------------------------------------------------------------------------- 1 | # 2 | msgid "" 3 | msgstr "" 4 | "Project-Id-Version: Odoo Server\n" 5 | "Report-Msgid-Bugs-To: \n" 6 | "POT-Creation-Date: 1985-04-14 17:12+0000\n" 7 | "PO-Revision-Date: 1985-04-14 02:03+0000\n" 8 | "Last-Translator: Moisés López \n" 9 | "Language-Team: \n" 10 | "MIME-Version: 1.0\n" 11 | "Content-Type: text/plain; charset=UTF-8\n" 12 | "Content-Transfer-Encoding: \n" 13 | "Plural-Forms: \n" 14 | 15 | #. module: broken_module 16 | #: model:ir.model.fields,field_description5:broken_module.field_wizard_description5 17 | #, python-format 18 | msgid "'Duplicate PO message definition' ignored for i18n_extra" 19 | msgstr "'translation' 1" 20 | 21 | #. module: broken_module 22 | #: model:ir.model.fields,field_description10:broken_module.field_wizard_description10 23 | #, python-format 24 | msgid "'Duplicate PO message definition' ignored for i18n_extra" 25 | msgstr "'translation' 2" 26 | -------------------------------------------------------------------------------- /test_repo/test_module/model_view.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | view.model.form 7 | test.model 8 | 9 |
10 | 11 | 12 |
13 |
14 | 15 | 16 | 17 | By name 18 | test.model 19 | {'group_by': ['name']} 20 | 21 | 22 | 23 |
24 |
25 | -------------------------------------------------------------------------------- /.pre-commit-hooks.yaml: -------------------------------------------------------------------------------- 1 | # Do not use this file as example 2 | # Check the README 3 | - id: oca-checks-odoo-module 4 | name: Checks for Odoo modules 5 | description: Multiple checks for Odoo modules 6 | entry: oca-checks-odoo-module 7 | args: [] 8 | language: python 9 | types_or: ["csv", "python", "xml"] 10 | # TODO: Check if should consider uppercase extension 11 | files: \.(csv|xml)$|/\_\_(manifest|openerp)\_\_.py$ 12 | # require_serial to evaluate the whole module in-one-shot to have full context about other xmlids and so on 13 | require_serial: true 14 | - id: oca-checks-po 15 | name: Checks for .po[t] files 16 | description: Multiple checks for PO files 17 | entry: oca-checks-po 18 | args: [] 19 | language: python 20 | # Notice the "pofile" type does not consider "pot" files 21 | # The command "identify-cli file.pot" 22 | # returns "text" 23 | types_or: ["text"] 24 | files: \.(po|pot)$ 25 | require_serial: false 26 | -------------------------------------------------------------------------------- /test_repo/broken_module/skip_xml_check_3.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | view.model.form80 8 | test.model 9 | 10 | 11 | view.model.form80 12 | test.model 13 | 14 | 15 | 16 | view.model.form80 17 | test.model 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /test_repo/broken_module/template1_disable.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 11 | 17 | 18 | 21 | 22 | 25 | 26 | 29 | 30 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | /.venv 5 | /.pytest_cache 6 | 7 | # C extensions 8 | *.so 9 | 10 | # Distribution / packaging 11 | .Python 12 | env/ 13 | bin/ 14 | build/ 15 | develop-eggs/ 16 | dist/ 17 | dist_wo_pbr/ 18 | eggs/ 19 | lib64/ 20 | parts/ 21 | sdist/ 22 | var/ 23 | *.egg-info/ 24 | .installed.cfg 25 | *.egg 26 | *.eggs 27 | 28 | # Installer logs 29 | pip-log.txt 30 | pip-delete-this-directory.txt 31 | 32 | # Unit test / coverage reports 33 | htmlcov/ 34 | .tox/ 35 | .coverage 36 | .coverage\.* 37 | .coverage\_* 38 | .cache 39 | nosetests.xml 40 | coverage.xml 41 | 42 | # Translations 43 | *.mo 44 | 45 | # Pycharm 46 | .idea 47 | 48 | # Eclipse 49 | .settings 50 | 51 | # Visual Studio cache/options directory 52 | .vs/ 53 | .vscode 54 | 55 | # OSX Files 56 | .DS_Store 57 | 58 | # Django stuff: 59 | *.log 60 | 61 | # Mr Developer 62 | .mr.developer.cfg 63 | .project 64 | .pydevproject 65 | 66 | # Rope 67 | .ropeproject 68 | 69 | # Sphinx documentation 70 | docs/_build/ 71 | 72 | # Backup files 73 | *~ 74 | *.swp 75 | 76 | # OCA rules 77 | !static/lib/ 78 | 79 | # Auto-generated 80 | ChangeLog 81 | .pre-commit-config-local.yaml 82 | -------------------------------------------------------------------------------- /src/oca_pre_commit_hooks/cli_po.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | """Module that contains the command line app. 3 | Why does this file exist, and why not put this in __main__? 4 | You might be tempted to import things from __main__ later, but that will cause 5 | problems: the code will get executed twice: 6 | - When you run `python -mpre_commit_vauxoo` python will execute 7 | ``__main__.py`` as a script. That means there won't be any 8 | ``pre_commit_vauxoo.__main__`` in ``sys.modules``. 9 | - When you import __main__ it will get executed again (as a module) because 10 | there's no ``pre_commit_vauxoo.__main__`` in ``sys.modules``. 11 | Also see (1) from http://click.pocoo.org/5/setuptools/#setuptools-integration 12 | """ 13 | import sys 14 | 15 | from oca_pre_commit_hooks import checks_odoo_module_po 16 | from oca_pre_commit_hooks.global_parser import GlobalParser 17 | 18 | 19 | def main(argv=None): 20 | parser = GlobalParser() 21 | parser.add_argument( 22 | "po_files", 23 | nargs="*", 24 | help="PO files.", 25 | ) 26 | if argv is None: 27 | argv = sys.argv[1:] 28 | kwargs = vars(parser.parse_args(argv)) 29 | return checks_odoo_module_po.main(**kwargs) 30 | 31 | 32 | if __name__ == "__main__": 33 | main() 34 | -------------------------------------------------------------------------------- /src/oca_pre_commit_hooks/cli.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | """Module that contains the command line app. 3 | Why does this file exist, and why not put this in __main__? 4 | You might be tempted to import things from __main__ later, but that will cause 5 | problems: the code will get executed twice: 6 | - When you run `python -mpre_commit_vauxoo` python will execute 7 | ``__main__.py`` as a script. That means there won't be any 8 | ``pre_commit_vauxoo.__main__`` in ``sys.modules``. 9 | - When you import __main__ it will get executed again (as a module) because 10 | there's no ``pre_commit_vauxoo.__main__`` in ``sys.modules``. 11 | Also see (1) from http://click.pocoo.org/5/setuptools/#setuptools-integration 12 | """ 13 | 14 | import sys 15 | 16 | from oca_pre_commit_hooks import checks_odoo_module 17 | from oca_pre_commit_hooks.global_parser import GlobalParser 18 | 19 | 20 | def main(argv=None): 21 | parser = GlobalParser() 22 | parser.add_argument( 23 | "files_or_modules", 24 | nargs="*", 25 | help="Odoo __manifest__.py paths or Odoo module paths.", 26 | ) 27 | if argv is None: 28 | argv = sys.argv[1:] 29 | kwargs = vars(parser.parse_args(argv)) 30 | return checks_odoo_module.main(**kwargs) 31 | 32 | 33 | if __name__ == "__main__": 34 | main() 35 | -------------------------------------------------------------------------------- /test_repo/broken_module/model_view.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | view.model.form 7 | test.model 8 | 9 |
10 | 11 | 12 | o.value 13 | 14 | 15 | o.value 16 | 17 |
18 | 19 | 20 |
21 | 22 |
23 |
24 | 25 | 26 | 27 | 28 | 29 |
30 |
31 | -------------------------------------------------------------------------------- /test_repo/broken_module/__openerp__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | { 3 | 'name': 'Broken module for tests', 4 | # missing license 5 | 'author': 'Vauxoo, Many People', # Missing oca author 6 | 'development_status': 'Alpha', 7 | 'description': 'Should be a README.rst file', 8 | 'version': '8_0.1.0.0', 9 | 'website': 'https://odoo-community.org', 10 | 'depends': ['base'], 11 | 'qweb': ['template1.xml', '*emplate1_copy2.xml'], 12 | 'assets': { 13 | 'point_of_sale.assets': [ 14 | 'broken_module/*emplate1_copy.xml', 15 | ], 16 | }, 17 | 'data': [ 18 | 'model_view.xml', 'model_view2.xml', 'model_view_odoo.xml', 19 | 'model_view_odoo2.xml', 20 | 'deprecated_disable.xml', 21 | 'file_no_exist.xml', 22 | 'skip_xml_check.xml', 23 | 'skip_xml_check_2.xml', 24 | 'skip_xml_check_3.xml', 25 | 'report.xml', 26 | 'template1_disable.xml', 27 | 'ir.model.access.csv', 28 | 'xml_wo_header.xml', 29 | ], 30 | 'demo': ['demo/duplicated_id_demo.xml', 'file_no_exist.xml'], 31 | 'test': ['file_no_exist.yml'], 32 | 'installable': True, 33 | 'name': 'Duplicated value', 34 | 'active': True, # Deprecated active key 35 | "oca_data_manual": ["report/manual.xml"], # Custom OCA key to disable file-not-used 36 | } 37 | -------------------------------------------------------------------------------- /test_repo/broken_module/models/model_inhe2.py: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | 3 | from openerp import models 4 | 5 | 6 | class TestModel(models.Model): 7 | _inherit = 'res.company' 8 | 9 | 10 | class TestModel2(models.Model): 11 | _inherit = 'res.company' 12 | 13 | 14 | class TestModel3(models.Model): 15 | _inherit = 'res.partner' 16 | 17 | 18 | class TestModel4(models.Model): 19 | _inherit = 'res.partner' 20 | 21 | 22 | class TestModel41(models.Model): 23 | _name = 'res.partner' 24 | _inherit = 'res.partner' 25 | 26 | 27 | class TestModel5(models.Model): 28 | _inherit = 'valid.duplicated' # pylint: disable=R7980 29 | 30 | 31 | class TestModel6(models.Model): 32 | _inherit = 'valid.duplicated' 33 | 34 | 35 | class TestModel7(models.Model): 36 | _name = 'valid.duplicated.2' 37 | _inherit = 'valid.duplicated' 38 | 39 | 40 | class TestModel8(models.Model): 41 | _inherit = ['valid.duplicated', 'valid.duplicated2'] 42 | 43 | def method_1(self): 44 | _inherit = 'not-class-attribute' 45 | return _inherit 46 | 47 | def method_2(self): 48 | _inherit = 'not-class-attribute' 49 | return _inherit 50 | 51 | 52 | class TestModel9(models.Model): 53 | _inherit = 'res.user' 54 | 55 | 56 | class TestModel10(models.Model): 57 | _inherit = 'res.user' 58 | _name = 'my.inherited.user' 59 | -------------------------------------------------------------------------------- /test_repo/broken_module/template1_copy.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 9 | 10 | 16 | 17 | 20 | 21 | 24 | 25 | 28 | 29 | 30 | 31 | 32 |
33 | New Value 34 |
35 |
36 |
37 |
38 | 39 |
40 | -------------------------------------------------------------------------------- /test_repo/broken_module/template1_copy2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 9 | 10 | 16 | 17 | 20 | 21 | 24 | 25 | 28 | 29 | 30 | 31 | 32 |
33 | New Value 34 |
35 |
36 |
37 |
38 | 39 |
40 | -------------------------------------------------------------------------------- /test_repo/broken_module/template1.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 9 | 10 | 16 | 17 | 20 | 21 | 24 | 25 | 28 | 29 | 32 | 33 | 36 | 37 | 38 | 39 | 40 |
41 | New Value 42 |
43 |
44 |
45 |
46 | 47 |
48 | -------------------------------------------------------------------------------- /tests/test_fixit.py: -------------------------------------------------------------------------------- 1 | import os 2 | import unittest 3 | from pathlib import Path 4 | 5 | from fixit.config import collect_rules, parse_rule 6 | from fixit.ftypes import Config 7 | from fixit.testing import generate_lint_rule_test_cases 8 | 9 | from oca_pre_commit_hooks import checks_odoo_module_fixit 10 | 11 | 12 | class FixitTest(unittest.TestCase): 13 | def test_fixit(self): 14 | """Run 'fixit test' based on fixit.cli.test method""" 15 | os.environ["FIXIT_ODOO_VERSION"] = "18.0" 16 | os.environ["FIXIT_AUTOFIX"] = "True" 17 | 18 | rule = parse_rule( 19 | ".checks_odoo_module_fixit", 20 | Path(os.path.dirname(os.path.dirname(os.path.abspath(checks_odoo_module_fixit.__file__)))), 21 | ) 22 | lint_rules = collect_rules(Config(enable=[rule], disable=[], python_version=None)) 23 | test_cases = generate_lint_rule_test_cases(lint_rules) 24 | print("") 25 | for test_case_class in test_cases: 26 | with self.subTest(rule_class=test_case_class.__name__): 27 | suite = unittest.defaultTestLoader.loadTestsFromTestCase(test_case_class) 28 | for test in suite: 29 | test_result = unittest.TestResult() 30 | test.run(test_result) 31 | if test_result.failures or test_result.errors: 32 | print(f"❌ Failed: {test.id()}") 33 | for _fail, traceback in test_result.failures + test_result.errors: 34 | print(traceback) 35 | self.fail(f"Subtest {test.id()} failed") 36 | else: 37 | print(f"✅ Subtest {test.id()} passed") 38 | -------------------------------------------------------------------------------- /.pylintrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | [MASTER] 4 | load-plugins=pylint.extensions.docstyle, pylint.extensions.mccabe 5 | score=n 6 | 7 | [MESSAGES CONTROL] 8 | enable=all 9 | # Enable all then relax disable instead of disable all and enable one-by-one 10 | disable=c-extension-no-member, 11 | fixme, 12 | import-error, 13 | inconsistent-return-statements, 14 | line-too-long, 15 | locally-disabled, 16 | logging-too-many-args, 17 | missing-class-docstring, 18 | missing-function-docstring, 19 | missing-module-docstring, 20 | suppressed-message, 21 | too-few-public-methods, 22 | too-many-ancestors, 23 | too-many-arguments, 24 | too-many-boolean-expressions, 25 | too-many-branches, 26 | too-many-branches, 27 | too-many-format-args, 28 | too-many-function-args, 29 | too-many-instance-attributes, 30 | too-many-instance-attributes, 31 | too-many-lines, 32 | too-many-locals, 33 | too-many-locals, 34 | too-many-nested-blocks, 35 | too-many-public-methods, 36 | too-many-return-statements, 37 | too-many-star-expressions, 38 | too-many-statements, 39 | 40 | [REPORTS] 41 | msg-template={path}:{line}: [{msg_id}({symbol}), {obj}] {msg} 42 | output-format=colorized 43 | reports=no 44 | 45 | [SIMILARITIES] 46 | min-similarity-lines=14 47 | ignore-comments=yes 48 | ignore-docstrings=yes 49 | 50 | [DESIGN] 51 | # McCabe complexity cyclomatic threshold for too-complex check 52 | # Value definied from https://en.wikipedia.org/wiki/Cyclomatic_complexity 53 | # - The figure of 10 had received substantial corroborating evidence, 54 | # but that in some circumstances it may be appropriate to relax the restriction 55 | # and permit modules with a complexity as high as 15 56 | max-complexity=15 57 | -------------------------------------------------------------------------------- /pytest.ini: -------------------------------------------------------------------------------- 1 | [pytest] 2 | norecursedirs = 3 | .git 4 | .tox 5 | .env 6 | dist 7 | build 8 | migrations 9 | 10 | python_files = 11 | test_*.py 12 | *_test.py 13 | tests.py 14 | addopts = 15 | -ra 16 | --strict-markers 17 | --ignore=docs/conf.py 18 | --ignore=setup.py 19 | --ignore=ci 20 | --ignore=.eggs 21 | --doctest-modules 22 | --doctest-glob=\*.rst 23 | --tb=short 24 | --pyargs 25 | # The order of these options matters. testpaths comes after addopts so that 26 | # oca_pre_commit_hooks in testpaths is interpreted as 27 | # --pyargs oca_pre_commit_hooks. 28 | # Any tests in the src/ directory (that is, tests installed with the package) 29 | # can be run by any user with pytest --pyargs oca_pre_commit_hooks. 30 | # Packages that are sensitive to the host machine, most famously NumPy, 31 | # include tests with the installed package so that any user can check 32 | # at any time that everything is working properly. 33 | # If you do choose to make installable tests, this will run the installed 34 | # tests as they are actually installed (same principle as when we ensure that 35 | # we always test the installed version of the package). 36 | # If you have no need for this (and your src/ directory is very large), 37 | # you can save a few milliseconds on testing by telling pytest not to search 38 | # the src/ directory by removing 39 | # --pyargs and oca_pre_commit_hooks from the options here. 40 | testpaths = 41 | src/oca_pre_commit_hooks 42 | tests/ 43 | 44 | # Idea from: https://til.simonwillison.net/pytest/treat-warnings-as-errors 45 | filterwarnings = 46 | error 47 | # You can add exclusions, some examples: 48 | # ignore:'oca_pre_commit_hooks' defines default_app_config:PendingDeprecationWarning:: 49 | # ignore:The {{% if::: 50 | # ignore:Coverage disabled via --no-cov switch! 51 | -------------------------------------------------------------------------------- /test_repo/test_module/except_pass.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """Test Except Pass usage""" 3 | 4 | 5 | class TestExceptPass(object): 6 | """Test Except Pass class """ 7 | 8 | def test_method(self): 9 | try: 10 | raise Exception('Exception') 11 | except Exception: # except-pass 12 | pass 13 | 14 | def test_2_method(self): 15 | """This pass is skip for body of except has more than one line """ 16 | try: 17 | raise Exception('Exception') 18 | except Exception: 19 | pass 20 | print('Exception') 21 | 22 | def test_3_method(self): 23 | """This pass is skip for the exception is assigned""" 24 | exception = False 25 | try: 26 | raise Exception('Exception') 27 | except Exception: 28 | pass 29 | if exception: 30 | pass 31 | 32 | def test_4_method(self): 33 | userError = False 34 | try: 35 | raise Exception('Exception') 36 | except Exception: 37 | pass 38 | if userError: 39 | pass 40 | 41 | def test_5_method(self): 42 | exception = False 43 | try: 44 | raise Exception('Exception') 45 | except (Exception, IndexError): 46 | pass 47 | if exception: 48 | pass 49 | 50 | def test_6_method(self): 51 | try: 52 | raise Exception('Exception') 53 | except (Exception, IndexError): # except-pass 54 | pass 55 | 56 | def test_7_method(self): 57 | exception = False 58 | try: 59 | raise Exception('Exception') 60 | except (Exception, IndexError, NameError): 61 | pass 62 | except Exception: # except-pass 63 | pass 64 | if exception: 65 | pass 66 | -------------------------------------------------------------------------------- /test_repo/test_module/website_templates_disable.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 12 | 13 | 14 | 23 | 24 |