Split ListSpy to its own module
This commit is contained in:
81
babi/list_spy.py
Normal file
81
babi/list_spy.py
Normal file
@@ -0,0 +1,81 @@
|
||||
import functools
|
||||
from typing import Callable
|
||||
from typing import Iterator
|
||||
from typing import List
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Protocol # python3.8+
|
||||
else:
|
||||
Protocol = object
|
||||
|
||||
|
||||
class MutableSequenceNoSlice(Protocol):
|
||||
def __len__(self) -> int: ...
|
||||
def __getitem__(self, idx: int) -> str: ...
|
||||
def __setitem__(self, idx: int, val: str) -> None: ...
|
||||
def __delitem__(self, idx: int) -> None: ...
|
||||
def insert(self, idx: int, val: str) -> None: ...
|
||||
|
||||
def __iter__(self) -> Iterator[str]:
|
||||
for i in range(len(self)):
|
||||
yield self[i]
|
||||
|
||||
def append(self, val: str) -> None:
|
||||
self.insert(len(self), val)
|
||||
|
||||
def pop(self, idx: int = -1) -> str:
|
||||
victim = self[idx]
|
||||
del self[idx]
|
||||
return victim
|
||||
|
||||
|
||||
def _del(lst: MutableSequenceNoSlice, *, idx: int) -> None:
|
||||
del lst[idx]
|
||||
|
||||
|
||||
def _set(lst: MutableSequenceNoSlice, *, idx: int, val: str) -> None:
|
||||
lst[idx] = val
|
||||
|
||||
|
||||
def _ins(lst: MutableSequenceNoSlice, *, idx: int, val: str) -> None:
|
||||
lst.insert(idx, val)
|
||||
|
||||
|
||||
class ListSpy(MutableSequenceNoSlice):
|
||||
def __init__(self, lst: MutableSequenceNoSlice) -> None:
|
||||
self._lst = lst
|
||||
self._undo: List[Callable[[MutableSequenceNoSlice], None]] = []
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return f'{type(self).__name__}({self._lst})'
|
||||
|
||||
def __len__(self) -> int:
|
||||
return len(self._lst)
|
||||
|
||||
def __getitem__(self, idx: int) -> str:
|
||||
return self._lst[idx]
|
||||
|
||||
def __setitem__(self, idx: int, val: str) -> None:
|
||||
self._undo.append(functools.partial(_set, idx=idx, val=self._lst[idx]))
|
||||
self._lst[idx] = val
|
||||
|
||||
def __delitem__(self, idx: int) -> None:
|
||||
if idx < 0:
|
||||
idx %= len(self)
|
||||
self._undo.append(functools.partial(_ins, idx=idx, val=self._lst[idx]))
|
||||
del self._lst[idx]
|
||||
|
||||
def insert(self, idx: int, val: str) -> None:
|
||||
if idx < 0:
|
||||
idx %= len(self)
|
||||
self._undo.append(functools.partial(_del, idx=idx))
|
||||
self._lst.insert(idx, val)
|
||||
|
||||
def undo(self, lst: MutableSequenceNoSlice) -> None:
|
||||
for fn in reversed(self._undo):
|
||||
fn(lst)
|
||||
|
||||
@property
|
||||
def has_modifications(self) -> bool:
|
||||
return bool(self._undo)
|
||||
79
babi/main.py
79
babi/main.py
@@ -19,7 +19,6 @@ from typing import cast
|
||||
from typing import Dict
|
||||
from typing import Generator
|
||||
from typing import IO
|
||||
from typing import Iterator
|
||||
from typing import List
|
||||
from typing import Match
|
||||
from typing import NamedTuple
|
||||
@@ -27,14 +26,11 @@ from typing import Optional
|
||||
from typing import Pattern
|
||||
from typing import Sequence
|
||||
from typing import Tuple
|
||||
from typing import TYPE_CHECKING
|
||||
from typing import TypeVar
|
||||
from typing import Union
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Protocol # python3.8+
|
||||
else:
|
||||
Protocol = object
|
||||
from babi.list_spy import ListSpy
|
||||
from babi.list_spy import MutableSequenceNoSlice
|
||||
|
||||
VERSION_STR = 'babi v0'
|
||||
TCallable = TypeVar('TCallable', bound=Callable[..., Any])
|
||||
@@ -100,77 +96,6 @@ def _scrolled_line(s: str, x: int, width: int) -> str:
|
||||
return s.ljust(width)
|
||||
|
||||
|
||||
class MutableSequenceNoSlice(Protocol):
|
||||
def __len__(self) -> int: ...
|
||||
def __getitem__(self, idx: int) -> str: ...
|
||||
def __setitem__(self, idx: int, val: str) -> None: ...
|
||||
def __delitem__(self, idx: int) -> None: ...
|
||||
def insert(self, idx: int, val: str) -> None: ...
|
||||
|
||||
def __iter__(self) -> Iterator[str]:
|
||||
for i in range(len(self)):
|
||||
yield self[i]
|
||||
|
||||
def append(self, val: str) -> None:
|
||||
self.insert(len(self), val)
|
||||
|
||||
def pop(self, idx: int = -1) -> str:
|
||||
victim = self[idx]
|
||||
del self[idx]
|
||||
return victim
|
||||
|
||||
|
||||
def _del(lst: MutableSequenceNoSlice, *, idx: int) -> None:
|
||||
del lst[idx]
|
||||
|
||||
|
||||
def _set(lst: MutableSequenceNoSlice, *, idx: int, val: str) -> None:
|
||||
lst[idx] = val
|
||||
|
||||
|
||||
def _ins(lst: MutableSequenceNoSlice, *, idx: int, val: str) -> None:
|
||||
lst.insert(idx, val)
|
||||
|
||||
|
||||
class ListSpy(MutableSequenceNoSlice):
|
||||
def __init__(self, lst: MutableSequenceNoSlice) -> None:
|
||||
self._lst = lst
|
||||
self._undo: List[Callable[[MutableSequenceNoSlice], None]] = []
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return f'{type(self).__name__}({self._lst})'
|
||||
|
||||
def __len__(self) -> int:
|
||||
return len(self._lst)
|
||||
|
||||
def __getitem__(self, idx: int) -> str:
|
||||
return self._lst[idx]
|
||||
|
||||
def __setitem__(self, idx: int, val: str) -> None:
|
||||
self._undo.append(functools.partial(_set, idx=idx, val=self._lst[idx]))
|
||||
self._lst[idx] = val
|
||||
|
||||
def __delitem__(self, idx: int) -> None:
|
||||
if idx < 0:
|
||||
idx %= len(self)
|
||||
self._undo.append(functools.partial(_ins, idx=idx, val=self._lst[idx]))
|
||||
del self._lst[idx]
|
||||
|
||||
def insert(self, idx: int, val: str) -> None:
|
||||
if idx < 0:
|
||||
idx %= len(self)
|
||||
self._undo.append(functools.partial(_del, idx=idx))
|
||||
self._lst.insert(idx, val)
|
||||
|
||||
def undo(self, lst: MutableSequenceNoSlice) -> None:
|
||||
for fn in reversed(self._undo):
|
||||
fn(lst)
|
||||
|
||||
@property
|
||||
def has_modifications(self) -> bool:
|
||||
return bool(self._undo)
|
||||
|
||||
|
||||
class Key(NamedTuple):
|
||||
wch: Union[int, str]
|
||||
keyname: bytes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import pytest
|
||||
|
||||
from babi.main import ListSpy
|
||||
from babi.list_spy import ListSpy
|
||||
|
||||
|
||||
def test_list_spy_repr():
|
||||
|
||||
Reference in New Issue
Block a user