def __init__(self, control, host=None, port=None, max_workers=None):
        if host is None:
            host = config.get_string('koapy.backend.kiwoom_open_api_plus.grpc.host', 'localhost')
        if port is None:
            port = config.get('koapy.backend.kiwoom_open_api_plus.grpc.port')
        if port == 0:
            port = get_free_localhost_port()
        if max_workers is None:
            max_workers = config.get_int('koapy.backend.kiwoom_open_api_plus.grpc.server.max_workers', 8)

        self._control = control
        self._host = host
        self._port = port
        self._max_workers = max_workers

        self._address = self._host + ':' + str(self._port)
        self._servicer = KiwoomOpenApiPlusServiceServicer(self._control)
        self._executor = futures.ThreadPoolExecutor(max_workers=self._max_workers)

        self._server = None
        self._server_started = False
        self._server_stopped = False

        self.reinitialize_server()

        atexit.register(self._executor.shutdown, False)
 def is_ready(self, timeout=None):
     if timeout is None:
         timeout = config.get_int('koapy.backend.kiwoom_open_api_plus.grpc.client.is_ready.timeout', 10)
     try:
         grpc.channel_ready_future(self._channel).result(timeout=timeout)
         return True
     except grpc.FutureTimeoutError:
         return False
Пример #3
0
 def __init__(self,
              port=None,
              client_check_timeout=None,
              verbosity=None,
              log_level=None):
     self._port = port or config.get(
         'koapy.grpc.port') or get_free_localhost_port()
     self._client_check_timeout = client_check_timeout
     self._verbosity = verbosity
     if log_level is None:
         if self._verbosity is not None:
             log_level = verbosity_to_loglevel(self._verbosity)
     self._log_level = log_level
     if self._log_level is not None:
         set_loglevel(self._log_level)
     self._server_proc_args = [
         'python', '-m', 'koapy.pyqt5.tools.start_tray_application',
         '--port',
         str(self._port)
     ]
     if self._verbosity:
         self._server_proc_args.append('-' + 'v' * self._verbosity)
     self._server_proc = None
     self._server_proc_terminate_timeout = config.get_int(
         'koapy.grpc.context.server.terminate.timeout', 10)
     self._client = KiwoomOpenApiServiceClient(port=self._port)
     logging.debug('Testing if client is ready...')
     if not self._client.is_ready(client_check_timeout):
         logging.debug('Client is not ready, creating a new server')
         self._server_proc = subprocess.Popen(self._server_proc_args)
         assert self._client.is_ready()
         self._stub = self._client.get_stub()
     else:
         logging.debug('Client is ready, using existing server')
         self._stub = self._client.get_stub()
     self._lock = threading.RLock()
     self._enter_count = 0
Пример #4
0
    def __init__(self, port=None, client_check_timeout=None, verbosity=None, log_level=None):
        if port is None:
            port = config.get('koapy.backend.kiwoom_open_api_plus.grpc.port', 0) or get_free_localhost_port()

        if log_level is None and verbosity is not None:
            log_level = verbosity_to_loglevel(verbosity)
        if verbosity is None and log_level is not None:
            verbosity = loglevel_to_verbosity(log_level)

        self._port = port
        self._client_check_timeout = client_check_timeout
        self._verbosity = verbosity
        self._log_level = log_level

        if self._log_level is not None:
            set_loglevel(self._log_level)

        self._server_executable = config.get('koapy.context.server.executable', None)
        if not isinstance(self._server_executable, str):
            self._server_executable = None
        if self._server_executable is None:
            envpath = config.get('koapy.context.server.executable.conda.envpath', None)
            if envpath is not None and isinstance(envpath, str):
                self._server_executable = subprocess.check_output([ # pylint: disable=unexpected-keyword-arg
                    'conda', 'run', '-p', envpath,
                    'python', '-c', 'import sys; print(sys.executable)',
                ], encoding=sys.stdout.encoding, creationflags=subprocess.CREATE_NO_WINDOW).strip()
        if self._server_executable is None:
            envname = config.get('koapy.context.server.executable.conda.envname', None)
            if envname is not None and isinstance(envname, str):
                self._server_executable = subprocess.check_output([ # pylint: disable=unexpected-keyword-arg
                    'conda', 'run', '-n', envname,
                    'python', '-c', 'import sys; print(sys.executable)',
                ], encoding=sys.stdout.encoding, creationflags=subprocess.CREATE_NO_WINDOW).strip()
        if self._server_executable is None:
            self._server_executable = sys.executable

        self._server_proc_args = [self._server_executable, '-m', 'koapy.cli', 'serve']
        if self._port is not None:
            self._server_proc_args.extend(['-p', str(self._port)])
        if self._verbosity is not None:
            self._server_proc_args.extend(['-' + 'v' * self._verbosity])

        self._server_proc = None
        self._server_proc_terminate_timeout = config.get_int('koapy.context.server.terminate.timeout', 10)

        self._client = KiwoomOpenApiPlusServiceClient(port=self._port)

        self.logger.debug('Testing if client is ready...')
        if not self._client.is_ready(self._client_check_timeout):
            assert platform.architecture()[0] == '32bit', 'Server should run under 32bit environment'
            self.logger.debug('Client is not ready, creating a new server')
            self._server_proc = subprocess.Popen(self._server_proc_args)
            assert self._client.is_ready(), 'Failed to create server'
            self._stub = self._client.get_stub()
        else:
            self.logger.debug('Client is ready, using existing server')
            self._stub = self._client.get_stub()

        self._context_lock = threading.RLock()
        self._enter_count = 0
Пример #5
0
    def __init__(self,
                 port=None,
                 client_check_timeout=None,
                 verbosity=None,
                 log_level=None):
        if port is None:
            port = (config.get("koapy.backend.kiwoom_open_api_plus.grpc.port",
                               0) or get_free_localhost_port())

        if log_level is None and verbosity is not None:
            log_level = verbosity_to_loglevel(verbosity)
        if verbosity is None and log_level is not None:
            verbosity = loglevel_to_verbosity(log_level)

        self._port = port
        self._client_check_timeout = client_check_timeout
        self._verbosity = verbosity
        self._log_level = log_level

        if self._log_level is not None:
            set_loglevel(self._log_level)

        self._server_executable = config.get("koapy.context.server.executable",
                                             None)
        if not isinstance(self._server_executable, str):
            self._server_executable = None
        if self._server_executable is None:
            envpath = config.get(
                "koapy.context.server.executable.conda.envpath", None)
            if envpath is not None and isinstance(envpath, str):
                self._server_executable = subprocess.check_output(
                    [  # pylint: disable=unexpected-keyword-arg
                        "conda",
                        "run",
                        "-p",
                        envpath,
                        "python",
                        "-c",
                        "import sys; print(sys.executable)",
                    ],
                    encoding=sys.stdout.encoding,
                    creationflags=subprocess.CREATE_NO_WINDOW,
                ).strip()
        if self._server_executable is None:
            envname = config.get(
                "koapy.context.server.executable.conda.envname", None)
            if envname is not None and isinstance(envname, str):
                self._server_executable = subprocess.check_output(
                    [  # pylint: disable=unexpected-keyword-arg
                        "conda",
                        "run",
                        "-n",
                        envname,
                        "python",
                        "-c",
                        "import sys; print(sys.executable)",
                    ],
                    encoding=sys.stdout.encoding,
                    creationflags=subprocess.CREATE_NO_WINDOW,
                ).strip()
        if self._server_executable is None:
            self._server_executable = sys.executable

        self._server_proc_args = [
            self._server_executable, "-m", "koapy.cli", "serve"
        ]
        if self._port is not None:
            self._server_proc_args.extend(["-p", str(self._port)])
        if self._verbosity is not None:
            self._server_proc_args.extend(["-" + "v" * self._verbosity])

        self._server_proc = None
        self._server_proc_terminate_timeout = config.get_int(
            "koapy.context.server.terminate.timeout", 10)

        self._client = KiwoomOpenApiPlusServiceClient(port=self._port)

        self.logger.debug("Testing if client is ready...")
        if not self._client.is_ready(self._client_check_timeout):
            assert (platform.architecture()[0] == "32bit"
                    ), "Server should run under 32bit environment"
            self.logger.debug("Client is not ready, creating a new server")
            self._server_proc = subprocess.Popen(self._server_proc_args)
            assert self._client.is_ready(), "Failed to create server"
            self._stub = self._client.get_stub()
        else:
            self.logger.debug("Client is ready, using existing server")
            self._stub = self._client.get_stub()

        self._context_lock = threading.RLock()
        self._enter_count = 0
class KiwoomOpenApiPlusServiceClientSideSignalConnector:

    _lock = threading.RLock()
    _observers = {}
    _max_workers = config.get_int(
        'koapy.backend.kiwoom_open_api_plus.grpc.client.signal_connector.max_workers',
        8)
    _executor = futures.ThreadPoolExecutor(max_workers=_max_workers)

    def __init__(self, stub, name):
        self._stub = stub
        self._name = name

    @classmethod
    def _stop_observer(cls, observer):
        request = KiwoomOpenApiPlusService_pb2.BidirectionalListenRequest()
        observer.on_next(request)
        observer.on_completed()

    def _get_observer(self, callback, default=None):
        return self._observers.setdefault(self._stub, {}).setdefault(
            self._name, {}).get(callback, default)

    def _remove_observer(self, callback):
        with self._lock:
            observer = self._get_observer(callback)
            if observer:
                self._stop_observer(observer)
                del self._observers[self._stub][self._name][callback]
            return observer

    def _add_observer(self, callback):
        with self._lock:
            self._remove_observer(callback)
            observer = QueueBasedIterableObserver()
            self._observers[self._stub][self._name][callback] = observer
            return observer

    @classmethod
    def shutdown(cls):
        with cls._lock:
            for _stub, names in cls._observers.items():
                for _name, observers in names.items():
                    for _callback, observer in observers.items():
                        cls._stop_observer(observer)
        cls._executor.shutdown(False)

    def connect(self, callback):
        with self._lock:
            observer = self._add_observer(callback)

            def fn():
                request = KiwoomOpenApiPlusService_pb2.BidirectionalListenRequest(
                )
                request.listen_request.slots.append(self._name)  # pylint: disable=no-member
                observer.on_next(request)
                observer_iterator = iter(observer)
                for i, response in enumerate(
                        self._stub.BidirectionalListen(observer_iterator)):  # pylint: disable=unused-variable
                    args = convert_arguments_from_protobuf_to_python(
                        response.arguments)
                    callback(*args)
                    request = KiwoomOpenApiPlusService_pb2.BidirectionalListenRequest(
                    )
                    observer.on_next(request)

            future = self._executor.submit(fn)

            def done(future):
                err = future.exception()
                if err:
                    raise err

            future.add_done_callback(done)

    def disconnect(self, callback):
        with self._lock:
            self._remove_observer(callback)