diff --git a/pylint_odoo/checkers/no_modules.py b/pylint_odoo/checkers/no_modules.py index 83c4b740..79095621 100644 --- a/pylint_odoo/checkers/no_modules.py +++ b/pylint_odoo/checkers/no_modules.py @@ -187,6 +187,11 @@ settings.DESC_DFLT ), 'W%d11' % settings.BASE_NOMODULE_ID: ( + 'Field parameter "%s" is no longer supported. Use "%s" instead.', + 'renamed-field-parameter', + settings.DESC_DFLT + ), + 'W%d12' % settings.BASE_NOMODULE_ID: ( '"eval" referenced detected.', 'eval-referenced', settings.DESC_DFLT @@ -226,6 +231,10 @@ DFTL_NO_MISSING_RETURN = [ '__init__', 'setUp', 'tearDown', ] +DFTL_DEPRECATED_FIELD_PARAMETERS = [ + # From odoo/odoo 10.0: odoo/odoo/fields.py:29 + 'digits_compute:digits', 'select:index' +] class NoModuleChecker(BaseChecker): @@ -269,6 +278,19 @@ class NoModuleChecker(BaseChecker): 'help': 'List of attributes deprecated, ' + 'separated by a comma.' }), + ('deprecated_field_parameters', { + 'type': 'csv', + 'metavar': '', + 'default': DFTL_DEPRECATED_FIELD_PARAMETERS, + 'help': 'List of deprecated field parameters, separated by a ' + 'comma. If the param was renamed, separate the old and ' + 'new name with a colon. If the param was removed, keep ' + 'the right side of the colon empty. ' + '"deprecated_param:" means that "deprecated_param" was ' + 'deprecated and it doesn\'t have a new alternative. ' + '"deprecated_param:new_param" means that it was ' + 'deprecated and renamed as "new_param". ' + }), ('method_required_super', { 'type': 'csv', 'metavar': '', @@ -311,9 +333,32 @@ class NoModuleChecker(BaseChecker): }), ) + def open(self): + super(NoModuleChecker, self).open() + self.config.deprecated_field_parameters = \ + self.colon_list_to_dict(self.config.deprecated_field_parameters) + + def colon_list_to_dict(self, colon_list): + """Converts a colon list to a dictionary. + + :param colon_list: A list of strings representing keys and values, + separated with a colon. If a key doesn't have a value, keep the + right side of the colon empty. + :type colon_list: list + :returns: A dictionary with the values assigned to corresponding keys. + :rtype: dict + + :Example: + + >>> self.colon_list_to_dict(['colon:list', 'empty_key:']) + {'colon': 'list', 'empty_key': ''} + """ + return dict(item.split(":") for item in colon_list) + @utils.check_messages('translation-field', 'invalid-commit', 'method-compute', 'method-search', 'method-inverse', 'sql-injection', + 'renamed-field-parameter' ) def visit_call(self, node): if node.as_string().lower().startswith('fields.'): @@ -322,6 +367,7 @@ def visit_call(self, node): argument_aux = argument if isinstance(argument, astroid.Keyword): argument_aux = argument.value + deprecated = self.config.deprecated_field_parameters if argument.arg in ['compute', 'search', 'inverse'] and \ isinstance(argument_aux, astroid.Const) and \ isinstance(argument_aux.value, string_types) and \ @@ -329,6 +375,11 @@ def visit_call(self, node): '_' + argument.arg + '_'): self.add_message('method-' + argument.arg, node=argument_aux) + elif (argument.arg in deprecated): + self.add_message( + 'renamed-field-parameter', node=node, + args=(argument.arg, deprecated[argument.arg]) + ) if isinstance(argument_aux, astroid.CallFunc) and \ isinstance(argument_aux.func, astroid.Name) and \ argument_aux.func.name == '_': diff --git a/pylint_odoo/test/main.py b/pylint_odoo/test/main.py index c346c003..e458bda6 100644 --- a/pylint_odoo/test/main.py +++ b/pylint_odoo/test/main.py @@ -55,6 +55,7 @@ 'wrong-tabs-instead-of-spaces': 2, 'eval-referenced': 5, 'xml-syntax-error': 2, + 'renamed-field-parameter': 2, 'xml-attribute-translatable': 1, } diff --git a/pylint_odoo/test_repo/broken_module/models/broken_model.py b/pylint_odoo/test_repo/broken_module/models/broken_model.py index ea275855..bcab36f0 100644 --- a/pylint_odoo/test_repo/broken_module/models/broken_model.py +++ b/pylint_odoo/test_repo/broken_module/models/broken_model.py @@ -46,6 +46,18 @@ class TestModel(models.Model): copy=True, ) + my_ok_field = fields.Float( + 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", + ) + def my_method1(self, variable1): # Shouldn't show error of field-argument-translate self.my_method2(_('hello world'))