Metadata-Version: 1.0
Name: tuxedo
Version: 0.0.2
Summary: Python bindings for writing Oracle Tuxedo clients and servers
Home-page: https://github.com/aivarsk/tuxedo-python
Author: Aivars Kalvans
Author-email: aivars.kalvans@gmail.com
License: UNKNOWN
Description: Tuxedo-Python
        -------------
        
        I'm a fan of the way `tuxmodule <https://github.com/henschkowski/tuxmodule/blob/master/README.md>`_ enables you to interact with Oracle Tuxedo. Unfortunately, it's out-dated and somehow limited. So I cloned tuxmodule and started to clean up compiler warnings and work on some features I had in mind:
        
        - A multi-threaded server
        - Support nested FML32 buffers and more types
        - Support newest Oracle Tuxedo features like ``tpadvertisex()`` and ``tpappthrinit()``
        - Receive response even when the service returns TPFAIL (instead of exception)
        
        But I realized that's too much of C for me, so I decided to write my own Python module for Oracle Tuxedo in C++ and `pybind11 <https://github.com/pybind/pybind11>`_ focusing on the parts I find most important first.
        
        General
        -------
        
        ``tuxedo`` module supports only ``STRING`` and ``FML32`` buffer types at the moment.
        
        ``STRING`` is mapped to/from Python ``str`` type.
        
        ``FML32`` is mapped to/from Python ``dict`` type with field names (``str``) as keys and lists (``list``) of different types (``int``, ``str``, ``float`` or ``dict``) as values. ``dict`` to ``FML32`` conversion also treats types ``int``, ``str``, ``float`` or ``dict`` as lists with a single element:
        
        .. code:: python
        
          {'TA_CLASS': 'Single value'}
        
        converted to ``FML32`` and then back to ``dict`` becomes
        
        .. code:: python
        
          {'TA_CLASS': ['Single value']}
        
        
        All XATMI functions that take buffer and length arguments in C take only buffer argument in Python.
        
        Calling a service
        -----------------
        
        ``tuxedo.tpcall()`` and ``tuxedo.tpgetrply()`` functions return a tuple with 3 elements or throw an exception when no data is received. This is the part I believe ``tuxmodule`` got wrong: a service may return a response
        both when it succeeds (``TPSUCCESS``) and fails (``TPFAIL``) and often the failure response contains some important information.
        
        - 0 or ``TPESVCFAIL``
        - ``tpurcode`` (the second argument to ``tpreturn``)
        - data buffer
        
        .. code:: python
        
          rval, rcode, data = t.tpcall('.TMIB', {'TA_CLASS': 'T_SVCGRP', 'TA_OPERATION': 'GET'})
          if rval == 0:
            # Service returned TPSUCCESS
          else:
            # rval == tuxedo.TPESVCFAIL
            # Service returned TPFAIL 
        
        Writing servers
        ---------------
        
        Tuxedo servers are written as Python classes. ``tpsvrinit`` method of object will be called when Tuxedo calls ``tpsvrinit(3c)`` function and it must return 0 on success or -1 on error. A common task for ``tpsvrinit`` is to advertise services the server provides by calling ``tuxedo.tpadvertise()`` with a service name. A method with the same name must exist. ``tpsvrdone``, ``tpsvrthrinit`` and ``tpsvrthrdone`` will be called when Tuxedo calls corresponding functions.
        
        Each service method receives a single argument with incoming buffer and service must end with either call to ``tuxedo.tpreturn()`` or ``tuxedo.tpforward()``. Following two code fragments are equivalent but I believe the first one is less error-prone. Unlike in C ``tuxedo.tpreturn()`` and ``tuxedo.tpforward()`` do not perform ``longjmp`` but set up arguments for those calls once service method will return.
        
        .. code:: python
        
              def ECHO(self, args):
                  return t.tpreturn(t.TPSUCCESS, 0, args)
        
        .. code:: python
        
              def ECHO(self, args):
                  t.tpreturn(t.TPSUCCESS, 0, args)
        
        
        After that ``tuxedo.run()`` must be called with an instance of the class and command-line arguments to start Tuxedo server's main loop.
        
        .. code:: python
        
          import sys
          import tuxedo as t
        
          class Server:
              def tpsvrinit(self, args):
                  t.tpadvertise('ECHO')
                  return 0
        
              def tpsvrthrinit(self, args):
                  return 0
        
              def tpsvrthrdone(self):
                  pass
        
              def tpsvrdone(self):
                  pass
        
              def ECHO(self, args):
                  return t.tpreturn(t.TPSUCCESS, 0, args)
        
          if __name__ == '__main__':
              t.run(Server(), sys.argv)
        
        Writing clients
        ---------------
        
        Nothing special is needed to implement Tuxedo clients, just import the module and start calling XATMI functions.
        
        .. code:: python
        
          import sys
          import tuxedo as t
        
          rval, rcode, data = t.tpcall('.TMIB', {'TA_CLASS': 'T_SVCGRP', 'TA_OPERATION': 'GET'})
        
        Demo
        ----
        
        ``demo`` has some proof-of-concept code:
        
        - ``client.py`` Oracle Tuxedo client
        - ``api.py`` HTTP+JSON server running inside Oracle Tuxedo server
        - ``ecb.py`` HTTP+XML client running inside Oracle Tuxedo server
        - ``mem.py`` multi-threaded in-memory cache
        
        TODO
        ----
        
        - Improving multi-threading since Python interpreter is single-threaded (more granual release and acquire GIL)
        - Implementing few more useful APIs
        
Platform: UNKNOWN
