Skip to content

Add type hints to type-specific lists #28

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Nov 14, 2022
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 46 additions & 20 deletions pyxx/arrays/classes/typedlist.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,22 @@
type.
"""

import collections.abc
import itertools
from typing import Any
import sys
from typing import Any, overload, Type, TypeVar

from pyxx.arrays.functions.size import max_list_item_len

if sys.version_info < (3, 9):
from typing import Iterable, MutableSequence
else:
from collections.abc import Iterable, MutableSequence

class TypedList(collections.abc.MutableSequence):

T = TypeVar('T')


class TypedList(MutableSequence[T]):
"""A list whose elements must be of a specific type

This class defines a custom version of Python's :py:class:`list` object.
Expand All @@ -21,8 +29,9 @@ class TypedList(collections.abc.MutableSequence):
can be used to manage data in a :py:class:`TypedList` instance.
"""

def __init__(self, *values: Any, list_type: type,
print_multiline: bool = True, multiline_padding: int = 1):
def __init__(self, *values: T, list_type: Type[T],
print_multiline: bool = True,
multiline_padding: int = 1) -> None:
"""Creates a :py:class:`TypedList` list instance

Creates an instance of the :py:class:`TypedList` object. This list
Expand All @@ -31,9 +40,9 @@ def __init__(self, *values: Any, list_type: type,

Parameters
----------
*values : Any
*values : T
Items to add to the list when initializing the list
list_type : type
list_type : Type[T]
The required type of all items in the list
print_multiline : bool, optional
Whether to return a printable string representation of the list in
Expand Down Expand Up @@ -89,15 +98,23 @@ def __eq__(self, value: object) -> bool:

return True

@overload
def __getitem__(self, index: int) -> T:
...

@overload
def __getitem__(self, index: slice) -> MutableSequence[T]:
...

def __getitem__(self, index):
"""Retrieves an item at a specified index from the list"""
return self._data[index]

def __len__(self):
def __len__(self) -> int:
"""Returns the number of items in the list"""
return len(self._data)

def __repr__(self):
def __repr__(self) -> str:
"""Create a string representation illustrating the list and its
contents"""
if self.print_multiline:
Expand All @@ -120,7 +137,15 @@ def __repr__(self):

return str(self._data)

def __setitem__(self, index, value) -> None:
@overload
def __setitem__(self, index: int, value: T) -> None:
...

@overload
def __setitem__(self, index: slice, value: Iterable[T]) -> None:
...

def __setitem__(self, index, value):
"""Sets the value of items at one or more indices in the list

Like the built-in :py:class:`list` object, this method can either set
Expand All @@ -131,7 +156,7 @@ def __setitem__(self, index, value) -> None:
if isinstance(index, int):
self.__check_item_type(value)
elif isinstance(index, slice) \
and isinstance(value, collections.abc.Iterable):
and isinstance(value, Iterable):
for val in value:
self.__check_item_type(val)
else:
Expand All @@ -143,22 +168,22 @@ def __setitem__(self, index, value) -> None:
# Store items in list
self._data[index] = value

def __str__(self):
def __str__(self) -> str:
"""Returns a string representation of the list"""
return self.__repr__()

def insert(self, index: int, value: Any):
def insert(self, index: int, value: T):
"""Inserts a value at a given index in the list"""
self.__check_item_type(value)
self._data.insert(index, value)

@property
def list_type(self):
def list_type(self) -> Type[T]:
"""The required type of all items in the list"""
return self._list_type

@property
def print_multiline(self):
def print_multiline(self) -> bool:
"""Whether to display the object's string representation in
multiline format"""
return self._print_multiline
Expand All @@ -172,7 +197,7 @@ def print_multiline(self, print_multiline: bool):
self._print_multiline = print_multiline

@property
def multiline_padding(self):
def multiline_padding(self) -> int:
"""The number of spaces on either side of the list of items in
the list when displaying the list's string representation in
multiline format"""
Expand All @@ -186,7 +211,7 @@ def multiline_padding(self, multiline_padding: int):
self._multiline_padding = multiline_padding


class TypedListWithID(TypedList):
class TypedListWithID(TypedList[T]):
"""A list whose elements must be of a specific type, where each class
instance is given a unique identifier

Expand All @@ -207,8 +232,9 @@ class TypedListWithID(TypedList):
# class instance
_id = itertools.count(0)

def __init__(self, *values, list_type: type,
print_multiline: bool = True, multiline_padding: int = 1):
def __init__(self, *values: T, list_type: Type[T],
print_multiline: bool = True,
multiline_padding: int = 1) -> None:
super().__init__(
*values,
list_type=list_type,
Expand All @@ -220,6 +246,6 @@ def __init__(self, *values, list_type: type,
self.__id = next(self._id)

@property
def id(self):
def id(self) -> int:
"""A unique class instance identification number"""
return self.__id