From 43c77204803e06b4a9dcd3b8fa050f3df66bfde2 Mon Sep 17 00:00:00 2001 From: Daniel Dolezal Date: Mon, 6 Apr 2026 04:30:02 +0200 Subject: [PATCH] fix circular import errors so the server and start again --- server/GameBoard.py | 3 ++- server/dataset/Dataset.py | 7 +++++-- .../game_state_store/MemoryGameBoardStore.py | 7 +++++-- server/game_state_store/RedisGameBoardStore.py | 7 +++++-- server/services/game_runtime.py | 2 +- server/storage/LocalStorage.py | 18 +++++++++++------- server/storage/__init__.py | 5 ++++- snakes/TemplateSnake.py | 8 ++++++-- 8 files changed, 39 insertions(+), 18 deletions(-) diff --git a/server/GameBoard.py b/server/GameBoard.py index 2ea8e17..cdc8d36 100644 --- a/server/GameBoard.py +++ b/server/GameBoard.py @@ -1,7 +1,8 @@ +from snakes.TemplateSnake import TemplateSnake from datetime import datetime class GameBoard: - def __init__(self, game_id:str, width:int, height:int, ruleset:dict, source:str, map:str, snake_class): + def __init__(self, game_id:str, width:int, height:int, ruleset:dict, source:str, map:str, snake_class:TemplateSnake): self.id = game_id self.width = width self.height = height diff --git a/server/dataset/Dataset.py b/server/dataset/Dataset.py index 11dd089..84bff64 100644 --- a/server/dataset/Dataset.py +++ b/server/dataset/Dataset.py @@ -1,9 +1,12 @@ -from server.GameBoard import GameBoard +from typing import TYPE_CHECKING + +if TYPE_CHECKING: + from server.GameBoard import GameBoard class Dataset: VALID_MOVES = {"up", "down", "left", "right"} - def __init__(self, game_board:GameBoard): + def __init__(self, game_board:'GameBoard'): self.game_board = game_board def _did_we_win(self): diff --git a/server/game_state_store/MemoryGameBoardStore.py b/server/game_state_store/MemoryGameBoardStore.py index 6f70373..3ded10c 100644 --- a/server/game_state_store/MemoryGameBoardStore.py +++ b/server/game_state_store/MemoryGameBoardStore.py @@ -1,10 +1,13 @@ -from server.GameBoard import GameBoard +from typing import TYPE_CHECKING + +if TYPE_CHECKING: + from server.GameBoard import GameBoard class MemoryGameBoardStore: def __init__(self, **kwargs): self._state:dict[str, object] = {} - async def save(self, game_id:str, game_board:GameBoard) -> None: + async def save(self, game_id:str, game_board:'GameBoard') -> None: self._state[game_id] = game_board async def load(self, game_id:str): diff --git a/server/game_state_store/RedisGameBoardStore.py b/server/game_state_store/RedisGameBoardStore.py index afabb88..c7183e2 100644 --- a/server/game_state_store/RedisGameBoardStore.py +++ b/server/game_state_store/RedisGameBoardStore.py @@ -1,6 +1,9 @@ -from server.GameBoard import GameBoard +from typing import TYPE_CHECKING import inspect, pickle +if TYPE_CHECKING: + from server.GameBoard import GameBoard + class RedisGameBoardStore: def __init__(self, redis_url:str="redis://localhost:6379/0", key_prefix:str="snake:gameboard", ttl_seconds:int=900, **kwargs): self.redis_url = redis_url @@ -23,7 +26,7 @@ class RedisGameBoardStore: def _key(self, game_id:str) -> str: return f"{self.key_prefix}:{game_id}" - async def save(self, game_id:str, game_board:GameBoard) -> None: + async def save(self, game_id:str, game_board:'GameBoard') -> None: redis = await self._get_redis() payload = pickle.dumps(game_board, protocol=pickle.HIGHEST_PROTOCOL) await redis.set(self._key(game_id), payload, ex=self.ttl_seconds) diff --git a/server/services/game_runtime.py b/server/services/game_runtime.py index 9b00e5e..50860e0 100644 --- a/server/services/game_runtime.py +++ b/server/services/game_runtime.py @@ -4,7 +4,7 @@ import time from server.metrics import MetricsCollector from server.GameBoard import GameBoard -from storage import StorageLoader +from server.storage import StorageLoader from snakes import SnakeBuilder class GameRuntimeService: diff --git a/server/storage/LocalStorage.py b/server/storage/LocalStorage.py index e2b6098..1ef67cf 100644 --- a/server/storage/LocalStorage.py +++ b/server/storage/LocalStorage.py @@ -1,5 +1,9 @@ +from typing import TYPE_CHECKING + +if TYPE_CHECKING: + from server.GameBoard import GameBoard + from server.dataset.Dataset import Dataset -from server.GameBoard import GameBoard from server.Files import save_file import aiofiles @@ -21,7 +25,7 @@ class LocalStorage: self.dataset_compress_rotated = os.getenv("DATASET_COMPRESS_ROTATED", "true").strip().lower() in ("1", "true", "yes", "on") self.dataset_max_bytes = int(float(os.getenv("DATASET_JSONL_MAX_MB", "50")) * 1024 * 1024) - def _get_active_dataset_path(self, game_board:GameBoard): + def _get_active_dataset_path(self, game_board:'GameBoard'): if not self.dataset_rotate_daily: return self.dataset_jsonl_path @@ -60,7 +64,7 @@ class LocalStorage: self._gzip_file(os.path.join(folder, name)) - async def _rotate_if_needed(self, active_path:str, game_board:GameBoard): + async def _rotate_if_needed(self, active_path:str, game_board:'GameBoard'): if self.dataset_max_bytes <= 0: return if not await aiofiles.os.path.exists(active_path): @@ -81,7 +85,7 @@ class LocalStorage: if self.dataset_compress_rotated: self._gzip_file(rotated_path) - def _build_dataset_rows(self, dataset_payload:dict, game_board:GameBoard): + def _build_dataset_rows(self, dataset_payload:dict, game_board:'GameBoard'): game_info = dataset_payload.get("game", {}) snake_info = dataset_payload.get("snake", {}) @@ -102,7 +106,7 @@ class LocalStorage: }) return rows - async def _append_dataset_jsonl(self, dataset_payload:dict, game_board:GameBoard): + async def _append_dataset_jsonl(self, dataset_payload:dict, game_board:'GameBoard'): rows = self._build_dataset_rows(dataset_payload, game_board) if len(rows) == 0: return @@ -116,7 +120,7 @@ class LocalStorage: for row in rows: await f.write(json.dumps(row, ensure_ascii=False) + "\n") - def _get_correct_folder_for_save_file(self, game_board:GameBoard, file_name:str, game_type:str, leader_board:bool, winner:bool): + def _get_correct_folder_for_save_file(self, game_board:'GameBoard', file_name:str, game_type:str, leader_board:bool, winner:bool): storage_folder = self.file_path if leader_board: storage_folder = os.path.join(storage_folder, "00_Leaderboards") @@ -136,7 +140,7 @@ class LocalStorage: return os.path.join(storage_folder, file_name) - async def save(self, game_board:GameBoard): + async def save(self, game_board:'GameBoard'): game_type = game_board.get_type_of_game() dataset = Dataset(game_board).build(only_good_moves=True) diff --git a/server/storage/__init__.py b/server/storage/__init__.py index 0ac5113..fc6ce3d 100644 --- a/server/storage/__init__.py +++ b/server/storage/__init__.py @@ -1,6 +1,9 @@ +from .LocalStorage import LocalStorage +from .EdgeDB import EdgeDB + class StorageLoader: @classmethod - def build(self, selected_storage: str): + def build(self, selected_storage:str) -> LocalStorage|EdgeDB: storage_module = __import__(f"server.storage.{selected_storage}", fromlist=[selected_storage]) storage_class = getattr(storage_module, selected_storage) return storage_class diff --git a/snakes/TemplateSnake.py b/snakes/TemplateSnake.py index c219e17..73f38f1 100644 --- a/snakes/TemplateSnake.py +++ b/snakes/TemplateSnake.py @@ -1,4 +1,8 @@ -from server.GameBoard import GameBoard +from typing import TYPE_CHECKING + +if TYPE_CHECKING: + from server.GameBoard import GameBoard + import random class TemplateSnake: @@ -22,7 +26,7 @@ class TemplateSnake: def add_calculations(self, calculations:dict): self.calculations.append(calculations) - def choose_move(self, game_data:GameBoard): + def choose_move(self, game_data:'GameBoard'): self.game_board = game_data self.calculations = [] self.eat_the_snake_overwrite = False