Why Gemfury? Push, build, and install  RubyGems npm packages Python packages Maven artifacts PHP packages Go Modules Debian packages RPM packages NuGet packages

Repository URL to install this package:

Details    
blpapi / event.py
Size: Mime:
# event.py

"""A module which defines events related operations.

This file defines an 'Event'. One or more 'Event's are generated as a result of
a subscription or a request. 'Event's contain 'Message' objects which can be
accessed using a 'MessageIterator'. This file also defines a 'EventQueue' for
handling replies synchronously.

Usage
-----
The following code snippet shows how a 'EventQueue' is used with a
'generateToken' request. For any established session 'session' pass an
'EventQueue' object 'tokenEventQueue' when calling 'generateToken'. All
'Event's in responses to 'generateToken' request will be returned in
'tokenEventQueue'.

    tokenEventQueue = EventQueue()
    session.generateToken(eventQueue=tokenEventQueue)

Synchronously read the response 'event' and parse over messages using 'token'

    ev = tokenEventStatus.nextEvent()
    token = None
    if ev.eventType() == blpapi.Event.TOKEN_STATUS:
        for msg in ev:
           if msg.messageType() == TOKEN_SUCCESS:
               token = msg.getElementAsString(TOKEN)
           elif msg.messageType() == TOKEN_FAILURE:
               break
    if not token:
        raise Exception("Failed to get token")

"""

from .message import Message
from . import internals
from . import utils
from .utils import get_handle
from .compat import with_metaclass

# pylint: disable=useless-object-inheritance

class MessageIterator(object):
    """An iterator over the :class:`Message` objects within an :class:`Event`.

    Few clients will ever make direct use of :class:`MessageIterator` objects;
    Python ``for`` loops allow clients to operate directly in terms of
    :class:`Event` and :class:`Message` objects.
    """

    def __init__(self, event):
        self.__handle = \
            internals.blpapi_MessageIterator_create(get_handle(event))
        self.__event = event

    def __del__(self):
        try:
            self.destroy()
        except (NameError, AttributeError):
            pass

    def destroy(self):
        if self.__handle:
            internals.blpapi_MessageIterator_destroy(self.__handle)
            self.__handle = None

    def __iter__(self):
        return self

    def __next__(self):
        retCode, message = internals.blpapi_MessageIterator_next(self.__handle)
        if retCode:
            raise StopIteration()
        else:
            return Message(message, self.__event)

    next = __next__


@with_metaclass(utils.MetaClassForClassesWithEnums)
class Event(object):
    """A single event resulting from a subscription or a request.

    :class:`Event` objects are created by the API and passed to the application
    either through a registered ``eventHandler`` or :class:`EventQueue` or
    returned either from the ``nextEvent()`` or ``tryNextEvent()`` methods.
    :class:`Event` objects contain :class:`Message` objects which can be
    accessed using an iteration over :class:`Event`::

        for message in event:
            ...

    The :class:`Event` object is a handle to an event. The event is the basic
    unit of work provided to applications. Each :class:`Event` object consists
    of an ``eventType`` attribute and zero or more :class:`Message` objects.

    :class:`Event` objects are always created by the API, never directly by the
    application.

    The class attributes represent the possible types of event.
    """

    ADMIN = internals.EVENTTYPE_ADMIN
    """Admin event"""
    SESSION_STATUS = internals.EVENTTYPE_SESSION_STATUS
    """Status updates for a session"""
    SUBSCRIPTION_STATUS = internals.EVENTTYPE_SUBSCRIPTION_STATUS
    """Status updates for a subscription"""
    REQUEST_STATUS = internals.EVENTTYPE_REQUEST_STATUS
    """Status updates for a request"""
    RESPONSE = internals.EVENTTYPE_RESPONSE
    """The final (possibly only) response to a request"""
    PARTIAL_RESPONSE = internals.EVENTTYPE_PARTIAL_RESPONSE
    """A partial response to a request"""
    SUBSCRIPTION_DATA = internals.EVENTTYPE_SUBSCRIPTION_DATA
    """Data updates resulting from a subscription"""
    SERVICE_STATUS = internals.EVENTTYPE_SERVICE_STATUS
    """Status updates for a service"""
    TIMEOUT = internals.EVENTTYPE_TIMEOUT
    """An Event returned from nextEvent() if it timed out"""
    AUTHORIZATION_STATUS = internals.EVENTTYPE_AUTHORIZATION_STATUS
    """Status updates for user authorization"""
    RESOLUTION_STATUS = internals.EVENTTYPE_RESOLUTION_STATUS
    """Status updates for a resolution operation"""
    TOPIC_STATUS = internals.EVENTTYPE_TOPIC_STATUS
    """Status updates about topics for service providers"""
    TOKEN_STATUS = internals.EVENTTYPE_TOKEN_STATUS
    """Status updates for a generate token request"""
    REQUEST = internals.EVENTTYPE_REQUEST
    """Request event"""
    UNKNOWN = -1
    """Unknown event"""

    def __init__(self, handle, sessions):
        self.__handle = handle
        self.__sessions = sessions

    def __del__(self):
        try:
            self.destroy()
        except (NameError, AttributeError):
            pass

    def destroy(self):
        """Destructor"""
        if self.__handle:
            internals.blpapi_Event_release(self.__handle)
            self.__handle = None

    def eventType(self):
        """
        Returns:
            int: Type of messages contained by this :class:`Event`.
        """
        return internals.blpapi_Event_eventType(self.__handle)

    def __iter__(self):
        """
        Returns:
            Iterator over messages contained in this :class:`Event`.
        """
        return MessageIterator(self)

    def _handle(self):
        """Return the internal implementation."""
        return self.__handle

    def _sessions(self):
        """Return session(s) that this 'Event' is related to.

        For internal use."""
        return self.__sessions

    # Protect enumeration constant(s) defined in this class and in classes
    # derived from this class from changes:


class EventQueue(object):
    """A construct used to handle replies to request synchronously.

    When a request is submitted an application can either handle the responses
    asynchronously as they arrive or use an :class:`EventQueue` to handle all
    responses for a given request or requests synchronously. The
    :class:`EventQueue` will only deliver responses to the request(s) it is
    associated with.
    """
    def __init__(self):
        """
        Construct an empty :class:`EventQueue` which can be passed to
        :meth:`~Session.sendRequest()` and
        :meth:`~Session.sendAuthorizationRequest()` methods.
        """
        self.__handle = internals.blpapi_EventQueue_create()
        self.__sessions = set()

    def __del__(self):
        try:
            self.destroy()
        except (NameError, AttributeError):
            pass

    def destroy(self):
        """Destructor."""
        if self.__handle:
            internals.blpapi_EventQueue_destroy(self.__handle)
            self.__handle = None

    def nextEvent(self, timeout=0):
        """
        Args:
            timeout (int): Timeout threshold in milliseconds.

        Returns:
            Event: The next :class:`Event` available from the
            :class:`EventQueue`.

        If the specified ``timeout`` is zero this method will wait forever for
        the next event. If the specified ``timeout`` is non zero then if no
        :class:`Event` is available within the specified ``timeout`` an
        :class:`Event` with type of :attr:`~Event.TIMEOUT` will be returned.
        """
        res = internals.blpapi_EventQueue_nextEvent(self.__handle, timeout)
        return Event(res, self._getSessions())

    def tryNextEvent(self):
        """
        Returns:
            Event: If the :class:`EventQueue` is non-empty, the next
            :class:`Event` available, otherwise ``None``.
        """
        res = internals.blpapi_EventQueue_tryNextEvent(self.__handle)
        if res[0]:
            return None
        return Event(res[1], self._getSessions())

    def purge(self):
        """Purge any :class:`Event` objects in this :class:`EventQueue`.

        Purges any :class:`Event` objects in this :class:`EventQueue` which
        have not been processed and cancel any pending requests linked to this
        :class:`EventQueue`.  The :class:`EventQueue` can subsequently be
        re-used for a subsequent request.
        """
        internals.blpapi_EventQueue_purge(self.__handle)
        self.__sessions.clear()

    def _handle(self):
        """Return the internal implementation. For internal use."""
        return self.__handle

    def _registerSession(self, session):
        """Add a new session to this 'EventQueue'. For internal use."""
        self.__sessions.add(session)

    def _getSessions(self):
        """Get a list of sessions this EventQueue related to.

        For internal use.
        """
        sessions = list(self.__sessions)
        return sessions

__copyright__ = """
Copyright 2012. Bloomberg Finance L.P.

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to
deal in the Software without restriction, including without limitation the
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
sell copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:  The above
copyright notice and this permission notice shall be included in all copies
or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
"""