From 4706a61a1533b85d49a8ded01de51f3cd56966a6 Mon Sep 17 00:00:00 2001 From: Daniel Silverstone Date: Wed, 17 Oct 2018 13:36:46 +0100 Subject: _loader/loader.py: Be more explanatory in CircDep exception When a circular dependency is detected, the reported error hilights only one part of the loop in question. This change ensures that the entire loop is listed so that the user has a greater chance of easily determining the correct fix. Signed-off-by: Daniel Silverstone --- buildstream/_loader/loader.py | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) (limited to 'buildstream/_loader/loader.py') diff --git a/buildstream/_loader/loader.py b/buildstream/_loader/loader.py index 1bdbca90f..5f6d23a71 100644 --- a/buildstream/_loader/loader.py +++ b/buildstream/_loader/loader.py @@ -296,12 +296,14 @@ class Loader(): # Raises: # (LoadError): In case there was a circular dependency error # - def _check_circular_deps(self, element_name, check_elements=None, validated=None): + def _check_circular_deps(self, element_name, check_elements=None, validated=None, sequence=None): if check_elements is None: check_elements = {} if validated is None: validated = {} + if sequence is None: + sequence = [] element = self._elements[element_name] @@ -314,16 +316,24 @@ class Loader(): return if check_elements.get(element_name) is not None: + # Create `chain`, the loop of element dependencies from this + # element back to itself, by trimming everything before this + # element from the sequence under consideration. + chain = sequence[sequence.index(element_name):] + chain.append(element_name) raise LoadError(LoadErrorReason.CIRCULAR_DEPENDENCY, - "Circular dependency detected for element: {}" - .format(element.name)) + ("Circular dependency detected at element: {}\n" + + "Dependency chain: {}") + .format(element.name, " -> ".join(chain))) # Push / Check each dependency / Pop check_elements[element_name] = True + sequence.append(element_name) for dep in element.deps: loader = self._get_loader_for_dep(dep) - loader._check_circular_deps(dep.name, check_elements, validated) + loader._check_circular_deps(dep.name, check_elements, validated, sequence) del check_elements[element_name] + sequence.pop() # Eliminate duplicate paths validated[element_name] = True -- cgit v1.2.1