@@ -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
85106def 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