The Tuscany Python extension allows Python scripts to be used as components in SCA composites and as clients that can invoke SCA services.
See PythonCalculator for a sample that demonstrates the use of the Python extension.
In order to install and use the Tuscany SCA Python Extension there are some extra requirements in addition to the Tuscany SCA requirements:
Software | Download Link |
Python version 2.4 |
http://www.python.org/download/ Please download and follow the installation instructions. You can build the Tuscany SCA Python Extension with other versions of Python - versions 2.3.4 and higher have been tested. |
This section will explain the Tuscany Python programming model to help you to write your own Python components and clients.
The Tuscany Python component and client support comes from a Python extension package that is built in the <tuscany_sca_install_dir>/extensions/python/bin directory on Windows and <tuscany_sca_install_dir>/extensions/python/lib on Linux. This package must be made available to your Python environment by adding this directory to your PYTHONPATH environment variable. This makes the sca module available for use by clients and allows references and properties to be used in your Python components
Using the sca module, a Python client can search for an SCA service with:
import sca calculator = sca.locateservice("CalculatorComponent/CalculatorService")
This finds the component and service as defined in the composite and componentType side files and returns a proxy object that can call the SCA service. You can then simply call a business method on "calculator", like this:
result = calculator.add(12.3, 45.6)
Python component implementations are standard Python scripts, where class-level functions or module-level functions can be invoked by the Tuscany runtime. To use a Python component implementation, use the implementation.python element in your .composite file. For example, the following snippet will use the Python script at path/to/module/PythonModuleName.py, where the path is relative to the location of the composite file:
<implementation.python module="PythonModuleName" path="path/to/module"/>
To instantiate a class instance and use a class-level function, the Python class must have a default constructor (an __init__ method that takes no arguments besides 'self') and the class attribute must be defined in the implementation.python element in your composite, like so:
<implementation.python module="PythonModuleName" path="relative/path/to/module" class="PythonClassName"/>
Tuscany currently only supports passing simple types (strings, ints, floats, etc) into and out of Python components. Support for more complex types, such as Service Data Objects, will be added in later releases.
Additionally, Tuscany currently requires a componentType file that corresponds to the name of the Python module, e.g. for the Python Calculator sample, the module name is 'CalculatorImpl' and the componentType file is 'CalculatorImpl.componentType'. The componentType file specifies what services are available on the component and which references are called by the component. For example, CalculatorImpl.componentType contains the following:
<componentType xmlns="http://www.osoa.org/xmlns/sca/1.0"> <service name="CalculatorService"> <interface.python/> </service> <reference name="divideService"> <interface.python/> </reference> </componentType>
References are automatically added to your Python component implementation when the runtime loads the implementation script, so they can be used like so:
# The module-level div function def div(val1, val2): # Use the divideService reference result = divideService.divide(val1, val2) return result
and in your composite file:
<component name="CalculatorComponent"> <implementation.python module="CalculatorImpl"/> <reference name="divideService">DivideComponent/DivideService</reference> </component>
A composite with a property defined for a component like so:
<component name="DivideComponent"> <implementation.python module="DivideImpl"/> <property name="doRounding">true</property> </component>
and in the associated .componentType file like so:
<componentType ... ... <property name="doRounding" type="xsd:boolean"/> </componentType>
means the property is automatically instantiated and assigned the property value in the Python component implementation, so it can be used like so:
def divide(val1, val2): result = float(val1) / float(val2) print "Python - DivideImpl.divide " + str(val1) + " / " + str(val2) + " = " + str(result) # Use the doRounding property if doRounding: result = round(result) print "Python - DivideImpl.divide is rounding the result to " + str(result) return result
First place to look is at the Tuscany FAQ at http://incubator.apache.org/tuscany/faq.html
Any problem with this release can be reported to the Tuscany mailing lists or create a JIRA issue at http://issues.apache.org/jira/browse/Tuscany.