Module pedantic.tests.tests_generic_classes

Expand source code
import unittest
from typing import Generic, TypeVar, Any, List, Optional, Union

from pedantic.constants import TYPE_VAR_METHOD_NAME, TYPE_VAR_SELF
from pedantic.decorators.class_decorators import pedantic_class
from pedantic.exceptions import PedanticTypeVarMismatchException


class TestGenericClasses(unittest.TestCase):
    def test_pedantic_generic_class(self):
        T = TypeVar('T')

        @pedantic_class
        class LoggedVar(Generic[T]):
            def __init__(self, value: T, name: str, logger: Any) -> None:
                self.name = name
                self.logger = logger
                self.value = value

            def set(self, new: T) -> None:
                self.log(message='Set ' + repr(self.value))
                self.value = new

            def get(self) -> T:
                self.log(message='Get ' + repr(self.value))
                return self.value

            def log(self, message: str) -> None:
                self.logger = self.name + message

        o = LoggedVar[int](value=42, name='hi', logger='test')
        o.set(new=57)
        self.assertTrue(isinstance(o.get(), int))

        with self.assertRaises(expected_exception=PedanticTypeVarMismatchException):
            o.set(new=3.14)

    def test_stack(self):
        T = TypeVar('T')

        @pedantic_class
        class Stack(Generic[T]):
            def __init__(self) -> None:
                self.items: List[T] = []

            def push(self, item: T) -> None:
                self.items.append(item)

            def pop(self) -> T:
                return self.items.pop()

            def empty(self) -> bool:
                return not self.items

            def top(self) -> Optional[T]:
                if len(self.items) > 0:
                    return self.items[len(self.items) - 1]
                else:
                    return None

        my_stack = Stack[str]()
        get_type_vars = getattr(my_stack, TYPE_VAR_METHOD_NAME)
        self.assertEqual(get_type_vars(), {T: str, TYPE_VAR_SELF: Stack})
        with self.assertRaises(expected_exception=IndexError):
            my_stack.pop()
        self.assertIsNone(my_stack.top())
        self.assertIsNone(my_stack.top())
        # self.assertFalse(T in get_type_vars())
        my_stack.push(item='hi')
        self.assertTrue(T in get_type_vars())
        my_stack.push(item='world')
        self.assertTrue(T in get_type_vars())
        self.assertTrue(len(get_type_vars()), 1)
        self.assertEqual(my_stack.pop(), 'world')
        self.assertEqual(my_stack.pop(), 'hi')
        self.assertIsNone(my_stack.top())
        with self.assertRaises(expected_exception=PedanticTypeVarMismatchException):
            my_stack.push(item=42)

        my_other_stack = Stack[int]()
        get_type_vars = getattr(my_other_stack, TYPE_VAR_METHOD_NAME)
        self.assertEqual(get_type_vars(), {T: int, TYPE_VAR_SELF: Stack})
        with self.assertRaises(expected_exception=IndexError):
            my_other_stack.pop()
        self.assertIsNone(my_other_stack.top())
        self.assertIsNone(my_other_stack.top())
        my_other_stack.push(item=100)
        self.assertTrue(len(get_type_vars()), 1)
        my_other_stack.push(item=142)
        self.assertTrue(len(get_type_vars()), 1)
        self.assertEqual(my_other_stack.pop(), 142)
        self.assertEqual(my_other_stack.pop(), 100)
        self.assertIsNone(my_other_stack.top())
        with self.assertRaises(expected_exception=PedanticTypeVarMismatchException):
            my_other_stack.push(item='42')

    def test_generic_class_initialised_without_generics(self):
        T = TypeVar('T')

        @pedantic_class
        class MyClass(Generic[T]):
            def __init__(self, a: T) -> None:
                self.a = a

            def get_a(self) -> T:
                return self.a

            def set_a(self, val: T) -> None:
                self.a = val

        with self.assertRaises(expected_exception=PedanticTypeVarMismatchException):
            m = MyClass(a=42)

    def test_generic_class_initialised_without_generics_2(self):
        T = TypeVar('T')

        @pedantic_class
        class MyClass(Generic[T]):
            def __init__(self, a: T) -> None:
                self.a = a

            def get_a(self) -> T:
                return self.a

            def set_a(self, val: T) -> None:
                self.a = val

        MyClass(a=42)  # it is not recognized if it isn't assigned

    def test_generic_class_inheritance(self):
        class Parent:
            pass

        class Child1(Parent):
            pass

        class Child2(Parent):
            pass

        T = TypeVar('T')

        @pedantic_class
        class MyClass(Generic[T]):
            def __init__(self, a: T) -> None:
                self.a = a

            def get_a(self) -> T:
                return self.a

            def set_a(self, val: T) -> None:
                self.a = val

        m = MyClass[Parent](a=Child1())
        self.assertTrue(isinstance(m.get_a(), Child1))
        self.assertFalse(isinstance(m.get_a(), Child2))
        m.set_a(val=Child2())
        self.assertTrue(isinstance(m.get_a(), Child2))
        self.assertFalse(isinstance(m.get_a(), Child1))

    def test_merge_dicts(self):
        def create():
            T = TypeVar('T')

            @pedantic_class
            class MyClass(Generic[T]):
                def __init__(self, a: T) -> None:
                    self.a = a

                def get_a(self) -> T:
                    return self.a

                def set_a(self, val: T) -> None:
                    self.a = val
            return MyClass(a=42)
        a = create()
        with self.assertRaises(expected_exception=PedanticTypeVarMismatchException):
            a.set_a(val='hi')

    def test_recursion_depth_exceeded(self):
        T = TypeVar('T')

        @pedantic_class
        class Stack(Generic[T]):
            def __init__(self) -> None:
                self.items: List[T] = []

            def len(self) -> int:
                return len(self.items)

            def push(self, item: T) -> None:
                self.items.append(item)

            def pop(self) -> T:
                if len(self.items) > 0:
                    return self.items.pop()
                else:
                    raise ValueError()

            def empty(self) -> bool:
                return not self.items

            def top(self) -> Optional[T]:
                if len(self.items) > 0:
                    return self.items[len(self.items) - 1]
                else:
                    return None

            def __len__(self) -> int:
                return len(self.items)

        def create_stack():
            stack = Stack[int]()
            return stack

        with self.assertRaises(expected_exception=PedanticTypeVarMismatchException):
            stack: Stack[int] = Stack()
            self.assertTrue(stack.empty())
        with self.assertRaises(expected_exception=PedanticTypeVarMismatchException):
            stack = Stack()
            self.assertTrue(stack.empty())
        stack = create_stack()
        self.assertTrue(stack.empty())

    def test_generic_union(self):
        T = TypeVar('T')

        @pedantic_class
        class Stack(Generic[T]):
            def __init__(self) -> None:
                self.items: List[T] = []

            def len(self) -> int:
                return len(self.items)

            def push(self, item: T) -> None:
                self.items.append(item)

            def pop(self) -> T:
                if len(self.items) > 0:
                    return self.items.pop()
                else:
                    raise ValueError()

            def empty(self) -> bool:
                return not self.items

            def top(self) -> Optional[T]:
                if len(self.items) > 0:
                    return self.items[len(self.items) - 1]
                else:
                    return None

            def __len__(self) -> int:
                return len(self.items)

        s = Stack[Union[int, float, str]]()
        s.push(item=42)
        s.push(item='hello')
        s.push(item=3.1415)
        with self.assertRaises(expected_exception=PedanticTypeVarMismatchException):
            s.push(item=[1, 2])

    def test_inheritance(self):
        T = TypeVar('T')

        @pedantic_class
        class Stack(Generic[T]):
            def __init__(self) -> None:
                self.items: List[T] = []

            def len(self) -> int:
                return len(self.items)

            def push(self, item: T) -> None:
                self.items.append(item)

            def pop(self) -> T:
                if len(self.items) > 0:
                    return self.items.pop()
                else:
                    raise ValueError()

            def empty(self) -> bool:
                return not self.items

            def top(self) -> Optional[T]:
                if len(self.items) > 0:
                    return self.items[len(self.items) - 1]
                else:
                    return None

            def __len__(self) -> int:
                return len(self.items)

        @pedantic_class
        class Parent:
            pass

        @pedantic_class
        class Child1(Parent):
            pass

        @pedantic_class
        class Child2(Parent):
            pass

        parent_stack = Stack[Parent]()
        parent_stack.push(item=Child1())
        parent_stack.push(item=Child2())
        parent_stack.push(item=Parent())

        child_1_stack = Stack[Child1]()
        child_1_stack.push(item=Child1())
        with self.assertRaises(expected_exception=PedanticTypeVarMismatchException):
            child_1_stack.push(item=Child2())
        with self.assertRaises(expected_exception=PedanticTypeVarMismatchException):
            child_1_stack.push(item=Parent())

Classes

class TestGenericClasses (methodName='runTest')

A class whose instances are single test cases.

By default, the test code itself should be placed in a method named 'runTest'.

If the fixture may be used for many test cases, create as many test methods as are needed. When instantiating such a TestCase subclass, specify in the constructor arguments the name of the test method that the instance is to execute.

Test authors should subclass TestCase for their own tests. Construction and deconstruction of the test's environment ('fixture') can be implemented by overriding the 'setUp' and 'tearDown' methods respectively.

If it is necessary to override the init method, the base class init method must always be called. It is important that subclasses should not change the signature of their init method, since instances of the classes are instantiated automatically by parts of the framework in order to be run.

When subclassing TestCase, you can set these attributes: * failureException: determines which exception will be raised when the instance's assertion methods fail; test methods raising this exception will be deemed to have 'failed' rather than 'errored'. * longMessage: determines whether long messages (including repr of objects used in assert methods) will be printed on failure in addition to any explicit message passed. * maxDiff: sets the maximum length of a diff in failure messages by assert methods using difflib. It is looked up as an instance attribute so can be configured by individual tests if required.

Create an instance of the class that will use the named test method when executed. Raises a ValueError if the instance does not have a method with the specified name.

Expand source code
class TestGenericClasses(unittest.TestCase):
    def test_pedantic_generic_class(self):
        T = TypeVar('T')

        @pedantic_class
        class LoggedVar(Generic[T]):
            def __init__(self, value: T, name: str, logger: Any) -> None:
                self.name = name
                self.logger = logger
                self.value = value

            def set(self, new: T) -> None:
                self.log(message='Set ' + repr(self.value))
                self.value = new

            def get(self) -> T:
                self.log(message='Get ' + repr(self.value))
                return self.value

            def log(self, message: str) -> None:
                self.logger = self.name + message

        o = LoggedVar[int](value=42, name='hi', logger='test')
        o.set(new=57)
        self.assertTrue(isinstance(o.get(), int))

        with self.assertRaises(expected_exception=PedanticTypeVarMismatchException):
            o.set(new=3.14)

    def test_stack(self):
        T = TypeVar('T')

        @pedantic_class
        class Stack(Generic[T]):
            def __init__(self) -> None:
                self.items: List[T] = []

            def push(self, item: T) -> None:
                self.items.append(item)

            def pop(self) -> T:
                return self.items.pop()

            def empty(self) -> bool:
                return not self.items

            def top(self) -> Optional[T]:
                if len(self.items) > 0:
                    return self.items[len(self.items) - 1]
                else:
                    return None

        my_stack = Stack[str]()
        get_type_vars = getattr(my_stack, TYPE_VAR_METHOD_NAME)
        self.assertEqual(get_type_vars(), {T: str, TYPE_VAR_SELF: Stack})
        with self.assertRaises(expected_exception=IndexError):
            my_stack.pop()
        self.assertIsNone(my_stack.top())
        self.assertIsNone(my_stack.top())
        # self.assertFalse(T in get_type_vars())
        my_stack.push(item='hi')
        self.assertTrue(T in get_type_vars())
        my_stack.push(item='world')
        self.assertTrue(T in get_type_vars())
        self.assertTrue(len(get_type_vars()), 1)
        self.assertEqual(my_stack.pop(), 'world')
        self.assertEqual(my_stack.pop(), 'hi')
        self.assertIsNone(my_stack.top())
        with self.assertRaises(expected_exception=PedanticTypeVarMismatchException):
            my_stack.push(item=42)

        my_other_stack = Stack[int]()
        get_type_vars = getattr(my_other_stack, TYPE_VAR_METHOD_NAME)
        self.assertEqual(get_type_vars(), {T: int, TYPE_VAR_SELF: Stack})
        with self.assertRaises(expected_exception=IndexError):
            my_other_stack.pop()
        self.assertIsNone(my_other_stack.top())
        self.assertIsNone(my_other_stack.top())
        my_other_stack.push(item=100)
        self.assertTrue(len(get_type_vars()), 1)
        my_other_stack.push(item=142)
        self.assertTrue(len(get_type_vars()), 1)
        self.assertEqual(my_other_stack.pop(), 142)
        self.assertEqual(my_other_stack.pop(), 100)
        self.assertIsNone(my_other_stack.top())
        with self.assertRaises(expected_exception=PedanticTypeVarMismatchException):
            my_other_stack.push(item='42')

    def test_generic_class_initialised_without_generics(self):
        T = TypeVar('T')

        @pedantic_class
        class MyClass(Generic[T]):
            def __init__(self, a: T) -> None:
                self.a = a

            def get_a(self) -> T:
                return self.a

            def set_a(self, val: T) -> None:
                self.a = val

        with self.assertRaises(expected_exception=PedanticTypeVarMismatchException):
            m = MyClass(a=42)

    def test_generic_class_initialised_without_generics_2(self):
        T = TypeVar('T')

        @pedantic_class
        class MyClass(Generic[T]):
            def __init__(self, a: T) -> None:
                self.a = a

            def get_a(self) -> T:
                return self.a

            def set_a(self, val: T) -> None:
                self.a = val

        MyClass(a=42)  # it is not recognized if it isn't assigned

    def test_generic_class_inheritance(self):
        class Parent:
            pass

        class Child1(Parent):
            pass

        class Child2(Parent):
            pass

        T = TypeVar('T')

        @pedantic_class
        class MyClass(Generic[T]):
            def __init__(self, a: T) -> None:
                self.a = a

            def get_a(self) -> T:
                return self.a

            def set_a(self, val: T) -> None:
                self.a = val

        m = MyClass[Parent](a=Child1())
        self.assertTrue(isinstance(m.get_a(), Child1))
        self.assertFalse(isinstance(m.get_a(), Child2))
        m.set_a(val=Child2())
        self.assertTrue(isinstance(m.get_a(), Child2))
        self.assertFalse(isinstance(m.get_a(), Child1))

    def test_merge_dicts(self):
        def create():
            T = TypeVar('T')

            @pedantic_class
            class MyClass(Generic[T]):
                def __init__(self, a: T) -> None:
                    self.a = a

                def get_a(self) -> T:
                    return self.a

                def set_a(self, val: T) -> None:
                    self.a = val
            return MyClass(a=42)
        a = create()
        with self.assertRaises(expected_exception=PedanticTypeVarMismatchException):
            a.set_a(val='hi')

    def test_recursion_depth_exceeded(self):
        T = TypeVar('T')

        @pedantic_class
        class Stack(Generic[T]):
            def __init__(self) -> None:
                self.items: List[T] = []

            def len(self) -> int:
                return len(self.items)

            def push(self, item: T) -> None:
                self.items.append(item)

            def pop(self) -> T:
                if len(self.items) > 0:
                    return self.items.pop()
                else:
                    raise ValueError()

            def empty(self) -> bool:
                return not self.items

            def top(self) -> Optional[T]:
                if len(self.items) > 0:
                    return self.items[len(self.items) - 1]
                else:
                    return None

            def __len__(self) -> int:
                return len(self.items)

        def create_stack():
            stack = Stack[int]()
            return stack

        with self.assertRaises(expected_exception=PedanticTypeVarMismatchException):
            stack: Stack[int] = Stack()
            self.assertTrue(stack.empty())
        with self.assertRaises(expected_exception=PedanticTypeVarMismatchException):
            stack = Stack()
            self.assertTrue(stack.empty())
        stack = create_stack()
        self.assertTrue(stack.empty())

    def test_generic_union(self):
        T = TypeVar('T')

        @pedantic_class
        class Stack(Generic[T]):
            def __init__(self) -> None:
                self.items: List[T] = []

            def len(self) -> int:
                return len(self.items)

            def push(self, item: T) -> None:
                self.items.append(item)

            def pop(self) -> T:
                if len(self.items) > 0:
                    return self.items.pop()
                else:
                    raise ValueError()

            def empty(self) -> bool:
                return not self.items

            def top(self) -> Optional[T]:
                if len(self.items) > 0:
                    return self.items[len(self.items) - 1]
                else:
                    return None

            def __len__(self) -> int:
                return len(self.items)

        s = Stack[Union[int, float, str]]()
        s.push(item=42)
        s.push(item='hello')
        s.push(item=3.1415)
        with self.assertRaises(expected_exception=PedanticTypeVarMismatchException):
            s.push(item=[1, 2])

    def test_inheritance(self):
        T = TypeVar('T')

        @pedantic_class
        class Stack(Generic[T]):
            def __init__(self) -> None:
                self.items: List[T] = []

            def len(self) -> int:
                return len(self.items)

            def push(self, item: T) -> None:
                self.items.append(item)

            def pop(self) -> T:
                if len(self.items) > 0:
                    return self.items.pop()
                else:
                    raise ValueError()

            def empty(self) -> bool:
                return not self.items

            def top(self) -> Optional[T]:
                if len(self.items) > 0:
                    return self.items[len(self.items) - 1]
                else:
                    return None

            def __len__(self) -> int:
                return len(self.items)

        @pedantic_class
        class Parent:
            pass

        @pedantic_class
        class Child1(Parent):
            pass

        @pedantic_class
        class Child2(Parent):
            pass

        parent_stack = Stack[Parent]()
        parent_stack.push(item=Child1())
        parent_stack.push(item=Child2())
        parent_stack.push(item=Parent())

        child_1_stack = Stack[Child1]()
        child_1_stack.push(item=Child1())
        with self.assertRaises(expected_exception=PedanticTypeVarMismatchException):
            child_1_stack.push(item=Child2())
        with self.assertRaises(expected_exception=PedanticTypeVarMismatchException):
            child_1_stack.push(item=Parent())

Ancestors

  • unittest.case.TestCase

Methods

def test_generic_class_inheritance(self)
Expand source code
def test_generic_class_inheritance(self):
    class Parent:
        pass

    class Child1(Parent):
        pass

    class Child2(Parent):
        pass

    T = TypeVar('T')

    @pedantic_class
    class MyClass(Generic[T]):
        def __init__(self, a: T) -> None:
            self.a = a

        def get_a(self) -> T:
            return self.a

        def set_a(self, val: T) -> None:
            self.a = val

    m = MyClass[Parent](a=Child1())
    self.assertTrue(isinstance(m.get_a(), Child1))
    self.assertFalse(isinstance(m.get_a(), Child2))
    m.set_a(val=Child2())
    self.assertTrue(isinstance(m.get_a(), Child2))
    self.assertFalse(isinstance(m.get_a(), Child1))
def test_generic_class_initialised_without_generics(self)
Expand source code
def test_generic_class_initialised_without_generics(self):
    T = TypeVar('T')

    @pedantic_class
    class MyClass(Generic[T]):
        def __init__(self, a: T) -> None:
            self.a = a

        def get_a(self) -> T:
            return self.a

        def set_a(self, val: T) -> None:
            self.a = val

    with self.assertRaises(expected_exception=PedanticTypeVarMismatchException):
        m = MyClass(a=42)
def test_generic_class_initialised_without_generics_2(self)
Expand source code
def test_generic_class_initialised_without_generics_2(self):
    T = TypeVar('T')

    @pedantic_class
    class MyClass(Generic[T]):
        def __init__(self, a: T) -> None:
            self.a = a

        def get_a(self) -> T:
            return self.a

        def set_a(self, val: T) -> None:
            self.a = val

    MyClass(a=42)  # it is not recognized if it isn't assigned
def test_generic_union(self)
Expand source code
def test_generic_union(self):
    T = TypeVar('T')

    @pedantic_class
    class Stack(Generic[T]):
        def __init__(self) -> None:
            self.items: List[T] = []

        def len(self) -> int:
            return len(self.items)

        def push(self, item: T) -> None:
            self.items.append(item)

        def pop(self) -> T:
            if len(self.items) > 0:
                return self.items.pop()
            else:
                raise ValueError()

        def empty(self) -> bool:
            return not self.items

        def top(self) -> Optional[T]:
            if len(self.items) > 0:
                return self.items[len(self.items) - 1]
            else:
                return None

        def __len__(self) -> int:
            return len(self.items)

    s = Stack[Union[int, float, str]]()
    s.push(item=42)
    s.push(item='hello')
    s.push(item=3.1415)
    with self.assertRaises(expected_exception=PedanticTypeVarMismatchException):
        s.push(item=[1, 2])
def test_inheritance(self)
Expand source code
def test_inheritance(self):
    T = TypeVar('T')

    @pedantic_class
    class Stack(Generic[T]):
        def __init__(self) -> None:
            self.items: List[T] = []

        def len(self) -> int:
            return len(self.items)

        def push(self, item: T) -> None:
            self.items.append(item)

        def pop(self) -> T:
            if len(self.items) > 0:
                return self.items.pop()
            else:
                raise ValueError()

        def empty(self) -> bool:
            return not self.items

        def top(self) -> Optional[T]:
            if len(self.items) > 0:
                return self.items[len(self.items) - 1]
            else:
                return None

        def __len__(self) -> int:
            return len(self.items)

    @pedantic_class
    class Parent:
        pass

    @pedantic_class
    class Child1(Parent):
        pass

    @pedantic_class
    class Child2(Parent):
        pass

    parent_stack = Stack[Parent]()
    parent_stack.push(item=Child1())
    parent_stack.push(item=Child2())
    parent_stack.push(item=Parent())

    child_1_stack = Stack[Child1]()
    child_1_stack.push(item=Child1())
    with self.assertRaises(expected_exception=PedanticTypeVarMismatchException):
        child_1_stack.push(item=Child2())
    with self.assertRaises(expected_exception=PedanticTypeVarMismatchException):
        child_1_stack.push(item=Parent())
def test_merge_dicts(self)
Expand source code
def test_merge_dicts(self):
    def create():
        T = TypeVar('T')

        @pedantic_class
        class MyClass(Generic[T]):
            def __init__(self, a: T) -> None:
                self.a = a

            def get_a(self) -> T:
                return self.a

            def set_a(self, val: T) -> None:
                self.a = val
        return MyClass(a=42)
    a = create()
    with self.assertRaises(expected_exception=PedanticTypeVarMismatchException):
        a.set_a(val='hi')
def test_pedantic_generic_class(self)
Expand source code
def test_pedantic_generic_class(self):
    T = TypeVar('T')

    @pedantic_class
    class LoggedVar(Generic[T]):
        def __init__(self, value: T, name: str, logger: Any) -> None:
            self.name = name
            self.logger = logger
            self.value = value

        def set(self, new: T) -> None:
            self.log(message='Set ' + repr(self.value))
            self.value = new

        def get(self) -> T:
            self.log(message='Get ' + repr(self.value))
            return self.value

        def log(self, message: str) -> None:
            self.logger = self.name + message

    o = LoggedVar[int](value=42, name='hi', logger='test')
    o.set(new=57)
    self.assertTrue(isinstance(o.get(), int))

    with self.assertRaises(expected_exception=PedanticTypeVarMismatchException):
        o.set(new=3.14)
def test_recursion_depth_exceeded(self)
Expand source code
def test_recursion_depth_exceeded(self):
    T = TypeVar('T')

    @pedantic_class
    class Stack(Generic[T]):
        def __init__(self) -> None:
            self.items: List[T] = []

        def len(self) -> int:
            return len(self.items)

        def push(self, item: T) -> None:
            self.items.append(item)

        def pop(self) -> T:
            if len(self.items) > 0:
                return self.items.pop()
            else:
                raise ValueError()

        def empty(self) -> bool:
            return not self.items

        def top(self) -> Optional[T]:
            if len(self.items) > 0:
                return self.items[len(self.items) - 1]
            else:
                return None

        def __len__(self) -> int:
            return len(self.items)

    def create_stack():
        stack = Stack[int]()
        return stack

    with self.assertRaises(expected_exception=PedanticTypeVarMismatchException):
        stack: Stack[int] = Stack()
        self.assertTrue(stack.empty())
    with self.assertRaises(expected_exception=PedanticTypeVarMismatchException):
        stack = Stack()
        self.assertTrue(stack.empty())
    stack = create_stack()
    self.assertTrue(stack.empty())
def test_stack(self)
Expand source code
def test_stack(self):
    T = TypeVar('T')

    @pedantic_class
    class Stack(Generic[T]):
        def __init__(self) -> None:
            self.items: List[T] = []

        def push(self, item: T) -> None:
            self.items.append(item)

        def pop(self) -> T:
            return self.items.pop()

        def empty(self) -> bool:
            return not self.items

        def top(self) -> Optional[T]:
            if len(self.items) > 0:
                return self.items[len(self.items) - 1]
            else:
                return None

    my_stack = Stack[str]()
    get_type_vars = getattr(my_stack, TYPE_VAR_METHOD_NAME)
    self.assertEqual(get_type_vars(), {T: str, TYPE_VAR_SELF: Stack})
    with self.assertRaises(expected_exception=IndexError):
        my_stack.pop()
    self.assertIsNone(my_stack.top())
    self.assertIsNone(my_stack.top())
    # self.assertFalse(T in get_type_vars())
    my_stack.push(item='hi')
    self.assertTrue(T in get_type_vars())
    my_stack.push(item='world')
    self.assertTrue(T in get_type_vars())
    self.assertTrue(len(get_type_vars()), 1)
    self.assertEqual(my_stack.pop(), 'world')
    self.assertEqual(my_stack.pop(), 'hi')
    self.assertIsNone(my_stack.top())
    with self.assertRaises(expected_exception=PedanticTypeVarMismatchException):
        my_stack.push(item=42)

    my_other_stack = Stack[int]()
    get_type_vars = getattr(my_other_stack, TYPE_VAR_METHOD_NAME)
    self.assertEqual(get_type_vars(), {T: int, TYPE_VAR_SELF: Stack})
    with self.assertRaises(expected_exception=IndexError):
        my_other_stack.pop()
    self.assertIsNone(my_other_stack.top())
    self.assertIsNone(my_other_stack.top())
    my_other_stack.push(item=100)
    self.assertTrue(len(get_type_vars()), 1)
    my_other_stack.push(item=142)
    self.assertTrue(len(get_type_vars()), 1)
    self.assertEqual(my_other_stack.pop(), 142)
    self.assertEqual(my_other_stack.pop(), 100)
    self.assertIsNone(my_other_stack.top())
    with self.assertRaises(expected_exception=PedanticTypeVarMismatchException):
        my_other_stack.push(item='42')