aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/bus.py83
-rw-r--r--src/native_bus.pyx160
2 files changed, 237 insertions, 6 deletions
diff --git a/src/bus.py b/src/bus.py
index 7146e83..ddc0410 100644
--- a/src/bus.py
+++ b/src/bus.py
@@ -57,7 +57,7 @@ class Bus:
NOWAIT = 1
'''
- Function shall fail with errno set to `EAGAIN`
+ Function shall fail with `os.errno.EAGAIN`
if the it would block and this flag is used
'''
@@ -141,9 +141,10 @@ class Bus:
'''
Broadcast a message a bus
- @param message:str The message to write, may not be longer than 2047 bytes after UTF-8 encoding
- @param flags:int `Bus.NOWAIT` if the function shall fail if there is another process attempting
- to broadcast on the bus
+ @param message:str The message to write, may not be longer than 2047 bytes
+ after UTF-8 encoding
+ @param flags:int `Bus.NOWAIT` if the function shall fail with `os.errno.EAGAIN`
+ 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:
@@ -178,6 +179,80 @@ class Bus:
raise self.__oserror()
+ def poll_start(self, flags : int = 0):
+ '''
+ Announce that the thread is listening on the bus.
+ This is required so the will does not miss any
+ messages due to race conditions. Additionally,
+ not calling this function will cause the bus the
+ misbehave, is `Bus.poll` is written to expect
+ this function to have been called.
+
+ @param flags:int `Bus.NOWAIT` if the bus should fail with `os.errno.EAGAIN`
+ if there isn't already a message available on the bus when
+ `Bus.poll` is called
+ '''
+ from native_bus import bus_poll_start_wrapped
+ if bus_poll_start_wrapped(self.bus, flags) == -1:
+ raise self.__oserror()
+
+
+ def poll_stop(self):
+ '''
+ Announce that the thread has stopped listening on the bus.
+ This is required so that the thread does not cause others
+ to wait indefinitely.
+ '''
+ from native_bus import bus_poll_stop_wrapped
+ if bus_poll_stop_wrapped(self.bus) == -1:
+ raise self.__oserror()
+
+
+ def poll(self) -> str:
+ '''
+ Wait for a message to be broadcasted on the bus.
+ The caller should make a copy of the received message,
+ without freeing the original copy, and parse it in a
+ separate thread. When the new thread has started be
+ started, the caller of this function should then
+ either call `Bus.poll` again or `Bus.poll_stop`.
+
+ @return :str The received message
+ '''
+ from native_bus import bus_poll_wrapped
+ if bus_poll_wrapped(self.bus) == None:
+ raise self.__oserror()
+
+
+ def chown(self, owner : int, group : int):
+ '''
+ Change the ownership of a bus
+
+ `os.stat` can be used of the bus's associated file to get the bus's ownership
+
+ @param owner:int The user ID of the bus's new owner
+ @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()
+
+
+ def chmod(self, mode : int):
+ '''
+ Change the permissions for a bus
+
+ `os.stat` can be used of the bus's associated file to get the bus's permissions
+
+ @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
+ '''
+ from native_bus import bus_chmod_wrapped
+ if bus_chmod_wrapped(self.pathname, mode) == -1:
+ raise self.__oserror()
+
+
def __oserror(self):
'''
Create an OSError
diff --git a/src/native_bus.pyx b/src/native_bus.pyx
index fdcf341..c3c4039 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 posix.types cimport uid_t, gid_t, mode_t
cdef extern int bus_create(const char *, int, char **)
@@ -98,6 +99,71 @@ Listen (in a loop, forever) for new message on a bus
@return 0 on success, -1 on error
'''
+cdef extern int bus_poll_start(long, int)
+'''
+Announce that the thread is listening on the bus.
+This is required so the will does not miss any
+messages due to race conditions. Additionally,
+not calling this function will cause the bus the
+misbehave, is `bus_poll` 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
+ `EAGAIN` if there isn't already a message available on
+ the bus when `bus_poll` is called
+@return 0 on success, -1 on error
+'''
+
+cdef extern int bus_poll_stop(long)
+'''
+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
+'''
+
+cdef extern const char *bus_poll(long)
+'''
+Wait for a message to be broadcasted on the bus.
+The caller should make a copy of the received message,
+without freeing the original copy, and parse it in a
+separate thread. When the new thread has started be
+started, the caller of this function should then
+either call `bus_poll` again or `bus_poll_stop`.
+
+@param bus Bus information
+@return The received message, `NULL` on error
+'''
+
+cdef extern int bus_chown(const char *, uid_t, gid_t)
+'''
+Change the ownership of a bus
+
+`stat(2)` 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
+'''
+
+cdef extern int bus_chmod(const char *, mode_t)
+'''
+Change the permissions for a bus
+
+`stat(2)` 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
+'''
+
+
def bus_allocate() -> int:
'''
@@ -193,8 +259,8 @@ def bus_write_wrapped(bus : int, message : str, flags : int) -> int:
@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 if other process is attempting
- to write
+ @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
'''
cdef const char* cmessage
@@ -234,3 +300,93 @@ def bus_read_wrapped(bus : int, callback : callable, user_data) -> int:
user = (callback, user_data)
return bus_read(<long>bus, <int (*)(const char *, void *)>&bus_callback_wrapper, <void *>user)
+
+def bus_poll_start_wrapped(bus : int, flags : int) -> int:
+ '''
+ Announce that the thread is listening on the bus.
+ This is required so the will does not miss any
+ messages due to race conditions. Additionally,
+ not calling this function will cause the bus the
+ 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
+ '''
+ return bus_poll_start(<long>bus, <int>flags)
+
+
+def bus_poll_stop_wrapped(bus : int) -> int:
+ '''
+ 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
+ '''
+ return bus_poll_stop(<long>bus)
+
+
+def bus_poll_wrapped(bus : int) -> str:
+ '''
+ Wait for a message to be broadcasted on the bus.
+ The caller should make a copy of the received message,
+ without freeing the original copy, and parse it in a
+ separate thread. When the new thread has started be
+ started, the caller of this function should then
+ either call `bus_poll_wrapped` again or
+ `bus_poll_stop_wrapped`.
+
+ @param bus Bus information
+ @return The received message, `None` on error
+ '''
+ cdef const char* msg
+ cdef bytes bs
+ msg = bus_poll(<long>bus)
+ if msg is NULL:
+ return None
+ bs = msg
+ return bs.decode('utf-8', 'strict')
+
+
+def bus_chown_wrapped(file : str, owner : int, group : int) -> int:
+ '''
+ 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
+ '''
+ 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)
+
+
+def bus_chmod_wrapped(file : str, mode : int) -> int:
+ '''
+ 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
+ '''
+ cdef const char* cfile
+ cdef bytes bs
+ bs = file.encode('utf-8') + bytes([0])
+ cfile = bs
+ return bus_chmod(cfile, <mode_t>mode)
+