%load_ext cython
%%cython
cimport cython
cdef class FUSEErrorExt(Exception):
'''
This exception may be raised by request handlers to indicate that
the requested operation could not be carried out. The system call
that resulted in the request (if any) will then fail with error
code *errno_*.
'''
# If we call this variable "errno", we will get syntax errors
# during C compilation (maybe something else declares errno as
# a macro?)
cdef int errno_
property errno:
'''Error code to return to client process'''
def __get__(self):
return self.errno_
def __set__(self, val):
self.errno_ = val
def __init__(self, errno):
self.errno_ = errno
class FUSEErrorInt(Exception):
def __init__(self, errno):
self.errno = errno
def test_ext():
a = 0
for i in range(100):
try:
raise FUSEErrorExt(i)
except FUSEErrorExt as exc:
a += exc.errno
except:
print('This should not happen')
return a
def test_int():
a = 0
for i in range(100):
try:
raise FUSEErrorInt(i)
except FUSEErrorInt as exc:
a += exc.errno
except:
print('This should not happen')
return a
assert test_ext() == test_int()
%timeit test_ext()
%timeit test_int()
(Unfortunately we cannot use @cython.freelist for derived classes)
cache = dict()
def getError(errno):
try:
return cache[errno]
except KeyError:
cache[errno] = FUSEErrorExt(errno)
return cache[errno]
def test_ext_cached():
a = 0
for i in range(100):
try:
raise getError(i)
except FUSEErrorExt as exc:
a += exc.errno
except:
print('This should not happen')
return a
assert test_ext() == test_ext_cached()
%timeit test_ext()
%timeit test_ext_cached()
def handler(i):
return getError(i)
def test_ext_direct():
a = 0
for i in range(100):
res = handler(i)
if isinstance(res, FUSEErrorExt):
a += res.errno
return a
assert test_ext_cached() == test_ext_direct()
%timeit test_ext_cached()
%timeit test_ext_direct()