Created
May 1, 2024 14:54
-
-
Save DJStompZone/d630d5617c99fbe2cf9f8ad9387cef3b to your computer and use it in GitHub Desktop.
Contrived MethodCaller Demo
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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