class Booking(models.Model): _name = 'booking.booking' # bookings = fields.One2many(compute='booking') @api.models def _url(self): self.url = "/booking/%s" % "something" url = fields.Char(string="Url", compute=_url) @api.models def _name(self): self.name = 'Some good name' name = fields.Char(string="Name", compute=_name) date_start = fields.DateTime(string='Start') date_end = fields.DateTime(string='End') # employee_id # partner_id # product_id # company_id = # status selection = draft,open,canceled,done # descriptin ? # arv in maillogg @api.model def now_week(self): year = datetime.datetime.today().strftime("%Y") week = datetime.datetime.today().strftime("%V") _logger.warning('%s %s' % (year, week)) return self.week_days(year, week) @api.model def week_days(self, year, week): if datetime.date(int(year), 1, 1).isocalendar()[2] <= 4: week = str(int(week) - 1) year_week = year + '-W' + week one_day = datetime.datetime.strptime(year_week + '-1', "%Y-W%W-%w") weekday_dates = [ day.replace(hour=0, minute=0, second=0) for day in rrule.rrule(rrule.DAILY, dtstart=one_day, until=(one_day + datetime.timedelta(days=1)).replace( hour=0, minute=0, second=0)) ] # weekday_dates.append(DateTime.strptime(year_week + '-1', "%Y-W%W-%w")) # for i in range(0, 7): # weekday_dates.append(datetime.timedelta.__init__(DateTime, days=1)) _logger.warning('<<<<<<<<<<<weekday>>>>>>>>>>>: %s' % weekday_dates[0].replace(hour=9, minute=9, second=9)) return weekday_dates def booking(self, calendar_time, planned_time, booked_time): available_time = [] return available_time
class TestModel(models.Model): _name = 'test.model' _inherit = ['mail.thread'] _columns = {} # deprecated columns _defaults = {} # deprecated defaults length = fields.Integer() # Deprecated length by js errors name = fields.Char( _(u"Näme"), # Don't need translate help=u"My hëlp", required=False, compute='_compute_name', # good compute method name search='_search_name', # good search method name inverse='_inverse_name', # good inverse method name ) # Imported openerp.fields use Char (Upper case) other_field = fields.char( name=_("Other field"), copy=True, compute='my_method_compute', # bad compute method name search='my_method_search', # bad search method name inverse='my_method_inverse', # bad inverse method name ) compute_none = fields.Char(compute=None) other_field2 = fields.char( 'Other Field2', copy=True, ) field_related = fields.Char('Field Related', related='model_id.related_field') other_field_related = fields.Char(related='model_id.related_field', string='Other Field Related') # This is a inherit overwrite field then don't should show errors related # with creation of fields. def method_date(self): date = fields.Date.to_string( fields.Datetime.context_timestamp(self, timestamp=fields.Datetime.now())) self.with_context({'overwrite_context': True}).write({}) ctx = {'overwrite_context': True} self.with_context(ctx).write({}) ctx2 = ctx self.with_context(ctx2).write({}) self.with_context(**ctx).write({}) self.with_context(overwrite_context=False).write({}) return date my_ok_field = fields.Float( "My correctly named field", digits=(6, 6), # OK: Valid field parameter index=True, # OK: Valid field parameter help="My ok field", ) my_ko_field = fields.Float( digits_compute=lambda cr: (6, 6), # Deprecated field parameter select=True, # Deprecated field parameter help="My ko field", string="My Ko Field", # String parameter equal to name of variable ) """The name of the variable is equal to the string parameter Tested all fields.*""" boolean_variable_1 = fields.Boolean(string='Boolean Variable 1', help="Help") boolean_variable_2 = fields.Boolean("Boolean Variable 2", help="Help") char_variable_1 = fields.Char(string='Char Variable 1', help="Help") char_variable_2 = fields.Char("Char Variable 2", help="Help") text_variable_1 = fields.Text(string='Text Variable 1', help="Help") text_variable_2 = fields.Text("Text Variable 2", help="Help") html_variable_1 = fields.Html(string='Html Variable 1', help="Help") html_variable_2 = fields.Html("Html Variable 2", help="Help") integer_variable_1 = fields.Integer(string='Integer Variable 1', help="Help") integer_variable_2 = fields.Integer("Integer Variable 2", help="Help") float_variable_1 = fields.Float(string='Float Variable 1', help="Help") float_variable_2 = fields.Float("Float Variable 2", help="Help") date_variable_1 = fields.Date(string='Date Variable 1', help="Help") date_variable_2 = fields.Date("Date Variable 2", help="Help") date_time_variable_1 = fields.DateTime(string='Date Time Variable 1', help="Help") date_time_variable_2 = fields.DateTime("Date Time Variable 2", help="Help") binary_variable_1 = fields.Binary(string='Binary Variable 1', help="Help") binary_variable_2 = fields.Binary("Binary Variable 2", help="Help") selection_variable_1 = fields.Selection(selection=[('a', 'A')], string='Selection Variable 1', help="Help") selection_variable_2 = fields.Selection([('a', 'A')], "Selection Variable 2", help="Help") reference_variable_1 = fields.Reference(selection=[('res.user', 'User')], string="Reference Variable 1", help="Help") reference_variable_2 = fields.Reference([('res.user', 'User')], "Reference Variable 2", help="Help") many_2_one_variable_1 = fields.Many2one(comodel_name='res.users', string='Many 2 One Variable 1', help="Help") many_2_one_variable_2 = fields.Many2one('res.users', "Many 2 One Variable 2", help="Help") one_2_many_variable_1 = fields.One2many(comodel_name='res.users', inverse_name='rel_id', string='One 2 Many Variable 1', help="Help") one_2_many_variable_2 = fields.One2many('res.users', 'rel_id', "One 2 Many Variable 2", help="Help") many_2_many_variable_1 = fields.Many2many(comodel_name='res.users', relation='table_name', column1='col_name', column2='other_col_name', string='Many 2 Many Variable 1', help="Help") many_2_many_variable_2 = fields.Many2many('res.users', 'table_name', 'col_name', 'other_col_name', "Many 2 Many Variable 2", help="Help") field_case_sensitive = fields.Char('Field Case SENSITIVE', help="Field case sensitive") name_equal_to_string = fields.Float("Name equal to string", help="Name Equal To String") many_2_one = fields.Many2one('res.users', "Many 2 One", help="Many 2 one") many_2_many = fields.Many2many('res.users', 'relation', 'fk_column_from', 'fk_column_to', "Many 2 many", help="Many 2 Many") def my_method1(self, variable1): # Shouldn't show error of field-argument-translate self.my_method2(_('hello world')) # Message post without translation function self.message_post(subject='Subject not translatable', body='Body not translatable %s' % variable1) self.message_post(subject='Subject not translatable %(variable)s' % {'variable': variable1}, body='Body not translatable {}'.format(variable1), message_type='notification') self.message_post('Body not translatable', 'Subject not translatable {a}'.format(a=variable1)) self.message_post( 'Body not translatable %s' % variable1, 'Subject not translatable %(variable)s' % {'variable': variable1}) self.message_post('Body not translatable', subject='Subject not translatable') self.message_post( body='<h1>%s</h1><p>%s</p>' % (_('Paragraph translatable'), 'Paragraph not translatable')) # Message post with translation function self.message_post(subject=_('Subject translatable'), body=_('Body translatable')) self.message_post(_('Body translatable'), _('Subject translatable')) self.message_post(_('Body translatable'), subject=_('Subject translatable')) self.message_post(_('A CDR has been recovered for %s') % (variable1, )) self.message_post(_('A CDR has been recovered for %s') % variable1) self.message_post(_('Var {a}').format(a=variable1)) self.message_post(_('Var %(variable)s') % {'variable': variable1}) self.message_post(subject=_('Subject translatable'), body=_('Body translatable %s') % variable1) self.message_post(subject=_('Subject translatable %(variable)s') % {'variable': variable1}, message_type='notification') self.message_post(_('Body translatable'), _('Subject translatable {a}').format(a=variable1)) self.message_post( _('Body translatable %s') % variable1, _('Subject translatable %(variable)s') % {'variable': variable1}) self.message_post('<p>%s</p>' % _('Body translatable')) self.message_post(body='<p>%s</p>' % _('Body translatable')) # There is no way to know if the variable is translated, then ignoring self.message_post(variable1) self.message_post(body=variable1 + variable1) self.message_post(body=(variable1 + variable1)) self.message_post(body=variable1 % variable1) self.message_post(body=(variable1 % variable1)) # translation function with variables in the term variable2 = variable1 self.message_post(_('Variable not translatable: %s' % variable1)) self.message_post( _('Variables not translatable: %s, %s' % (variable1, variable2))) self.message_post(body=_('Variable not translatable: %s' % variable1)) self.message_post(body=_('Variables not translatable: %s %s' % (variable1, variable2))) error_msg = _('Variable not translatable: %s' % variable1) error_msg = _('Variables not translatable: %s, %s' % (variable1, variable2)) error_msg = _('Variable not translatable: {}'.format(variable1)) error_msg = _('Variables not translatable: {}, {variable2}'.format( variable1, variable2=variable2)) # string with parameters without name # so you can't change the order in the translation _('%s %d') % ('hello', 3) _('%s %s') % ('hello', 'world') # Valid cases _('%(strname)s') % {'strname': 'hello'} _('%(strname)s %(intname)d') % {'strname': 'hello', 'intname': 3} _('%s') % 'hello' _('%d') % 3 return error_msg def my_method2(self, variable2): return variable2 def my_method3(self, cr): cr.commit() # Dangerous use of commit old api self.env.cr.commit() # Dangerous use of commit self._cr.commit() # Dangerous use of commit self.cr.commit() # Dangerous use of commit return cr def my_method4(self, variable2): self.env.cr2.commit() # This should not be detected return variable2 def my_method5(self, variable2): self.env.cr.commit2() # This should not be detected return variable2 def my_method6(self): user_id = 1 if user_id != 99: # Method without translation raise UserError('String without translation') def my_method7(self): user_id = 1 if user_id != 99: # Method with translation raise UserError(_('String with translation')) def my_method8(self): user_id = 1 if user_id != 99: str_error = 'String with translation 2' # Don't check raise UserError(str_error) def my_method9(self): user_id = 1 if user_id != 99: # Method without translation raise UserError("String without translation 2") def my_method10(self): # A example of built-in raise without parameters # Shouldn't show error from lint raise ZeroDivisionError raise ZeroDivisionError() def my_method11(self): # A example of built-in raise with parameters # Shouldn't show error from lint raise ZeroDivisionError("String without translation") # raise without class-exception to increase coverage raise raise "obsolete case" def my_method12(self): # Should show error raise exceptions.Warning( 'String with params format {p1}'.format(p1='v1')) raise exceptions.Warning('qp2w String with params format %(p1)s' % {'p1': 'v1'}) def my_method13(self): # Shouldn't show error raise exceptions.Warning( _('String with params format {p1}').format(p1='v1')) raise exceptions.Warning( _('String with params format {p1}'.format(p1='v1'))) raise exceptions.Warning( _('String with params format %(p1)s') % {'p1': 'v1'}) raise exceptions.Warning( _('String with params format %(p1)s' % {'p1': 'v1'})) def old_api_method_alias(self, cursor, user, ids, context=None): # old api pass def sql_method(self, ids, cr): # Use of query parameters: nothing wrong here self._cr.execute('SELECT name FROM account WHERE id IN %s', (tuple(ids), )) self.env.cr.execute('SELECT name FROM account WHERE id IN %s', (tuple(ids), )) cr.execute('SELECT name FROM account WHERE id IN %s', (tuple(ids), )) self.cr.execute('SELECT name FROM account WHERE id IN %s', (tuple(ids), )) def sql_injection_ignored_cases(self, ids, cr2): # This cr.execute2 or cr2.execute should not be detected self._cr.execute2('SELECT name FROM account WHERE id IN %s' % (tuple(ids), )) cr2.execute('SELECT name FROM account WHERE id IN %s' % (tuple(ids), )) # Ignore when the query is built using private attributes self._cr.execute('DELETE FROM %s WHERE id IN %%s' % self._table, (tuple(ids), )) # Ignore string parsed with "".format() if args are psycopg2.sql.* calls query = "SELECT * FROM table" # imported from pyscopg2 import sql self._cr.execute( sql.SQL("""CREATE or REPLACE VIEW {} as ({})""").format( sql.Identifier(self._table), sql.SQL(query))) self._cr.execute( sql.SQL("""CREATE or REPLACE VIEW {table} as ({query})""").format( table=sql.Identifier(self._table), query=sql.SQL(query), )) # imported from pyscopg2.sql import SQL, Identifier self._cr.execute( SQL("""CREATE or REPLACE VIEW {} as ({})""").format( Identifier(self._table), SQL(query), )) self._cr.execute( SQL("""CREATE or REPLACE VIEW {table} as ({query})""").format( table=Identifier(self._table), query=SQL(query), )) # imported from pyscopg2 direclty self._cr.execute( psycopg2.SQL("""CREATE or REPLACE VIEW {} as ({})""").format( psycopg2.sql.Identifier(self._table), psycopg2.sql.SQL(query), )) self._cr.execute( psycopg2.sql.SQL( """CREATE or REPLACE VIEW {table} as ({query})""").format( table=Identifier(self._table), query=SQL(query), )) # Variables build using pyscopg2.sql.* callers table = Identifier('table_name') sql_query = SQL(query) # format params self._cr.execute( SQL("""CREATE or REPLACE VIEW {} as ({})""").format( table, sql_query, )) # format dict self._cr.execute( SQL("""CREATE or REPLACE VIEW {table} as ({query})""").format( table=table, query=sql_query, )) self._cr.execute('SELECT name FROM %(table)s' % {'table': self._table}) # old api def sql_injection_modulo_operator(self, cr, uid, ids, context=None): # Use of % operator: risky self._cr.execute('SELECT name FROM account WHERE id IN %s' % (tuple(ids), )) self.env.cr.execute('SELECT name FROM account WHERE id IN %s' % (tuple(ids), )) cr.execute('SELECT name FROM account WHERE id IN %s' % (tuple(ids), )) self.cr.execute('SELECT name FROM account WHERE id IN %s' % (tuple(ids), )) operator = 'WHERE' # Ignore sql-injection because of there is a parameter e.g. "ids" self._cr.execute('SELECT name FROM account %s id IN %%s' % operator, ids) var = 'SELECT name FROM account WHERE id IN %s' values = ([ 1, 2, 3, ], ) self._cr.execute(var % values) self._cr.execute('SELECT name FROM account WHERE id IN %(ids)s' % {'ids': ids}) def sql_injection_executemany(self, ids, cr, v1, v2): # Check executemany() as well self.cr.executemany('INSERT INTO account VALUES (%s, %s)' % (v1, v2)) def sql_injection_format(self, ids, cr): # Use of .format(): risky self.cr.execute('SELECT name FROM account WHERE id IN {}'.format(ids)) var = 'SELECT name FROM account WHERE id IN {}' values = (1, 2, 3) self._cr.execute(var.format(values)) self.cr.execute( 'SELECT name FROM account WHERE id IN {ids}'.format(ids=ids)) def sql_injection_plus_operator(self, ids, cr): # Use of +: risky self.cr.execute('SELECT name FROM account WHERE id IN ' + str(tuple(ids))) operator = 'WHERE' # Ignore sql-injection because of there is a parameter e.g. "ids" self._cr.execute('SELECT name FROM account ' + operator + ' id IN %s', ids) self.cr.execute( ('SELECT name FROM account ' + operator + ' id IN (1)')) self.cr.execute('SELECT name FROM account ' + operator + ' id IN %s' % (tuple(ids), )) self.cr.execute( ('SELECT name FROM account ' + operator + ' id IN %s') % (tuple(ids), )) def sql_injection_before(self, ids): # query built before execute: risky as well var = 'SELECT name FROM account WHERE id IN %s' % tuple(ids) self._cr.execute(var) var[1] = 'SELECT name FROM account WHERE id IN %s' % tuple(ids) self._cr.execute(var[1]) var = 'SELECT name FROM account WHERE id IN %(ids)s' % { 'ids': tuple(ids) } self._cr.execute(var) var[1] = 'SELECT name FROM account WHERE id IN %(ids)s' % { 'ids': tuple(ids) } self._cr.execute(var[1]) def sql_no_injection_private_attributes(self, _variable, variable): # Skip sql-injection using private attributes self._cr.execute("CREATE VIEW %s AS (SELECT * FROM res_partner)" % self._table) # Real sql-injection cases self._cr.execute("CREATE VIEW %s AS (SELECT * FROM res_partner)" % self.table) self._cr.execute("CREATE VIEW %s AS (SELECT * FROM res_partner)" % _variable) self._cr.execute("CREATE VIEW %s AS (SELECT * FROM res_partner)" % variable) def sql_no_injection_private_methods(self): # Skip sql-injection using private methods self.env.cr.execute(""" CREATE OR REPLACE VIEW %s AS ( %s %s %s %s ) """ % ( self._table, self._select(), self._from(), self._where(), self._group_by(), )) def func(self, a): length = len(a) return length
class TestModel(models.Model): _name = 'test.model' _columns = {} # deprecated columns _defaults = {} # deprecated defaults length = fields.Integer() # Deprecated length by js errors name = fields.Char( _(u"Näme"), # Don't need translate help=u"My hëlp", required=False, compute='_compute_name', # good compute method name search='_search_name', # good search method name inverse='_inverse_name', # good inverse method name ) # Imported openerp.fields use Char (Upper case) other_field = fields.char( name=_("Other field"), copy=True, compute='my_method_compute', # bad compute method name search='my_method_search', # bad search method name inverse='my_method_inverse', # bad inverse method name ) compute_none = fields.Char(compute=None) other_field2 = fields.char( 'Other Field2', copy=True, ) my_ok_field = fields.Float( "My correctly named field", digits=(6, 6), # OK: Valid field parameter index=True, # OK: Valid field parameter help="My ok field", ) my_ko_field = fields.Float( digits_compute=lambda cr: (6, 6), # Deprecated field parameter select=True, # Deprecated field parameter help="My ko field", string="My Ko Field", # String parameter equal to name of variable ) """The name of the variable is equal to the string parameter Tested all fields.*""" boolean_variable_1 = fields.Boolean(string='Boolean Variable 1', help="Help") boolean_variable_2 = fields.Boolean("Boolean Variable 2", help="Help") char_variable_1 = fields.Char(string='Char Variable 1', help="Help") char_variable_2 = fields.Char("Char Variable 2", help="Help") text_variable_1 = fields.Text(string='Text Variable 1', help="Help") text_variable_2 = fields.Text("Text Variable 2", help="Help") html_variable_1 = fields.Html(string='Html Variable 1', help="Help") html_variable_2 = fields.Html("Html Variable 2", help="Help") integer_variable_1 = fields.Integer(string='Integer Variable 1', help="Help") integer_variable_2 = fields.Integer("Integer Variable 2", help="Help") float_variable_1 = fields.Float(string='Float Variable 1', help="Help") float_variable_2 = fields.Float("Float Variable 2", help="Help") date_variable_1 = fields.Date(string='Date Variable 1', help="Help") date_variable_2 = fields.Date("Date Variable 2", help="Help") date_time_variable_1 = fields.DateTime(string='Date Time Variable 1', help="Help") date_time_variable_2 = fields.DateTime("Date Time Variable 2", help="Help") binary_variable_1 = fields.Binary(string='Binary Variable 1', help="Help") binary_variable_2 = fields.Binary("Binary Variable 2", help="Help") selection_variable_1 = fields.Selection(selection=[('a', 'A')], string='Selection Variable 1', help="Help") selection_variable_2 = fields.Selection([('a', 'A')], "Selection Variable 2", help="Help") reference_variable_1 = fields.Reference(selection=[('res.user', 'User')], string="Reference Variable 1", help="Help") reference_variable_2 = fields.Reference([('res.user', 'User')], "Reference Variable 2", help="Help") many_2_one_variable_1 = fields.Many2one(comodel_name='res.users', string='Many 2 One Variable 1', help="Help") many_2_one_variable_2 = fields.Many2one('res.users', "Many 2 One Variable 2", help="Help") one_2_many_variable_1 = fields.One2many(comodel_name='res.users', inverse_name='rel_id', string='One 2 Many Variable 1', help="Help") one_2_many_variable_2 = fields.One2many('res.users', 'rel_id', "One 2 Many Variable 2", help="Help") many_2_many_variable_1 = fields.Many2many(comodel_name='res.users', relation='table_name', column1='col_name', column2='other_col_name', string='Many 2 Many Variable 1', help="Help") many_2_many_variable_2 = fields.Many2many('res.users', 'table_name', 'col_name', 'other_col_name', "Many 2 Many Variable 2", help="Help") field_case_sensitive = fields.Char( 'Field Case SENSITIVE', help="Field case sensitive" ) name_equal_to_string = fields.Float( "Name equal to string", help="Name Equal To String" ) many_2_one = fields.Many2one( 'res.users', "Many 2 One", help="Many 2 one" ) many_2_many = fields.Many2many( 'res.users', 'relation', 'fk_column_from', 'fk_column_to', "Many 2 many", help="Many 2 Many" ) # This is a inherit overwrite field then don't should show errors related # with creation of fields. field_state_overwrite = fields.Selection( selection_add=[('new_item', 'New Item')]) ids = ["parent_id_1", "parent_id_2"] def method_date(self): date = fields.Date.to_string( fields.Datetime.context_timestamp(self, timestamp=fields.Datetime.now()) ) return date def my_method1(self, variable1): # Shouldn't show error of field-argument-translate self.my_method2(_('hello world')) def my_method2(self, variable2): return variable2 def my_method3(self, cr): cr.commit() # Dangerous use of commit old api self.env.cr.commit() # Dangerous use of commit self._cr.commit() # Dangerous use of commit self.cr.commit() # Dangerous use of commit return cr def my_method4(self, variable2): self.env.cr2.commit() # This should not be detected return variable2 def my_method5(self, variable2): self.env.cr.commit2() # This should not be detected return variable2 def my_method6(self): user_id = 1 if user_id != 99: # Method without translation raise UserError('String without translation') def my_method7(self): user_id = 1 if user_id != 99: # Method with translation raise UserError(_('String with translation')) def my_method8(self): user_id = 1 if user_id != 99: str_error = 'String with translation 2' # Don't check raise UserError(str_error) def my_method9(self): user_id = 1 if user_id != 99: # Method without translation raise UserError("String without translation 2") def my_method10(self): # A example of built-in raise without parameters # Shouldn't show error from lint raise ZeroDivisionError raise ZeroDivisionError() def my_method11(self): # A example of built-in raise with parameters # Shouldn't show error from lint raise ZeroDivisionError("String without translation") # raise without class-exception to increase coverage raise raise "obsolete case" def my_method12(self): # Should show error raise exceptions.Warning( 'String with params format {p1}'.format(p1='v1')) raise exceptions.Warning( 'qp2w String with params format %(p1)s' % {'p1': 'v1'}) def my_method13(self): # Shouldn't show error raise exceptions.Warning(_( 'String with params format {p1}').format(p1='v1')) raise exceptions.Warning(_( 'String with params format {p1}'.format(p1='v1'))) raise exceptions.Warning(_( 'String with params format %(p1)s') % {'p1': 'v1'}) raise exceptions.Warning(_( 'String with params format %(p1)s' % {'p1': 'v1'})) def sql_method(self, ids, cr): # This is the better way and should not be detected self._cr.execute( 'SELECT name FROM account WHERE id IN %s', (tuple(ids),)) self.env.cr.execute( 'SELECT name FROM account WHERE id IN %s', (tuple(ids),)) cr.execute( 'SELECT name FROM account WHERE id IN %s', (tuple(ids),)) self.cr.execute( 'SELECT name FROM account WHERE id IN %s', (tuple(ids),)) def old_api_method_alias(self, cursor, user, ids, context=None): # old api pass def sql_injection_method(self, cr, uid, ids, context=None): # old api # SQL injection, bad way self._cr.execute( 'SELECT name FROM account WHERE id IN %s' % (tuple(ids),)) self.env.cr.execute( 'SELECT name FROM account WHERE id IN %s' % (tuple(ids),)) cr.execute( 'SELECT name FROM account WHERE id IN %s' % (tuple(ids),)) self.cr.execute( 'SELECT name FROM account WHERE id IN %s' % (tuple(ids),)) self.cr.execute( 'SELECT name FROM account WHERE id IN {}'.format(ids)) def sql_injection_method3(self, ids, cr2): # This cr.execute2 or cr2.execute should not be detected self._cr.execute2( 'SELECT name FROM account WHERE id IN %s' % (tuple(ids),)) cr2.execute( 'SELECT name FROM account WHERE id IN %s' % (tuple(ids),)) def sql_injection_method5(self, ids): var = 'SELECT name FROM account WHERE id IN %s' values = ([1, 2, 3, ], ) self._cr.execute(var % values) # sql injection too
class TestModel(models.Model): _name = 'test.model' _inherit = ['mail.thread'] _columns = {} # deprecated columns _defaults = {} # deprecated defaults length = fields.Integer() # Deprecated length by js errors name = fields.Char( _(u"Näme"), # Don't need translate help=u"My hëlp", required=False, compute='_compute_name', # good compute method name search='_search_name', # good search method name inverse='_inverse_name', # good inverse method name ) # Imported openerp.fields use Char (Upper case) other_field = fields.char( name=_("Other field"), copy=True, compute='my_method_compute', # bad compute method name search='my_method_search', # bad search method name inverse='my_method_inverse', # bad inverse method name ) compute_none = fields.Char(compute=None) other_field2 = fields.char( 'Other Field2', copy=True, ) # This is a inherit overwrite field then don't should show errors related # with creation of fields. def method_date(self): date = fields.Date.to_string( fields.Datetime.context_timestamp(self, timestamp=fields.Datetime.now()) ) return date my_ok_field = fields.Float( "My correctly named field", digits=(6, 6), # OK: Valid field parameter index=True, # OK: Valid field parameter help="My ok field", ) my_ko_field = fields.Float( digits_compute=lambda cr: (6, 6), # Deprecated field parameter select=True, # Deprecated field parameter help="My ko field", string="My Ko Field", # String parameter equal to name of variable ) """The name of the variable is equal to the string parameter Tested all fields.*""" boolean_variable_1 = fields.Boolean(string='Boolean Variable 1', help="Help") boolean_variable_2 = fields.Boolean("Boolean Variable 2", help="Help") char_variable_1 = fields.Char(string='Char Variable 1', help="Help") char_variable_2 = fields.Char("Char Variable 2", help="Help") text_variable_1 = fields.Text(string='Text Variable 1', help="Help") text_variable_2 = fields.Text("Text Variable 2", help="Help") html_variable_1 = fields.Html(string='Html Variable 1', help="Help") html_variable_2 = fields.Html("Html Variable 2", help="Help") integer_variable_1 = fields.Integer(string='Integer Variable 1', help="Help") integer_variable_2 = fields.Integer("Integer Variable 2", help="Help") float_variable_1 = fields.Float(string='Float Variable 1', help="Help") float_variable_2 = fields.Float("Float Variable 2", help="Help") date_variable_1 = fields.Date(string='Date Variable 1', help="Help") date_variable_2 = fields.Date("Date Variable 2", help="Help") date_time_variable_1 = fields.DateTime(string='Date Time Variable 1', help="Help") date_time_variable_2 = fields.DateTime("Date Time Variable 2", help="Help") binary_variable_1 = fields.Binary(string='Binary Variable 1', help="Help") binary_variable_2 = fields.Binary("Binary Variable 2", help="Help") selection_variable_1 = fields.Selection(selection=[('a', 'A')], string='Selection Variable 1', help="Help") selection_variable_2 = fields.Selection([('a', 'A')], "Selection Variable 2", help="Help") reference_variable_1 = fields.Reference(selection=[('res.user', 'User')], string="Reference Variable 1", help="Help") reference_variable_2 = fields.Reference([('res.user', 'User')], "Reference Variable 2", help="Help") many_2_one_variable_1 = fields.Many2one(comodel_name='res.users', string='Many 2 One Variable 1', help="Help") many_2_one_variable_2 = fields.Many2one('res.users', "Many 2 One Variable 2", help="Help") one_2_many_variable_1 = fields.One2many(comodel_name='res.users', inverse_name='rel_id', string='One 2 Many Variable 1', help="Help") one_2_many_variable_2 = fields.One2many('res.users', 'rel_id', "One 2 Many Variable 2", help="Help") many_2_many_variable_1 = fields.Many2many(comodel_name='res.users', relation='table_name', column1='col_name', column2='other_col_name', string='Many 2 Many Variable 1', help="Help") many_2_many_variable_2 = fields.Many2many('res.users', 'table_name', 'col_name', 'other_col_name', "Many 2 Many Variable 2", help="Help") field_case_sensitive = fields.Char( 'Field Case SENSITIVE', help="Field case sensitive" ) name_equal_to_string = fields.Float( "Name equal to string", help="Name Equal To String" ) many_2_one = fields.Many2one( 'res.users', "Many 2 One", help="Many 2 one" ) many_2_many = fields.Many2many( 'res.users', 'relation', 'fk_column_from', 'fk_column_to', "Many 2 many", help="Many 2 Many" ) def my_method1(self, variable1): # Shouldn't show error of field-argument-translate self.my_method2(_('hello world')) # Message post without translation function self.message_post(subject='Subject not translatable', body='Body not translatable %s' % variable1) self.message_post(subject='Subject not translatable %(variable)s' % {'variable': variable1}, body='Body not translatable {}'.format(variable1), message_type='notification') self.message_post('Body not translatable', 'Subject not translatable {a}'.format(a=variable1)) self.message_post('Body not translatable %s' % variable1, 'Subject not translatable %(variable)s' % {'variable': variable1}) self.message_post('Body not translatable', subject='Subject not translatable') # Message post with translation function self.message_post(subject=_('Subject not translatable'), body=_('Body not translatable')) self.message_post(_('Body not translatable'), _('Subject not translatable')) self.message_post(_('Body not translatable'), subject=_('Subject not translatable')) def my_method2(self, variable2): return variable2 def my_method3(self, cr): cr.commit() # Dangerous use of commit old api self.env.cr.commit() # Dangerous use of commit self._cr.commit() # Dangerous use of commit self.cr.commit() # Dangerous use of commit return cr def my_method4(self, variable2): self.env.cr2.commit() # This should not be detected return variable2 def my_method5(self, variable2): self.env.cr.commit2() # This should not be detected return variable2 def my_method6(self): user_id = 1 if user_id != 99: # Method without translation raise UserError('String without translation') def my_method7(self): user_id = 1 if user_id != 99: # Method with translation raise UserError(_('String with translation')) def my_method8(self): user_id = 1 if user_id != 99: str_error = 'String with translation 2' # Don't check raise UserError(str_error) def my_method9(self): user_id = 1 if user_id != 99: # Method without translation raise UserError("String without translation 2") def my_method10(self): # A example of built-in raise without parameters # Shouldn't show error from lint raise ZeroDivisionError raise ZeroDivisionError() def my_method11(self): # A example of built-in raise with parameters # Shouldn't show error from lint raise ZeroDivisionError("String without translation") # raise without class-exception to increase coverage raise raise "obsolete case" def my_method12(self): # Should show error raise exceptions.Warning( 'String with params format {p1}'.format(p1='v1')) raise exceptions.Warning( 'qp2w String with params format %(p1)s' % {'p1': 'v1'}) def my_method13(self): # Shouldn't show error raise exceptions.Warning(_( 'String with params format {p1}').format(p1='v1')) raise exceptions.Warning(_( 'String with params format {p1}'.format(p1='v1'))) raise exceptions.Warning(_( 'String with params format %(p1)s') % {'p1': 'v1'}) raise exceptions.Warning(_( 'String with params format %(p1)s' % {'p1': 'v1'})) def old_api_method_alias(self, cursor, user, ids, context=None): # old api pass def sql_method(self, ids, cr): # Use of query parameters: nothing wrong here self._cr.execute( 'SELECT name FROM account WHERE id IN %s', (tuple(ids),)) self.env.cr.execute( 'SELECT name FROM account WHERE id IN %s', (tuple(ids),)) cr.execute( 'SELECT name FROM account WHERE id IN %s', (tuple(ids),)) self.cr.execute( 'SELECT name FROM account WHERE id IN %s', (tuple(ids),)) def sql_injection_ignored_cases(self, ids, cr2): # This cr.execute2 or cr2.execute should not be detected self._cr.execute2( 'SELECT name FROM account WHERE id IN %s' % (tuple(ids),)) cr2.execute( 'SELECT name FROM account WHERE id IN %s' % (tuple(ids),)) # Ignore when the query is built using private attributes self._cr.execute( 'DELETE FROM %s WHERE id IN %%s' % self._table, (tuple(ids),)) # old api def sql_injection_modulo_operator(self, cr, uid, ids, context=None): # Use of % operator: risky self._cr.execute( 'SELECT name FROM account WHERE id IN %s' % (tuple(ids),)) self.env.cr.execute( 'SELECT name FROM account WHERE id IN %s' % (tuple(ids),)) cr.execute( 'SELECT name FROM account WHERE id IN %s' % (tuple(ids),)) self.cr.execute( 'SELECT name FROM account WHERE id IN %s' % (tuple(ids),)) operator = 'WHERE' self._cr.execute( 'SELECT name FROM account %s id IN %%s' % operator, ids) var = 'SELECT name FROM account WHERE id IN %s' values = ([1, 2, 3, ], ) self._cr.execute(var % values) def sql_injection_executemany(self, ids, cr, v1, v2): # Check executemany() as well self.cr.executemany( 'INSERT INTO account VALUES (%s, %s)' % (v1, v2)) def sql_injection_format(self, ids, cr): # Use of .format(): risky self.cr.execute( 'SELECT name FROM account WHERE id IN {}'.format(ids)) def sql_injection_plus_operator(self, ids, cr): # Use of +: risky self.cr.execute( 'SELECT name FROM account WHERE id IN ' + str(tuple(ids))) operator = 'WHERE' self._cr.execute( 'SELECT name FROM account ' + operator + ' id IN %s', ids) self.cr.execute( ('SELECT name FROM account ' + operator + ' id IN (1)')) self.cr.execute( 'SELECT name FROM account ' + operator + ' id IN %s' % (tuple(ids),)) self.cr.execute( ('SELECT name FROM account ' + operator + ' id IN %s') % (tuple(ids),)) def sql_injection_before(self, ids): # query built before execute: risky as well var = 'SELECT name FROM account WHERE id IN %s' % tuple(ids) self._cr.execute(var) var[1] = 'SELECT name FROM account WHERE id IN %s' % tuple(ids) self._cr.execute(var[1])