Generating Server Bindings for Python in libadr

The Oracle Solaris 11.4 code that is generated is currently compatible with Python 2.7 and Python 3.5. However, Python updates might affect that compatibility, so you should specify the exact version of Python. Furthermore, do not add new Python 2.7 code. This version of Python is near the end of support by the community.

This section provides examples for generating server bindings for Python 3.5.

Example 3-9 Generating Server Bindings for Python 3.5

This example shows how to generate Python server bindings for the API Snake, which has the interface, Cobra, with one method, multiply.

<api xmlns="https://xmlns.oracle.com/radadr"
    name="com.oracle.solaris.rad.snake">

 <summary>
     Snake API
 </summary>

 <doc>
      <para>
        This is a testing module for Python Server Modules.
      </para>
</doc>

<version major="1" minor="0"/>

<interface name="Cobra" stability="private">

   <method name="multiply" stability="private">
   <doc>
     Multiply two numbers.
    </doc>
    <result type="integer"/>
    <argument name="first" type="integer"/>
    <argument name="second" type="integer"/>
</method>

</interface>

</api>

The following example shows how to generate Python server bindings for snake.adr in the build sub-directory.

$ radadrgen -l python35 -s server -d build snake.adr

When you run radadrgen in this example, the following files are generated:

  • api.snake.h and api.snake_impl.c C files – These files are generated so that the Python module can reuse the existing RAD marshalling and dispatching framework.

  • com/oracle/solaris/rad/snake_iface.py Python file – This file contains an abstract definition of an interface, which should be extended to provide a concrete implementation.

Example 3-10 Showing a radadrgen-Generated Interface From the Python File

"""
Snake API

This is a testing module for Python Server Modules.


"""
try:
    import modapi
except ImportError:
    import rad.server.modapidoc as modapi
from rad.server import RADInstance
from rad.client import *
import abc
import six

dom = "com.oracle.solaris.rad.snake"
vers = (1, 0)

@ClassStability("private")
class Cobra(six.with_metaclass(abc.ABCMeta, RADInstance)):
    """"""

    _rad_type = "Cobra"
    _rad_domain = dom
    _rad_version = vers
    _rad_singleton = None

    __metaclass__ = abc.ABCMeta

    def __init__(self, name = None, user = None, freef = None, dynamic = False):
        super(Cobra, self).__init__(_rad_moddata, name, user, freef, dynamic)

    @MethodStability("private")
    @abc.abstractmethod
    def multiply(self, first, second):
        """Multiply two numbers."""
        pass

The methods in the example are decorated to indicate that they are abstract and to indicate their RAD stability level. You can write the Python code to implement the abstract interface.

Example 3-11 Implementing Interfaces Generated by radadrgen

from . import snake_iface
import rad.client as radcli
import rad.server as radser

class Cobra(snake_iface.Cobra):

    def __init__(self, name = None, user = None, freef = None):
        super(Cobra, self).__init__(name, user, freef)

    def multiply(self, first, second):
        return (first * second)

def rad_init():
    radser.rad_log(radser.rad_log_lvl.RL_DEBUG,
        "Initializing: %s" % "com.oracle.solaris.rad.snake")
    Cobra._rad_insert_singleton(radser.rad_container)
    return 0

def rad_fini(handle):
    radser.rad_log(radser.rad_log_lvl.RL_DEBUG,
        "Finalizing: %s" % "com.oracle.solaris.rad.snake")
    return 0

In this example, the Snake module is implemented and is exporting the rad_init and rad_fini functions, which provides the capability for the module to setup or remove an execution environment. In this example, you are logging and creating a singleton instance to represent the Snake module.

The RAD daemon converts the ADR (RAD's native data representation format) types to or from the Python types. For basic types, the conversion is straightforward mapping. For derived types, the conversion is more complex, but essentially follows the same process as illustrated above for interfaces. radadrgen generates the required types in the binding. The various generated components are identical to any such components in the Python client binding.