[IMP] test_lint: detect useless manifest content

Keep the manifests as light as possible, to easily see custom behavior/content.
Complete the work of previous commits cleaning the manifests content:

* 42bad1a6d2
* ef7005f524

and make sure this kind of cleanup commit is not necessary in the future
because it is now automatically verified by a dedicated test.

closes odoo/odoo#107735

Related: odoo/enterprise#34903
Signed-off-by: Julien Castiaux <juc@odoo.com>
This commit is contained in:
Victor Feyens
2022-12-16 16:17:41 +01:00
parent 608aa8ca88
commit 13ccd9cee4
26 changed files with 99 additions and 36 deletions
+1 -1
View File
@@ -3,7 +3,7 @@
{
'name': 'Extended Addresses',
'summary': 'Add extra fields on addresses',
'sequence': '19',
'sequence': 19,
'version': '1.1',
'category': 'Hidden',
'description': """
-1
View File
@@ -9,6 +9,5 @@ The module adds google user in res user.
========================================
""",
'depends': ['base_setup'],
'data': [],
'license': 'LGPL-3',
}
@@ -15,7 +15,6 @@
'security/ir.model.access.csv',
],
'installable': True,
'application': False,
'auto_install': True,
'license': 'LGPL-3',
}
+1 -1
View File
@@ -3,7 +3,7 @@
{
'name': 'Web Routing',
'summary': 'Web Routing',
'sequence': '9100',
'sequence': 9100,
'category': 'Hidden',
'description': """
Proposes advanced routing options not available in web or base to keep
-2
View File
@@ -2,10 +2,8 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
{
'name': 'Bulgaria - Accounting',
'icon': '/l10n_bg/static/description/icon.png',
'version': '1.0',
'category': 'Accounting/Localizations/Account Charts',
'author': 'Odoo S.A.',
'description': """
Chart accounting and taxes for Bulgaria
""",
-1
View File
@@ -6,7 +6,6 @@
'version': '1.0',
'category': 'Accounting/Localizations',
'description': "This is the base module that defines the DIN 5008 standard in Odoo.",
'author': 'Odoo S.A.',
'depends': ['account'],
'data': [
'report/din5008_report.xml',
-1
View File
@@ -8,7 +8,6 @@
This module integrate with the ETA Portal to automatically sign and send your invoices to the tax Authority.
Special thanks to Plementus <info@plementus.com> for their help in developing this module.
""",
'author': 'Odoo S.A.',
'website': 'https://www.odoo.com',
'category': 'account',
'version': '0.1',
-1
View File
@@ -3,7 +3,6 @@
{
'name': 'G.C.C. - Arabic/English Invoice',
'version': '1.0.0',
'author': 'Odoo S.A.',
'category': 'Accounting/Localizations',
'description': """
Arabic/English for GCC
-1
View File
@@ -2,7 +2,6 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
{
'name': 'Gulf Cooperation Council - Point of Sale',
'author': 'Odoo S.A.',
'category': 'Accounting/Localizations/Point of Sale',
'description': """
GCC POS Localization
-1
View File
@@ -6,7 +6,6 @@
'version': '1.0',
'category': 'Accounting/Localizations/Account Charts',
'description': """ This is the base module to manage chart of accounting and localization for Hong Kong """,
'author': 'Odoo S.A.',
'depends': ['account'],
'data': [
'data/account_chart_template_data.xml',
+1 -2
View File
@@ -4,14 +4,13 @@
"name": "Croatia - Accounting",
"description": """
Croatian Chart of Accounts updated (RRIF ver.2021)
Sources:
https://www.rrif.hr/dok/preuzimanje/Bilanca-2016.pdf
https://www.rrif.hr/dok/preuzimanje/RRIF-RP2021.PDF
https://www.rrif.hr/dok/preuzimanje/RRIF-RP2021-ENG.PDF
""",
"version": "13.0",
"author": "Odoo S.A.",
'category': 'Accounting/Localizations/Account Charts',
'depends': [
-1
View File
@@ -13,7 +13,6 @@
'account_edi_proxy_client',
],
'auto_install': ['l10n_it', 'account_edi'],
'author': 'Odoo S.A.',
'description': """
E-invoice implementation
""",
-1
View File
@@ -8,7 +8,6 @@
'description': """
This provides a base chart of accounts and taxes template for use in Odoo.
""",
'author': 'Odoo S.A.',
'depends': [
'account',
],
-2
View File
@@ -55,6 +55,4 @@ There are 2 main Payment Methods additions:
'wizards/account_payment_register_views.xml',
],
'installable': True,
'auto_install': False,
'application': False,
}
+1 -1
View File
@@ -10,7 +10,7 @@
{
"name": "Romania - Accounting",
"author": ["Fekete Mihai (NextERP Romania SRL)", "Odoo S.A."],
"author": "Fekete Mihai (NextERP Romania SRL), Odoo S.A.",
'category': 'Accounting/Localizations/Account Charts',
'version': '1.0',
"depends": [
-1
View File
@@ -2,7 +2,6 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
{
'name': 'Saudi Arabia - Point of Sale',
'author': 'Odoo S.A.',
'category': 'Accounting/Localizations/Point of Sale',
'description': """
K.S.A. POS Localization
-1
View File
@@ -4,7 +4,6 @@
{
"name": "Slovenian - Accounting",
"version": "1.1",
"author": "Odoo S.A.",
"category": "Accounting/Localizations/Account Charts",
"description": """
Chart of accounts and taxes for Slovenia.
+1 -1
View File
@@ -5,7 +5,7 @@
'name': 'Phone Numbers Validation',
'version': '2.1',
'summary': 'Validate and format phone numbers',
'sequence': '9999',
'sequence': 9999,
'category': 'Hidden',
'description': """
Phone Numbers Validation
+1 -1
View File
@@ -4,7 +4,7 @@
{
'name': 'Customer Portal',
'summary': 'Customer Portal',
'sequence': '9000',
'sequence': 9000,
'category': 'Hidden',
'description': """
This module adds required base code for a fully integrated customer portal.
-1
View File
@@ -6,7 +6,6 @@
'category': 'Sales/Point of Sale',
'sequence': 6,
'summary': 'Integrate your POS with a Stripe payment terminal',
'description': '',
'data': [
'views/pos_payment_method_views.xml',
'views/assets_stripe.xml',
@@ -7,9 +7,7 @@
"summary": "Spreadsheet",
"description": "Spreadsheet",
"depends": ["spreadsheet"],
"demo": [],
"installable": True,
"auto_install": False,
"license": "LGPL-3",
"data": [
"security/security.xml",
@@ -10,7 +10,6 @@ To configure product attributes, activate *Attributes & Variants* in the Website
Finally, the module comes with an option to display an attribute summary table in product web pages (available in Customize menu).
""",
'author': 'Odoo S.A.',
'category': 'Website/Website',
'version': '1.0',
'depends': ['website_sale'],
@@ -6,7 +6,6 @@
'description': """
Allow shoppers of your eCommerce store to create personalized collections of products they want to buy and save them for future reference.
""",
'author': 'Odoo S.A.',
'category': 'Website/Website',
'version': '1.0',
'depends': ['website_sale'],
+1 -1
View File
@@ -46,7 +46,7 @@ class TestModuleManifest(BaseCase):
'demo_xml': [],
'depends': [],
'description': '',
'external_dependencies': [],
'external_dependencies': {},
'icon': '/base/static/description/icon.png',
'init_xml': [],
'installable': True,
+91 -7
View File
@@ -1,9 +1,14 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo.modules import get_modules
from odoo.modules.module import load_manifest, _DEFAULT_MANIFEST
from odoo.tests import BaseCase
import logging
from ast import literal_eval
from odoo.modules import get_modules
from odoo.modules.module import _DEFAULT_MANIFEST, module_manifest, get_module_path, get_module_resource
from odoo.tests import BaseCase
from odoo.tools import file_open
_logger = logging.getLogger(__name__)
MANIFEST_KEYS = {
'name', 'icon', 'addons_path', 'license', # mandatory keys
@@ -13,9 +18,88 @@ MANIFEST_KEYS = {
class ManifestLinter(BaseCase):
def test_manifests_keys(self):
def _load_manifest(self, module):
"""Do not rely on odoo/modules/module -> load_manifest
as we want to check manifests content, independently of the
values from _DEFAULT_MANIFEST added automatically by load_manifest
"""
mod_path = get_module_path(module, downloaded=True)
manifest_file = module_manifest(mod_path)
manifest_data = {}
with file_open(manifest_file, mode='r') as f:
manifest_data.update(literal_eval(f.read()))
return manifest_data
def test_manifests(self):
for module in get_modules():
with self.subTest(module=module):
manifest_keys = load_manifest(module).keys()
unknown_keys = manifest_keys - MANIFEST_KEYS
self.assertEqual(unknown_keys, set(), f"Unknown manifest keys in module {module!r}. Either there are typos or they must be white listed.")
manifest_data = self._load_manifest(module)
self._test_manifest_keys(module, manifest_data)
self._test_manifest_values(module, manifest_data)
def _test_manifest_keys(self, module, manifest_data):
manifest_keys = manifest_data.keys()
unknown_keys = manifest_keys - MANIFEST_KEYS
self.assertEqual(unknown_keys, set(), f"Unknown manifest keys in module {module!r}. Either there are typos or they must be white listed.")
def _test_manifest_values(self, module, manifest_data):
verified_keys = [
'application', 'auto_install',
'summary', 'description', 'author',
'demo', 'data', 'test',
# todo installable ?
]
for key in manifest_data:
value = manifest_data[key]
if key in _DEFAULT_MANIFEST:
if key in verified_keys:
self.assertNotEqual(
value,
_DEFAULT_MANIFEST[key],
f"Setting manifest key {key} to the default manifest value for module {module!r}. "
"You can remove this key from the dict to reduce noise/inconsistencies between manifests specifications"
" and ease understanding of manifest content."
)
expected_type = type(_DEFAULT_MANIFEST[key])
if not isinstance(value, expected_type):
if key != 'auto_install':
_logger.warning(
"Wrong type for manifest value %s in module %s, expected %s",
key, module, expected_type)
elif not isinstance(value, list):
_logger.warning(
"Wrong type for manifest value %s in module %s, expected bool or list",
key, module)
elif key == 'icon':
self._test_manifest_icon_value(module, value)
def _test_manifest_icon_value(self, module, value):
self.assertTrue(
isinstance(value, str),
f"Wrong type for manifest value icon in module {module!r}, expected string",
)
self.assertNotEqual(
value,
f"/{module}/static/description/icon.png",
f"Setting manifest key icon to the default manifest value for module {module!r}. "
"You can remove this key from the dict to reduce noise/inconsistencies between manifests specifications"
" and ease understanding of manifest content."
)
if not value:
_logger.warning(
"Empty value specified as icon in manifest of module %r."
" Please specify a correct value or remove this key from the manifest.",
module)
else:
path_parts = value.split('/')
path = get_module_resource(path_parts[1], *path_parts[2:])
if not path:
_logger.warning(
"Icon value specified in manifest of module %s wasn't found in given path."
" Please specify a correct value or remove this key from the manifest.",
module)
+1 -1
View File
@@ -35,7 +35,7 @@ _DEFAULT_MANIFEST = {
'demo_xml': [],
'depends': [],
'description': '',
'external_dependencies': [],
'external_dependencies': {},
#icon: f'/{module}/static/description/icon.png', # automatic
'init_xml': [],
'installable': True,