*improvements of base_module_quality:

*defined generic framework, use of inheritance, ...
	*restructured
	*added config file of pylint
	*added speed_test (to be continued)
	*removed unecessary files

bzr revid: qdp@tinyerp.com-20081216172015-4o856cgffpytl9ru
This commit is contained in:
qdp
2008-12-16 18:20:15 +01:00
parent 2b2c7e256b
commit 02694646b6
10 changed files with 410 additions and 165 deletions
+11
View File
@@ -0,0 +1,11 @@
This module provide a generic framework to define your own quality test.
All you have to do is to:
* create a folder with your test in 'base_module_quality' (e.g: mkdir base_module_quality\mytest)
* create a .py file in it with same name as the folder you just created (e.g: touch base_module_quality\mytest\mytest.py)
* edit your file and define a class 'quality_check' that
* inherits the class 'abstract_quality_test' (defined in base_module_quality.py)
* implements the __init__() method accordingly to what you want to test.
+9 -1
View File
@@ -24,7 +24,15 @@
"author" : "Tiny",
"version" : "1.0",
"depends" : ["base",],
"description": "Sample module to check the quality",
"description": """"
This module's aim is to check the quality of other modules.
It defines a wizard on the list of modules in OpenERP, which allow you to evaluate them on different critera such as: the respect of OpenERP coding standards, the speed efficency...
This module also provide generic framework to define your own quality test. For further info, coders may take a look into base_module_quality\README.txt
""",
"init_xml" : [],
"update_xml" : ["base_module_quality_wizard.xml"],
"category" : "Tiny Specific Modules/Base module quality",
@@ -23,7 +23,7 @@
import netsvc
from osv import fields, osv
class quality_check(object):
class abstract_quality_check(object):
'''
This Class provide...
'''
@@ -38,15 +38,6 @@ class quality_check(object):
'''
raise 'Not Implemented'
#~ def __get_result__(self, cr, uid, module_ids):
#~ '''
#~ '''
#~ return _result
#~ def __get_detailed_result__(self, cr, uid, module_ids):
#~ '''
#~ '''
#~ return _result_details
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
@@ -20,7 +20,7 @@
#
##############################################################################
import pylint_test
#import pylint_test
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
@@ -23,36 +23,12 @@
import netsvc
from osv import fields, osv
import os
from tools import config
from base_module_quality import base_module_quality
#~ class _test_pylint(quality_check):
#~ def __init__(self, url, add_folder=None):
#~ print "dans le test"
#~ list_files = os.listdir(url)
#~ new_list = []
#~ subfolder = {}
#~ for i in list_files:
#~ if os.path.isdir(i):
#~ path = os.path.join(url, i)
#~ new_list.append(os.listdir(path))
#~ res = _test_pylint(self, path, add_folder=i)
#~ subfolder.update(res)
#~ dict_files = {}
#~ for file in list_files:
#~ if file.split('.')[-1] == 'py' and not file.startswith('__init__'):
#~ file_path = os.path.join(url, file)
#~ res = os.popen('pylint '+file_path+' | tail -4').read()
#~ if res.startswith('Global'):
#~ if add_folder:
#~ dict_files[add_folder + '/' + file] = res
#~ else:
#~ dict_files[file] = res
#~ dict_files.update(subfolder)
#~ print "dict_files", dict_files
#~ return dict_files
class _test_pylint(base_module_quality.quality_check):
class quality_test(base_module_quality.abstract_quality_check):
def __init__(self, module_path):
self._result = """
@@ -63,6 +39,7 @@ Pylint Test:
"""
config_file_path = config['addons_path']+'/base_module_quality/pylint_test/pylint_test_config.txt'
list_files = os.listdir(module_path)
new_list = []
subfolder = {}
@@ -78,9 +55,8 @@ Pylint Test:
print list_files
for file in list_files:
if file.split('.')[-1] == 'py' and not file.endswith('__init__.py') and not file.endswith('__terp__.py'):
#--rcfile=<file> Specify a configuration file.
file_path = os.path.join(module_path, file)
res = os.popen('pylint --persistent=n '+file_path).read()
res = os.popen('pylint --rcfile='+config_file_path+' '+file_path).read()
n += 1
leftchar = -1
while res[leftchar:leftchar+1] != ' ' and leftchar-1 <= 0:
@@ -0,0 +1,308 @@
# lint Python modules using external checkers.
#
# This is the main checker controling the other ones and the reports
# generation. It is itself both a raw checker and an astng checker in order
# to:
# * handle message activation / deactivation at the module level
# * handle some basic but necessary stats'data (number of classes, methods...)
#
[MASTER]
# Specify a configuration file.
#rcfile=
# Profiled execution.
profile=no
# Add <file or directory> to the black list. It should be a base name, not a
# path. You may set this option multiple times.
ignore=CVS
# Pickle collected data for later comparisons.
persistent=no
# Set the cache size for astng objects.
cache-size=500
# List of plugins (as comma separated values of python modules names) to load,
# usually to register additional checkers.
load-plugins=
[COMMANDS]
# Display a help message for the given message id and exit. The value may be a
# comma separated list of message ids.
#help-msg=
[MESSAGES CONTROL]
# Enable only checker(s) with the given id(s). This option conflict with the
# disable-checker option
#enable-checker=
# Enable all checker(s) except those with the given id(s). This option conflict
# with the disable-checker option
#disable-checker=
# Enable all messages in the listed categories.
#enable-msg-cat=
# Disable all messages in the listed categories.
#disable-msg-cat=
# Enable the message(s) with the given id(s).
#enable-msg=
# Disable the message(s) with the given id(s).
#disable-msg=
[REPORTS]
# set the output format. Available formats are text, parseable, colorized and
# html
output-format=text
# Include message's id in output
include-ids=no
# Put messages in a separate file for each module / package specified on the
# command line instead of printing them on stdout. Reports (if any) will be
# written in a file name "pylint_global.[txt|html]".
files-output=no
# Tells wether to display a full report or only the messages
reports=yes
# Python expression which should return a note less than 10 (10 is the highest
# note).You have access to the variables errors warning, statement which
# respectivly contain the number of errors / warnings messages and the total
# number of statements analyzed. This is used by the global evaluation report
# (R0004).
evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10)
# Add a comment according to your evaluation note. This is used by the global
# evaluation report (R0004).
comment=no
# Enable the report(s) with the given id(s).
#enable-report=
# Disable the report(s) with the given id(s).
#disable-report=
# checks for
# * unused variables / imports
# * undefined variables
# * redefinition of variable from builtins or from an outer scope
# * use of variable before assigment
#
[VARIABLES]
# Tells wether we should check for unused import in __init__ files.
init-import=no
# A regular expression matching names used for dummy variables (i.e. not used).
dummy-variables-rgx=_|dummy
# List of additional names supposed to be defined in builtins. Remember that
# you should avoid to define new builtins when possible.
additional-builtins=
# try to find bugs in the code using type inference
#
[TYPECHECK]
# Tells wether missing members accessed in mixin class should be ignored. A
# mixin class is detected if its name ends with "mixin" (case insensitive).
ignore-mixin-members=yes
# When zope mode is activated, consider the acquired-members option to ignore
# access to some undefined attributes.
zope=no
# List of members which are usually get through zope's acquisition mecanism and
# so shouldn't trigger E0201 when accessed (need zope=yes to be considered).
acquired-members=REQUEST,acl_users,aq_parent
# checks for :
# * doc strings
# * modules / classes / functions / methods / arguments / variables name
# * number of arguments, local variables, branchs, returns and statements in
# functions, methods
# * required module attributes
# * dangerous default values as arguments
# * redefinition of function / method / class
# * uses of the global statement
#
[BASIC]
# Required attributes for module, separated by a comma
required-attributes=
# Regular expression which should only match functions or classes name which do
# not require a docstring
no-docstring-rgx=__.*__
# Regular expression which should only match correct module names
module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$
# Regular expression which should only match correct module level names
const-rgx=(([A-Z_][A-Z1-9_]*)|(__.*__))$
# Regular expression which should only match correct class names
class-rgx=[A-Z_][a-zA-Z0-9]+$
# Regular expression which should only match correct function names
function-rgx=[a-z_][a-z0-9_]{2,30}$
# Regular expression which should only match correct method names
method-rgx=[a-z_][a-z0-9_]{2,30}$
# Regular expression which should only match correct instance attribute names
attr-rgx=[a-z_][a-z0-9_]{2,30}$
# Regular expression which should only match correct argument names
argument-rgx=[a-z_][a-z0-9_]{2,30}$
# Regular expression which should only match correct variable names
variable-rgx=[a-z_][a-z0-9_]{2,30}$
# Regular expression which should only match correct list comprehension /
# generator expression variable names
inlinevar-rgx=[A-Za-z_][A-Za-z0-9_]*$
# Good variable names which should always be accepted, separated by a comma
good-names=i,j,k,ex,Run,_
# Bad variable names which should always be refused, separated by a comma
bad-names=foo,bar,baz,toto,tutu,tata
# List of builtins function names that should not be used, separated by a comma
bad-functions=map,filter,apply,input
# checks for
# * external modules dependencies
# * relative / wildcard imports
# * cyclic imports
# * uses of deprecated modules
#
[IMPORTS]
# Deprecated modules which should not be used, separated by a comma
deprecated-modules=regsub,string,TERMIOS,Bastion,rexec
# Create a graph of every (i.e. internal and external) dependencies in the
# given file (report R0402 must not be disabled)
import-graph=
# Create a graph of external dependencies in the given file (report R0402 must
# not be disabled)
ext-import-graph=
# Create a graph of internal dependencies in the given file (report R0402 must
# not be disabled)
int-import-graph=
# checks for :
# * methods without self as first argument
# * overridden methods signature
# * access only to existant members via self
# * attributes not defined in the __init__ method
# * supported interfaces implementation
# * unreachable code
#
[CLASSES]
# List of interface methods to ignore, separated by a comma. This is used for
# instance to not check methods defines in Zope's Interface base class.
ignore-iface-methods=isImplementedBy,deferred,extends,names,namesAndDescriptions,queryDescriptionFor,getBases,getDescriptionFor,getDoc,getName,getTaggedValue,getTaggedValueTags,isEqualOrExtendedBy,setTaggedValue,isImplementedByInstancesOf,adaptWith,is_implemented_by
# List of method names used to declare (i.e. assign) instance attributes.
defining-attr-methods=__init__,__new__,setUp
# checks for sign of poor/misdesign:
# * number of methods, attributes, local variables...
# * size, complexity of functions, methods
#
[DESIGN]
# Maximum number of arguments for function / method
max-args=5
# Maximum number of locals for function / method body
max-locals=15
# Maximum number of return / yield for function / method body
max-returns=6
# Maximum number of branch for function / method body
max-branchs=12
# Maximum number of statements in function / method body
max-statements=50
# Maximum number of parents for a class (see R0901).
max-parents=7
# Maximum number of attributes for a class (see R0902).
max-attributes=7
# Minimum number of public methods for a class (see R0903).
min-public-methods=2
# Maximum number of public methods for a class (see R0904).
max-public-methods=20
# checks for :
# * unauthorized constructions
# * strict indentation
# * line length
# * use of <> instead of !=
#
[FORMAT]
# Maximum number of characters on a single line.
max-line-length=80
# Maximum number of lines in a module
max-module-lines=1000
# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1
# tab).
indent-string=' '
# checks for similarities and duplicated code. This computation may be
# memory / CPU intensive, so you should disable it if you experiments some
# problems.
#
[SIMILARITIES]
# Minimum lines number of a similarity.
min-similarity-lines=4
# Ignore comments when computing similarities.
ignore-comments=yes
# Ignore docstrings when computing similarities.
ignore-docstrings=yes
# checks for:
# * warning notes in the code like FIXME, XXX
# * PEP 263: source code with non ascii character but no encoding declaration
#
[MISCELLANEOUS]
# List of note tags to take in consideration, separated by a comma.
notes=FIXME,XXX,TODO
@@ -20,6 +20,5 @@
#
##############################################################################
import pylint_test
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
@@ -0,0 +1,48 @@
# -*- encoding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2008 Tiny SPRL (<http://tiny.be>). All Rights Reserved
# $Id$
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
import netsvc
from osv import fields, osv
import os
from tools import config
from base_module_quality import base_module_quality
class quality_test(base_module_quality.abstract_quality_check):
def __init__(self, module_path):
self._result = """
Speed Test:
------------
This test checks the speed of the module
to be continued...
"""
return None
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
@@ -27,21 +27,20 @@ import netsvc
import sys
import tools
import os
import pylint
import base_module_quality
form_check = '''<?xml version="1.0"?>
<form string="Quality check">
<field name="test" />
</form>'''
fields_check = {
'test': {
'string':'Tests', 'type':'selection', 'required':True,
'selection': [('pylint', 'Pylint'), ('othertest','other')],
'default': lambda *args: 'pylint'
},
}
#~ form_check = '''<?xml version="1.0"?>
#~ <form string="Quality check">
#~ <field name="test" />
#~ </form>'''
#~ fields_check = {
#~ 'test': {
#~ 'string':'Tests', 'type':'selection', 'required':True,
#~ 'selection': [('pylint', 'Pylint'), ('othertest','other')],
#~ 'default': lambda *args: 'pylint'
#~ },
#~ }
view_form = """<?xml version="1.0"?>
<form string="Check quality">
@@ -69,46 +68,34 @@ class wiz_quality_check(wizard.interface):
from tools import config
list_folders=os.listdir(config['addons_path']+'/base_module_quality/')
for item in list_folders:
path = config['addons_path']+'/base_module_quality/wizard/'+item
path = config['addons_path']+'/base_module_quality/'+item
if os.path.exists(path+'/'+item+'.py') and item not in ['report','wizard', 'security']:
pool=pooler.get_pool(cr.dbname)
module_data = pool.get('ir.module.module').browse(cr, uid, data['ids'])
ad = tools.config['addons_path']
module_path = os.path.join(ad, module_data[0].name)
#import pylint_test
item='base_module_quality.'+item
x = __import__(item)
val = x.__init__(str(module_path))
print "VALL",x._result
from base_module_quality import base_module_quality
item2='base_module_quality.'+item+'.'+item
x = __import__(item2)
x2 = getattr(x,item)
x3 = getattr(x2,item)
val = x3.quality_test(str(module_path))
string_ret += val._result
return {'general_info':string_ret}
#mra version
#~ result = pylint_test._test_pylint(self, url)
#~ string_ret = ''
#~ for i in result:
#~ string_ret = string_ret + i + ':\n' + result[i]
#~ string_ret = ""
#~ if data['form']['test'] == 'pylint':
#~ pool=pooler.get_pool(cr.dbname)
#~ module_data = pool.get('ir.module.module').browse(cr, uid, data['ids'])
#~ from pylint_test import pylint_test
#~ ad = tools.config['addons_path']
#~ url = os.path.join(ad, module_data[0].name)
#~ result = pylint_test._test_pylint(self, url)
#~ string_ret = ''
#~ for i in result:
#~ string_ret = string_ret + i + ':\n' + result[i]
states = {
#~ 'init': {
#~ 'actions': [],
#~ 'result': {'type':'form', 'arch':form_check, 'fields':fields_check, 'state':[('end','Cancel'),('do','Do Test')]}
#~ },
'init': {
'actions': [],
'result': {'type':'form', 'arch':form_check, 'fields':fields_check, 'state':[('end','Cancel'),('do','Do Test')]}
},
'do': {
'actions': [_check],
'result': {'type':'form', 'arch':view_form, 'fields':view_field, 'state':[('end','Ok')]},
},
@@ -1,83 +0,0 @@
# -*- encoding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2008 Tiny SPRL (<http://tiny.be>). All Rights Reserved
# $Id$
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
import netsvc
from osv import fields, osv
import os
class _test_pylint(quality_check):
def __init__(self, url, add_folder=None):
print "dans le test"
list_files = os.listdir(url)
new_list = []
subfolder = {}
for i in list_files:
if os.path.isdir(i):
path = os.path.join(url, i)
new_list.append(os.listdir(path))
res = _test_pylint(self, path, add_folder=i)
subfolder.update(res)
dict_files = {}
for file in list_files:
if file.split('.')[-1] == 'py' and not file.startswith('__init__'):
file_path = os.path.join(url, file)
res = os.popen('pylint '+file_path+' | tail -4').read()
if res.startswith('Global'):
if add_folder:
dict_files[add_folder + '/' + file] = res
else:
dict_files[file] = res
dict_files.update(subfolder)
print "dict_files", dict_files
return dict_files
_test_pylint()
#~ def _test_pylint(self, url, add_folder=None):
#~ list_files = os.listdir(url)
#~ new_list = []
#~ subfolder = {}
#~ for i in list_files:
#~ if os.path.isdir(i):
#~ path = os.path.join(url, i)
#~ new_list.append(os.listdir(path))
#~ res = _test_pylint(self, path, add_folder=i)
#~ subfolder.update(res)
#~ dict_files = {}
#~ for file in list_files:
#~ if file.split('.')[-1] == 'py' and not file.startswith('__init__'):
#~ file_path = os.path.join(url, file)
#~ res = os.popen('pylint '+file_path+' | tail -4').read()
#~ if res.startswith('Global'):
#~ if add_folder:
#~ dict_files[add_folder + '/' + file] = res
#~ else:
#~ dict_files[file] = res
#~ dict_files.update(subfolder)
#~ return dict_files
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: