-
-
Notifications
You must be signed in to change notification settings - Fork 168
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[ADD] New missing-python-import check
This new check finds all files that have a class which inherits from one of Odoo's models classes and ensures they are imported. This is required since classes that interact with the ORM (create models, or inherit them) MUST be imported in the corresponding __init__.py file, otherwise they won't have an effect.
- Loading branch information
Showing
15 changed files
with
228 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
from . import odoo_addons | ||
from . import vim_comment | ||
from . import custom_logging | ||
from . import import_checker |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
from functools import lru_cache | ||
from pathlib import Path | ||
from typing import Set | ||
|
||
from astroid.nodes import ImportFrom, Module | ||
from pylint.checkers.utils import only_required_for_messages | ||
from pylint.lint import PyLinter | ||
|
||
from .odoo_base_checker import OdooBaseChecker | ||
|
||
ODOO_MSGS = { | ||
# C->convention R->refactor W->warning E->error F->fatal | ||
"E8401": ( | ||
"This python file is not imported and has no effect", | ||
"missing-python-import", | ||
"Import it on the corresponding __init__.py file", | ||
), | ||
} | ||
|
||
|
||
class ImportChecker(OdooBaseChecker): | ||
msgs = ODOO_MSGS | ||
name = "odoolint" | ||
|
||
def __init__(self, linter: PyLinter): | ||
self.imports = {} | ||
self.orm_files = {} | ||
|
||
super().__init__(linter) | ||
|
||
@lru_cache() | ||
def _get_odoo_import_orm_names(self, module: Module) -> Set[str]: | ||
results = set() | ||
for import_stmt in filter(lambda node: isinstance(node, ImportFrom), module.body): | ||
if import_stmt.modname == "odoo": | ||
if any("models" in name for name in import_stmt.names): | ||
results.add("models") | ||
elif import_stmt.modname == "odoo.models": | ||
results.update([name[0] for name in import_stmt.names]) | ||
|
||
return results | ||
|
||
@only_required_for_messages("missing-python-import") | ||
def visit_classdef(self, node) -> None: | ||
odoo_imports = self._get_odoo_import_orm_names(node.parent) | ||
if "models" in odoo_imports: | ||
not_orm = not any( | ||
(basename.startswith("models.") or basename in odoo_imports) for basename in node.basenames | ||
) | ||
else: | ||
not_orm = not any(basename in odoo_imports for basename in node.basenames) | ||
|
||
if not_orm: | ||
return | ||
|
||
node_dir = str(Path(node.parent.file).parent) | ||
if not self.orm_files.get(node_dir, False): | ||
self.orm_files[node_dir] = set() | ||
|
||
self.orm_files[node_dir].add(node.parent) | ||
|
||
@only_required_for_messages("missing-python-import") | ||
def visit_importfrom(self, node) -> None: | ||
if node.modname or Path(node.parent.file).name != "__init__.py": | ||
return | ||
|
||
node_dir = str(Path(node.parent.file).parent) | ||
if not self.imports.get(node_dir, False): | ||
self.imports[node_dir] = set() | ||
|
||
for name in node.names: | ||
self.imports[node_dir].add(name[0]) | ||
|
||
def close(self) -> None: | ||
for key, values in self.orm_files.items(): | ||
for value in values: | ||
if Path(value.file).name[:-3] not in self.imports.get(key, {}): | ||
self.add_message("missing-python-import", node=value) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
This module is designed to test messages related to import errors. | ||
Expected Messages: | ||
|
||
* missing-python-import: 2 | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
from . import models |
10 changes: 10 additions & 0 deletions
10
testing/resources/test_repo/imports_module/__manifest__.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
{ | ||
'name': 'Test Import Messages', | ||
'license': 'AGPL-3', | ||
'author': 'Vauxoo, Odoo Community Association (OCA)', | ||
'version': '11.0.0.0.0', | ||
'depends': [ | ||
'base', | ||
], | ||
'data': [], | ||
} |
2 changes: 2 additions & 0 deletions
2
testing/resources/test_repo/imports_module/models/__init__.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
from . import res_partner | ||
from . import project_task |
6 changes: 6 additions & 0 deletions
6
testing/resources/test_repo/imports_module/models/fail_model.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
from odoo.models import BaseModel | ||
|
||
class FailModel(BaseModel): | ||
_name = "fail.model" | ||
|
||
not_imported = fields.Boolean(default=True) |
14 changes: 14 additions & 0 deletions
14
testing/resources/test_repo/imports_module/models/project_task.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
from odoo import models, fields | ||
import argparse | ||
|
||
|
||
class MyParser(argparse.ArgumentParser): | ||
|
||
def random_function(self): | ||
return f"{self.name} -- This class does not need importing. But the other one in this file does!" | ||
|
||
|
||
class ProjectTask(models.Model): | ||
_name = "project.task" | ||
|
||
random_field = fields.Boolean() |
8 changes: 8 additions & 0 deletions
8
testing/resources/test_repo/imports_module/models/res_partner.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
from odoo import fields | ||
from odoo.models import BaseModel | ||
|
||
|
||
class ResPartner(BaseModel): | ||
_name = "res.partner" | ||
|
||
random_field = fields.Char() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
from . import pass_wizard |
7 changes: 7 additions & 0 deletions
7
testing/resources/test_repo/imports_module/wizard/fail_wizard.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
from odoo import fields, models | ||
|
||
|
||
class FailWizard(models.AbstractModel): | ||
_name = "fail.wizard" | ||
|
||
name = fields.Char() |
8 changes: 8 additions & 0 deletions
8
testing/resources/test_repo/imports_module/wizard/pass_wizard.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
from odoo.models import AbstractModel | ||
from odoo import fields | ||
|
||
|
||
class PassWizard(AbstractModel): | ||
_name = "pass.wizard" | ||
|
||
name = fields.Char(required=True) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters