Source code for schrodinger.infra.mmlist
"""
A wrapper for the mmlist mmlib.
Copyright Schrodinger, LLC. All rights reserved.
"""
from schrodinger.infra import mm
from schrodinger.infra import mmobject
[docs]class mmlist(mmobject.MmObject):
    """
    Wrap an anderlying mmlist "instance" and provides access to its members
    through the python sequence syntax.
    """
[docs]    def __init__(self, handle_or_list, manage_handle=True):
        """
        Initialize an object with an existing mmlist handle or python list
        of ints.
        """
        try:  # FIXME: which of these 2 statements needs to be in try?
            mm.mmlist_initialize(mm.error_handler)
            handle = _mmlist_from_pylist(handle_or_list)
        except:
            handle = int(handle_or_list)
        # mmlist_in_use currently isn't wrapped in mmlist.i, so check to see
        # if it's there before trying to call it.
        # FIXME: Wrap mmlist_in_use() and remove hasattr section:
        if hasattr(mm, 'mmlist_in_use') and not mm.mmlist_in_use(handle):
            raise Exception("There is no active MMlist for the handle %d." %
                            handle)
        super().__init__(handle, manage_handle)
        mm.mmlist_terminate() 
    def _delete(self):
        """
        A function to terminate this object. Required for MmObject
        interface.
        """
        mm.mmlist_delete(self.handle)
[docs]    def initialize(error_handler=None):
        """
        Initialize mmlist.
        """
        if error_handler is None:
            error_handler = mm.error_handler
        mm.mmlist_initialize(mm.error_handler) 
    initialize = staticmethod(initialize)
[docs]    def terminate():
        """
        Terminate mmlist.
        """
        mm.mmlist_terminate() 
    terminate = staticmethod(terminate)
    def __repr__(self):
        """
        Programmer-readable representation, prints the mmlist handle
        """
        return "mmlist(%d)" % self.handle
[docs]    def __len__(self):
        """
        Return the number of elements in the mmlist.
        """
        return mm.mmlist_get_size(self.handle) 
    def __getitem__(self, index):
        """
        Return an item from the underlying mmlist library.
        """
        size = mm.mmlist_get_size(self.handle)
        if index >= size or index < 0:
            raise IndexError
        return mm.mmlist_get(self.handle, index)
    def __setitem__(self, index, value):
        """
        Set an item in the underlying mmlist library.
        """
        size = mm.mmlist_get_size(self.handle)
        if index >= size or index < 0:
            raise IndexError
        return mm.mmlist_set(self.handle, index, value)
    def __delitem__(self, index):
        raise Exception("mmlist objects cannot delete items.")
    def __iter__(self):
        """
        Provide an iterator over the list. This also allows one to create a
        python list by invoking list() on an instantiated mmlist object.
        """
        # As with all iterators, changing the underlying object while
        # iterating is not going to be safe.
        return map(self.__getitem__, range(len(self)))
        # FIXME: Would it be simpler to do the following:
        #
        # for i in range(len(self)):
        #     yield self[i]
        #
        # This will also remove the need to import the intertools module.
        # Is there a reason not to do this?
[docs]    def __contains__(self, value):
        """
        Returns True if the list contains the specified value, False otherwise
        """
        return bool(mm.mmlist_in_list(self, value))  
def _mmlist_from_pylist(pylist):
    """
    Create an mmlist from a python list, and return the integer handle of
    that mmlist. Note that the mmlist will now accept a python sequence as
    the first argument to the constructor.
    """
    handle = mm.mmlist_new(len(pylist))
    for i, val in enumerate(pylist):
        mm.mmlist_set(handle, i, 0 if val is None else int(val))
    return handle
def _mmlist_to_pylist(mmlist_handle):
    """
    Create a standard python list from the provided mmlist handle.
    If mmlist_handle is an mmlist object, it's easier to just invoke
    list(mmlist_handle).
    """
    size = mm.mmlist_get_size(mmlist_handle)
    pylist = []
    for i in range(size):
        pylist.append(mm.mmlist_get(mmlist_handle, i))
    return pylist