From 3da10189b7b45f5a8a4c17dff8bd18c8a03e9947 Mon Sep 17 00:00:00 2001 From: Daniel Dolezal Date: Mon, 6 Apr 2026 19:24:45 +0200 Subject: [PATCH] move snake config read functions into battlesnake template and use TemplateSnake as default Version of Snakes --- server/Server.py | 36 +++----------------------------- server/blueprints/battlesnake.py | 29 ++++++++++++++++++++++--- snakes/__init__.py | 14 ++++++++++--- 3 files changed, 40 insertions(+), 39 deletions(-) diff --git a/server/Server.py b/server/Server.py index 308d4ff..29776f6 100644 --- a/server/Server.py +++ b/server/Server.py @@ -1,6 +1,5 @@ from quart_common.web.logger import build_logger, await_log from quart_common.web.env import env_bool, env_int -from server.Files import read_file from server.game_state_store import GameStateStoreBuilder from snakes import SnakeBuilder @@ -14,8 +13,7 @@ from server.metrics import ( MetricsCollector, ) -import asyncio, signal, logging, json, os, re, time -from typing import cast +import asyncio, signal, logging, os, re, time from quart import Quart from server.blueprints import ( @@ -32,15 +30,6 @@ from server.services import ( ) class Server: - default_snake_config = { - 'apiversion': '1', - 'author': '', - 'color': '#888888', - 'head': 'default', - 'tail': 'default', - 'version': '1.0.0', - } - def __init__(self, data_path:str, snake_type:str, storage_type:str, debug:bool=False, check_tls_security:bool=False, game_state_backend:str='memory', game_state_redis_url:str='redis://localhost:6379/0', game_state_ttl_sec:int=900, game_state_local_cache:bool=True, metrics_backend:str='memory', metrics_redis_url:str='redis://localhost:6379/0', metrics_ttl_sec:int|None=None, gameplay_db_enabled:bool=True, gameplay_db_path:str|None=None, gameplay_db_busy_timeout_ms:int=5000): self.debug = debug self.snake_type = snake_type @@ -97,6 +86,7 @@ class Server: self.logger = build_logger('Battlesnake', debug_env_var='DEBUG_SERVER') self.snake_version = self._get_snake_version() + self.gameplay_database = None if gameplay_db_enabled: db_path = gameplay_db_path or os.path.join(data_path, 'data', 'database', 'gameplay.sqlite3') @@ -190,30 +180,10 @@ class Server: except Exception: continue - async def _read_json_config_or_create(self) -> dict[str, str]: - snake_config = cast(dict[str, str]|None, await read_file(self.config_file, json.load)) - if not snake_config: - return await self._override_snake_config_with_environment_variables(self.default_snake_config) - return await self._override_snake_config_with_environment_variables(snake_config) - - async def _override_snake_config_with_environment_variables(self, config:dict[str, str]) -> dict[str, str]: - config['version'] = self.snake_version - - for key in ('author', 'color', 'head', 'tail'): - value = os.environ.get(f'SNAKE_{key.upper()}') - if value is not None: - config[key] = value - - version_override = os.environ.get('SNAKE_VERSION') - if version_override is not None: - config['version'] = version_override - - return config - def _get_snake_version(self) -> str: configured_version = SnakeBuilder.get_version(self.snake_type) if configured_version is None: - return self.default_snake_config['version'] + return str(SnakeBuilder.get_version('TemplateSnake')) return str(configured_version) def _get_stale_game_timeout_sec(self) -> int: diff --git a/server/blueprints/battlesnake.py b/server/blueprints/battlesnake.py index a63dac4..1fc807c 100644 --- a/server/blueprints/battlesnake.py +++ b/server/blueprints/battlesnake.py @@ -5,7 +5,9 @@ from quart import Blueprint, request, jsonify from quart_common.web.logger import await_log from server.database import StorageLoader +from snakes import DEFAULT_SNAKE_CONFIG from server.GameBoard import GameBoard +from server.Files import read_file if TYPE_CHECKING: from server.Server import Server @@ -13,12 +15,33 @@ if TYPE_CHECKING: def create_battlesnake_blueprint(server:'Server') -> Blueprint: blueprint = Blueprint('battlesnake', __name__) + async def _override_snake_config_with_environment_variables(config:dict[str, str]) -> dict[str, str]: + print(config) + config['version'] = server.snake_version + + for key in ('author', 'color', 'head', 'tail'): + value = os.environ.get(f'SNAKE_{key.upper()}') + if value is not None: + config[key] = value + + version_override = os.environ.get('SNAKE_VERSION') + if version_override is not None: + config['version'] = version_override + + return config + @blueprint.get('/') async def on_info(): server.metrics_collector.record_http_request('info') - snake_config = await server._read_json_config_or_create() - await await_log(server.logger.info(f'INFO Snake: {snake_config}')) - return snake_config + + snake_config = cast(dict[str, str]|None, await read_file(server.config_file, json.load)) + if not snake_config: + snake_json = await _override_snake_config_with_environment_variables(DEFAULT_SNAKE_CONFIG) + else: + snake_json = await _override_snake_config_with_environment_variables(snake_config) + + await await_log(server.logger.info(f'INFO Snake: {snake_json}')) + return snake_json @blueprint.post('/start') async def on_start(): diff --git a/snakes/__init__.py b/snakes/__init__.py index 0c7c2a5..ca0f17c 100644 --- a/snakes/__init__.py +++ b/snakes/__init__.py @@ -11,7 +11,15 @@ SNAKE_REGISTRY = { "UltimateBattleSnake": "4.5.0", } -def build_snake(selected_snake: str): +DEFAULT_SNAKE_CONFIG = { + 'apiversion': '1', + 'author': '', + 'color': '#888888', + 'head': 'default', + 'tail': 'default', +} + +def build_snake(selected_snake:str): if selected_snake not in SNAKE_REGISTRY: raise ValueError(f"Unknown snake: {selected_snake}") @@ -19,7 +27,7 @@ def build_snake(selected_snake: str): snake_class = getattr(snake_module, selected_snake) return snake_class() -def get_snake_version(selected_snake: str) -> str | None: +def get_snake_version(selected_snake:str) -> str|None: version = SNAKE_REGISTRY.get(selected_snake) if version is None: return None @@ -31,5 +39,5 @@ class SnakeBuilder: return build_snake(selected_snake) @classmethod - def get_version(self, selected_snake: str) -> str | None: + def get_version(self, selected_snake:str) -> str|None: return get_snake_version(selected_snake)