Package: iPOPO
iPOPO: A Service-Oriented Component Model for PythoniPOPOis a Python-based Service-Oriented
Component Model (SOCM) based on Pelix, a dynamic service platform.
They are inspired on two popular Java technologies for the development of
long-lived applications: theiPOJOcomponent model and theOSGiService Platform.
iPOPO enables to conceive long-running and modular IT services.Seehttps://ipopo.readthedocs.io/for documentation and more information.Note on this versionThis is the 1.x branch of iPOPO, which is intended to work with both Python 2.7
and 3.x.If you are working with Python 3.7+ andasyncio, you should look at the 2.x
branch.Usage surveyIn order to gain insight from the iPOPO community, I’ve put areally short surveyon Google Forms (no login required).Please, feel free to answer it, the more answers, the better.
All feedback is really appreciated.ContentsiPOPO: A Service-Oriented Component Model for PythonNote on this versionUsage surveyInstallOption 1: Using pipOption 2: From sourceCheck installConceptsSampleService providerService consumerRun!Batteries includedFeedbackContributingCompatibilityLicenseInstallOption 1: Using pipiPOPO is available onPyPIand can be
installed usingpip:# Install system-wide$sudopipinstalliPOPO# ... or user-wide installation$pipinstall--useriPOPOOption 2: From source$gitclonehttps://github.com/tcalmant/ipopo.git$cdipopo$pythonsetup.pyinstallCheck installTo check if Pelix is installed correctly, run the following command:$python-mpelix.shell--versionPelix0.8.0from/home/tcalmant/git/ipopo/pelix/framework.pyConceptsPelix brings the concept ofbundlein Python.
A bundle is a module with a life cycle: it can be installed, started, stopped,
updated anduninstalled.A bundle can declare a class acting as bundle activator, using the@BundleActivatordecorator.
This class will be instantiated by the framework and itsstart()andstop()method will be called to notify the bundle about its activation and
deactivation.When it is active, a bundle can register services.
A service is an object implementing a specification and associated to a set of
properties.
A component will then be able to select and consume a service according to the
specification(s) it provides and to its properties.The components are a concept brought by iPOPO.
A component, or component instance, is an object managed by a container.
The container handles the interactions between the component and the Pelix
framework.
That way, the component contains only the code required for its task, not for
its bindings with the framework.
A component is an instance of a component factory, a classmanipulatedby iPOPOdecorators.For more information, see theconcepts pageon the wiki.SampleThis sample gives a quick overview of the usage of iPOPO.
For more information, take a look atiPOPO in 10 minutes.Service providerThe following code defines a component factory (a class) which instances will
provide asample.helloservice.# iPOPO decoratorsfrompelix.ipopo.decoratorsimportComponentFactory,Provides,Instantiate# Manipulates the class and sets its (unique) factory name@ComponentFactory("hello-provider-factory")# Indicate that the components will provide a service@Provides("sample.hello")# Tell iPOPO to instantiate a component instance as soon as the file is loaded@Instantiate("hello-provider-auto")# A component class must always inherit from object (new-style class)classHelloProvider(object):"""
    A sample service provider
    """defhello(self,name="world"):"""
        Says hello
        """print("Hello,",name,"!")defbye(self,name="cruel world"):"""
        Says bye
        """print("Bye,",name,"!")When the bundle providing this component factory will be started, iPOPO will
automatically instantiate a component, due to the@Instantiatedecorator.
It is also possible to instantiate a component using shell commands.Each component instance will provide asample.helloservice, which can be
consumed by any bundle or any other component.Service consumerThe following code defines a component factory (a class) which instances will
consume asample.helloservice. If multiple services are available, iPOPO
will select the one with the highest rank and the lowest service ID
(i.e.the oldest service).# iPOPO decoratorsfrompelix.ipopo.decoratorsimportComponentFactory,Requires,Instantiate,\Validate,Invalidate# Manipulates the class and sets its (unique) factory name@ComponentFactory("hello-consumer-factory")# Indicate that the components require a sample.hello service to work# and to inject the found service in the _svc field@Requires('_svc',"sample.hello")# Tell iPOPO to instantiate a component instance as soon as the file is loaded@Instantiate("hello-consumer-auto")# A component class must always inherit from object (new-style class)classHelloConsumer(object):"""
    A sample service consumer
    """def__init__(self):"""
        Defines (injected) members
        """self._svc=None@Validatedefvalidate(self,context):"""
        Component validated: all its requirements have been injected
        """self._svc.hello("Consumer")@Invalidatedefinvalidate(self,context):"""
        Component invalidated: one of its requirements is going away
        """self._svc.bye("Consumer")When the bundle providing this component factory will be started, iPOPO will
automatically instantiate a component, due to the@Instantiatedecorator.Each component instance will require asample.helloservice. Once iPOPO
has injected all the required services (here, a singlesample.helloservice)
in a component instance, this instance will be consideredvalidand iPOPO
will call its method decorated by@Validate.
There, the component can consume its dependencies, start threads, etc..
It is recommended for this method to start threads and to return quickly, as it
blocks iPOPO and the Pelix framework.When a required service is unregistered by its provider, the component
instances consuming it are invalidated.
When the method decorated by@Invalidateis called, the service is still
injected and should be usable (except for special cases, like remote services).Run!To run this sample, you’ll need to copy the snippets above in different files:copy theService providersnippet in a file calledprovider.pycopy theService consumersnippet in a file calledconsumer.pyThen, run a Pelix shell in the same folder as those files, and execute the
commands listed in this trace:$python-mpelix.shell**PelixShellprompt**$# Install the bundles$installproviderBundleID:11$installconsumerBundleID:12$# Start the bundles (the order isn't important here)$start1112Startingbundle11(provider)...Startingbundle12(consumer)...Hello,Consumer!$# View iPOPO instances$instances+----------------------+------------------------------+-------+|Name|Factory|State|+======================+==============================+=======+|hello-consumer-auto|hello-consumer-factory|VALID|+----------------------+------------------------------+-------+|hello-provider-auto|hello-provider-factory|VALID|+----------------------+------------------------------+-------+|ipopo-shell-commands|ipopo-shell-commands-factory|VALID|+----------------------+------------------------------+-------+3componentsrunning$# View details about the consumer$instancehello-consumer-autoName.....:hello-consumer-autoFactory..:hello-consumer-factoryBundleID:12State....:VALIDServices.:Dependencies:Field:_svcSpecification:sample.helloFilter......:NoneOptional.....:FalseAggregate....:FalseHandler......:SimpleDependencyBindings:ServiceReference(ID=11,Bundle=11,Specs=['sample.hello'])Properties:+---------------+---------------------+|Key|Value|+===============+=====================+|instance.name|hello-consumer-auto|+---------------+---------------------+$# Modify the provider file (e.g. change the 'Hello' string by 'Hi')$# Update the provider bundle (ID: 11)$update11Updatingbundle11(provider)...Bye,Consumer!Hi,Consumer!$# Play with other commands (see help)First, theinstallcommands are used to install the bundle: they will be
imported but their activator won’t be called. If this command fails, the bundle
is not installed and is not referenced by the framework.If the installation succeeded, the bundle can be started: it’s activator is
called (if any). Then, iPOPO detects the component factories provided by the
bundle and instantiates the components declared using the@Instantiatedecorator.Theinstancesandinstancecommands can be use to print the state and
bindings of the components. Some other commands are very useful, likeslandsdto list the registered services and print their details. Use thehelpcommand to see which ones can be used.The last part of the trace shows what happens when updating a bundle.
First, update the source code of the provider bundle,e.g.by changing the
string it prints in thehello()method.
Then, tell the framework to update the bundle using theupdatecommand.
This command requires a bundle ID, which has been given as a result of theinstallcommand and can be found usingbl.When updating a bundle, the framework stops it and reloads it (usingimp.reload).
If the update fails, the old version is kept.
If the bundle was active before the update, it is restarted by the framework.Stopping a bundle causes iPOPO to kill the component instance(s) of the
factories it provided.
Therefore, no one provides thesample.helloservice, which causes the
consumer component to be invalidated.
When the provider bundle is restarted, a new provider component is instantiated
and its service is injected in the consumer, which becomes valid again.Batteries includedPelix/iPOPO comes with some useful services:Pelix Shell: a simple shell to control the framework (manage bundles,
show the state of components, …).
The shell is split in 5 parts:the parser: a shell interpreter class, which can be reused to create other
shells (with a basic support of variables);the shell core service: callable from any bundle, it executes the given
command lines;the UIs: text UI (console) and remote shell (TCP/TLS, XMPP)the commands providers: iPOPO commands, report, EventAdmin, …the completion providers: Pelix, iPOPOSee theshell tutorialfor more information.An HTTP service, based on the HTTP server from the standard library.
It provides the concept ofservlet, borrowed from Java.See theHTTP service referencefor more information.There is also arouting utility class,
based on decorators, which eases the development of REST-like servlets.Remote Services: export and import services to/from other Pelix framework or
event Java OSGi frameworks!See theremote services referencefor more information.Pelix also provides an implementation of theEventAdmin service,
inspired from theOSGi specification.FeedbackFeel free to send feedback on your experience of Pelix/iPOPO, via the mailing
lists:User list:http://groups.google.com/group/ipopo-usersDevelopment list:http://groups.google.com/group/ipopo-devBugs and features requests can be submitted using theIssue Trackeron GitHub.ContributingAll contributions are welcome!Create anissueto discuss
about your idea or the problem you encounterForkthe projectDevelop your changesCheck your code withpylintandpep8If necessary, write some unit testsCommit your changes, indicating in each commit a reference to the issue
you’re working onPush the commits on your repositoryCreate aPull RequestEnjoy!Please note that your contributions will be released under the project’s
license, which is theApache Software License 2.0.CompatibilityPelix and iPOPO are tested usingTravis-CIwith Python 2.7
and 3.4 to 3.6.
Pypy is not tested anymore due to various bugs during tests setup.iPOPO doesn’t support Python 2.6 anymore (since version 0.5.6).LicenseiPOPO is released under theApache Software License 2.0.