def build(self): self.icon = ICON # how you're supposed to set an icon self.title = f"KaTrain v{VERSION}" self.theme_cls.theme_style = "Dark" self.theme_cls.primary_palette = "Gray" self.theme_cls.primary_hue = "200" kv_file = find_package_resource("katrain/gui.kv") popup_kv_file = find_package_resource("katrain/popups.kv") resource_add_path(PATHS["PACKAGE"] + "/fonts") resource_add_path(PATHS["PACKAGE"] + "/sounds") resource_add_path(PATHS["PACKAGE"] + "/img") resource_add_path(os.path.abspath(os.path.expanduser(DATA_FOLDER))) # prefer resources in .katrain theme_file = resource_find("theme.json") if theme_file: try: with open(theme_file) as f: theme_overrides = json.load(f) for k, v in theme_overrides.items(): setattr(Theme, k, v) print(f"[{theme_file}] Found theme override {k} = {v}") except Exception as e: # noqa E722 print(f"Failed to load theme file {theme_file}: {e}") Theme.DEFAULT_FONT = resource_find(Theme.DEFAULT_FONT) Builder.load_file(kv_file) Window.bind(on_request_close=self.on_request_close) Window.bind(on_dropfile=lambda win, file: self.gui.load_sgf_file(file.decode("utf8"))) self.gui = KaTrainGui() Builder.load_file(popup_kv_file) return self.gui
def get_engine_path(self, exe): if not exe: if kivy_platform == "win": exe = "katrain/KataGo/katago.exe" elif kivy_platform == "linux": exe = "katrain/KataGo/katago" else: exe = find_package_resource("katrain/KataGo/katago-osx") # github actions built if not os.path.isfile(exe) or "arm64" in platform.version().lower(): exe = "katago" # e.g. MacOS after brewing if exe.startswith("katrain"): exe = find_package_resource(exe) exepath, exename = os.path.split(exe) if exepath and not os.path.isfile(exe): self.katrain.log(i18n._("Kata exe not found").format(exe=exe), OUTPUT_ERROR) return None elif not exepath: paths = os.getenv("PATH", ".").split(os.pathsep) + ["/opt/homebrew/bin/"] exe_with_paths = [os.path.join(path, exe) for path in paths if os.path.isfile(os.path.join(path, exe))] if not exe_with_paths: self.katrain.log(i18n._("Kata exe not found in path").format(exe=exe), OUTPUT_ERROR) return None exe = exe_with_paths[0] return exe
def __init__(self, katrain, config, override_command=None): self.katrain = katrain if override_command: self.command = override_command else: executable = config["katago"].strip() if not executable: if platform == "win": executable = "katrain/KataGo/katago.exe" elif platform == "linux": executable = "katrain/KataGo/katago" else: # e.g. MacOS after brewing executable = "katago" model = find_package_resource(config["model"]) cfg = find_package_resource(config["config"]) exe = find_package_resource(executable) self.command = f'"{exe}" analysis -model "{model}" -config "{cfg}" -analysis-threads {config["threads"]}' self.queries = {} # outstanding query id -> start time and callback self.config = config self.query_counter = 0 self.katago_process = None self.base_priority = 0 self.override_settings = {} # mainly for bot scripts to hook into self._lock = threading.Lock() self.analysis_thread = None self.stderr_thread = None self.start()
def __init__(self, katrain, config): self.katrain = katrain self.queries = {} # outstanding query id -> start time and callback self.config = config self.query_counter = 0 self.katago_process = None self.base_priority = 0 self.override_settings = { "reportAnalysisWinratesAs": "BLACK" } # force these settings self.analysis_thread = None self.stderr_thread = None self.write_stdin_thread = None self.shell = False self.write_queue = queue.Queue() exe = config.get("katago", "").strip() if config.get("altcommand", ""): self.command = config["altcommand"] self.shell = True else: if not exe: if platform == "win": exe = "katrain/KataGo/katago.exe" elif platform == "linux": exe = "katrain/KataGo/katago" else: # e.g. MacOS after brewing exe = "katago" model = find_package_resource(config["model"]) cfg = find_package_resource(config["config"]) if exe.startswith("katrain"): exe = find_package_resource(exe) exepath, exename = os.path.split(exe) if exepath and not os.path.isfile(exe): self.katrain.log( i18n._("Kata exe not found").format(exe=exe), OUTPUT_ERROR) return # don't start elif not exepath and not any( os.path.isfile(os.path.join(path, exe)) for path in os.environ.get("PATH", "").split(os.pathsep)): self.katrain.log( i18n._("Kata exe not found in path").format(exe=exe), OUTPUT_ERROR) return # don't start elif not os.path.isfile(model): self.katrain.log( i18n._("Kata model not found").format(model=model), OUTPUT_ERROR) return # don't start elif not os.path.isfile(cfg): self.katrain.log( i18n._("Kata config not found").format(config=cfg), OUTPUT_ERROR) return # don't start self.command = shlex.split( f'"{exe}" analysis -model "{model}" -config "{cfg}" -analysis-threads {config["threads"]}' ) self.start()
def __init__(self, katrain, config): super().__init__(katrain, config) self.queries = {} # outstanding query id -> start time and callback self.query_counter = 0 self.katago_process = None self.base_priority = 0 self.override_settings = {"reportAnalysisWinratesAs": "BLACK"} # force these settings self.analysis_thread = None self.stderr_thread = None self.write_stdin_thread = None self.shell = False self.write_queue = queue.Queue() self.thread_lock = threading.Lock() exe = config.get("katago", "").strip() if config.get("altcommand", ""): self.command = config["altcommand"] self.shell = True else: model = find_package_resource(config["model"]) cfg = find_package_resource(config["config"]) exe = self.get_engine_path(config["katago"]) if not exe: return if not os.path.isfile(model): self.katrain.log(i18n._("Kata model not found").format(model=model), OUTPUT_ERROR) return # don't start if not os.path.isfile(cfg): self.katrain.log(i18n._("Kata config not found").format(config=cfg), OUTPUT_ERROR) return # don't start self.command = shlex.split( f'"{exe}" analysis -model "{model}" -config "{cfg}" -analysis-threads {config["threads"]} -override-config "homeDataDir={os.path.expanduser(DATA_FOLDER)}"' ) self.start()
def build(self): self.icon = ICON # how you're supposed to set an icon self.title = f"KaTrain v{VERSION}" self.theme_cls.theme_style = "Dark" self.theme_cls.primary_palette = "Gray" self.theme_cls.primary_hue = "200" kv_file = find_package_resource("katrain/gui.kv") popup_kv_file = find_package_resource("katrain/popups.kv") resource_add_path(PATHS["PACKAGE"] + "/fonts") resource_add_path(PATHS["PACKAGE"] + "/sounds") resource_add_path(PATHS["PACKAGE"] + "/img") resource_add_path(os.path.abspath( os.path.expanduser(DATA_FOLDER))) # prefer resources in .katrain theme_file = resource_find("theme.json") if theme_file: try: with open(theme_file) as f: theme_overrides = json.load(f) for k, v in theme_overrides.items(): setattr(Theme, k, v) print(f"[{theme_file}] Found theme override {k} = {v}") except Exception as e: # noqa E722 print(f"Failed to load theme file {theme_file}: {e}") Theme.DEFAULT_FONT = resource_find(Theme.DEFAULT_FONT) Builder.load_file(kv_file) Window.bind(on_request_close=self.on_request_close) Window.bind(on_dropfile=lambda win, file: self.gui.load_sgf_file( file.decode("utf8"))) self.gui = KaTrainGui() Builder.load_file(popup_kv_file) win_size = self.gui.config("ui_state/size", []) win_left = self.gui.config("ui_state/left", None) win_top = self.gui.config("ui_state/top", None) if not win_size: window_scale_fac = 1 try: from screeninfo import get_monitors for m in get_monitors(): window_scale_fac = min(window_scale_fac, (m.height - 100) / 1000, (m.width - 100) / 1300) except Exception as e: window_scale_fac = 0.85 win_size = [1300 * window_scale_fac, 1000 * window_scale_fac] Window.size = (win_size[0], win_size[1]) if win_left is not None and win_top is not None: Window.left = win_left Window.top = win_top return self.gui
def __init__(self, katrain, config, override_command=None): self.katrain = katrain self.queries = {} # outstanding query id -> start time and callback self.config = config self.query_counter = 0 self.katago_process = None self.base_priority = 0 self.override_settings = {} # mainly for bot scripts to hook into self._lock = threading.Lock() self.analysis_thread = None self.stderr_thread = None if override_command: self.command = override_command else: exe = config["katago"].strip() if not exe: if platform == "win": exe = "katrain/KataGo/katago.exe" elif platform == "linux": exe = "katrain/KataGo/katago" else: # e.g. MacOS after brewing exe = "katago" model = find_package_resource(config["model"]) cfg = find_package_resource(config["config"]) if exe.startswith("katrain"): exe = find_package_resource(exe) exepath, exename = os.path.split(exe) if exepath and not os.path.isfile(exe): self.katrain.log( i18n._("Kata exe not found").format(exe=exe), OUTPUT_ERROR) return # don't start elif not exepath and not any( os.path.isfile(os.path.join(path, exe)) for path in os.environ.get("PATH", "").split(os.pathsep)): self.katrain.log( i18n._("Kata exe not found in path").format(exe=exe), OUTPUT_ERROR) return # don't start elif not os.path.isfile(model): self.katrain.log( i18n._("Kata model not found").format(model=model), OUTPUT_ERROR) return # don't start elif not os.path.isfile(cfg): self.katrain.log( i18n._("Kata config not found").format(config=cfg), OUTPUT_ERROR) return # don't start self.command = f'"{exe}" analysis -model "{model}" -config "{cfg}" -analysis-threads {config["threads"]}' self.start()
def __init__(self, katrain): super().__init__(katrain, katrain.config("contribute")) self.katrain = katrain base_dir = os.path.expanduser("~/.katrain/katago_contribute") self.katago_process = None self.stdout_thread = None self.stderr_thread = None self.shell = False self.active_games = {} self.finished_games = set() self.showing_game = None self.last_advance = 0 self.move_count = 0 self.uploaded_games_count = 0 self.last_move_for_game = defaultdict(int) self.visits_count = 0 self.start_time = 0 self.server_error = None self.save_sgf = self.config.get("savesgf", False) self.save_path = self.config.get("savepath", "./dist_sgf/") self.move_speed = self.config.get("movespeed", 2.0) exe = self.get_engine_path(self.config.get("katago")) cacert_path = os.path.join(os.path.split(exe)[0], "cacert.pem") if not os.path.isfile(cacert_path): try: shutil.copyfile( find_package_resource("katrain/KataGo/cacert.pem"), cacert_path) except Exception as e: self.katrain.log( f"Could not copy cacert file ({e}), please add it manually to your katago.exe directory", OUTPUT_ERROR, ) cfg = find_package_resource(self.config.get("config")) settings_dict = { "username": self.config.get("username"), "password": self.config.get("password"), "maxSimultaneousGames": self.config.get("maxgames") or self.DEFAULT_MAX_GAMES, "includeOwnership": self.config.get("ownership") or False, "logGamesAsJson": True, "homeDataDir": os.path.expanduser(DATA_FOLDER), } self.max_buffer_games = 2 * settings_dict["maxSimultaneousGames"] settings = {f"{k}={v}" for k, v in settings_dict.items()} self.command = shlex.split( f'"{exe}" contribute -config "{cfg}" -base-dir "{base_dir}" -override-config "{",".join(settings)}"' ) self.start()
def _load_config(self, force_package_config): if len(sys.argv) > 1 and sys.argv[1].endswith("config.json"): config_file = os.path.abspath(sys.argv[1]) self.log(f"Using command line config file {config_file}", OUTPUT_INFO) else: user_config_file = find_package_resource(self.USER_CONFIG_FILE) package_config_file = find_package_resource( self.PACKAGE_CONFIG_FILE) if force_package_config: config_file = package_config_file else: try: if not os.path.exists(user_config_file): os.makedirs(os.path.split(user_config_file)[0], exist_ok=True) shutil.copyfile(package_config_file, user_config_file) config_file = user_config_file self.log( f"Copied package config to local file {config_file}", OUTPUT_INFO) else: # user file exists try: version = JsonStore(user_config_file).get( "general")["version"] except Exception: # noqa E722 broken file etc version = "0.0.0" if version < CONFIG_MIN_VERSION: backup = user_config_file + f".{version}.backup" shutil.copyfile(user_config_file, backup) shutil.copyfile(package_config_file, user_config_file) self.log( f"Copied package config file to {user_config_file} as user file is outdated or broken ({version}<{CONFIG_MIN_VERSION}). Old version stored as {backup}", OUTPUT_INFO, ) config_file = user_config_file self.log(f"Using user config file {config_file}", OUTPUT_INFO) except Exception as e: config_file = package_config_file self.log( f"Using package config file {config_file} (exception {e} occurred when finding or creating user config)", OUTPUT_INFO, ) try: self._config_store = JsonStore(config_file, indent=4) except Exception as e: self.log(f"Failed to load config {config_file}: {e}", OUTPUT_ERROR) sys.exit(1) self._config = dict(self._config_store) return config_file
def run_app(): kv_file = find_package_resource("katrain/gui.kv") popup_kv_file = find_package_resource("katrain/popups.kv") resource_add_path(os.path.split(kv_file)[0]) Builder.load_file(kv_file) Builder.load_file(popup_kv_file) app = KaTrainApp() signal.signal(signal.SIGINT, app.signal_handler) try: app.run() except Exception as e: print(e) app.on_request_close() raise
def switch_lang(self, lang): if lang == self.lang: return # get the right locales directory, and instantiate a gettext self.lang = lang self.font_name = self.FONTS.get(lang) or DEFAULT_FONT i18n_dir, _ = os.path.split( find_package_resource("katrain/i18n/__init__.py")) locale_dir = os.path.join(i18n_dir, "locales") locales = gettext.translation("katrain", locale_dir, languages=[lang]) self.ugettext = locales.gettext # update all the kv rules attached to this text for widget, func, args in self.observers: try: func(args[0], None, None) self.set_widget_font(widget) except ReferenceError: pass # proxy no longer exists except Exception as e: print("Error in switching languages", e) for cb in self.callbacks: try: cb(self) except Exception as e: print(f"Failed callback on language change: {e}", file=sys.stderr)
def build(self): self.icon = ICON # how you're supposed to set an icon kv_file = find_package_resource("katrain/gui.kv") popup_kv_file = find_package_resource("katrain/popups.kv") resource_add_path(os.path.split(kv_file)[0]) Builder.load_file(kv_file) Builder.load_file(popup_kv_file) self.gui = KaTrainGui() self.title = f"KaTrain v{VERSION}" self.theme_cls.theme_style = "Dark" self.theme_cls.primary_palette = "Blue" Window.bind(on_request_close=self.on_request_close) return self.gui
def check_models(self, *args): # WIP try: model = self.collect_properties(self)["engine/model"] except InputParseError: self.model_files.values = [] return if os.path.exists(model): if os.path.isdir(model): path = model.rstrip("\\/") file = None else: if model.startswith("katrain"): model = find_package_resource(model) path, file = os.path.split(model) files = sorted([ os.path.split(f)[1] for ftype in ["*.bin.gz", "*.txt.gz"] for f in glob.glob(path + os.path.sep + ftype) ]) self.model_files.values = files print(file, files, file in files) if file in files: self.model_files.text = file else: self.model_files.values = []
def build(self): self.icon = ICON # how you're supposed to set an icon self.title = f"KaTrain v{VERSION}" self.theme_cls.theme_style = "Dark" self.theme_cls.primary_palette = "Gray" self.theme_cls.primary_hue = "200" kv_file = find_package_resource("katrain/gui.kv") popup_kv_file = find_package_resource("katrain/popups.kv") resource_add_path(PATHS["PACKAGE"]) Builder.load_file(kv_file) Window.bind(on_request_close=self.on_request_close) Window.bind(on_dropfile=lambda win, file: self.gui.load_sgf_file(file.decode("utf8"))) self.gui = KaTrainGui() Builder.load_file(popup_kv_file) return self.gui
def check_error(self, _dt=None): file = find_package_resource(self.input_value, silent_errors=True) self.error = self.check_path and not (file and os.path.exists(file))
"""isort:skip_file""" # first, logging level lower import os os.environ["KCFG_KIVY_LOG_LEVEL"] = os.environ.get("KCFG_KIVY_LOG_LEVEL", "warning") if "KIVY_AUDIO" not in os.environ: os.environ["KIVY_AUDIO"] = "sdl2" # some backends hard crash / this seems to be most stable # next, icon from katrain.core.utils import find_package_resource, PATHS from kivy.config import Config from kivy.utils import platform ICON = find_package_resource("katrain/img/icon.ico") Config.set("kivy", "window_icon", ICON) # finally, window size WINDOW_SCALE_FAC, WINDOW_X, WINDOW_Y = 1, 1300, 1000 try: from screeninfo import get_monitors for m in get_monitors(): WINDOW_SCALE_FAC = min(WINDOW_SCALE_FAC, (m.height - 100) / WINDOW_Y, (m.width - 100) / WINDOW_X) except Exception as e: if platform != "macosx": print(f"Exception {e} while getting screen resolution.") WINDOW_SCALE_FAC = 0.85 Config.set("graphics", "width", max(400, int(WINDOW_X * WINDOW_SCALE_FAC))) Config.set("graphics", "height", max(400, int(WINDOW_Y * WINDOW_SCALE_FAC))) Config.set("input", "mouse", "mouse,multitouch_on_demand")
# first, logging level lower import os os.environ["KCFG_KIVY_LOG_LEVEL"] = os.environ.get("KCFG_KIVY_LOG_LEVEL", "warning") os.environ['KIVY_AUDIO'] = "sdl2" # force working audio # next, icon from katrain.core.utils import find_package_resource # isort:skip from kivy.config import Config # isort:skip ICON = find_package_resource("katrain/img/icon.ico") # isort:skip # find icon Config.set("kivy", "window_icon", ICON) # isort:skip # set icon # finally, window size from kivy.metrics import dp WINDOW_X, WINDOW_Y = 1300, 1000 try: from screeninfo import get_monitors scale = 1.0 for m in get_monitors(): scale = min(scale, (m.height - 100) / WINDOW_Y, (m.width - 100) / WINDOW_X) WINDOW_SCALE_FAC = max(0.4, scale) except Exception as e: print("Exception while getting screen resolution", e) WINDOW_SCALE_FAC = 1 Config.set("graphics", "width", int(WINDOW_SCALE_FAC * WINDOW_X)) Config.set("graphics", "height", int(WINDOW_SCALE_FAC * WINDOW_Y)) Config.set("input", "mouse", "mouse,multitouch_on_demand") import signal
def __init__(self, katrain, config): self.katrain = katrain self.queries = {} # outstanding query id -> start time and callback self.config = config self.query_counter = 0 self.katago_process = None self.base_priority = 0 self.override_settings = { "reportAnalysisWinratesAs": "BLACK" } # force these settings self.analysis_thread = None self.stderr_thread = None self.write_stdin_thread = None self.shell = False self.write_queue = queue.Queue() self.thread_lock = threading.Lock() exe = config.get("katago", "").strip() if config.get("altcommand", ""): self.command = config["altcommand"] self.shell = True else: if not exe: if kivy_platform == "win": exe = "katrain/KataGo/katago.exe" elif kivy_platform == "linux": exe = "katrain/KataGo/katago" else: exe = find_package_resource( "katrain/KataGo/katago-osx") # github actions built if not os.path.isfile(exe) or "arm64" in platform.version( ).lower(): exe = "katago" # e.g. MacOS after brewing model = find_package_resource(config["model"]) cfg = find_package_resource(config["config"]) if exe.startswith("katrain"): exe = find_package_resource(exe) exepath, exename = os.path.split(exe) if exepath and not os.path.isfile(exe): self.katrain.log( i18n._("Kata exe not found").format(exe=exe), OUTPUT_ERROR) return # don't start elif not exepath: paths = os.getenv("PATH", ".").split( os.pathsep) + ["/opt/homebrew/bin/"] exe_with_paths = [ os.path.join(path, exe) for path in paths if os.path.isfile(os.path.join(path, exe)) ] if not exe_with_paths: self.katrain.log( i18n._("Kata exe not found in path").format(exe=exe), OUTPUT_ERROR) return # don't start exe = exe_with_paths[0] elif not os.path.isfile(model): self.katrain.log( i18n._("Kata model not found").format(model=model), OUTPUT_ERROR) return # don't start elif not os.path.isfile(cfg): self.katrain.log( i18n._("Kata config not found").format(config=cfg), OUTPUT_ERROR) return # don't start self.command = shlex.split( f'"{exe}" analysis -model "{model}" -config "{cfg}" -analysis-threads {config["threads"]}' ) self.start()