2009-10-14 11:15:34 +00:00
# -*- coding: utf-8 -*-
2009-07-03 05:20:40 +00:00
##############################################################################
2010-06-24 07:13:42 +00:00
#
2009-07-03 05:20:40 +00:00
# OpenERP, Open Source Management Solution
2010-01-12 09:18:39 +00:00
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
2009-07-03 05:20:40 +00:00
#
# This program is free software: you can redistribute it and/or modify
2009-10-14 11:15:34 +00:00
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
2009-07-03 05:20:40 +00:00
#
# 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
2009-10-14 11:15:34 +00:00
# GNU Affero General Public License for more details.
2009-07-03 05:20:40 +00:00
#
2009-10-14 11:15:34 +00:00
# You should have received a copy of the GNU Affero General Public License
2010-06-24 07:13:42 +00:00
# along with this program. If not, see <http://www.gnu.org/licenses/>.
2009-07-03 05:20:40 +00:00
#
##############################################################################
import os
from tools . translate import _
from base_module_quality import base_module_quality
class quality_test ( base_module_quality . abstract_quality_check ) :
def __init__ ( self ) :
super ( quality_test , self ) . __init__ ( )
self . name = _ ( " PEP-8 Test " )
self . note = _ ( """
PEP - 8 Test , copyright of py files check , method can not call from loops
""" )
self . bool_installed_only = False
self . bad_standard = 0
self . good_standard = 0
self . result_py = { }
2009-08-28 07:24:57 +00:00
self . min_score = 40
2009-07-03 05:20:40 +00:00
return None
def run_test ( self , cr , uid , module_path ) :
list_files = os . listdir ( module_path )
for i in list_files :
path = os . path . join ( module_path , i )
if os . path . isdir ( path ) :
for j in os . listdir ( path ) :
list_files . append ( os . path . join ( i , j ) )
py_list = [ ]
for file_py in list_files :
2010-06-24 07:13:42 +00:00
if file_py . split ( ' . ' ) [ - 1 ] == ' py ' and not file_py . endswith ( ' __init__.py ' ) and not file_py . endswith ( ' __openerp__.py ' ) :
2009-07-03 05:20:40 +00:00
file_path = os . path . join ( module_path , file_py )
py_list . append ( file_path )
open_files = map ( lambda x : open ( x , ' r ' ) , py_list )
if not py_list :
self . error = True
self . result = _ ( " No python file found " )
return None
#below functions check:
#1. Imports should usually be on separate lines
#2. Imports are always put at the top of the file, just after any module comments and docstrings, and before module globals and constants
self . check_import ( open_files )
#1. there should be a one space after , : ;
self . check_space ( open_files )
#1. Have all the .py files a copyright?
self . check_licence ( open_files )
#1. Does the module avoid unecessary queries like when we put a browse into a loop?
self . check_loop ( open_files )
#1.More than one space around an assignment (or other) operator to align it with another.
# self.check_space_operator(open_files)
#1. For sequences, (strings, lists, tuples), use the fact that empty sequences are false
#for e.g : if seq: => good & if len(seq): => not good
self . check_len ( open_files )
# below function checks
# 1. Don't compare boolean values to True or False using == and !=
self . check_boolean ( open_files )
self . score = self . good_standard and float ( self . good_standard ) / float ( self . good_standard + self . bad_standard )
2009-08-28 07:24:57 +00:00
if self . score * 100 < self . min_score :
self . message = ' Score is below than minimal score( %s %% ) ' % self . min_score
2009-07-03 05:20:40 +00:00
self . result = self . get_result ( { module_path : [ int ( self . score * 100 ) ] } )
self . result_details + = self . get_result_general ( self . result_py )
return None
def check_import ( self , open_files ) :
for py in open_files :
py . seek ( 0 )
class_or_def = False
line_counter = 0
file_name = py . name . split ( ' / ' ) [ - 1 ]
while True :
line_counter + = 1
line = py . readline ( )
if not line : break
if ( ( line . find ( ' class ' ) > - 1 ) or ( line . find ( ' def ' ) > - 1 ) ) :
class_or_def = True
import_found = line . find ( ' import ' )
comment_found = line . find ( ' # ' )
if comment_found == - 1 and import_found != - 1 :
self . good_standard + = 1
if ( class_or_def ) :
self . bad_standard + = 1
self . result_py [ file_name + str ( line_counter ) ] = [ file_name , line_counter , ' Imports are always put at the top of the file, just after any module comments and docstrings, and before module globals and constants ' ]
if ( line . find ( ' from ' ) < 0 and line . find ( ' , ' ) != - 1 ) :
self . bad_standard + = 1
self . result_py [ file_name + str ( line_counter ) ] = [ file_name , line_counter , ' Imports should usually be on separate lines ' ]
def check_licence ( self , open_files ) :
for py in open_files :
py . seek ( 0 )
bad_position = False
copyright_found = False
gnu_found = False
license_found = False
gnu_website_found = False
line_counter = 0
file_name = py . name . split ( ' / ' ) [ - 1 ]
while True :
declaration = False
flag = False
line_counter + = 1
line = py . readline ( )
if not line : break
if ( ( line . find ( ' class ' ) > - 1 ) or ( line . find ( ' def ' ) > - 1 ) or ( line . find ( ' import ' ) > - 1 ) ) :
bad_position = True
comment_found = line . find ( ' # ' )
copyright_found = line . find ( ' Copyright ' )
gnu_found = line . find ( ' GNU ' )
license_found = line . find ( ' License ' )
gnu_website_found = line . find ( ' www.gnu.org/licenses ' )
if ( ( copyright_found > - 1 ) or ( gnu_found > - 1 ) or ( license_found > - 1 ) or ( gnu_website_found > - 1 ) ) :
self . good_standard + = 1
declaration = True
flag = True
break
if ( comment_found > - 1 ) and bad_position and declaration :
self . bad_standard + = 1
self . result_py [ file_name + str ( line_counter ) ] = [ file_name , line_counter , ' Declaration of copyright must be at the top of file ' ]
break
if bad_position and ( not flag ) :
self . bad_standard + = 1
self . result_py [ file_name ] = [ file_name , ' -- ' , ' File is not copyright ' ]
def check_loop ( self , open_files ) :
for py in open_files :
py . seek ( 0 )
methods = [ ' browse ' , ' search ' , ' read ' , ' copy ' , ' unlink ' ]
place_for = 1000
file_name = py . name . split ( ' / ' ) [ - 1 ]
line_counter = 0
counter = 0
while True :
line_counter + = 1
line = py . readline ( )
if not line : break
place_method = 0
for i in line :
if ( i == ' ' ) :
place_method + = 1
elif ( i != ' ' ) :
break
elif ( place_method > 100 ) :
break
if ( line . find ( ' for ' ) > - 1 ) :
place_for = place_method
if ( place_for < place_method ) :
counter + = 1
for method in methods :
got = line . find ( method )
if ( got > - 1 ) :
self . bad_standard + = 1
self . result_py [ file_name + str ( line_counter ) ] = [ file_name , line_counter , ' puting method inside loop is not good ' ]
self . good_standard + = counter
def check_space ( self , open_files ) :
for py in open_files :
py . seek ( 0 )
counter_line = 0
file_name = py . name . split ( ' / ' ) [ - 1 ]
counter = 0
while True :
counter_line + = 1
line = py . readline ( )
if not line : break
pos_comma = line . find ( ' , ' )
pos_semicolon = line . find ( ' ; ' )
pos_colon = line . find ( ' : ' )
space_find = - 1
if ( pos_comma != - 1 or pos_semicolon != - 1 or pos_colon != - 1 ) :
counter + = 1
for i in line :
space_find + = 1
if ( i == ' ' ) :
if ( ( space_find + 1 ) == pos_comma ) or ( ( space_find + 1 ) == pos_semicolon ) or ( ( space_find + 1 ) == pos_colon ) :
self . bad_standard + = 1
self . result_py [ file_name + str ( counter_line ) ] = [ file_name , counter_line , ' You should not have space before (: ; ,) ' ]
self . good_standard + = counter # to be check
def check_space_operator ( self , open_files ) :
for py in open_files :
py . seek ( 0 )
space_counter = 0
eq_found = False
operator_found = False
line_counter = 0
file_name = py . name . split ( ' / ' ) [ - 1 ]
while True :
line_counter + = 1
line = py . readline ( )
if not line : break
for counter in line :
if ( counter == ' ' ) :
space_counter + = 1
else :
if ( space_counter > 1 ) :
if counter in [ ' = ' , ' < ' , ' > ' , ' ! ' , ' + ' , ' - ' , ' * ' , ' / ' , ' ^ ' , ' % ' ] or operator_found :
self . bad_standard + = 1
self . result_py [ file_name + str ( line_counter ) ] = [ file_name , line_counter , ' More than one space around an assignment (or other) operator to align it with another ' ]
operator_found = False
space_counter = 0
if counter in [ ' = ' , ' < ' , ' > ' , ' ! ' , ' + ' , ' - ' , ' * ' , ' / ' , ' ^ ' , ' % ' ] :
self . good_standard + = 1
operator_found = True
def check_len ( self , open_files ) :
for py in open_files :
py . seek ( 0 )
line_counter = 0
file_name = py . name . split ( ' / ' ) [ - 1 ]
while True :
line_counter + = 1
line = py . readline ( )
if not line : break
if ( line . find ( ' if ' ) > - 1 ) and ( line . find ( ' len( ' ) > - 1 ) and ( line . find ( ' ) ' ) > - 1 ) :
self . good_standard + = 1
if ( line . find ( ' : ' ) > - 1 ) and not line . find ( ' < ' ) > - 1 and not line . find ( ' > ' ) > - 1 and not line . find ( ' = ' ) > - 1 and not line . find ( ' ! ' ) > - 1 :
self . bad_standard + = 1
self . result_py [ file_name + str ( line_counter ) ] = [ file_name , line_counter , ' For sequences, (strings, lists, tuples), use the fact that empty sequences are false ' ]
def check_boolean ( self , open_files ) :
for py in open_files :
py . seek ( 0 )
line_counter = 0
file_name = py . name . split ( ' / ' ) [ - 1 ]
while True :
line_counter + = 1
line = py . readline ( )
if not line : break
if ( line . find ( ' if ' ) > - 1 ) :
self . good_standard + = 1
if ( ( line . find ( ' == ' ) > - 1 ) or ( line . find ( ' != ' ) > - 1 ) ) and ( ( line . find ( ' True ' ) > - 1 ) or ( line . find ( ' False ' ) > - 1 ) ) :
self . bad_standard + = 1
self . result_py [ file_name + str ( line_counter ) ] = [ file_name , line_counter , " Don ' t compare boolean values to True or False using == or != " ]
def get_result ( self , dict_obj ) :
header = ( ' { | border= " 1 " cellspacing= " 0 " cellpadding= " 5 " align= " left " \n ! %-40s \n ' , [ _ ( ' Result of pep8_test in % ' ) ] )
if not self . error :
return self . format_table ( header , data_list = dict_obj )
return " "
def get_result_general ( self , dict_obj ) :
2009-09-29 12:20:27 +00:00
str_html = ''' <html><strong>Result</strong><head> %s </head><body><table class= " tablestyle " > ''' % ( self . get_style ( ) )
header = ( ' <tr><th class= " tdatastyle " > %s </th><th class= " tdatastyle " > %s </th><th class= " tdatastyle " > %s </th></tr> ' , [ _ ( ' Object Name ' ) , _ ( ' Line number ' ) , _ ( ' Suggestion ' ) ] )
2009-07-03 05:20:40 +00:00
if not self . error :
res = str_html + self . format_html_table ( header , data_list = dict_obj ) + ' </table></body></html> '
2009-09-29 12:20:27 +00:00
res = res . replace ( ''' <td ''' , ''' <td class= " tdatastyle " ''' )
2009-07-03 05:20:40 +00:00
return res
return " "
2012-03-05 18:40:03 +00:00
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: