Python on the other hand is more active in that if something fails or faults, it raises an exception that typically must be handled or the program will exit, dumping a traceback to stderr.
The TeeOS solution is to turn each errno into an exception class of its own:
ErrnoExcepts = {}
# errno 1
class EPERM(Exception):
def __init__(self):
self.desc = 'Operation not permitted'
self.errno = 1
def __str__(self):
return repr(self.desc)
ErrnoExcepts[1] = EPERM
# errno 2
class ENOENT(Exception):
def __init__(self):
self.desc = 'No such file or directory'
self.errno = 2
def __str__(self):
return repr(self.desc)
ErrnoExcepts[2] = ENOENT
def RaiseErrnoException(errno):
'''Given an errno; will raise the matching Python exception
'''
raise ErrnoExcepts[errno]
In a function or method that will be calling functions from the C libs:
def _mnt(device, target, fstype, flags, data, libcfile = 'libc.so.0'):
from ctypes import CDLL, get_errno
from Teeos.SysUtils.ErrnoExceptions import RaiseErrnoException
# We can't use find_library() because TeeOS does not have
# 'gcc', 'ldconfig' or 'objdump'.
# http://docs.python.org/library/ctypes.html#finding-shared-libraries
libc = CDLL(libcfile, use_errno = True)
if libc.mount(device, target, fstype, flags, data):
RaiseErrnoException(get_errno())
return False
return True
Now when using the _mnt() function (used in the Mounter class) if there is a non-zero return from the C libs mount() function, a descriptive Python exception will be raised.
>>> from Teeos.SysUtils.Mount import Mounter
>>> procMount = Mounter(None, '/proc', 'proc', 0, None)
>>> procMount.Mount()
True
>>> procMount.Mount()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/teeos/system-packages/Teeos/SysUtils/Mount.py", line 45, in Mount
self.fstype, self.mflags, self.data)
File "/teeos/system-packages/Teeos/SysUtils/Mount.py", line 11, in _mnt
RaiseErrnoException(get_errno())
File "/teeos/system-packages/Teeos/SysUtils/ErrnoExceptions.py", line 1181, in RaiseErrnoException
raise ErrnoExcepts[errno]
Teeos.SysUtils.ErrnoExceptions.EBUSY: 'Device or resource busy'
>>>
The second call to the _mnt() function raised the exception EBUSY, as proc was already mounted.
As long as all 'user facing' classes rely on the underlying system functions like _mnt(), error handling can be in a very 'Pythonic' way with Pythons own exception handling methods.