diff --git a/chess/pgn.py b/chess/pgn.py index 5ae5b43b..3d4d7e5f 100644 --- a/chess/pgn.py +++ b/chess/pgn.py @@ -1636,13 +1636,14 @@ def read_game(handle: TextIO, *, Visitor: Any = GameBuilder) -> Any: if not isinstance(managed_headers, Headers): unmanaged_headers = Headers({}) - if not line.startswith("["): + stripped = line.lstrip() + if not stripped.startswith("["): break consecutive_empty_lines = 0 if not skipping_game: - tag_match = TAG_REGEX.match(line) + tag_match = TAG_REGEX.match(stripped) if tag_match: visitor.visit_header(tag_match.group(1), tag_match.group(2)) if unmanaged_headers is not None: diff --git a/test.py b/test.py index cc8a95b7..ac906638 100755 --- a/test.py +++ b/test.py @@ -2233,6 +2233,24 @@ def test_read_game(self): self.assertEqual(sixth_game.headers["White"], "Deep Blue (Computer)") self.assertEqual(sixth_game.headers["Result"], "1-0") + def test_read_game_with_leading_whitespace_before_header(self): + pgn = io.StringIO( + ' [Event "TCEC Season 27 - Entrance League"]\n' + '[Site "https://tcec-chess.com"]\n' + '[White "Patricia 3.1_dev_ca7ef0a3"]\n' + '[Black "Weiss 2.1-dev11"]\n' + '[Result "*"]\n' + "\n" + "1. d4 *" + ) + + game = chess.pgn.read_game(pgn) + + self.assertEqual(game.headers["Event"], "TCEC Season 27 - Entrance League") + self.assertEqual(game.headers["White"], "Patricia 3.1_dev_ca7ef0a3") + self.assertEqual(game.next().move, chess.Move.from_uci("d2d4")) + self.assertEqual(game.errors, []) + def test_read_game_with_multicomment_move(self): pgn = io.StringIO("1. e4 {A common opening} 1... e5 {A common response} {An uncommon comment}") game = chess.pgn.read_game(pgn)