Skip to content

Commit

Permalink
Warn on missplaced requirement function calls
Browse files Browse the repository at this point in the history
  • Loading branch information
AbrilRBS committed Mar 18, 2024
1 parent 79a9c18 commit b8f014a
Show file tree
Hide file tree
Showing 4 changed files with 42 additions and 11 deletions.
10 changes: 7 additions & 3 deletions conans/client/conanfile/configure.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,11 @@ def run_configure_method(conanfile, down_options, profile_options, ref):

PackageType.compute_package_type(conanfile)

conanfile.build_requires = BuildRequirements(conanfile.requires)
conanfile.test_requires = TestRequirements(conanfile.requires)
conanfile.tool_requires = ToolRequirements(conanfile.requires)
conanfile._conan_add_requirement_allowed = True

conanfile.build_requires = BuildRequirements(conanfile)
conanfile.test_requires = TestRequirements(conanfile)
conanfile.tool_requires = ToolRequirements(conanfile)

if hasattr(conanfile, "requirements"):
with conanfile_exception_formatter(conanfile, "requirements"):
Expand All @@ -44,3 +46,5 @@ def run_configure_method(conanfile, down_options, profile_options, ref):
if hasattr(conanfile, "build_requirements"):
with conanfile_exception_formatter(conanfile, "build_requirements"):
conanfile.build_requirements()

delattr(conanfile, "_conan_add_requirement_allowed")
2 changes: 1 addition & 1 deletion conans/model/conan_file.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ def __init__(self, display_name=""):
self.generators = [self.generators]
if isinstance(self.settings, str):
self.settings = [self.settings]
self.requires = Requirements(self.requires, self.build_requires, self.test_requires,
self.requires = Requirements(self, self.requires, self.build_requires, self.test_requires,
self.tool_requires)

self.options = Options(self.options or {}, self.default_options)
Expand Down
26 changes: 19 additions & 7 deletions conans/model/requires.py
Original file line number Diff line number Diff line change
Expand Up @@ -387,42 +387,52 @@ def deduce_package_id_mode(self, pkg_type, dep_node, non_embed_mode, embed_mode,

class BuildRequirements:
# Just a wrapper around requires for backwards compatibility with self.build_requires() syntax
def __init__(self, requires):
self._requires = requires
def __init__(self, conanfile):
self._conanfile = conanfile
self._requires = conanfile.requires

def __call__(self, ref, package_id_mode=None, visible=False, run=None, options=None,
override=None):
# TODO: Check which arguments could be user-defined
if not getattr(self._conanfile, "_conan_add_requirement_allowed", False):
self._conanfile.output.warning("build_requires() should only be declared in requirements()/build_requirements()", warn_tag="misplaced_requirement")
self._requires.build_require(ref, package_id_mode=package_id_mode, visible=visible, run=run,
options=options, override=override)


class ToolRequirements:
# Just a wrapper around requires for backwards compatibility with self.build_requires() syntax
def __init__(self, requires):
self._requires = requires
def __init__(self, conanfile):
self._conanfile = conanfile
self._requires = conanfile.requires

def __call__(self, ref, package_id_mode=None, visible=False, run=True, options=None,
override=None):
# TODO: Check which arguments could be user-defined
if not getattr(self._conanfile, "_conan_add_requirement_allowed", False):
self._conanfile.output.warning("tool_requires() should only be declared in requirements()/build_requirements()", warn_tag="misplaced_requirement")
self._requires.tool_require(ref, package_id_mode=package_id_mode, visible=visible, run=run,
options=options, override=override)


class TestRequirements:
# Just a wrapper around requires for backwards compatibility with self.build_requires() syntax
def __init__(self, requires):
self._requires = requires
def __init__(self, conanfile):
self._conanfile = conanfile
self._requires = conanfile.requires

def __call__(self, ref, run=None, options=None, force=None):
if not getattr(self._conanfile, "_conan_add_requirement_allowed", False):
self._conanfile.output.warning("test_requires() should only be declared in requirements()/build_requirements()", warn_tag="misplaced_requirement")
self._requires.test_require(ref, run=run, options=options, force=force)


class Requirements:
""" User definitions of all requires in a conanfile
"""
def __init__(self, declared=None, declared_build=None, declared_test=None,
def __init__(self, conanfile, declared=None, declared_build=None, declared_test=None,
declared_build_tool=None):
self._conanfile = conanfile
self._requires = OrderedDict()
# Construct from the class definitions
if declared is not None:
Expand Down Expand Up @@ -486,6 +496,8 @@ def values(self):

# TODO: Plan the interface for smooth transition from 1.X
def __call__(self, str_ref, **kwargs):
if not getattr(self._conanfile, "_conan_add_requirement_allowed", False):
self._conanfile.output.warning("requires() should only be declared in requirements()/build_requirements()", warn_tag="misplaced_requirement")
if str_ref is None:
return
assert isinstance(str_ref, str)
Expand Down
15 changes: 15 additions & 0 deletions conans/test/integration/build_requires/build_requires_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -581,3 +581,18 @@ def test_build_missing_build_requires():
c.run("install app --build=missing")
assert "- Build" not in c.out
assert re.search(r"Skipped binaries(\s*)tool/0.1, tooldep/0.1", c.out)


def test_requirement_in_wrong_method():
tc = TestClient()
tc.save({"conanfile.py": textwrap.dedent("""
from conan import ConanFile
class Pkg(ConanFile):
name = "pkg"
version = "0.1"
def configure(self):
self.requires("foo/1.0")
""")})
tc.run('create . -cc="core:warnings_as_errors=[\'*\']"', assert_error=True)
assert "ERROR: misplaced_requirement: requires() should only be declared in requirements()/build_requirements()" in tc.out

0 comments on commit b8f014a

Please sign in to comment.