diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/bus.py | 63 | ||||
-rw-r--r-- | src/native_bus.pyx | 200 |
2 files changed, 154 insertions, 109 deletions
@@ -89,9 +89,9 @@ class Bus: @return :str The pathname of the bus ''' from native_bus import bus_create_wrapped - self.pathname = bus_create_wrapped(self.pathname, flags) + (self.pathname, e) = bus_create_wrapped(self.pathname, flags) if self.pathname is None: - raise self.__oserror() + raise self.__oserror(e) return self.pathname @@ -100,8 +100,9 @@ class Bus: Remove the bus ''' from native_bus import bus_unlink_wrapped - if bus_unlink_wrapped(self.pathname) == -1: - raise self.__oserror() + (r, e) = bus_unlink_wrapped(self.pathname) + if r == -1: + raise self.__oserror(e) def open(self, flags : int = 0): @@ -112,14 +113,16 @@ class Bus: ''' from native_bus import bus_close_wrapped, bus_allocate, bus_open_wrapped if self.bus is not None: - if bus_close_wrapped(self.bus) == -1: - raise self.__oserror() + (r, e) = bus_close_wrapped(self.bus) + if r == -1: + raise self.__oserror(e) else: - self.bus = bus_allocate() + (self.bus, e) = bus_allocate() if self.bus == 0: - raise self.__oserror() - if bus_open_wrapped(self.bus, self.pathname, flags) == -1: - raise self.__oserror() + raise self.__oserror(e) + (r, e) = bus_open_wrapped(self.bus, self.pathname, flags) + if r == -1: + raise self.__oserror(e) def close(self): @@ -131,8 +134,9 @@ class Bus: except: return if self.bus is not None: - if bus_close_wrapped(self.bus) == -1: - raise self.__oserror() + (r, e) = bus_close_wrapped(self.bus) + if r == -1: + raise self.__oserror(e) bus_deallocate(self.bus) self.bus = None @@ -147,8 +151,9 @@ class Bus: if there is another process attempting to broadcast on the bus ''' from native_bus import bus_write_wrapped - if bus_write_wrapped(self.bus, message, flags) == -1: - raise self.__oserror() + (r, e) = bus_write_wrapped(self.bus, message, flags) + if r == -1: + raise self.__oserror(e) def read(self, callback : callable, user_data = None): @@ -193,8 +198,9 @@ class Bus: `Bus.poll` is called ''' from native_bus import bus_poll_start_wrapped - if bus_poll_start_wrapped(self.bus, flags) == -1: - raise self.__oserror() + (r, e) = bus_poll_start_wrapped(self.bus, flags) + if r == -1: + raise self.__oserror(e) def poll_stop(self): @@ -204,8 +210,9 @@ class Bus: to wait indefinitely. ''' from native_bus import bus_poll_stop_wrapped - if bus_poll_stop_wrapped(self.bus) == -1: - raise self.__oserror() + (r, e) = bus_poll_stop_wrapped(self.bus) + if r == -1: + raise self.__oserror(e) def poll(self) -> bytes: @@ -221,9 +228,9 @@ class Bus: NB! The received message will not be decoded from UTF-8 ''' from native_bus import bus_poll_wrapped - message = bus_poll_wrapped(self.bus) + (message, e) = bus_poll_wrapped(self.bus) if message is None: - raise self.__oserror() + raise self.__oserror(e) return message @@ -237,8 +244,9 @@ class Bus: @param group:int The group ID of the bus's new group ''' from native_bus import bus_chown_wrapped - if bus_chown_wrapped(self.pathname, owner, group) == -1: - raise self.__oserror() + (r, e) = bus_chown_wrapped(self.pathname, owner, group) + if r == -1: + raise self.__oserror(e) def chmod(self, mode : int): @@ -252,18 +260,19 @@ class Bus: edit the bus's associated file ''' from native_bus import bus_chmod_wrapped - if bus_chmod_wrapped(self.pathname, mode) == -1: - raise self.__oserror() + (r, e) = bus_chmod_wrapped(self.pathname, mode) + if r == -1: + raise self.__oserror(e) - def __oserror(self): + def __oserror(self, err : int): ''' Create an OSError + @param err:int The value of errno @return :OSError The OS error ''' - import os, ctypes - err = ctypes.get_errno() + import os err = OSError(err, os.strerror(err)) if err.errno == os.errno.ENOENT: err.filename = self.pathname diff --git a/src/native_bus.pyx b/src/native_bus.pyx index 75bb92a..7dd0601 100644 --- a/src/native_bus.pyx +++ b/src/native_bus.pyx @@ -26,6 +26,7 @@ DEALINGS IN THE SOFTWARE. cimport cython from libc.stdlib cimport malloc, free +from libc.errno cimport errno from posix.types cimport uid_t, gid_t, mode_t @@ -165,36 +166,40 @@ Change the permissions for a bus -def bus_allocate() -> int: +def bus_allocate() -> tuple: ''' Allocate memory for a bus - @return The address of the allocated memory + @return :int The address of the allocated memory + @return :int The value of `errno` ''' n = 2 * sizeof(long long) + sizeof(int) + sizeof(char *) - return <long>malloc(n) + r = <long>malloc(n) + e = errno + return (r, e) def bus_deallocate(address : int): ''' Deallocate memory for a bus - @param address The address of the allocated memory + @param address:int The address of the allocated memory ''' free(<void *><long>address) -def bus_create_wrapped(file : str, flags : int) -> str: +def bus_create_wrapped(file : str, flags : int) -> tuple: ''' Create a new bus - @param file The pathname of the bus, `None` to create a random one - @param flags `BUS_EXCL` (if `file` is not `None`) to fail if the file - already exists, otherwise if the file exists, nothing - will happen; - `BUS_INTR` to fail if interrupted - @return The pathname of the bus, `None` on error; - `file` is returned unless `file` is `None` + @param file:str The pathname of the bus, `None` to create a random one + @param flags:int `BUS_EXCL` (if `file` is not `None`) to fail if the file + already exists, otherwise if the file exists, nothing + will happen; + `BUS_INTR` to fail if interrupted + @return :str The pathname of the bus, `None` on error; + `file` is returned unless `file` is `None` + @return :int The value of `errno` ''' cdef const char* cfile cdef char* ofile @@ -203,71 +208,85 @@ def bus_create_wrapped(file : str, flags : int) -> str: bs = file.encode('utf-8') + bytes([0]) cfile = bs r = bus_create(cfile, flags, <char **>NULL) - return file if r == 0 else None + e = errno + return (file if r == 0 else None, e) r = bus_create(<char *>NULL, flags, &ofile) + e = errno if r == 0: bs = ofile - return bs.decode('utf-8', 'strict') - return None + return (bs.decode('utf-8', 'strict'), e) + return (None, e) -def bus_unlink_wrapped(file : str) -> int: +def bus_unlink_wrapped(file : str) -> tuple: ''' Remove a bus - @param file The pathname of the bus - @return 0 on success, -1 on error + @param file:str The pathname of the bus + @return :int 0 on success, -1 on error + @return :int The value of `errno` ''' cdef const char* cfile cdef bytes bs bs = file.encode('utf-8') + bytes([0]) cfile = bs - return bus_unlink(cfile) + r = bus_unlink(cfile) + e = errno + return (r, e) -def bus_open_wrapped(bus : int, file : str, flags : int) -> int: +def bus_open_wrapped(bus : int, file : str, flags : int) -> tuple: ''' Open an existing bus - @param bus Bus information to fill - @param file The filename of the bus - @param flags `BUS_RDONLY`, `BUS_WRONLY` or `BUS_RDWR`, - the value must not be negative - @return 0 on success, -1 on error + @param bus:int Bus information to fill + @param file:str The filename of the bus + @param flags:int `BUS_RDONLY`, `BUS_WRONLY` or `BUS_RDWR`, + the value must not be negative + @return :int 0 on success, -1 on error + @return :int The value of `errno` ''' cdef const char* cfile cdef bytes bs bs = file.encode('utf-8') + bytes([0]) cfile = bs - return bus_open(<long>bus, cfile, <int>flags) + r = bus_open(<long>bus, cfile, <int>flags) + e = errno + return (r, e) -def bus_close_wrapped(bus : int) -> int: +def bus_close_wrapped(bus : int) -> tuple: ''' Close a bus - @param bus Bus information - @return 0 on success, -1 on error + @param bus:int Bus information + @return :int 0 on success, -1 on error + @return :int The value of `errno` ''' - return bus_close(<long>bus) + r = bus_close(<long>bus) + e = errno + return (r, e) -def bus_write_wrapped(bus : int, message : str, flags : int) -> int: +def bus_write_wrapped(bus : int, message : str, flags : int) -> tuple: ''' Broadcast a message a bus - @param bus Bus information - @param message The message to write, may not be longer than - `BUS_MEMORY_SIZE` including the NUL-termination - @param flags `BUS_NOWAIT` fail with errno set to `os.errno.EAGAIN` - if other process is attempting to write - @return 0 on success, -1 on error + @param bus:int Bus information + @param message:str The message to write, may not be longer than + `BUS_MEMORY_SIZE` including the NUL-termination + @param flags:int `BUS_NOWAIT` fail with errno set to `os.errno.EAGAIN` + if other process is attempting to write + @return :int 0 on success, -1 on error + @return :int The value of `errno` ''' cdef const char* cmessage cdef bytes bs bs = message.encode('utf-8') + bytes([0]) cmessage = bs - return bus_write(<long>bus, cmessage, <int>flags) + r = bus_write(<long>bus, cmessage, <int>flags) + e = errno + return (r, e) cdef int bus_callback_wrapper(const char *message, user_data): @@ -280,28 +299,31 @@ cdef int bus_callback_wrapper(const char *message, user_data): return <int>callback(bs, user_data) -def bus_read_wrapped(bus : int, callback : callable, user_data) -> int: +def bus_read_wrapped(bus : int, callback : callable, user_data) -> tuple: ''' Listen (in a loop, forever) for new message on a bus - @param bus Bus information - @param callback Function to call when a message is received, the - input parameters will be the read message and - `user_data` from `bus_read`'s parameter with the - same name. The message must have been parsed or - copied when `callback` returns as it may be over - overridden after that time. `callback` should - return either of the the values: - 0: stop listening - 1: continue listening - -1: an error has occurred - @return 0 on success, -1 on error + @param bus:int Bus information + @param callback:(str?, ¿V?)→int Function to call when a message is received, the + input parameters will be the read message and + `user_data` from `bus_read`'s parameter with the + same name. The message must have been parsed or + copied when `callback` returns as it may be over + overridden after that time. `callback` should + return either of the the values: + 0: stop listening + 1: continue listening + -1: an error has occurred + @return :int 0 on success, -1 on error + @return :int The value of `errno` ''' user = (callback, user_data) - return bus_read(<long>bus, <int (*)(const char *, void *)>&bus_callback_wrapper, <void *>user) + r = bus_read(<long>bus, <int (*)(const char *, void *)>&bus_callback_wrapper, <void *>user) + e = errno + return (r, e) -def bus_poll_start_wrapped(bus : int, flags : int) -> int: +def bus_poll_start_wrapped(bus : int, flags : int) -> tuple: ''' Announce that the thread is listening on the bus. This is required so the will does not miss any @@ -310,29 +332,35 @@ def bus_poll_start_wrapped(bus : int, flags : int) -> int: misbehave, is `bus_poll_wrapped` is written to expect this function to have been called. - @param bus Bus information - @param flags `BUS_NOWAIT` if the bus should fail and set `errno` to - `os.errno.EAGAIN` if there isn't already a message - available on - the bus when `bus_poll` is called - @return 0 on success, -1 on error + @param bus:int Bus information + @param flags:int `BUS_NOWAIT` if the bus should fail and set `errno` to + `os.errno.EAGAIN` if there isn't already a message + available on + the bus when `bus_poll` is called + @return :int 0 on success, -1 on error + @return :int The value of `errno` ''' - return bus_poll_start(<long>bus, <int>flags) + r = bus_poll_start(<long>bus, <int>flags) + e = errno + return (r, e) -def bus_poll_stop_wrapped(bus : int) -> int: +def bus_poll_stop_wrapped(bus : int) -> tuple: ''' Announce that the thread has stopped listening on the bus. This is required so that the thread does not cause others to wait indefinitely. - @param bus Bus information - @return 0 on success, -1 on error + @param bus:int Bus information + @return :int 0 on success, -1 on error + @return :int The value of `errno` ''' - return bus_poll_stop(<long>bus) + r = bus_poll_stop(<long>bus) + e = errno + return (r, e) -def bus_poll_wrapped(bus : int) -> bytes: +def bus_poll_wrapped(bus : int) -> tuple: ''' Wait for a message to be broadcasted on the bus. The caller should make a copy of the received message, @@ -342,51 +370,59 @@ def bus_poll_wrapped(bus : int) -> bytes: either call `bus_poll_wrapped` again or `bus_poll_stop_wrapped`. - @param bus Bus information - @return The received message, `None` on error + @param bus::int Bus information + @return :bytes The received message, `None` on error + @return :int The value of `errno` ''' cdef const char* msg cdef bytes bs msg = bus_poll(<long>bus) + e = errno if msg is NULL: - return None + return (None, e) bs = msg - return bs + return (bs, e) -def bus_chown_wrapped(file : str, owner : int, group : int) -> int: +def bus_chown_wrapped(file : str, owner : int, group : int) -> tuple: ''' Change the ownership of a bus `os.stat` can be used of the bus's associated file to get the bus's ownership - @param file The pathname of the bus - @param owner The user ID of the bus's new owner - @param group The group ID of the bus's new group - @return 0 on success, -1 on error + @param file:str The pathname of the bus + @param owner:int The user ID of the bus's new owner + @param group:int The group ID of the bus's new group + @return :int 0 on success, -1 on error + @return :int The value of `errno` ''' cdef const char* cfile cdef bytes bs bs = file.encode('utf-8') + bytes([0]) cfile = bs - return bus_chown(cfile, <uid_t>owner, <gid_t>group) + r = bus_chown(cfile, <uid_t>owner, <gid_t>group) + e = errno + return (r, e) -def bus_chmod_wrapped(file : str, mode : int) -> int: +def bus_chmod_wrapped(file : str, mode : int) -> tuple: ''' Change the permissions for a bus `os.stat` can be used of the bus's associated file to get the bus's permissions - @param file The pathname of the bus - @param mode The permissions of the bus, any permission for a user implies - full permissions for that user, except only the owner may - edit the bus's associated file - @return 0 on success, -1 on error + @param file:str The pathname of the bus + @param mode:int The permissions of the bus, any permission for a user implies + full permissions for that user, except only the owner may + edit the bus's associated file + @return :int 0 on success, -1 on error + @return :int The value of `errno` ''' cdef const char* cfile cdef bytes bs bs = file.encode('utf-8') + bytes([0]) cfile = bs - return bus_chmod(cfile, <mode_t>mode) + r = bus_chmod(cfile, <mode_t>mode) + e = errno + return (r, e) |