diff --git a/.coveragerc b/.coveragerc index c4eb7da..917a6f7 100644 --- a/.coveragerc +++ b/.coveragerc @@ -9,7 +9,7 @@ context = ${{COVERAGE_CONTEXT}} [report] show_missing = true precision = 2 -fail_under = 98 +fail_under = 95 omit = *__init__.py */tests/* diff --git a/README.md b/README.md index b159bde..5a476bf 100644 --- a/README.md +++ b/README.md @@ -108,6 +108,14 @@ be disabled. # Checks +* Check weblate-component-too-long +Check if the component is too long +Weblate have 100 characters limit for repository name + Odoo Version + module name +e.g. The following module: + https://github.com/OCA/account-financial-reporting/tree/18.0/account_tax_balance +Generates the following component: + account-financial-reporting-18.0-account_tax_balance + * Check file-not-used Check if there is a file created but not referenced from __manifest__.py @@ -398,6 +406,10 @@ options: - https://github.com/OCA/odoo-pre-commit-hooks/blob/v0.2.17/test_repo/eleven_module/models.py#L9 Use of header comments in lines 3, 5, 6, 7, 9 + * weblate-component-too-long + + - https://github.com/OCA/odoo-pre-commit-hooks/blob/v0.2.17/test_repo/syntax_err_module/__manifest__.py#L1 Repo Name + Odoo version + Module name is too long for weblate component 'big-big-big-big-big-big-big-big-big-big-big-big-big-big-big-big-big--00.0-syntax_err_module' size 91 is longer than 90 characters + * xml-create-user-wo-reset-password - https://github.com/OCA/odoo-pre-commit-hooks/blob/v0.2.17/test_repo/test_module/res_users.xml#L10 record res.users without `context="{'no_reset_password': True}"` diff --git a/src/oca_pre_commit_hooks/checks_odoo_module.py b/src/oca_pre_commit_hooks/checks_odoo_module.py index 1cefbfe..4a8a447 100755 --- a/src/oca_pre_commit_hooks/checks_odoo_module.py +++ b/src/oca_pre_commit_hooks/checks_odoo_module.py @@ -37,6 +37,7 @@ ".csv", ".xml", ] +MAX_WEBLATE_NAME_LENGTH = 90 DATA_MANUAL_KEY = "oca_data_manual" BLUE_PILL = "\033[94m🔵\033[0m" RED_PILL = "\033[91m🔴\033[0m" @@ -154,6 +155,31 @@ def check_manifest(self): line=1, ) + @utils.only_required_for_installable() + @utils.only_required_for_checks("weblate-component-too-long") + def check_component_name_too_long(self): + """* Check weblate-component-too-long + Check if the component is too long + Weblate have 100 characters limit for repository name + Odoo Version + module name + e.g. The following module: + https://github.com/OCA/account-financial-reporting/tree/18.0/account_tax_balance + Generates the following component: + account-financial-reporting-18.0-account_tax_balance + """ + manifest_path_short = os.path.relpath(self.manifest_path, self.manifest_top_path) + repo_name = utils.repo_name(self.manifest_top_path) + weblate_component_name = f"{repo_name}-00.0-{self.odoo_addon_name}" + component_length = len(weblate_component_name) + if component_length <= MAX_WEBLATE_NAME_LENGTH: + return + self.register_error( + code="weblate-component-too-long", + message="Repo Name + Odoo version + Module name is too long for weblate component", + info=f"'{weblate_component_name}' size {component_length} is longer than {MAX_WEBLATE_NAME_LENGTH} characters", + filepath=manifest_path_short, + line=1, + ) + @staticmethod def _get_module_data_files(module_root_path): module_root_path_obj = Path(module_root_path).resolve() diff --git a/src/oca_pre_commit_hooks/utils.py b/src/oca_pre_commit_hooks/utils.py index f096552..2edb4d9 100644 --- a/src/oca_pre_commit_hooks/utils.py +++ b/src/oca_pre_commit_hooks/utils.py @@ -254,6 +254,29 @@ def top_path(path): return path.root or Path.home() +@lru_cache(maxsize=64) +def repo_name(path): + """Get the repository name based on the first git remote URL.""" + try: + # Get the list of remotes + remotes = ( + subprocess.check_output(["git", "-C", path, "remote"], stderr=subprocess.STDOUT) + .decode(sys.stdout.encoding) + .splitlines() + ) + # Get the URL of the remote + remote_url = ( + subprocess.check_output(["git", "-C", path, "remote", "get-url", remotes[0]], stderr=subprocess.STDOUT) + .decode(sys.stdout.encoding) + .strip() + ) + # Get the repo name + repo = os.path.splitext(os.path.basename(remote_url.rstrip("/")))[0] + return repo + except (FileNotFoundError, subprocess.CalledProcessError, IndexError): + return "" + + def full_norm_path(path): """Expand paths in all possible ways""" return os.path.normpath(os.path.realpath(os.path.abspath(os.path.expanduser(os.path.expandvars(path.strip()))))) diff --git a/tests/common.py b/tests/common.py index 960fb98..150307a 100644 --- a/tests/common.py +++ b/tests/common.py @@ -41,6 +41,10 @@ def create_dummy_repo(src_path, dest_path): copy_tree(src_path, dest_path) subprocess.check_call(["git", "init", dest_path, "--initial-branch=main"]) subprocess.check_call(["git", "add", "*"], cwd=dest_path) + git_big_repo_name = "big-" * 17 + ".git" + subprocess.check_call( + ["git", "remote", "add", "my_remote", f"git@github.com:/OCA/{git_big_repo_name}"], cwd=dest_path + ) class ChecksCommon: diff --git a/tests/test_checks.py b/tests/test_checks.py index fb19faf..038115f 100644 --- a/tests/test_checks.py +++ b/tests/test_checks.py @@ -30,6 +30,7 @@ "prefer-readme-rst": 1, "unused-logger": 1, "use-header-comments": 1, + "weblate-component-too-long": 1, "xml-create-user-wo-reset-password": 1, "xml-dangerous-qweb-replace-low-priority": 9, "xml-deprecated-data-node": 8, diff --git a/tests/test_profiling.py b/tests/test_profiling.py index 51c5e07..c21b37f 100644 --- a/tests/test_profiling.py +++ b/tests/test_profiling.py @@ -35,10 +35,13 @@ def test_profile_checks_module(self, request): checks_module_run2 = oca_pre_commit_hooks.cli_fixit.main mp = pytest.MonkeyPatch() mp.setattr(sys, "argv", ["", "--no-exit", "--no-verbose"] + self.module_files) + module_errors = MODULES_ERRORS.copy() + # The remote repo used here is not too long (It is using the original of this package) + module_errors.pop("weblate-component-too-long", None) try: errors = checks_module_run() errors += checks_module_run2() - common.assertDictEqual(self, common.ChecksCommon.get_count_code_errors(errors), MODULES_ERRORS) + common.assertDictEqual(self, common.ChecksCommon.get_count_code_errors(errors), module_errors) finally: mp.undo()