Skip to content

Commit d88d469

Browse files
finish merge
1 parent 53a04b3 commit d88d469

1 file changed

Lines changed: 27 additions & 5 deletions

File tree

src/pygambit/catalog/catalog.py

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -65,13 +65,23 @@ class CatalogGameFromContrib(CatalogGame):
6565
Calling any subclass will return an instance of the corresponding game.
6666
"""
6767

68-
game_file: str | None = None
68+
game_file: str
69+
_cached_game: Game | None = None
6970

7071
def __new__(cls) -> Game:
72+
# Return cached game if available, otherwise load it
73+
if cls._cached_game is None:
74+
cls._cached_game = cls._load_game()
75+
# Return a fresh instance (not the cached one)
76+
return cls._load_game()
77+
78+
@classmethod
79+
def _load_game(cls) -> Game:
7180
"""Load the game from file."""
7281
if cls.game_file is None:
7382
raise NotImplementedError(f"{cls.__name__} must define 'game_file'")
7483

84+
cls.game_type = cls.game_file.split(".")[-1]
7585
file_path = _GAMEFILES_DIR / cls.game_file
7686

7787
if cls.game_type == "nfg":
@@ -81,6 +91,17 @@ def __new__(cls) -> Game:
8191
else:
8292
raise ValueError(f"Game file extension must be 'nfg' or 'efg', got '{cls.game_type}'")
8393

94+
def __init_subclass__(cls, **kwargs):
95+
"""Validate and extract metadata when subclass is defined."""
96+
super().__init_subclass__(**kwargs)
97+
98+
if not hasattr(cls, "game_file") or cls.game_file is None:
99+
raise TypeError(f"{cls.__name__} must define 'game_file' class attribute")
100+
101+
# Load game and extract metadata immediately when class is defined
102+
cls._cached_game = cls._load_game()
103+
cls._extract_metadata_from_game(cls._cached_game)
104+
84105

85106
def games(
86107
game_type: Literal["all", "nfg", "efg"] = "all",
@@ -104,14 +125,15 @@ def games(
104125
list[str]
105126
List of game class names matching the specified type.
106127
"""
128+
107129
def get_all_subclasses(cls):
108130
"""Recursively get all subclasses."""
109131
all_subclasses = []
110132
for subclass in cls.__subclasses__():
111-
if subclass.__name__ not in ["CatalogGameFromContrib"] and (
112-
game_type == "all" or subclass.game_type == game_type
113-
) and (
114-
num_players is None or subclass.num_players == num_players
133+
if (
134+
subclass.__name__ not in ["CatalogGameFromContrib"]
135+
and (game_type == "all" or subclass.game_type == game_type)
136+
and (num_players is None or subclass.num_players == num_players)
115137
):
116138
all_subclasses.append(subclass.__name__)
117139
all_subclasses.extend(get_all_subclasses(subclass))

0 commit comments

Comments
 (0)