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 main(cls, args): import argparse parser = argparse.ArgumentParser() command_choices = [ 'update_version_if_necessary', 'disable_autologin', 'open_login_window', 'show_account_window', ] default_command = 'update_version_if_necessary' parser.add_argument('command', nargs='?', choices=command_choices, default=default_command) args = parser.parse_args(args) if args.command == 'update_version_if_necessary': from koapy.config import config credential = config.get( 'koapy.backend.kiwoom_open_api_plus.credential') updater = cls(credential) updater.update_version_if_necessary() elif args.command == 'disable_autologin': cls.__disable_autologin() elif args.command == 'open_login_window': cls.__open_login_window() elif args.command == 'show_account_window': cls.__show_account_window() return 0
def version(verbose): set_verbosity(verbose) from koapy import KiwoomOpenApiPlusVersionUpdater from koapy.config import config credential = config.get('koapy.backend.kiwoom_open_api_plus.credential') updater = KiwoomOpenApiPlusVersionUpdater(credential) updater.update_version_if_necessary()
def __init__(self, host=None, port=None): self._host = host or config.get_string('koapy.backend.kiwoom_open_api_plus.grpc.host', 'localhost') self._port = port or config.get('koapy.backend.kiwoom_open_api_plus.grpc.port') if self._port is None: raise ValueError('Port is None') self._target = self._host + ':' + str(self._port) self._channel = grpc.insecure_channel(self._target) self._stub = KiwoomOpenApiPlusService_pb2_grpc.KiwoomOpenApiPlusServiceStub(self._channel) self._stub_wrapped = KiwoomOpenApiPlusServiceClientStubWrapper(self._stub)
def enable_autologin_with_control(control): logging.info('start enabling autologin') executor = futures.ThreadPoolExecutor() logging.info('showing account window') _future = executor.submit(control.ShowAccountWindow) desktop = pywinauto.Desktop(allow_magic_lookup=False) account_window = desktop.window(title_re=r'계좌비밀번호 입력 \(버전: [0-9].+[0-9]+\)') try: logging.info('waiting for account window to show up') timeout_account_window_ready = 5 account_window.wait('ready', timeout_account_window_ready) except pywinauto.timings.TimeoutError: logging.info('cannot find account window') raise else: logging.info('account window found') if is_in_development: account_window.logging.info_control_identifiers() logging.info('enabling auto login') account_window['AUTO'].check() account_passwords = config.get('koapy.backend.kiwoom.login.account_passwords') account_combo = account_window['ComboBox'] account_cnt = account_combo.item_count() logging.info('putting account passwords') for i in range(account_cnt): account_combo.select(i) account_no = account_combo.selected_text().split()[0] if account_no in account_passwords: account_window['Edit'].set_text(account_passwords[account_no]) elif '0000000000' in account_passwords: account_window['Edit'].set_text(account_passwords['0000000000']) account_window['등록'].click() logging.info('closing account window') account_window['닫기'].click() try: logging.info('wating account window to be closed') timeout_account_window_done = 5 account_window.wait_not('visible', timeout_account_window_done) except pywinauto.timings.TimeoutError: logging.info('cannot sure account window is closed') raise else: logging.info('account window closed') executor.shutdown()
def get_or_create_context(self): with contextlib.ExitStack() as stack: if self._context is None: default_context = config.get( 'koapy.data.updater.default_context') if default_context == 'koapy.backend.cybos.CybosPlusComObject.CybosPlusComObject': logging.debug('Using CybosPlus backend') default_context = CybosPlusComObject() else: if default_context != 'koapy.context.KiwoomOpenApiContext.KiwoomOpenApiContext': logging.warning( 'Unexpected default context %s, defaults to KiwoomOpenApiContext.', default_context) logging.debug('Using Kiwoom OpenAPI backend') default_context = KiwoomOpenApiContext() self._context = stack.enter_context(default_context) def unset_context(): self._context = None stack.callback(unset_context) else: logging.debug('Using existing given context of type %s', type(self._context)) if isinstance(self._context, KiwoomOpenApiContext): if self._chart_type == ChartType.DAY: self._date_column_name = '일자' self._date_format = '%Y%m%d' elif self._chart_type == ChartType.MINUTE: self._date_column_name = '체결시간' self._date_format = '%Y%m%d%H%M%S' else: raise ValueError elif isinstance(self._context, CybosPlusComObject): if self._chart_type == ChartType.DAY: self._date_column_name = '날짜' self._date_format = '%Y%m%d' elif self._chart_type == ChartType.MINUTE: self._date_column_name = '날짜' self._date_format = '%Y%m%d' self._time_column_name = '시간' self._time_format = '%H%M' else: raise ValueError else: raise TypeError self._context.EnsureConnected() yield self._context
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
# check http://marketdata.krx.co.kr/mdi#document=01100305 for more information import re import datetime import logging import requests from koapy.config import config user_agent = config.get('koapy.utils.krx.user_agent') oldest_year_available = 1975 def download_holidays_as_dict(year=None, page_first_call=False): now = datetime.datetime.now() def generate_otp(): headers = { 'Accept': '*/*', 'Accept-Encoding': 'gzip, deflate', 'Host': 'marketdata.krx.co.kr', 'Referer': 'http://marketdata.krx.co.kr/mdi', 'User-Agent': user_agent, 'X-Requested-With': 'XMLHttpRequest', } params = { 'bld': 'MKD/01/0110/01100305/mkd01100305_01', 'name': 'form', '_': str(int(now.timestamp() * 1000)),
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
def LoginUsingCredential(self, credential=None): # https://github.com/pywinauto/pywinauto/issues/472 import sys sys.coinit_flags = 2 import warnings warnings.simplefilter("ignore", UserWarning) import pywinauto if credential is None: from koapy.config import config credential = config.get( 'koapy.backend.kiwoom_open_api_plus.credential') is_in_development = False use_set_text = False userid = credential.get('user_id') password = credential.get('user_password') cert = credential.get('cert_password') is_save_userid = True is_simulation = credential.get('is_simulation') desktop = pywinauto.Desktop(allow_magic_lookup=False) login_window = desktop.window(title='Open API Login') try: self.logger.info('Waiting for login screen') timeout_login_screen_ready = 30 login_window.wait('ready', timeout_login_screen_ready) except pywinauto.timings.TimeoutError: self.logger.info('Cannot find login screen') raise else: self.logger.info('Login screen found') if is_in_development: login_window.print_control_identifiers() if userid: self.logger.info('Putting userid') if use_set_text: login_window['Edit1'].set_text(userid) else: login_window['Edit1'].set_focus() pywinauto.keyboard.send_keys(userid) pywinauto.keyboard.send_keys('{TAB}') if password: self.logger.info('Putting password') if use_set_text: login_window['Edit2'].set_text(password) else: login_window['Edit2'].set_focus() pywinauto.keyboard.send_keys(password) pywinauto.keyboard.send_keys('{TAB}') else: raise RuntimeError( 'password not set, please check config file') # not working properly if is_save_userid: self.logger.info('Checking to save userid') login_window['Button6'].check() else: self.logger.info('Unchecking to save userid') login_window['Button6'].uncheck_by_click() if not is_simulation: if not login_window['Edit3'].is_enabled(): self.logger.info('Unchecking to use simulation server') login_window['Button5'].uncheck_by_click() if cert: self.logger.info('Putting cert password') if use_set_text: login_window['Edit3'].set_text(cert) else: login_window['Edit3'].set_focus() pywinauto.keyboard.send_keys(cert) pywinauto.keyboard.send_keys('{TAB}') else: raise RuntimeError( 'cert passowrd not set, please check config file') else: if login_window['Edit3'].is_enabled(): self.logger.info('Checking to use simulation server') login_window['Button5'].check_by_click() self.logger.info('Logging in') login_window['Button1'].click()
import os from koapy.config import config # Set QT_API environment variable for correct Qt backend usage os.environ["QT_API"] = config.get("koapy.qtpy.qt_api", "pyside2") # Import proper Qt binding using qtpy from qtpy import * from qtpy import PYQT5, PYSIDE2, PythonQtError # PySide2 patch if PYSIDE2: import PySide2 if "QT_QPA_PLATFORM_PLUGIN_PATH" not in os.environ and hasattr( PySide2, "__file__"): QT_QPA_PLATFORM_PLUGIN_PATH = os.path.join( os.path.dirname(PySide2.__file__), "plugins", "platforms") os.environ["QT_QPA_PLATFORM_PLUGIN_PATH"] = QT_QPA_PLATFORM_PLUGIN_PATH
import os from koapy.utils.logging.Logging import Logging # pylint: disable=import-error from koapy.config import config # pylint: disable=import-error # Get logger logger = Logging.get_logger('koapy.compat.pyside2') # Set QT_API environment variable for correct Qt backend usage os.environ['QT_API'] = config.get('koapy.qtpy.qt_api', 'pyside2') # Import proper Qt binding using qtpy from qtpy import * from qtpy import PYQT5, PYSIDE2, PythonQtError # Test which Qt binding is being used if PYQT5: logger.debug('Using PyQt5 as Qt backend') elif PYSIDE2: logger.debug('Using PySide2 as Qt backend') else: raise PythonQtError('No Qt bindings could be found') # PySide2 patch if PYSIDE2: import PySide2 if 'QT_QPA_PLATFORM_PLUGIN_PATH' not in os.environ and hasattr(PySide2, '__file__'): QT_QPA_PLATFORM_PLUGIN_PATH = os.path.join(os.path.dirname(PySide2.__file__), 'plugins', 'platforms') os.environ['QT_QPA_PLATFORM_PLUGIN_PATH'] = QT_QPA_PLATFORM_PLUGIN_PATH
def CommConnect(self): """ https://github.com/ippoeyeslhw/cppy/blob/master/cp_luncher.py """ login_config = config.get('koapy.backend.cybos.login') userid = login_config.get('id') password = login_config.get('password') cert = login_config.get('cert') auto_account_password = login_config.get('auto_account_password') auto_cert_password = login_config.get('auto_cert_password') price_check_only = login_config.get('price_check_only') account_passwords = login_config.get('account_passwords') app = pywinauto.Application().start( r'C:\DAISHIN\STARTER\ncStarter.exe /prj:cp') desktop = pywinauto.Desktop(allow_magic_lookup=False) try: ask_stop = desktop.window(title='ncStarter') ask_stop.wait('ready', timeout=8) except pywinauto.timings.TimeoutError: pass else: if is_in_development: ask_stop.print_control_identifiers() if ask_stop['Static2'].window_text().endswith('종료하시겠습니까?'): ask_stop['Button1'].click() try: ask_stop = desktop.window(title='ncStarter') ask_stop.wait('ready', timeout=5) except pywinauto.timings.TimeoutError: pass else: if is_in_development: ask_stop.print_control_identifiers() if ask_stop['Static2'].window_text().endswith( '종료할 수 없습니다.'): ask_stop['Button'].click() raise RuntimeError('cannot stop existing server') starter = desktop.window(title='CYBOS Starter') starter.wait('ready', timeout=10) if is_in_development: starter.print_control_identifiers() if userid: starter['Edit1'].set_text(userid) if password: starter['Edit2'].set_text(password) else: raise RuntimeError('no password given') if not price_check_only: if cert: starter['Edit3'].set_text(cert) else: raise RuntimeError('no cert password given') if auto_account_password: starter['Button4'].check() try: confirm = desktop.window(title='대신증권') confirm.wait('ready', timeout=1) except pywinauto.timings.TimeoutError: pass else: if is_in_development: confirm.print_control_identifiers() confirm['Button'].click() if auto_cert_password: starter['Button5'].check() try: confirm = desktop.window(title='대신증권') confirm.wait('ready', timeout=1) except pywinauto.timings.TimeoutError: pass else: if is_in_development: confirm.print_control_identifiers() confirm['Button'].click() if price_check_only: starter['Button6'].check() starter['Button1'].click() should_stop = False while not should_stop: try: account_password = desktop.window(title='종합계좌 비밀번호 확인 입력') account_password.wait('ready', timeout=5) except pywinauto.timings.TimeoutError: should_stop = True else: if is_in_development: account_password.print_control_identifiers() account_no = account_password['Static'].window_text().split( ':')[-1].strip() if account_no in account_passwords: account_password['Edit'].set_text( account_passwords[account_no]) else: raise RuntimeError( 'no account password given for account %s' % account_no) account_password['Button1'].click() try: starter.wait_not('visible', timeout=10) except pywinauto.timings.TimeoutError: pass
def Connect(self, credential=None): """ https://github.com/ippoeyeslhw/cppy/blob/master/cp_luncher.py """ import pywinauto assert self.IsAdmin( ), 'Connect() method requires to be run as administrator' is_in_development = False if credential is None: from koapy.config import config credential = config.get( 'koapy.backend.daishin_cybos_plus.credential') userid = credential.get('user_id') password = credential.get('user_password') cert = credential.get('cert_password') auto_account_password = credential.get('auto_account_password') auto_cert_password = credential.get('auto_cert_password') price_check_only = credential.get('price_check_only') account_passwords = credential.get('account_passwords') self.logger.info('Starting CYBOS Starter application') app = pywinauto.Application().start( r'C:\DAISHIN\STARTER\ncStarter.exe /prj:cp') # pylint: disable=unused-variable desktop = pywinauto.Desktop(allow_magic_lookup=False) try: self.logger.info( 'Waiting for possible popup which asks for shutting down existing program' ) ask_stop = desktop.window(title='ncStarter') ask_stop.wait('ready', timeout=10) except pywinauto.timings.TimeoutError: self.logger.info('No existing program found to be shutdown') else: self.logger.info('Existing program found, shutting down') if is_in_development: ask_stop.print_control_identifiers() if ask_stop['Static2'].window_text().endswith('종료하시겠습니까?'): ask_stop['Button1'].click() try: self.logger.info( 'Wating for possible failure message on shutdown') ask_stop = desktop.window(title='ncStarter') ask_stop.wait('ready', timeout=10) except pywinauto.timings.TimeoutError: self.logger.info('Successfully shutdown existing program') else: self.logger.error('Failed to shutdown existing program') if is_in_development: ask_stop.print_control_identifiers() if ask_stop['Static2'].window_text().endswith( '종료할 수 없습니다.'): ask_stop['Button'].click() raise RuntimeError('Cannot stop existing program') try: self.logger.info('Waiting for CYBOS Starter login screen') starter = desktop.window(title='CYBOS Starter') starter.wait('ready', timeout=30) except pywinauto.timings.TimeoutError: self.logger.exception('Failed to find login screen') raise if is_in_development: starter.print_control_identifiers() if userid: self.logger.info('Putting user id') starter['Edit1'].set_text(userid) if password: self.logger.info('Putting user password') starter['Edit2'].set_text(password) else: raise RuntimeError('No user password given') if not price_check_only: if cert: self.logger.info('Putting cert password') starter['Edit3'].set_text(cert) else: raise RuntimeError('No cert password given') if price_check_only: if starter['Edit3'].is_enabled(): self.logger.info('Checking price check only option') starter['Button6'].check_by_click() else: if not starter['Edit3'].is_enabled(): starter['Button6'].uncheck_by_click() if auto_account_password: self.logger.info('Checking auto account password option') starter['Button4'].check() # check dosen't work try: confirm = desktop.window(title='대신증권') confirm.wait('ready', timeout=5) except pywinauto.timings.TimeoutError: pass else: if is_in_development: confirm.print_control_identifiers() confirm['Button'].click() else: starter['Button4'].uncheck() # uncheck dosen't work if auto_cert_password: self.logger.info('Checking auto cert password option') starter['Button5'].check() # check dosen't work try: confirm = desktop.window(title='대신증권') confirm.wait('ready', timeout=5) except pywinauto.timings.TimeoutError: pass else: if is_in_development: confirm.print_control_identifiers() confirm['Button'].click() else: starter['Button5'].uncheck() # uncheck dosen't work self.logger.info('Clicking login button') starter['Button1'].click() self.logger.info('Setting account passwords if necessary') should_stop = False while not should_stop: try: self.logger.info('Waiting for account password setting screen') account_password = desktop.window(title='종합계좌 비밀번호 확인 입력') account_password.wait('ready', timeout=5) except pywinauto.timings.TimeoutError: self.logger.info('Account password setting screen not found') should_stop = True else: self.logger.info('Account password setting screen found') if is_in_development: account_password.print_control_identifiers() account_no = account_password['Static'].window_text().split( ':')[-1].strip() if account_no in account_passwords: account_password['Edit'].set_text( account_passwords[account_no]) else: raise RuntimeError( 'No account password given for account %s' % account_no) account_password['Button1'].click() try: self.logger.info('Waiting for starter screen to be closed') starter.wait_not('visible', timeout=60) except pywinauto.timings.TimeoutError: self.logger.warning( 'Could not wait for starter screen to be closed') else: self.logger.info('Starter screen is closed') try: self.logger.info('Waiting for notice window') notice = desktop.window(title='공지사항') notice.wait('ready', timeout=60) except pywinauto.timings.TimeoutError: self.logger.info('No notice window found') else: self.logger.info('Closing notice window') notice.close() try: self.logger.info( 'Waiting for the notice window to be closed') notice.wait_not('visible', timeout=60) except pywinauto.timings.TimeoutError: self.logger.warning( 'Could not wait for notice screen to be closed') else: self.logger.info('Notice window is closed') if self.GetConnectState() == 0: self.logger.error('Failed to start and connect to CYBOS Plus') else: self.logger.info('Succesfully connected to CYBOS Plus') return self.GetConnectState()
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
def ConnectUsingPywinauto_Impl(cls, credential=None): """ https://github.com/ippoeyeslhw/cppy/blob/master/cp_luncher.py """ import pywinauto is_in_development = False if credential is None: from koapy.config import config credential = config.get( "koapy.backend.daishin_cybos_plus.credential") userid = credential.get("user_id") password = credential.get("user_password") cert = credential.get("cert_password") auto_account_password = credential.get("auto_account_password") auto_cert_password = credential.get("auto_cert_password") price_check_only = credential.get("price_check_only") account_passwords = credential.get("account_passwords") cls.logger.info("Starting CYBOS Starter application") app = pywinauto.Application().start( r"C:\DAISHIN\STARTER\ncStarter.exe /prj:cp") # pylint: disable=unused-variable desktop = pywinauto.Desktop(allow_magic_lookup=False) try: cls.logger.info( "Waiting for possible popup which asks for shutting down existing program" ) ask_stop = desktop.window(title="ncStarter") ask_stop.wait("ready", timeout=10) except pywinauto.timings.TimeoutError: cls.logger.info("No existing program found to be shutdown") else: cls.logger.info("Existing program found, shutting down") if is_in_development: ask_stop.print_control_identifiers() if ask_stop["Static2"].window_text().endswith("종료하시겠습니까?"): ask_stop["Button1"].click() try: cls.logger.info( "Wating for possible failure message on shutdown") ask_stop = desktop.window(title="ncStarter") ask_stop.wait("ready", timeout=10) except pywinauto.timings.TimeoutError: cls.logger.info("Successfully shutdown existing program") else: cls.logger.error("Failed to shutdown existing program") if is_in_development: ask_stop.print_control_identifiers() if ask_stop["Static2"].window_text().endswith( "종료할 수 없습니다."): ask_stop["Button"].click() raise RuntimeError("Cannot stop existing program") try: cls.logger.info("Waiting for CYBOS Starter login screen") starter = desktop.window(title="CYBOS Starter") starter.wait("ready", timeout=30) except pywinauto.timings.TimeoutError: cls.logger.exception("Failed to find login screen") raise if is_in_development: starter.print_control_identifiers() if userid: cls.logger.info("Putting user id") starter["Edit1"].set_text(userid) if password: cls.logger.info("Putting user password") starter["Edit2"].set_text(password) else: raise RuntimeError("No user password given") if not price_check_only: if cert: cls.logger.info("Putting cert password") starter["Edit3"].set_text(cert) else: raise RuntimeError("No cert password given") if price_check_only: if starter["Edit3"].is_enabled(): cls.logger.info("Checking price check only option") starter["Button6"].check_by_click() else: if not starter["Edit3"].is_enabled(): starter["Button6"].uncheck_by_click() if auto_account_password: cls.logger.info("Checking auto account password option") starter["Button4"].check() # check dosen't work try: confirm = desktop.window(title="대신증권") confirm.wait("ready", timeout=5) except pywinauto.timings.TimeoutError: pass else: if is_in_development: confirm.print_control_identifiers() confirm["Button"].click() else: starter["Button4"].uncheck() # uncheck dosen't work if auto_cert_password: cls.logger.info("Checking auto cert password option") starter["Button5"].check() # check dosen't work try: confirm = desktop.window(title="대신증권") confirm.wait("ready", timeout=5) except pywinauto.timings.TimeoutError: pass else: if is_in_development: confirm.print_control_identifiers() confirm["Button"].click() else: starter["Button5"].uncheck() # uncheck dosen't work cls.logger.info("Clicking login button") starter["Button1"].click() cls.logger.info("Setting account passwords if necessary") should_stop = False while not should_stop: try: cls.logger.info("Waiting for account password setting screen") account_password = desktop.window(title="종합계좌 비밀번호 확인 입력") account_password.wait("ready", timeout=5) except pywinauto.timings.TimeoutError: cls.logger.info("Account password setting screen not found") should_stop = True else: cls.logger.info("Account password setting screen found") if is_in_development: account_password.print_control_identifiers() account_no = (account_password["Static"].window_text().split( ":")[-1].strip()) if account_no in account_passwords: account_password["Edit"].set_text( account_passwords[account_no]) else: raise RuntimeError( "No account password given for account %s" % account_no) account_password["Button1"].click() try: cls.logger.info("Waiting for starter screen to be closed") starter.wait_not("visible", timeout=60) except pywinauto.timings.TimeoutError: cls.logger.warning( "Could not wait for starter screen to be closed") else: cls.logger.info("Starter screen is closed") try: cls.logger.info("Waiting for notice window") notice = desktop.window(title="공지사항") notice.wait("ready", timeout=60) except pywinauto.timings.TimeoutError: cls.logger.info("No notice window found") else: cls.logger.info("Closing notice window") notice.close() try: cls.logger.info( "Waiting for the notice window to be closed") notice.wait_not("visible", timeout=60) except pywinauto.timings.TimeoutError: cls.logger.warning( "Could not wait for notice screen to be closed") else: cls.logger.info("Notice window is closed")
def LoginUsingPywinauto_Impl(cls, credential=None): import pywinauto if credential is None: from koapy.config import config credential = config.get( "koapy.backend.kiwoom_open_api_plus.credential") is_in_development = False use_set_text = False userid = credential.get("user_id") password = credential.get("user_password") cert = credential.get("cert_password") is_save_userid = True is_simulation = credential.get("is_simulation") desktop = pywinauto.Desktop(allow_magic_lookup=False) login_window = desktop.window(title="Open API Login") try: cls.logger.info("Waiting for login screen") timeout_login_screen_ready = 30 login_window.wait("ready", timeout_login_screen_ready) except pywinauto.timings.TimeoutError: cls.logger.info("Cannot find login screen") raise else: cls.logger.info("Login screen found") if is_in_development: login_window.print_control_identifiers() if userid: cls.logger.info("Putting userid") if use_set_text: login_window["Edit1"].set_text(userid) else: login_window["Edit1"].set_focus() pywinauto.keyboard.send_keys(userid) pywinauto.keyboard.send_keys("{TAB}") if password: cls.logger.info("Putting password") if use_set_text: login_window["Edit2"].set_text(password) else: login_window["Edit2"].set_focus() pywinauto.keyboard.send_keys(password) pywinauto.keyboard.send_keys("{TAB}") else: raise RuntimeError( "'user_password' not set, please check credential") if is_save_userid: cls.logger.info("Checking to save userid") login_window["Button6"].check() # check doesn't work else: cls.logger.info("Unchecking to save userid") login_window["Button6"].uncheck() # uncheck doesn't work if not is_simulation: if not login_window["Edit3"].is_enabled(): cls.logger.info("Unchecking to use simulation server") login_window["Button5"].uncheck_by_click() if cert: cls.logger.info("Putting cert password") if use_set_text: login_window["Edit3"].set_text(cert) else: login_window["Edit3"].set_focus() pywinauto.keyboard.send_keys(cert) pywinauto.keyboard.send_keys("{TAB}") else: raise RuntimeError( "'cert_password' not set, please check credential") else: if login_window["Edit3"].is_enabled(): cls.logger.info("Checking to use simulation server") login_window["Button5"].check_by_click() cls.logger.info("Logging in") login_window["Button1"].click()
def login_semiauto(wait_closed=False): logging.info('starting to login') login_config = config.get('koapy.backend.kiwoom.login') userid = login_config.get('id') password = login_config.get('password') cert = login_config.get('cert') is_save_userid = True is_simulation = login_config.get('is_simulation') desktop = pywinauto.Desktop(allow_magic_lookup=False) login_window = desktop.window(title='Open API Login') try: logging.info('waiting for login screen') timeout_login_screen_ready = 30 login_window.wait('ready', timeout_login_screen_ready) except pywinauto.timings.TimeoutError: logging.info('cannot find login screen') raise else: logging.info('login screen found') if is_in_development: login_window.print_control_identifiers() if userid: logging.info('putting userid') if set_text_userid: login_window['Edit1'].set_text(userid) else: login_window['Edit1'].set_focus() pywinauto.keyboard.send_keys(userid) pywinauto.keyboard.send_keys('{TAB}') if password: logging.info('putting password') if set_text_password: login_window['Edit2'].set_text(password) else: login_window['Edit2'].set_focus() pywinauto.keyboard.send_keys(password) pywinauto.keyboard.send_keys('{TAB}') else: raise RuntimeError('password not set, please check config file') # not working properly if is_save_userid: logging.info('checking to save userid') login_window['Button6'].check() else: logging.info('unchecking to save userid') login_window['Button6'].uncheck_by_click() if not is_simulation: if not login_window['Edit3'].is_enabled(): logging.info('unchecking to use simulation server') login_window['Button5'].uncheck_by_click() if cert: logging.info('putting cert password') if set_text_cert: login_window['Edit3'].set_text(cert) else: login_window['Edit3'].set_focus() pywinauto.keyboard.send_keys(cert) pywinauto.keyboard.send_keys('{TAB}') else: raise RuntimeError( 'cert passowrd not set, please check config file') else: if login_window['Edit3'].is_enabled(): logging.info('checking to use simulation server') login_window['Button5'].check_by_click() logging.info('logging in') login_window['Button1'].click() if wait_closed: try: logging.info('waiting login screen to be closed') timeout_login_screen_closed = 30 login_window.wait_not('visible', timeout_login_screen_closed) except pywinauto.timings.TimeoutError: logging.info('login screen is not closing') raise else: logging.info('login screen closed') return login_window