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
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