... |
... |
@@ -296,12 +296,14 @@ class Loader(): |
296
|
296
|
# Raises:
|
297
|
297
|
# (LoadError): In case there was a circular dependency error
|
298
|
298
|
#
|
299
|
|
- def _check_circular_deps(self, element_name, check_elements=None, validated=None):
|
|
299
|
+ def _check_circular_deps(self, element_name, check_elements=None, validated=None, sequence=None):
|
300
|
300
|
|
301
|
301
|
if check_elements is None:
|
302
|
302
|
check_elements = {}
|
303
|
303
|
if validated is None:
|
304
|
304
|
validated = {}
|
|
305
|
+ if sequence is None:
|
|
306
|
+ sequence = []
|
305
|
307
|
|
306
|
308
|
element = self._elements[element_name]
|
307
|
309
|
|
... |
... |
@@ -314,16 +316,24 @@ class Loader(): |
314
|
316
|
return
|
315
|
317
|
|
316
|
318
|
if check_elements.get(element_name) is not None:
|
|
319
|
+ # Create `chain`, the loop of element dependencies from this
|
|
320
|
+ # element back to itself, by trimming everything before this
|
|
321
|
+ # element from the sequence under consideration.
|
|
322
|
+ chain = sequence[sequence.index(element_name):]
|
|
323
|
+ chain.append(element_name)
|
317
|
324
|
raise LoadError(LoadErrorReason.CIRCULAR_DEPENDENCY,
|
318
|
|
- "Circular dependency detected for element: {}"
|
319
|
|
- .format(element.name))
|
|
325
|
+ ("Circular dependency detected at element: {}\n" +
|
|
326
|
+ "Dependency chain: {}")
|
|
327
|
+ .format(element.name, " -> ".join(chain)))
|
320
|
328
|
|
321
|
329
|
# Push / Check each dependency / Pop
|
322
|
330
|
check_elements[element_name] = True
|
|
331
|
+ sequence.append(element_name)
|
323
|
332
|
for dep in element.deps:
|
324
|
333
|
loader = self._get_loader_for_dep(dep)
|
325
|
|
- loader._check_circular_deps(dep.name, check_elements, validated)
|
|
334
|
+ loader._check_circular_deps(dep.name, check_elements, validated, sequence)
|
326
|
335
|
del check_elements[element_name]
|
|
336
|
+ sequence.pop()
|
327
|
337
|
|
328
|
338
|
# Eliminate duplicate paths
|
329
|
339
|
validated[element_name] = True
|