Skip to content

Commit

Permalink
Report root node for unused components, test
Browse files Browse the repository at this point in the history
  • Loading branch information
elikoga committed Dec 20, 2023
1 parent 82a7607 commit b675af2
Show file tree
Hide file tree
Showing 5 changed files with 60 additions and 15 deletions.
21 changes: 21 additions & 0 deletions src/batou/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -453,6 +453,27 @@ def report(self):
)


class UnusedComponentsInitialized(ConfigurationError):
"""Some components were initialized but never used."""

sort_key = (5, "unused")

@classmethod
def from_context(cls, components, root):
self = cls()
self.unused_components = []
for component in components:
self.unused_components.append(repr(component.__class__.__name__))
self.root_name = root.name
return self

def __str__(self):
return f"Unused components: {', '.join(self.unused_components)}"

def report(self):
output.error(f"Unused components: {', '.join(self.unused_components)}")


class UnsatisfiedResources(ConfigurationError):
"""Some required resources were never provided."""

Expand Down
30 changes: 16 additions & 14 deletions src/batou/environment.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
SuperfluousSection,
UnknownComponentConfigurationError,
UnsatisfiedResources,
UnusedComponentsInitialized,
UnusedResources,
)
from batou._output import output
Expand Down Expand Up @@ -497,6 +498,7 @@ def configure(self):

for root in working_set:
try:
Component.instances.clear()
self.resources.reset_component_resources(root)
root.overrides = self.overrides.get(root.name, {})
root.prepare()
Expand All @@ -516,9 +518,20 @@ def configure(self):
)
)
else:
# configured this component successfully
# we won't have to retry it later
continue
unprepared_components = []
for component in Component.instances:
if not component._prepared:
unprepared_components.append(component)
if unprepared_components:
exceptions.append(
UnusedComponentsInitialized.from_context(
unprepared_components, root
)
)
if not exceptions:
# configured this component successfully
# we won't have to retry it later
continue
retry.add(root)

retry.update(self.resources.dirty_dependencies)
Expand Down Expand Up @@ -566,17 +579,6 @@ def configure(self):
UnusedResources.from_context(self.resources.unused)
)

# if any of Component.instances has ._prepared == False, then
# warn via output.annotate
if not exceptions:
for component in Component.instances:
if not component._prepared:
output.warn(
"A Component '{}' was initialized but was not prepared (configured).\nThis may not be what you want".format(
component.__class__.__name__
),
)

for root in order:
root.log_finish_configure()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,3 +62,12 @@ def configure(self):
class Sub(Component):
def configure(self):
self.log("Sub!")


class Unused(Component):
pass


class BadUnused(Component):
def configure(self):
Unused()
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
[environment]
connect_method = local

[hosts]
localhost = badunused
10 changes: 9 additions & 1 deletion src/batou/tests/test_environment.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

import batou
import batou.utils
from batou.component import Component
from batou.component import Component, RootComponent
from batou.environment import Config, Environment
from batou.host import Host

Expand Down Expand Up @@ -336,3 +336,11 @@ def test_resolver_overrides_invalid_address(sample_service):
errors = e.configure()
assert len(errors) == 1
assert "thisisinvalid" == errors[0].address


def test_unused_components_get_reported(sample_service):
e = Environment("test-unused")
e.load()
errors = e.configure()

assert any(isinstance(e, batou.UnusedComponentsInitialized) for e in errors)

0 comments on commit b675af2

Please sign in to comment.