From 328eb1362e8ebcd7a7e8326b7c625fd04b3fc6a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCrgen=20Precour?= Date: Mon, 1 Jan 2018 12:13:38 +0100 Subject: [PATCH] remote engine --- picochess.py | 32 ++++++++++++++++++-------------- uci/engine.py | 41 +++++++++++++++++++++++++++-------------- uci/write.py | 5 +++-- utilities.py | 6 ++++-- 4 files changed, 52 insertions(+), 32 deletions(-) diff --git a/picochess.py b/picochess.py index 20ee7fba..a6ca9d72 100755 --- a/picochess.py +++ b/picochess.py @@ -27,8 +27,9 @@ import time import queue import configargparse +from platform import machine -from uci.engine import UciEngine +from uci.engine import UciShell, UciEngine from uci.read import read_engine_ini import chess import chess.polyglot @@ -544,15 +545,18 @@ def _dgt_serial_nr(): # Command line argument parsing parser = configargparse.ArgParser(default_config_files=[os.path.join(os.path.dirname(__file__), 'picochess.ini')]) - parser.add_argument('-e', '--engine', type=str, help="UCI engine executable path such as 'engines/armv7l/a-stockf'", + parser.add_argument('-e', '--engine', type=str, help="UCI engine filename/path such as 'engines/armv7l/a-stockf'", default=None) parser.add_argument('-el', '--engine-level', type=str, help='UCI engine level', default=None) - parser.add_argument('-ers', '--engine-remote-server', type=str, help='adress of the remote engine server') + parser.add_argument('-er', '--engine-remote', type=str, + help="UCI engine filename/path such as 'engines/armv7l/a-stockf'", default=None) + parser.add_argument('-ers', '--engine-remote-server', type=str, help='adress of the remote engine server', + default=None) parser.add_argument('-eru', '--engine-remote-user', type=str, help='username for the remote engine server') parser.add_argument('-erp', '--engine-remote-pass', type=str, help='password for the remote engine server') parser.add_argument('-erk', '--engine-remote-key', type=str, help='key file for the remote engine server') parser.add_argument('-erh', '--engine-remote-home', type=str, help='engine home path for the remote engine server', - default='/opt/picochess') + default='') parser.add_argument('-d', '--dgt-port', type=str, help="enable dgt board on the given serial port such as '/dev/ttyUSB0'") parser.add_argument('-b', '--book', type=str, help="path of book such as 'books/b-flank.bin'", @@ -677,19 +681,20 @@ def _dgt_serial_nr(): update_picochess(args.dgtpi, args.enable_update_reboot, dgttranslate) # try the given engine first and if that fails the first/second from "engines.ini" then crush - engine_file = args.engine + engine_file = args.engine if args.engine_remote_server is None else args.engine_remote + engine_home = 'engines' + os.sep + machine() if args.engine_remote_server is None else args.engine_remote_home.rstrip(os.sep) engine_tries = 0 engine = engine_name = None + uci_shell = UciShell(hostname=args.engine_remote_server, username=args.engine_remote_user, + key_file=args.engine_remote_key, password=args.engine_remote_pass) while engine_tries < 2: if engine_file is None: - eng_ini = read_engine_ini() + eng_ini = read_engine_ini(uci_shell.get(), engine_home) engine_file = eng_ini[engine_tries]['file'] engine_tries += 1 - + engine_file = os.path.basename(engine_file) # Gentlemen, start your engines... - engine = UciEngine(file=engine_file, hostname=args.engine_remote_server, username=args.engine_remote_user, - key_file=args.engine_remote_key, password=args.engine_remote_pass, - home=args.engine_remote_home) + engine = UciEngine(file=engine_file, uci_shell=uci_shell, home=engine_home) try: engine_name = engine.get_name() break @@ -798,8 +803,7 @@ def _dgt_serial_nr(): # Closeout the engine process and threads if engine.quit(): # Load the new one and send args. - # Local engines only - engine = UciEngine(event.eng['file']) + engine = UciEngine(file=event.eng['file'], uci_shell=uci_shell) try: engine_name = engine.get_name() except AttributeError: @@ -807,7 +811,7 @@ def _dgt_serial_nr(): logging.error('new engine failed to start, reverting to %s', old_file) engine_fallback = True event.options = old_options - engine = UciEngine(old_file) + engine = UciEngine(file=old_file, uci_shell=uci_shell) try: engine_name = engine.get_name() except AttributeError: @@ -823,7 +827,7 @@ def _dgt_serial_nr(): logging.debug('new engine doesnt support brain mode, reverting to %s', old_file) engine_fallback = True if engine.quit(): - engine = UciEngine(old_file) + engine = UciEngine(file=old_file, uci_shell=uci_shell) engine.startup(old_options) engine.newgame(game.copy()) else: diff --git a/uci/engine.py b/uci/engine.py index 5b6450e5..6961dc12 100644 --- a/uci/engine.py +++ b/uci/engine.py @@ -30,26 +30,39 @@ from uci.read import read_engine_ini +class UciShell(object): + + """Handle the uci engine shell.""" + + def __init__(self, hostname=None, username=None, key_file=None, password=None): + super(UciShell, self).__init__() + if hostname: + logging.info('connecting to [%s]', hostname) + if key_file: + self.shell = spur.SshShell(hostname=hostname, username=username, private_key_file=key_file, + missing_host_key=paramiko.AutoAddPolicy()) + else: + self.shell = spur.SshShell(hostname=hostname, username=username, password=password, + missing_host_key=paramiko.AutoAddPolicy()) + else: + self.shell = None + + def get(self): + return self.shell + + class UciEngine(object): """Handle the uci engine communication.""" - def __init__(self, file: str, hostname=None, username=None, key_file=None, password=None, home=''): + def __init__(self, file: str, uci_shell: UciShell, home=''): super(UciEngine, self).__init__() try: - self.shell = None - if hostname: - logging.info('connecting to [%s]', hostname) - if key_file: - shell = spur.SshShell(hostname=hostname, username=username, private_key_file=key_file, - missing_host_key=paramiko.AutoAddPolicy()) - else: - shell = spur.SshShell(hostname=hostname, username=username, password=password, - missing_host_key=paramiko.AutoAddPolicy()) - self.shell = shell - if home: - file = home + os.sep + file - self.engine = chess.uci.spur_spawn_engine(shell, [file]) + self.shell = uci_shell.get() + if home: + file = home + os.sep + file + if self.shell: + self.engine = chess.uci.spur_spawn_engine(self.shell, [file]) else: self.engine = chess.uci.popen_engine(file, stderr=DEVNULL) diff --git a/uci/write.py b/uci/write.py index ab66cd96..1c21fd6c 100644 --- a/uci/write.py +++ b/uci/write.py @@ -18,7 +18,7 @@ import platform import configparser import os -from uci.engine import UciEngine +from uci.engine import UciShell, UciEngine def write_engine_ini(engine_path=None): @@ -99,9 +99,10 @@ def name_build(parts: list, maxlength: int, default_name: str): engine_list = sorted(os.listdir(engine_path)) config = configparser.ConfigParser() config.optionxform = str + uci_shell = UciShell() for engine_file_name in engine_list: if is_exe(engine_path + os.sep + engine_file_name): - engine = UciEngine(engine_path + os.sep + engine_file_name) + engine = UciEngine(file=engine_path + os.sep + engine_file_name, uci_shell=uci_shell) if engine: print(engine_file_name) try: diff --git a/utilities.py b/utilities.py index 381b278e..d5ad017b 100644 --- a/utilities.py +++ b/utilities.py @@ -194,7 +194,7 @@ def get_tags(): """Get the last 3 tags from git.""" git = git_name() tags = [(tags, tags[1] + tags[-2:]) for tags in do_popen([git, 'tag'], log=False).split('\n')[-4:-1]] - return tags # returns something like [('v0.9a', 09a'), ('v0.9b', '09b'), ('v0.9c', '09c')] + return tags # returns something like [('v0.9j', 09j'), ('v0.9k', '09k'), ('v0.9l', '09l')] def checkout_tag(tag): @@ -209,7 +209,7 @@ def update_picochess(dgtpi: bool, auto_reboot: bool, dgttranslate: DgtTranslate) git = git_name() branch = do_popen([git, 'rev-parse', '--abbrev-ref', 'HEAD'], log=False).rstrip() - if branch == 'stable' or branch == 'master': + if branch == 'master': # Fetch remote repo do_popen([git, 'remote', 'update']) # Check if update is needed - need to make sure, we get english answers @@ -226,6 +226,8 @@ def update_picochess(dgtpi: bool, auto_reboot: bool, dgttranslate: DgtTranslate) time.sleep(2) # give time to display the "update" message else: logging.debug('no update available') + else: + logging.debug('wrong branch %s', branch) def shutdown(dgtpi: bool, dev: str):