[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*ef7005f524and 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:
@@ -3,7 +3,7 @@
|
||||
{
|
||||
'name': 'Extended Addresses',
|
||||
'summary': 'Add extra fields on addresses',
|
||||
'sequence': '19',
|
||||
'sequence': 19,
|
||||
'version': '1.1',
|
||||
'category': 'Hidden',
|
||||
'description': """
|
||||
|
||||
@@ -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',
|
||||
}
|
||||
|
||||
@@ -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,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
|
||||
""",
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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': [
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
'account_edi_proxy_client',
|
||||
],
|
||||
'auto_install': ['l10n_it', 'account_edi'],
|
||||
'author': 'Odoo S.A.',
|
||||
'description': """
|
||||
E-invoice implementation
|
||||
""",
|
||||
|
||||
@@ -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',
|
||||
],
|
||||
|
||||
@@ -55,6 +55,4 @@ There are 2 main Payment Methods additions:
|
||||
'wizards/account_payment_register_views.xml',
|
||||
],
|
||||
'installable': True,
|
||||
'auto_install': False,
|
||||
'application': False,
|
||||
}
|
||||
|
||||
@@ -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": [
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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'],
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user