Skip to content

Commit

Permalink
[ADD] pylint_odoo: Add main package.
Browse files Browse the repository at this point in the history
  • Loading branch information
moylop260 committed Oct 11, 2015
1 parent 390a1ac commit df16010
Show file tree
Hide file tree
Showing 45 changed files with 1,427 additions and 0 deletions.
17 changes: 17 additions & 0 deletions .coveragerc
@@ -0,0 +1,17 @@
# Config file .coveragerc

[report]
include =
pylint_odoo/*

omit =
*/test_repo/*
*__init__.py
*__openerp__.py

# Regexes for lines to exclude from consideration
exclude_lines =
# Don't complain about self-execute
if __name__ == '__main__':
# Don't complain about uninstalled packages
except OSError as oserr:
39 changes: 39 additions & 0 deletions .travis.yml
@@ -0,0 +1,39 @@
language: python

sudo: false
cache:
apt: true
directories:
- $HOME/.cache/pip

python:
- "2.7"

addons:
apt:
packages:
- python-lxml # because pip installation is slow
- nodejs

virtualenv:
system_site_packages: true

install:
# Remove packages installed from addons-apt-packages of travis file
- find -L ${TRAVIS_BUILD_DIR} -name requirements.txt -exec sed -i '/lxml/d' {} \;
- find -L ${TRAVIS_BUILD_DIR} -name install.sh -exec sed -i '/node/d' {} \;

# Install dependencies
- ${TRAVIS_BUILD_DIR}/install.sh

# Install testing dependencies
- pip install --upgrade pyopenssl ndg-httpsclient pyasn1
- pip install coveralls flake8

script:
- flake8 --exclude=__init__.py .
- coverage run setup.py test

after_success:
- coveralls
- coverage report -m
56 changes: 56 additions & 0 deletions README.md
@@ -0,0 +1,56 @@
[![Build Status](https://travis-ci.org/OCA/pylint-odoo.svg?branch=master)](https://travis-ci.org/OCA/pylint-odoo)
[![Coverage Status](https://coveralls.io/repos/OCA/pylint-odoo/badge.svg?branch=master&service=github)](https://coveralls.io/github/OCA/pylint-odoo?branch=master)
[![Pypi Package](https://img.shields.io/pypi/v/pylint-odoo.svg)](https://pypi.python.org/pypi/pylint-odoo)



# Pylint Odoo plugin

Enable custom checks for Odoo modules.

[//]: # (checks)
Code | Description | short name
--- | --- | ---
C7902 | Missing ./README.rst file. Template here: %s | missing-readme
C8101 | Missing author required "%s" in manifest file | manifest-required-author
C8102 | Missing required key "%s" in manifest file | manifest-required-key
C8103 | Deprecated key "%s" in manifest file | manifest-deprecated-key
C8104 | Use `CamelCase` "%s" in class name "%s". You can use oca-autopep8 of https://github.com/OCA/maintainer-tools to auto fix it. | class-camelcase
C8105 | License "%s" not allowed in manifest file. | license-allowed
C8201 | No UTF-8 coding comment found: Use `# coding: utf-8` or `# -*- coding: utf-8 -*-` | no-utf8-coding-comment
E7901 | %s:%s %s | rst-syntax-error
E7902 | %s error: %s | xml-syntax-error
R8101 | Import `Warning` should be renamed as UserError `from openerp.exceptions import Warning as UserError` | openerp-exception-warning
W7901 | Dangerous filter without explicit `user_id` in xml_id %s | dangerous-filter-wo-user
W7902 | Duplicate xml record id %s | duplicate-xml-record-id
W7903 | %s | javascript-lint
W8101 | Detected api.one and api.multi decorators together. | api-one-multi-together
W8102 | Missing api.one or api.multi in copy function. | copy-wo-api-one
W8103 | Translation method _("string") in fields is not necessary. | translation-field
W8104 | api.one deprecated | api-one-deprecated
W8105 | attribute "%s" deprecated | attribute-deprecated
W8106 | Missing `super` call in "%s" method. | method-required-super
W8201 | Incoherent interpreter comment and executable permission. Interpreter: [%s] Exec perm: %s | incoherent-interpreter-exec-perm
W8202 | Use of vim comment | use-vim-comment

[//]: # (end checks)


## Install
`# pip install --upgrade git+https://github.com/oca/pylint-odoo.git`

Or

`# pip install --upgrade --pre pylint-odoo`


## Usage

`pylint --load-plugins=pylint_odoo -e odoolint ...`


Example to test just odoo-lint case:

`touch {ADDONS-PATH}/__init__.py`

`pylint --load-plugins=pylint_odoo -d all -e odoolint {ADDONS-PATH}`
4 changes: 4 additions & 0 deletions install.sh
@@ -0,0 +1,4 @@
wget -qO- https://deb.nodesource.com/setup | bash - \
&& apt-get install nodejs
npm install -g jshint
pip install .
32 changes: 32 additions & 0 deletions pylint_odoo/__init__.py
@@ -0,0 +1,32 @@

from . import checkers
from . augmentations.main import apply_augmentations


def register(linter):
"""Required method to auto register this checker"""
linter.register_checker(checkers.modules_odoo.ModuleChecker(linter))
linter.register_checker(checkers.no_modules.NoModuleChecker(linter))
linter.register_checker(checkers.format.FormatChecker(linter))

# register any checking fiddlers
apply_augmentations(linter)


def get_all_messages():
"""Get all messages of this plugin"""
all_msgs = {}
all_msgs.update(checkers.modules_odoo.ODOO_MSGS)
all_msgs.update(checkers.no_modules.ODOO_MSGS)
all_msgs.update(checkers.format.ODOO_MSGS)
return all_msgs


def messages2md():
all_msgs = get_all_messages()
md_msgs = 'Code | Description | short name\n--- | --- | ---'
for msg_code, (title, name_key, description) in \
sorted(all_msgs.iteritems()):
md_msgs += "\n{0} | {1} | {2}".format(msg_code, title, name_key)
md_msgs += '\n'
return md_msgs
1 change: 1 addition & 0 deletions pylint_odoo/augmentations/__init__.py
@@ -0,0 +1 @@
from . import main
23 changes: 23 additions & 0 deletions pylint_odoo/augmentations/main.py
@@ -0,0 +1,23 @@

import os

from pylint_plugin_utils import suppress_message
from pylint.checkers.base import BasicChecker
from .. import settings


def is_manifest_file(node):
"""Verify if the node file is a manifest file
:return: Boolean `True` if is manifest file else `False`"""
filename = os.path.basename(node.root().file)
is_manifest = filename in settings.MANIFEST_FILES
return is_manifest


def apply_augmentations(linter):
"""Apply suppression rules."""

# W0104 - pointless-statement
# manifest file have a valid pointless-statement dict
suppress_message(linter, BasicChecker.visit_discard,
'W0104', is_manifest_file)
3 changes: 3 additions & 0 deletions pylint_odoo/checkers/__init__.py
@@ -0,0 +1,3 @@
from . import modules_odoo
from . import no_modules
from . import format
87 changes: 87 additions & 0 deletions pylint_odoo/checkers/format.py
@@ -0,0 +1,87 @@

import os
import tokenize

from pylint.checkers import BaseTokenChecker
from pylint.interfaces import ITokenChecker

from .. import settings

ODOO_MSGS = {
# C->convention R->refactor W->warning E->error F->fatal

'C%d01' % settings.BASE_FORMAT_ID: (
'No UTF-8 coding comment found: '
'Use `# coding: utf-8` or `# -*- coding: utf-8 -*-`',
'no-utf8-coding-comment',
settings.DESC_DFLT
),
'W%d01' % settings.BASE_FORMAT_ID: (
'Incoherent interpreter comment and executable permission. '
'Interpreter: [%s] Exec perm: %s',
'incoherent-interpreter-exec-perm',
settings.DESC_DFLT
),
'W%d02' % settings.BASE_FORMAT_ID: (
'Use of vim comment',
'use-vim-comment',
settings.DESC_DFLT
),
}

MAGIC_COMMENT_CODING = 1
MAGIC_COMMENT_ENCODING = 2
MAGIC_COMMENT_INTERPRETER = 3
MAGIC_COMMENT_CODING_UTF8 = 4
NO_IDENTIFIED = -1


class FormatChecker(BaseTokenChecker):

# Auto call to `process_tokens` method
__implements__ = (ITokenChecker)

name = settings.CFG_SECTION
msgs = ODOO_MSGS

def get_magic_comment_type(self, comment, line_num):
if line_num >= 1 and line_num <= 2:
if "#!" == comment[:2]:
return MAGIC_COMMENT_INTERPRETER
elif "# -*- coding: " in comment or "# coding: " in comment:
if "# -*- coding: utf-8 -*-" in comment \
or "# coding: utf-8" in comment:
return MAGIC_COMMENT_CODING_UTF8
return MAGIC_COMMENT_CODING
elif "# -*- encoding: " in comment:
return MAGIC_COMMENT_ENCODING
return NO_IDENTIFIED

def is_vim_comment(self, comment):
return True if comment.strip('# ').lower().startswith('vim:') \
else False

def process_tokens(self, tokens):
tokens_identified = {}
for idx, (tok_type, token_content,
start_line_col, end_line_col,
line_content) in enumerate(tokens):
if tokenize.COMMENT == tok_type:
line_num = start_line_col[0]
magic_comment_type = self.get_magic_comment_type(
token_content, line_num)
if magic_comment_type != NO_IDENTIFIED:
tokens_identified[magic_comment_type] = [
token_content, line_num]
elif self.is_vim_comment(token_content):
self.add_message('use-vim-comment', line=line_num)
if not tokens_identified.get(MAGIC_COMMENT_CODING_UTF8) and \
not os.path.basename(self.linter.current_file) == '__init__.py':
self.add_message('no-utf8-coding-comment', line=1)
access_x = os.access(self.linter.current_file, os.X_OK)
interpreter_content, line_num = tokens_identified.get(
MAGIC_COMMENT_INTERPRETER, ['', 0])
if bool(interpreter_content) != access_x:
self.add_message(
'incoherent-interpreter-exec-perm',
line=line_num, args=(interpreter_content, access_x))

0 comments on commit df16010

Please sign in to comment.