from .error import ErrorCode, IndyError from ctypes import * import asyncio import sys import itertools import logging _futures = {} _futures_counter = itertools.count() def do_call(name: str, *args): logger = logging.getLogger(__name__) logger.debug("do_call: >>> name: %s, args: %s", name, args) event_loop = asyncio.get_event_loop() future = event_loop.create_future() command_handle = next(_futures_counter) _futures[command_handle] = (event_loop, future) err = getattr(_cdll(), name)(command_handle, *args) logger.debug("do_call: Function %s returned err: %i", name, err) if err != ErrorCode.Success: logger.warning("_do_call: Function %s returned error %i", name, err) future.set_exception(IndyError(ErrorCode(err))) logger.debug("do_call: <<< %s", future) return future def create_cb(cb_type: CFUNCTYPE): logger = logging.getLogger(__name__) logger.debug("create_cb: >>> cb_type: %s", cb_type) res = cb_type(_indy_callback) logger.debug("create_cb: <<< res: %s", res) return res def _indy_callback(command_handle: int, err: int, *args): logger = logging.getLogger(__name__) logger.debug("_indy_callback: >>> command_handle: %i, err %i, args: %s", command_handle, err, args) (event_loop, future) = _futures[command_handle] event_loop.call_soon_threadsafe(_indy_loop_callback, command_handle, err, *args) logger.debug("_indy_callback: <<<") def _indy_loop_callback(command_handle: int, err, *args): logger = logging.getLogger(__name__) logger.debug("_indy_loop_callback: >>> command_handle: %i, err %i, args: %s", command_handle, err, args) (event_loop, future) = _futures.pop(command_handle) if err != ErrorCode.Success: logger.warning("_indy_loop_callback: Function returned error %i", err) future.set_exception(IndyError(ErrorCode(err))) else: if len(args) == 0: res = None elif len(args) == 1: (res,) = args else: res = args logger.warning("_indy_loop_callback: Function returned %s", res) future.set_result(res) logger.debug("_indy_loop_callback <<<") def _cdll() -> CDLL: if not hasattr(_cdll, "cdll"): _cdll.cdll = _load_cdll() return _cdll.cdll def _load_cdll() -> CDLL: logger = logging.getLogger(__name__) logger.debug("_load_cdll: >>>") libindy_prefix_mapping = {"darwin": "lib", "linux": "lib", "linux2": "lib", "win32": ""} libindy_suffix_mapping = {"darwin": ".dylib", "linux": ".so", "linux2": ".so", "win32": ".dll"} os_name = sys.platform logger.debug("_load_cdll: Detected OS name: %s", os_name) try: libindy_prefix = libindy_prefix_mapping[os_name] libindy_suffix = libindy_suffix_mapping[os_name] except KeyError: logger.error("_load_cdll: OS isn't supported: %s", os_name) raise OSError("OS isn't supported: %s", os_name) libindy_name = "{0}indy{1}".format(libindy_prefix, libindy_suffix) logger.debug("_load_cdll: Resolved libindy name is: %s", libindy_name) try: res = CDLL(libindy_name) logger.debug("_load_cdll: <<< res: %s", res) return res except OSError as e: logger.error("_load_cdll: Can't load libindy: %s", e) raise e