Example #1
0
 def _arg_to_str(self, arg):
     if arg == str:
         import cppyy
         arg = cppyy._std_string_name()
     elif type(arg) != str:
         arg = arg.__name__
     return arg
Example #2
0
 def _arg_to_str(self, arg):
     if arg == str:
         import cppyy
         arg = cppyy._std_string_name()
     elif type(arg) != str:
         arg = arg.__name__
     return arg
Example #3
0
def _pythonize(pyclass):

    try:
        _pythonizations[pyclass.__name__](pyclass)
    except KeyError:
        pass

    # general note: use 'in pyclass.__dict__' rather than 'hasattr' to prevent
    # adding pythonizations multiple times in derived classes

    import cppyy

    # map __eq__/__ne__ through a comparison to None
    if '__eq__' in pyclass.__dict__:
        def __eq__(self, other):
            if other is None: return not self
            if not self and not other: return True
            try:
                return self._cxx_eq(other)
            except TypeError:
                return NotImplemented
        pyclass._cxx_eq = pyclass.__dict__['__eq__']
        pyclass.__eq__ = __eq__

    if '__ne__' in pyclass.__dict__:
        def __ne__(self, other):
            if other is None: return not not self
            if type(self) is not type(other): return True
            return self._cxx_ne(other)
        pyclass._cxx_ne = pyclass.__dict__['__ne__']
        pyclass.__ne__ = __ne__

    # map size -> __len__ (generally true for STL)
    if 'size' in pyclass.__dict__ and not '__len__' in pyclass.__dict__ \
           and callable(pyclass.size):
        pyclass.__len__ = pyclass.size

    # map push_back -> __iadd__ (generally true for STL)
    if 'push_back' in pyclass.__dict__ and not '__iadd__' in pyclass.__dict__:
        def __iadd__(self, ll):
            [self.push_back(x) for x in ll]
            return self
        pyclass.__iadd__ = __iadd__

    # map begin()/end() protocol to iter protocol on STL(-like) classes, but
    # not on vector, for which otherwise the user has to make sure that the
    # global == and != for its iterators are reflected, which is a hassle ...
    if not 'vector' in pyclass.__name__[:11] and \
            ('begin' in pyclass.__dict__ and 'end' in pyclass.__dict__):
        if cppyy._scope_byname(pyclass.__name__+'::iterator') or \
                cppyy._scope_byname(pyclass.__name__+'::const_iterator'):
            def __iter__(self):
                i = self.begin()
                while i != self.end():
                    yield i.__deref__()
                    i.__preinc__()
                i.destruct()
                raise StopIteration
            pyclass.__iter__ = __iter__
        # else: rely on numbered iteration

    # combine __getitem__ and __len__ to make a pythonized __getitem__
    if '__getitem__' in pyclass.__dict__ and '__len__' in pyclass.__dict__:
        pyclass._getitem__unchecked = pyclass.__getitem__
        if '__setitem__' in pyclass.__dict__ and '__iadd__' in pyclass.__dict__:
            pyclass.__getitem__ = python_style_sliceable_getitem
        else:
            pyclass.__getitem__ = python_style_getitem

    # string comparisons
    if pyclass.__name__ == cppyy._std_string_name():
        def eq(self, other):
            if type(other) == pyclass:
                return self.c_str() == other.c_str()
            else:
                return self.c_str() == other
        pyclass.__eq__  = eq
        pyclass.__str__ = pyclass.c_str

    # std::pair unpacking through iteration
    if 'std::pair' == pyclass.__name__[:9] or 'pair' == pyclass.__name__[:4]:
        def getitem(self, idx):
            if idx == 0: return self.first
            if idx == 1: return self.second
            raise IndexError("out of bounds")
        def return2(self):
            return 2
        pyclass.__getitem__ = getitem
        pyclass.__len__     = return2
Example #4
0
def _pythonize(pyclass):

    try:
        _pythonizations[pyclass.__name__](pyclass)
    except KeyError:
        pass

    # general note: use 'in pyclass.__dict__' rather than 'hasattr' to prevent
    # adding pythonizations multiple times in derived classes

    import cppyy

    # map __eq__/__ne__ through a comparison to None
    if '__eq__' in pyclass.__dict__:
        def __eq__(self, other):
            if other is None: return not self
            if not self and not other: return True
            try:
                return self._cxx_eq(other)
            except TypeError:
                return NotImplemented
        pyclass._cxx_eq = pyclass.__dict__['__eq__']
        pyclass.__eq__ = __eq__

    if '__ne__' in pyclass.__dict__:
        def __ne__(self, other):
            if other is None: return not not self
            if type(self) is not type(other): return True
            return self._cxx_ne(other)
        pyclass._cxx_ne = pyclass.__dict__['__ne__']
        pyclass.__ne__ = __ne__

    # map size -> __len__ (generally true for STL)
    if 'size' in pyclass.__dict__ and not '__len__' in pyclass.__dict__ \
           and callable(pyclass.size):
        pyclass.__len__ = pyclass.size

    # map push_back -> __iadd__ (generally true for STL)
    if 'push_back' in pyclass.__dict__ and not '__iadd__' in pyclass.__dict__:
        def __iadd__(self, ll):
            [self.push_back(x) for x in ll]
            return self
        pyclass.__iadd__ = __iadd__

    # map begin()/end() protocol to iter protocol on STL(-like) classes, but
    # not on vector, for which otherwise the user has to make sure that the
    # global == and != for its iterators are reflected, which is a hassle ...
    if not 'vector' in pyclass.__name__[:11] and \
            ('begin' in pyclass.__dict__ and 'end' in pyclass.__dict__):
        if cppyy._scope_byname(pyclass.__name__+'::iterator') or \
                cppyy._scope_byname(pyclass.__name__+'::const_iterator'):
            def __iter__(self):
                i = self.begin()
                while i != self.end():
                    yield i.__deref__()
                    i.__preinc__()
                i.destruct()
                raise StopIteration
            pyclass.__iter__ = __iter__
        # else: rely on numbered iteration

    # combine __getitem__ and __len__ to make a pythonized __getitem__
    if '__getitem__' in pyclass.__dict__ and '__len__' in pyclass.__dict__:
        pyclass._getitem__unchecked = pyclass.__getitem__
        if '__setitem__' in pyclass.__dict__ and '__iadd__' in pyclass.__dict__:
            pyclass.__getitem__ = python_style_sliceable_getitem
        else:
            pyclass.__getitem__ = python_style_getitem

    # string comparisons
    if pyclass.__name__ == cppyy._std_string_name():
        def eq(self, other):
            if type(other) == pyclass:
                return self.c_str() == other.c_str()
            else:
                return self.c_str() == other
        pyclass.__eq__  = eq
        pyclass.__str__ = pyclass.c_str

    # std::pair unpacking through iteration
    if 'std::pair' == pyclass.__name__[:9] or 'pair' == pyclass.__name__[:4]:
        def getitem(self, idx):
            if idx == 0: return self.first
            if idx == 1: return self.second
            raise IndexError("out of bounds")
        def return2(self):
            return 2
        pyclass.__getitem__ = getitem
        pyclass.__len__     = return2