aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMattias Andrée <maandree@operamail.com>2015-05-16 18:53:22 +0200
committerMattias Andrée <maandree@operamail.com>2015-05-16 18:53:22 +0200
commitdffaf87644217772f24deb68b320443373fbc7ef (patch)
tree5fc0a9d927a3db806c9d09f81f240a0726065163
parentfix poll (diff)
downloadpython-bus-3.0.tar.gz
python-bus-3.0.tar.bz2
python-bus-3.0.tar.xz
return the errno value that was set by the native bus functions, python clears errno3.0
Signed-off-by: Mattias Andrée <maandree@operamail.com>
-rw-r--r--src/bus.py63
-rw-r--r--src/native_bus.pyx200
2 files changed, 154 insertions, 109 deletions
diff --git a/src/bus.py b/src/bus.py
index 31908d0..ad7d3a5 100644
--- a/src/bus.py
+++ b/src/bus.py
@@ -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)