iPOPO Components
A component is an object with a life-cycle, requiring services and providing ones, and associated to properties. The code of a component is reduced to its functional purpose: its life-cycle, dependencies, etc. are handled by iPOPO. In iPOPO, a component is an instance of component factory, i.e. a Python class manipulated with the iPOPO decorators.
Life-cycle

The component life cycle is handled by an instance manager created by the iPOPO service. This instance manager will inject control methods, run-time dependencies, and will register the component services. All changes will be notified to the component using the callback methods it decorated.
State |
Description |
---|---|
INSTANTIATED |
The component has been instantiated. Its constructor has been called and the control methods have been injected |
VALIDATED |
All required dependencies have been injected. All services provided by the component will be registered right after this method returned |
KILLED |
The component has been invalidated and won’t be usable again |
ERRONEOUS |
The component raised an error during its validation. It is not destroyed and a validation can be retried manually |
API
iPOPO components are handled through the iPOPO core service, which can itself
be accessed through the Pelix API or the utility context manager
use_ipopo()
.
The core service provides the pelix.ipopo.core
specification.
- pelix.ipopo.constants.use_ipopo(bundle_context: BundleContext) Generator[IPopoService, None, None]
Utility context to use the iPOPO service safely in a “with” block. It looks after the the iPOPO service and releases its reference when exiting the context.
- Parameters:
bundle_context – The calling bundle context
- Returns:
The iPOPO service
- Raises:
BundleException – Service not found
The following snippet shows how to use this method:
from pelix.ipopo.constants import use_ipopo # ... considering "context" being a BundleContext object with use_ipopo(context) as ipopo: # use the iPOPO core service with the "ipopo" variable ipopo.instantiate("my.factory", "my.component", {"some.property": [1, 2, 3], "answer": 42}) # ... out of the "with" context, the iPOPO service has been released # and shouldn't be used
Here are the most commonly used methods from the iPOPO core service to handle components and factories:
- class pelix.ipopo.constants.IPopoService(*args, **kwargs)
Interface of the iPOPO core service
- get_factories() List[str]
Retrieves the names of the registered factories
- Returns:
A list of factories. Can be empty.
- get_factory_details(name: str) Dict[str, Any]
Retrieves a dictionary with details about the given factory
name
: The factory namebundle
: The Bundle object of the bundle providing the factoryproperties
: Copy of the components properties defined by the factoryrequirements
: List of the requirements defined by the factoryid
: Requirement ID (field where it is injected)specification
: Specification of the required serviceaggregate
: If True, multiple services will be injectedoptional
: If True, the requirement is optional
services
: List of the specifications of the services provided by components of this factoryhandlers
: Dictionary of the non-built-in handlers required by this factory. The dictionary keys are handler IDs, and it contains a tuple with:A copy of the configuration of the handler (0)
A flag indicating if the handler is present or not
- Parameters:
name – The name of a factory
- Returns:
A dictionary describing the factory
- Raises:
ValueError – Invalid factory
- get_instance_details(name: str) Dict[str, Any]
Retrieves a snapshot of the given component instance. The result dictionary has the following keys:
name
: The component namefactory
: The name of the component factorybundle_id
: The ID of the bundle providing the component factorystate
: The current component stateservices
: A{Service ID → Service reference}
dictionary, with all services provided by the componentdependencies
: A dictionary associating field names with the following dictionary:handler
: The name of the type of the dependency handlerfilter
(optional): The requirement LDAP filteroptional
: A flag indicating whether the requirement is optional or notaggregate
: A flag indicating whether the requirement is a set of services or notbinding
: A list of the ServiceReference the component is bound to
properties
: A dictionary key → value, with all properties of the component. The value is converted to its string representation, to avoid unexpected behaviours.
- Parameters:
name – The name of a component instance
- Returns:
A dictionary of details
- Raises:
ValueError – Invalid component name
- get_instances() List[Tuple[str, str, int]]
Retrieves the list of the currently registered component instances
- Returns:
A list of (name, factory name, state) tuples.
- instantiate(factory_name: str, name: str, properties: Dict[str, Any] | None = None) Any
Instantiates a component from the given factory, with the given name
- Parameters:
factory_name – Name of the component factory
name – Name of the instance to be started
properties – Initial properties of the component instance
- Returns:
The component instance
- Raises:
TypeError – The given factory is unknown
ValueError – The given name or factory name is invalid, or an instance with the given name already exists
Exception – Something wrong occurred in the factory
- kill(name: str) None
Kills the given component
- Parameters:
name – Name of the component to kill
- Raises:
ValueError – Invalid component name
- retry_erroneous(name: str, properties_update: Dict[str, Any] | None = None) int
Removes the ERRONEOUS state of the given component, and retries a validation
- Parameters:
name – Name of the component to retry
properties_update – A dictionary to update the initial properties of the component
- Returns:
The new state of the component
- Raises:
ValueError – Invalid component name
Listening to components events
The iPOPO service can be used to register to component events, using the following methods:
- class pelix.ipopo.constants.IPopoService(*args, **kwargs)
Interface of the iPOPO core service
- add_listener(listener: IPopoEventListener) bool
Register an iPOPO event listener.
The event listener must have a method with the following prototype:
def handle_ipopo_event(self, event): ''' event: A IPopoEvent object ''' # ...
- Parameters:
listener – The listener to register
- Returns:
True if the listener has been added to the registry
- remove_listener(listener: IPopoEventListener) bool
Unregister an iPOPO event listener.
- Parameters:
listener – The listener to register
- Returns:
True if the listener has been removed from the registry
A component listener must implement the following interface:
- class pelix.ipopo.constants.IPopoEventListener(*args, **kwargs)
Interface of iPOPO events listeners
- handle_ipopo_event(event: IPopoEvent) None
Handles an iPOPO event
- Parameters:
event – Event to handle
A word on Data classes
These indications have to be taken into account when using iPOPO decorators on data classes.
Important notes
All fields of the Data Class must have a default value. This will let the
@dataclass
decorator generate an__init__
method without explicit arguments, which is a requirement for iPOPO.If the
init=False
argument is given to@dataclass
, it is necessary to implement your own__init__
, defining all fields, otherwise generated methods like__repr__
won’t work.
Good to know
Injected fields (
@Property
,@Requires
, …) will lose the default value given in the class definition, in favor to the ones given to the iPOPO decorators. This is due to the redefinition of the fields by those decorators. Other fields are not touched at all.The
@dataclass
decorator can be used before or after the iPOPO decorators
iPOPO Waiting List
iPOPO provides a utility service to register components to a waiting list, which will try to instantiate them when a new iPOPO component factory or a new iPOPO handler is available. This is useful for softwares using a composition described in a configuration file: add an instant to the list and let iPOPO instantiate it when possible.
This feature is provided by the pelix.ipopo.waiting
bundle, which must be
installed and active. Note that the pelix.ipopo.core
bundle can be installed
and started later: the waiting list will try to instantiate components as
soon as the iPOPO service is found.
To use the iPOPO waiting list, get the pelix.ipopo.constants.IPopoWaitingList
service (or by its name: pelix.ipopo.waiting_list
) which provides the
following methods:
- class pelix.ipopo.constants.IPopoWaitingList(*args, **kwargs)
iPOPO instantiation waiting list
- add(factory: str, component: str, properties: Dict[str, Any] | None = None) None
Enqueues the instantiation of the given component
- Parameters:
factory – Factory name
component – Component name
properties – Component properties
- Raises:
ValueError – Component name already reserved in the queue
Exception – Error instantiating the component
- remove(component: str) None
Kills/Removes the component with the given name
- Parameters:
component – A component name
- Raises:
KeyError – Unknown component