Skip to content

Instantly share code, notes, and snippets.

@DJStompZone
Created May 1, 2024 14:54
Show Gist options
  • Save DJStompZone/d630d5617c99fbe2cf9f8ad9387cef3b to your computer and use it in GitHub Desktop.
Save DJStompZone/d630d5617c99fbe2cf9f8ad9387cef3b to your computer and use it in GitHub Desktop.
Contrived MethodCaller Demo
from typing import Iterable, Optional, SupportsIndex, overload, override
class Char(str):
"""Single character string or empty string wrapper."""
def __new__(cls, value: str) -> "Char":
if len(value) > 1:
raise ValueError("A Char must be a string of length 0 or 1")
return super().__new__(cls, value)
class CharArray(list[Char]):
"""Array of Char objects to ensure only single-character or empty strings are stored."""
@overload
def __init__(self, __iterable: Iterable[str], /) -> None: ...
@overload
def __init__(self, /) -> None: ...
def __init__(self, __iterable: Optional[Iterable[str]] = None, /) -> None:
if __iterable is not None:
super().__init__(map(Char, __iterable))
else:
super().__init__()
@override
def append(self, value: str) -> None:
if len(value) > 1:
raise ValueError("A Char must be a string of length 0 or 1")
super().append(Char(value))
@override
def extend(self, values: Iterable[str]) -> None:
for value in values:
self.append(value)
@override
def insert(self, index: SupportsIndex, value: str) -> None:
if len(value) > 1:
raise ValueError("A Char must be a string of length 0 or 1")
super().insert(index, Char(value))
@override
def __setitem__(self, i: SupportsIndex | slice, value) -> None:
if isinstance(i, slice):
if any(len(v) > 1 for v in value):
raise ValueError("All Chars must be strings of length 0 or 1")
super().__setitem__(i, map(Char, value))
else:
if len(value) > 1:
raise ValueError("A Char must be a string of length 0 or 1")
super().__setitem__(i, Char(value))
@override
@overload
def __getitem__(self, __i: SupportsIndex, /) -> Char: ...
@override
@overload
def __getitem__(self, __s: slice, /) -> "CharArray": ...
@override
def __getitem__(self, index: SupportsIndex | slice, /) -> "Char|CharArray":
result: Char | list[Char] = super().__getitem__(index)
if isinstance(index, slice) or isinstance(result, list):
return CharArray(result)
return result
@override
def __str__(self) -> str:
return "".join(super().__str__())
@override
def __repr__(self) -> str:
return f"CharArray({super().__repr__()})"
@classmethod
def from_str(cls, value: str) -> "CharArray":
return cls(list(value))
from operator import methodcaller
from random import randint
from localtypes import Char, CharArray
NUM = 100
mk_tests = lambda: (CharArray([Char(chr(randint(33, 47))) for _ in range(NUM)]), CharArray([Char(chr(randint(97, 122))) for _ in range(NUM)]))
is_spec = lambda value: type(value) in [str, Char] and not value.isalnum()
pop_last_spec = lambda l: len([e for e in l if is_spec(e)]) and methodcaller('pop', [i for i, ea in enumerate(l) if is_spec(ea)][-1])(l) or not __import__('this') or None
pop_last_2_spec = lambda l: len([e for e in l if is_spec(e)]) and [methodcaller('pop', [i for i, ea in enumerate(l) if is_spec(ea)][idx])(l) for idx in range(-1 * min([len([e for e in l if is_spec(e)]), 2]), 0)] or not __import__('this') or None
import pytest
from localtypes import Char, CharArray
def test_char_creation():
assert Char("a") == "a"
assert Char("") == ""
with pytest.raises(ValueError):
Char("ab")
def test_char_array_creation():
ca = CharArray("abc")
assert isinstance(ca, CharArray)
assert list(ca) == ["a", "b", "c"]
ca = CharArray(["a", "", "c"])
assert list(ca) == ["a", "", "c"]
with pytest.raises(ValueError):
CharArray(["a", "bc", "d"])
def test_char_array_index_access():
ca = CharArray("abc")
assert ca[0] == "a"
assert ca[1] == "b"
assert ca[2] == "c"
assert isinstance(ca[1:3], CharArray)
assert list(ca[1:3]) == ["b", "c"]
def test_char_array_modification():
ca = CharArray("abc")
ca.append("d")
assert list(ca) == ["a", "b", "c", "d"]
with pytest.raises(ValueError):
ca.append("de")
ca.extend("ef")
assert list(ca) == ["a", "b", "c", "d", "e", "f"]
with pytest.raises(ValueError):
ca.extend(["g", "hi"])
ca.insert(0, "z")
assert ca[0] == "z"
with pytest.raises(ValueError):
ca.insert(1, "xy")
ca[0] = "x"
assert ca[0] == "x"
with pytest.raises(ValueError):
ca[0] = "yz"
def test_char_array_comparison():
ca1 = CharArray("abc")
ca2 = CharArray("abc")
ca3 = CharArray("abcd")
assert ca1 == ca2
assert ca1 != ca3
assert ca1 != ["a", "b", "c", "d"]
assert list(ca1) == ["a", "b", "c"]
import pytest
from localtypes import Char, CharArray
from main import is_spec, mk_tests, pop_last_2_spec, pop_last_spec
@pytest.fixture
def with_spec_fixture() -> CharArray:
return mk_tests()[0]
@pytest.fixture
def without_spec_fixture() -> CharArray:
return mk_tests()[1]
# fmt: off
def test_is_spec(with_spec_fixture: CharArray, without_spec_fixture: CharArray) -> None:
assert all(is_spec(char) for char in with_spec_fixture), "All chars in with_spec should be non-alphanumeric"
assert not any(is_spec(char) for char in without_spec_fixture), "No chars in without_spec should be non-alphanumeric"
def test_pop_last_spec(with_spec_fixture: CharArray) -> None:
original_last: Char | None = with_spec_fixture[-1] if not with_spec_fixture[-1].isalnum() else None
pop_result = pop_last_spec(with_spec_fixture)
assert pop_result == original_last, "The popped result should match the last non-alphanumeric char"
def test_pop_last_2_spec(with_spec_fixture: CharArray) -> None:
original_last_two: list[Char] = [char for char in with_spec_fixture if not char.isalnum()]
original_last_two = original_last_two[max(-2, -1 * len(original_last_two)):]
pop_results = pop_last_2_spec(with_spec_fixture)
if 0 < len(original_last_two) < 3 and pop_results:
assert pop_results == original_last_two, "The popped results should match the last two non-alphanumeric chars"
else:
assert pop_results is None, "No results should be popped if less than one non-alphanumeric char exists"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment