diff --git a/gen_wrap.py b/gen_wrap.py index 6d4fdd60139c9b324266141fa2083b63604edb2f..8cca026a5b96b29c74f19a226384b6973500da50 100644 --- a/gen_wrap.py +++ b/gen_wrap.py @@ -278,10 +278,12 @@ libc_ffi.cdef(''' libc = libc_ffi.dlopen(None) -class Error(RuntimeError): +class Error(StandardError): pass +class IslTypeError(Error, TypeError): + pass _context_use_map = {} @@ -1006,7 +1008,7 @@ def write_method_wrapper(gen, cls_name, meth): .format( name=arg.name, py_cls=arg_py_cls)) with Indentation(pre_call): - pre_call('raise Error("{name} is not a {py_cls}")' + pre_call('raise IslTypeError("{name} is not a {py_cls}")' .format( name=arg.name, py_cls=arg_py_cls)) diff --git a/islpy/__init__.py b/islpy/__init__.py index fa907d781aab3883d62c857538b08efa6d1ecb48..098e71e65d3c306dcf6c1d5766f5314bfa3f7bb1 100644 --- a/islpy/__init__.py +++ b/islpy/__init__.py @@ -135,7 +135,7 @@ def _add_functionality(): # {{{ generic initialization, pickling - def obj_new_from_string(cls, s, context=None): + def obj_init(self, s, context=None): """Construct a new object from :class:`str` s. :arg context: a :class:`islpy.Context` to use. If not supplied, use a @@ -145,13 +145,8 @@ def _add_functionality(): if context is None: context = _DEFAULT_CONTEXT - result = cls.read_from_str(context, s) - result._made_from_string = True - return result - - def obj_bogus_init(self, s, context=None): - assert self._made_from_string - del self._made_from_string + new_me = self.read_from_str(context, s) + self._setup(new_me._release()) def generic_getstate(self): ctx = self.get_ctx() @@ -166,8 +161,7 @@ def _add_functionality(): for cls in ALL_CLASSES: if hasattr(cls, "read_from_str"): - cls.__new__ = staticmethod(obj_new_from_string) - cls.__init__ = obj_bogus_init + cls.__init__ = obj_init cls.__getstate__ = generic_getstate cls.__setstate__ = generic_setstate @@ -790,44 +784,60 @@ def _add_functionality(): # note: automatic upcasts for method arguments are provided through # 'implicitly_convertible' on the C++ side of the wrapper. - class UpcastWrapper(object): - def __init__(self, method, upcast): - self.method = method - self.upcast = upcast + def make_new_upcast_wrapper(method, upcast): + # This function provides a scope in which method and upcast + # are not changed from one iteration of the enclosing for + # loop to the next. + + def wrapper(basic_instance, *args, **kwargs): + special_instance = upcast(basic_instance) + return method(special_instance, *args, **kwargs) + + return wrapper + + def make_existing_upcast_wrapper(basic_method, special_method, upcast): + # This function provides a scope in which method and upcast + # are not changed from one iteration of the enclosing for + # loop to the next. + + def wrapper(basic_instance, *args, **kwargs): + try: + return basic_method(basic_instance, *args, **kwargs) + except _isl.IslTypeError: + special_instance = upcast(basic_instance) + return special_method(special_instance, *args, **kwargs) + + return wrapper def add_upcasts(basic_class, special_class, upcast_method): from functools import update_wrapper from inspect import ismethod for method_name in dir(special_class): - # do not overwrite existing methods - if hasattr(basic_class, method_name): - continue + special_method = getattr(special_class, method_name) - method = getattr(special_class, method_name) - - my_ismethod = ismethod(method) - for meth_superclass in type(method).__mro__: - if "function" in meth_superclass.__name__: - # inspect.ismethod does not work on Boost.Py callables in Py3, - # hence this hack. - my_ismethod = True - break + if not ismethod(special_method): + continue - if my_ismethod: - def make_wrapper(method, upcast): - # This function provides a scope in which method and upcast - # are not changed from one iteration of the enclosing for - # loop to the next. + if hasattr(basic_class, method_name): + # method already exists in basic class + basic_method = getattr(basic_class, method_name) - def wrapper(basic_instance, *args, **kwargs): - special_instance = upcast(basic_instance) - return method(special_instance, *args, **kwargs) + if not ismethod(basic_method): + continue - return wrapper + wrapper = make_existing_upcast_wrapper( + basic_method, special_method, upcast_method) + setattr( + basic_class, method_name, + update_wrapper(wrapper, basic_method)) + else: + # method does not yet exists in basic class - wrapper = make_wrapper(method, upcast_method) - setattr(basic_class, method_name, update_wrapper(wrapper, method)) + wrapper = make_new_upcast_wrapper(special_method, upcast_method) + setattr( + basic_class, method_name, + update_wrapper(wrapper, special_method)) for args_triple in [ (BasicSet, Set, Set.from_basic_set),