diff --git a/hooks/conan-center.py b/hooks/conan-center.py index b0b7b52f..bde8b574 100644 --- a/hooks/conan-center.py +++ b/hooks/conan-center.py @@ -7,8 +7,9 @@ import sys from logging import WARNING, ERROR, INFO, DEBUG, NOTSET + +from conans import tools, ConanFile import yaml -from conans import tools try: from conans import Settings except ImportError: @@ -46,6 +47,7 @@ "KB-H031": "CONANDATA.YML REDUCE", "KB-H032": "SYSTEM REQUIREMENTS", "KB-H034": "TEST PACKAGE - NO IMPORTS()", + "KB-H036": "CUSTOM METHODS", "KB-H037": "NO AUTHOR", "KB-H040": "NO TARGET NAME", "KB-H041": "NO FINAL ENDLINE", @@ -421,6 +423,31 @@ def test(out): if "def imports" in test_package_conanfile: out.error("The method `imports` is not allowed in test_package/conanfile.py") + @run_test("KB-H036", output) + def test(out): + def get_methods(conanfile): + methods = [] + for member in dir(conanfile): + + try: + if callable(getattr(conanfile, member)): + methods.append(str(member)) + except: + methods.append(str(member)) + return methods + + mock = ConanFile(conanfile.output, None) + valid_attrs = get_methods(mock) + current_attrs = get_methods(conanfile) + invalid_attrs = re.findall(r"def (__.*[^_])\s?\(", conanfile_content, re.MULTILINE) + for attr in current_attrs: + if not attr.startswith("_") and attr not in valid_attrs: + invalid_attrs.append(attr) + + if invalid_attrs: + out.error("Custom methods must be declared as protected. " \ + "The follow methods are invalid: '{}'".format("', '".join(invalid_attrs))) + @run_test("KB-H037", output) def test(out): author = getattr(conanfile, "author", None) diff --git a/tests/test_hooks/conan-center/test_conan-center.py b/tests/test_hooks/conan-center/test_conan-center.py index 8f8e7cc2..6f0eadec 100644 --- a/tests/test_hooks/conan-center/test_conan-center.py +++ b/tests/test_hooks/conan-center/test_conan-center.py @@ -118,6 +118,7 @@ def test_conanfile(self): self.assertIn("ERROR: [CONAN CENTER INDEX URL (KB-H027)] The attribute 'url' should " \ "point to: https://github.com/conan-io/conan-center-index", output) self.assertIn("[CMAKE MINIMUM VERSION (KB-H028)] OK", output) + self.assertIn("[CUSTOM METHODS (KB-H036)] OK", output) self.assertIn("[SYSTEM REQUIREMENTS (KB-H032)] OK", output) self.assertIn("[SINGLE REQUIRES (KB-H055)] OK", output) @@ -141,6 +142,7 @@ def test_conanfile_header_only(self): "recipe", output) self.assertIn("[META LINES (KB-H025)] OK", output) self.assertIn("[CMAKE MINIMUM VERSION (KB-H028)] OK", output) + self.assertIn("[CUSTOM METHODS (KB-H036)] OK", output) self.assertIn("[SYSTEM REQUIREMENTS (KB-H032)] OK", output) def test_conanfile_header_only_with_settings(self): @@ -162,6 +164,7 @@ def test_conanfile_header_only_with_settings(self): "recipe", output) self.assertIn("[META LINES (KB-H025)] OK", output) self.assertIn("[CMAKE MINIMUM VERSION (KB-H028)] OK", output) + self.assertIn("[CUSTOM METHODS (KB-H036)] OK", output) self.assertIn("[SYSTEM REQUIREMENTS (KB-H032)] OK", output) def test_conanfile_settings_clear_with_settings(self): @@ -204,6 +207,7 @@ def test_conanfile_installer(self): "recipe", output) self.assertIn("[META LINES (KB-H025)] OK", output) self.assertIn("[CMAKE MINIMUM VERSION (KB-H028)] OK", output) + self.assertIn("[CUSTOM METHODS (KB-H036)] OK", output) def test_shebang(self): conanfile = textwrap.dedent("""\ @@ -604,6 +608,41 @@ def system_requirements(self): self.assertIn("[SYSTEM REQUIREMENTS (KB-H032)] 'libusb' is part of the allowlist.", output) self.assertNotIn("ERROR: [SYSTEM REQUIREMENTS (KB-H032)]", output) + def test_invalid_recipe_methods(self): + conanfile = textwrap.dedent("""\ + from conans import ConanFile + class AConan(ConanFile): + url = "fake_url.com" + license = "fake_license" + description = "whatever" + homepage = "homepage.com" + topics = ("fake_topic", "another_fake_topic") + + def configure(self): + self.output.info("ok") + + def barbarian(self): + self.output.info("Conan") + + def __my_own_method(self): + self.output.info("foobar") + + def __my_private_method(self): + self.output.info("foobar") + + def __abs__(self): + return self.version + + def _baz(self): + self.output.info("qux") + + """) + tools.save('conanfile.py', content=conanfile) + output = self.conan(['create', '.', 'name/version@user/test']) + self.assertIn("ERROR: [CUSTOM METHODS (KB-H036)] Custom methods must be declared as " + "protected. The follow methods are invalid: '__my_own_method', " + "'__my_private_method', 'barbarian'", output) + def test_imports_not_allowed(self): conanfile_tp = textwrap.dedent("""\ from conans import ConanFile, tools