Skip to content

Commit ec399d1

Browse files
authored
Merge pull request #1100 from niklasf/stricter-subclass-typing
Stricter subclass typing
2 parents 32253d6 + 33eea7c commit ec399d1

File tree

6 files changed

+454
-324
lines changed

6 files changed

+454
-324
lines changed

CHANGELOG.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,13 @@ Changes:
1515
some 8 piece positions with decisive captures can be probed successfully.
1616
* The string wrapper returned by ``chess.svg`` functions now also implements
1717
``_repr_html_``.
18+
* Significant changes to ``chess.engine`` internals:
19+
``chess.engine.BaseCommand`` methods other than the constructor no longer
20+
receive ``engine: Protocol``.
21+
* Significant changes to board state internals: Subclasses of ``chess.Board``
22+
can no longer hook into board state recording/restoration and need to
23+
override relevant methods instead (``clear_stack``, ``copy``, ``root``,
24+
``push``, ``pop``).
1825

1926
New features:
2027

chess/__init__.py

Lines changed: 21 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
from typing import ClassVar, Callable, Counter, Dict, Generic, Hashable, Iterable, Iterator, List, Literal, Mapping, Optional, SupportsInt, Tuple, Type, TypeVar, Union
2626

2727
if typing.TYPE_CHECKING:
28-
from typing_extensions import TypeAlias
28+
from typing_extensions import Self, TypeAlias
2929

3030

3131
EnPassantSpec = Literal["legal", "fen", "xfen"]
@@ -1455,7 +1455,7 @@ def apply_transform(self, f: Callable[[Bitboard], Bitboard]) -> None:
14551455
self.occupied = f(self.occupied)
14561456
self.promoted = f(self.promoted)
14571457

1458-
def transform(self: BaseBoardT, f: Callable[[Bitboard], Bitboard]) -> BaseBoardT:
1458+
def transform(self, f: Callable[[Bitboard], Bitboard]) -> Self:
14591459
"""
14601460
Returns a transformed copy of the board (without move stack)
14611461
by applying a bitboard transformation function.
@@ -1473,11 +1473,11 @@ def transform(self: BaseBoardT, f: Callable[[Bitboard], Bitboard]) -> BaseBoardT
14731473
board.apply_transform(f)
14741474
return board
14751475

1476-
def apply_mirror(self: BaseBoardT) -> None:
1476+
def apply_mirror(self) -> None:
14771477
self.apply_transform(flip_vertical)
14781478
self.occupied_co[WHITE], self.occupied_co[BLACK] = self.occupied_co[BLACK], self.occupied_co[WHITE]
14791479

1480-
def mirror(self: BaseBoardT) -> BaseBoardT:
1480+
def mirror(self) -> Self:
14811481
"""
14821482
Returns a mirrored copy of the board (without move stack).
14831483
@@ -1491,7 +1491,7 @@ def mirror(self: BaseBoardT) -> BaseBoardT:
14911491
board.apply_mirror()
14921492
return board
14931493

1494-
def copy(self: BaseBoardT) -> BaseBoardT:
1494+
def copy(self) -> Self:
14951495
"""Creates a copy of the board."""
14961496
board = type(self)(None)
14971497

@@ -1509,10 +1509,10 @@ def copy(self: BaseBoardT) -> BaseBoardT:
15091509

15101510
return board
15111511

1512-
def __copy__(self: BaseBoardT) -> BaseBoardT:
1512+
def __copy__(self) -> Self:
15131513
return self.copy()
15141514

1515-
def __deepcopy__(self: BaseBoardT, memo: Dict[int, object]) -> BaseBoardT:
1515+
def __deepcopy__(self, memo: Dict[int, object]) -> Self:
15161516
board = self.copy()
15171517
memo[id(self)] = board
15181518
return board
@@ -1542,9 +1542,9 @@ def from_chess960_pos(cls: Type[BaseBoardT], scharnagl: int) -> BaseBoardT:
15421542

15431543
BoardT = TypeVar("BoardT", bound="Board")
15441544

1545-
class _BoardState(Generic[BoardT]):
1545+
class _BoardState:
15461546

1547-
def __init__(self, board: BoardT) -> None:
1547+
def __init__(self, board: Board) -> None:
15481548
self.pawns = board.pawns
15491549
self.knights = board.knights
15501550
self.bishops = board.bishops
@@ -1564,7 +1564,7 @@ def __init__(self, board: BoardT) -> None:
15641564
self.halfmove_clock = board.halfmove_clock
15651565
self.fullmove_number = board.fullmove_number
15661566

1567-
def restore(self, board: BoardT) -> None:
1567+
def restore(self, board: Board) -> None:
15681568
board.pawns = self.pawns
15691569
board.knights = self.knights
15701570
board.bishops = self.bishops
@@ -1694,14 +1694,14 @@ class Board(BaseBoard):
16941694
manipulation.
16951695
"""
16961696

1697-
def __init__(self: BoardT, fen: Optional[str] = STARTING_FEN, *, chess960: bool = False) -> None:
1697+
def __init__(self, fen: Optional[str] = STARTING_FEN, *, chess960: bool = False) -> None:
16981698
BaseBoard.__init__(self, None)
16991699

17001700
self.chess960 = chess960
17011701

17021702
self.ep_square = None
17031703
self.move_stack = []
1704-
self._stack: List[_BoardState[BoardT]] = []
1704+
self._stack: List[_BoardState] = []
17051705

17061706
if fen is None:
17071707
self.clear()
@@ -1786,7 +1786,7 @@ def clear_stack(self) -> None:
17861786
self.move_stack.clear()
17871787
self._stack.clear()
17881788

1789-
def root(self: BoardT) -> BoardT:
1789+
def root(self) -> Self:
17901790
"""Returns a copy of the root position."""
17911791
if self._stack:
17921792
board = type(self)(None, chess960=self.chess960)
@@ -2304,13 +2304,10 @@ def is_repetition(self, count: int = 3) -> bool:
23042304

23052305
return False
23062306

2307-
def _board_state(self: BoardT) -> _BoardState[BoardT]:
2308-
return _BoardState(self)
2309-
23102307
def _push_capture(self, move: Move, capture_square: Square, piece_type: PieceType, was_promoted: bool) -> None:
23112308
pass
23122309

2313-
def push(self: BoardT, move: Move) -> None:
2310+
def push(self, move: Move) -> None:
23142311
"""
23152312
Updates the position with the given *move* and puts it onto the
23162313
move stack.
@@ -2335,7 +2332,7 @@ def push(self: BoardT, move: Move) -> None:
23352332
"""
23362333
# Push move and remember board state.
23372334
move = self._to_chess960(move)
2338-
board_state = self._board_state()
2335+
board_state = _BoardState(self)
23392336
self.castling_rights = self.clean_castling_rights() # Before pushing stack
23402337
self.move_stack.append(self._from_chess960(self.chess960, move.from_square, move.to_square, move.promotion, move.drop))
23412338
self._stack.append(board_state)
@@ -2431,7 +2428,7 @@ def push(self: BoardT, move: Move) -> None:
24312428
# Swap turn.
24322429
self.turn = not self.turn
24332430

2434-
def pop(self: BoardT) -> Move:
2431+
def pop(self) -> Move:
24352432
"""
24362433
Restores the previous position and returns the last move from the stack.
24372434
@@ -2841,7 +2838,7 @@ def _validate_epd_opcode(self, opcode: str) -> None:
28412838
if blacklisted in opcode:
28422839
raise ValueError(f"invalid character {blacklisted!r} in epd opcode: {opcode!r}")
28432840

2844-
def _parse_epd_ops(self: BoardT, operation_part: str, make_board: Callable[[], BoardT]) -> Dict[str, Union[None, str, int, float, Move, List[Move]]]:
2841+
def _parse_epd_ops(self, operation_part: str, make_board: Callable[[], Self]) -> Dict[str, Union[None, str, int, float, Move, List[Move]]]:
28452842
operations: Dict[str, Union[None, str, int, float, Move, List[Move]]] = {}
28462843
state = "opcode"
28472844
opcode = ""
@@ -3834,16 +3831,16 @@ def apply_transform(self, f: Callable[[Bitboard], Bitboard]) -> None:
38343831
self.ep_square = None if self.ep_square is None else msb(f(BB_SQUARES[self.ep_square]))
38353832
self.castling_rights = f(self.castling_rights)
38363833

3837-
def transform(self: BoardT, f: Callable[[Bitboard], Bitboard]) -> BoardT:
3834+
def transform(self, f: Callable[[Bitboard], Bitboard]) -> Self:
38383835
board = self.copy(stack=False)
38393836
board.apply_transform(f)
38403837
return board
38413838

3842-
def apply_mirror(self: BoardT) -> None:
3839+
def apply_mirror(self) -> None:
38433840
super().apply_mirror()
38443841
self.turn = not self.turn
38453842

3846-
def mirror(self: BoardT) -> BoardT:
3843+
def mirror(self) -> Self:
38473844
"""
38483845
Returns a mirrored copy of the board.
38493846
@@ -3858,7 +3855,7 @@ def mirror(self: BoardT) -> BoardT:
38583855
board.apply_mirror()
38593856
return board
38603857

3861-
def copy(self: BoardT, *, stack: Union[bool, int] = True) -> BoardT:
3858+
def copy(self, *, stack: Union[bool, int] = True) -> Self:
38623859
"""
38633860
Creates a copy of the board.
38643861

0 commit comments

Comments
 (0)