ouisync.service
In-process embedding of the Ouisync service
1"""In-process embedding of the Ouisync service""" 2 3import asyncio 4import ctypes 5 6from ouisync.session import ErrorCode, dispatch_error 7 8from ._bindings import StatusCallback, bindings 9 10__all__ = ["Service", "init_log"] 11 12 13class Service: 14 """Manages the repositories and runs the sync protocol. It can be 15 interacted with using a [Session][ouisync.session.Session] connected to 16 the same config directory. 17 18 Note: to create a service, use `Service.start`. 19 """ 20 21 def __init__(self, handle: int): 22 self._handle: int | None = handle 23 24 @classmethod 25 async def start(cls, config_path, debug_label: str | None = None) -> "Service": 26 """Starts the service. 27 28 `config_path` is the path to the config directory of this service. 29 If it doesn't exist, it's created automatically. The service requires 30 both read and write access to it. 31 32 `debug_label` is an optional label used to distinguish multiple 33 services running in the same process. Used mainly for testing and 34 debugging the library itself. 35 """ 36 error_code, handle = await _invoke( 37 bindings().start_service, 38 str(config_path).encode(), 39 debug_label.encode() if debug_label is not None else None, 40 ) 41 42 if error_code != ErrorCode.OK: 43 raise dispatch_error(error_code) 44 45 return cls(handle) 46 47 async def stop(self): 48 """Stops this service. Has no effect if the service has already been 49 stopped.""" 50 handle = self._handle 51 if handle is None: 52 return 53 54 self._handle = None 55 56 error_code, _ = await _invoke(bindings().stop_service, handle) 57 58 if error_code != ErrorCode.OK: 59 raise dispatch_error(error_code) 60 61 62async def _invoke(func, *args): 63 """Calls one of the `start_service`/`stop_service` native functions, 64 appending the status callback and its (unused) context, and awaits its 65 completion. Returns `(error_code, return_value)`.""" 66 loop = asyncio.get_running_loop() 67 future: asyncio.Future = loop.create_future() 68 69 # The callback may be invoked from a thread other than this one, so it 70 # must hand the result back to the event loop thread-safely. Kept alive 71 # by this frame for as long as the native side may still call it. 72 @StatusCallback 73 def callback(_context: ctypes.c_void_p, error_code: int): 74 loop.call_soon_threadsafe(_resolve, future, error_code) 75 76 return_value = func(*args, callback, None) 77 error_code = ErrorCode(await future) 78 79 return error_code, return_value 80 81 82def _resolve(future: asyncio.Future, error_code: int): 83 if not future.done(): 84 future.set_result(error_code) 85 86 87def init_log(): 88 """Enables logging of Ouisync's internal messages. 89 90 Calling this function more than once has no effect. Currently there is 91 no way to disable the logging once it's been enabled. 92 """ 93 bindings().init_log()
14class Service: 15 """Manages the repositories and runs the sync protocol. It can be 16 interacted with using a [Session][ouisync.session.Session] connected to 17 the same config directory. 18 19 Note: to create a service, use `Service.start`. 20 """ 21 22 def __init__(self, handle: int): 23 self._handle: int | None = handle 24 25 @classmethod 26 async def start(cls, config_path, debug_label: str | None = None) -> "Service": 27 """Starts the service. 28 29 `config_path` is the path to the config directory of this service. 30 If it doesn't exist, it's created automatically. The service requires 31 both read and write access to it. 32 33 `debug_label` is an optional label used to distinguish multiple 34 services running in the same process. Used mainly for testing and 35 debugging the library itself. 36 """ 37 error_code, handle = await _invoke( 38 bindings().start_service, 39 str(config_path).encode(), 40 debug_label.encode() if debug_label is not None else None, 41 ) 42 43 if error_code != ErrorCode.OK: 44 raise dispatch_error(error_code) 45 46 return cls(handle) 47 48 async def stop(self): 49 """Stops this service. Has no effect if the service has already been 50 stopped.""" 51 handle = self._handle 52 if handle is None: 53 return 54 55 self._handle = None 56 57 error_code, _ = await _invoke(bindings().stop_service, handle) 58 59 if error_code != ErrorCode.OK: 60 raise dispatch_error(error_code)
Manages the repositories and runs the sync protocol. It can be interacted with using a [Session][ouisync.session.Session] connected to the same config directory.
Note: to create a service, use Service.start.
25 @classmethod 26 async def start(cls, config_path, debug_label: str | None = None) -> "Service": 27 """Starts the service. 28 29 `config_path` is the path to the config directory of this service. 30 If it doesn't exist, it's created automatically. The service requires 31 both read and write access to it. 32 33 `debug_label` is an optional label used to distinguish multiple 34 services running in the same process. Used mainly for testing and 35 debugging the library itself. 36 """ 37 error_code, handle = await _invoke( 38 bindings().start_service, 39 str(config_path).encode(), 40 debug_label.encode() if debug_label is not None else None, 41 ) 42 43 if error_code != ErrorCode.OK: 44 raise dispatch_error(error_code) 45 46 return cls(handle)
Starts the service.
config_path is the path to the config directory of this service.
If it doesn't exist, it's created automatically. The service requires
both read and write access to it.
debug_label is an optional label used to distinguish multiple
services running in the same process. Used mainly for testing and
debugging the library itself.
48 async def stop(self): 49 """Stops this service. Has no effect if the service has already been 50 stopped.""" 51 handle = self._handle 52 if handle is None: 53 return 54 55 self._handle = None 56 57 error_code, _ = await _invoke(bindings().stop_service, handle) 58 59 if error_code != ErrorCode.OK: 60 raise dispatch_error(error_code)
Stops this service. Has no effect if the service has already been stopped.
88def init_log(): 89 """Enables logging of Ouisync's internal messages. 90 91 Calling this function more than once has no effect. Currently there is 92 no way to disable the logging once it's been enabled. 93 """ 94 bindings().init_log()
Enables logging of Ouisync's internal messages.
Calling this function more than once has no effect. Currently there is no way to disable the logging once it's been enabled.