Disclaimer: Code shown here is not tested.
Figured out a half-solution after reading this:
Basically, you can access the other extensions at the cost of coupling some of them. It is useful for de-coupling the code, but not their functional dependency on each other. This is how to do it:
class DependencyA(DependencyProvider):
def setup(self):
...
def get_dependency(self, worker_ctx):
...
class DepencyB(DependencyProvider):
def setup(self):
...
def start(self):
# at this point all other extensions (entrypoints / dependencies) already went
# through the 'setup' phase.
# creates a map from attribute name (defined in the main service class) to the dependency
# provider.
dependency_providers = {dep.attr_name: dep for dep in self.container.dependencies}
# get dependency by attribute name
dependency_a = dependency_providers['dependency_a'].get_dependency(None)
# get dependency by simple type checking
results = list(filter(lambda d: isinstance(d, (DependencyA,)), dependency_providers.values()))
if len(results) >= 1:
dependency_a = results[0].get_dependency(None)
Definitely not simple, but helps to mitigate spaghetti code a little (when one dependency is doing too much).