From 9c413c7ed8e6f5a2d0a6bef9fe3dd629fef86112 Mon Sep 17 00:00:00 2001 From: "uri.akavia" Date: Tue, 26 Jul 2022 18:30:24 -0400 Subject: [PATCH] type hint changes in dictlist.py --- release-notes/next-release.md | 1 + src/cobra/core/dictlist.py | 54 +++++++++++++++++++---------------- 2 files changed, 30 insertions(+), 25 deletions(-) diff --git a/release-notes/next-release.md b/release-notes/next-release.md index 532c6b037..55206aa62 100644 --- a/release-notes/next-release.md +++ b/release-notes/next-release.md @@ -13,6 +13,7 @@ of SBO:0000633 (see https://sourceforge.net/p/sbo/term-request/113/) ## Other * Resolve `flake8` issues and add missing type annotations and docstrings in `src/cobra/io` and `tests/test_io` (#1212). +* Change type hints in dictlist.py to include Object and derivate classes, which reduces type mismatch warnings. ## Deprecated features diff --git a/src/cobra/core/dictlist.py b/src/cobra/core/dictlist.py index b4a41f0e2..a460547e2 100644 --- a/src/cobra/core/dictlist.py +++ b/src/cobra/core/dictlist.py @@ -12,12 +12,16 @@ Pattern, Tuple, Type, + TypeVar, Union, ) from numpy import bool_ -from cobra.core.object import Object +from .object import Object + + +Object_T = TypeVar("Object_T", bound=Object) class DictList(list): @@ -50,12 +54,12 @@ def __init__(self, *args): self.extend(other) # noinspection PyShadowingBuiltins - def has_id(self, id: Union[Object, str]) -> bool: + def has_id(self, id: Union[Object_T, str]) -> bool: """Check if id is in DictList.""" return id in self._dict # noinspection PyShadowingBuiltins - def _check(self, id: Union[Object, str]) -> None: + def _check(self, id: Union[Object_T, str]) -> None: """Make sure duplicate id's are not added. This function is called before adding in elements. @@ -69,7 +73,7 @@ def _generate_index(self) -> None: self._dict = {v.id: k for k, v in enumerate(self)} # noinspection PyShadowingBuiltins - def get_by_id(self, id: Union[Object, str]) -> Object: + def get_by_id(self, id: Union[Object_T, str]) -> Object_T: """Return the element with a matching id.""" return list.__getitem__(self, self._dict[id]) @@ -77,7 +81,7 @@ def list_attr(self, attribute: str) -> list: """Return a list of the given attribute for every object.""" return [getattr(i, attribute) for i in self] - def get_by_any(self, iterable: List[Union[str, Object, int]]) -> list: + def get_by_any(self, iterable: List[Union[str, Object_T, int]]) -> list: """Get a list of members using several different ways of indexing. Parameters @@ -168,21 +172,21 @@ def select_attribute(x: Optional[Any]) -> Any: results._extend_nocheck(matches) return results - def _replace_on_id(self, new_object: Object) -> None: + def _replace_on_id(self, new_object: Object_T) -> None: """Replace an object by another with the same id.""" the_id = new_object.id the_index = self._dict[the_id] list.__setitem__(self, the_index, new_object) # overriding default list functions with new ones - def append(self, entity: Object) -> None: + def append(self, entity: Object_T) -> None: """Append object to end.""" the_id = entity.id self._check(the_id) self._dict[the_id] = len(self) list.append(self, entity) - def union(self, iterable: Iterable[Object]) -> None: + def union(self, iterable: Iterable[Object_T]) -> None: """Add elements with id's not already in the model.""" _dict = self._dict append = self.append @@ -190,7 +194,7 @@ def union(self, iterable: Iterable[Object]) -> None: if i.id not in _dict: append(i) - def extend(self, iterable: Iterable[Object]) -> None: + def extend(self, iterable: Iterable[Object_T]) -> None: """Extend list by appending elements from the iterable. Sometimes during initialization from an older pickle, _dict @@ -223,7 +227,7 @@ def extend(self, iterable: Iterable[Object]) -> None: f"Is it present twice?" ) - def _extend_nocheck(self, iterable: Iterable[Object]) -> None: + def _extend_nocheck(self, iterable: Iterable[Object_T]) -> None: """Extend without checking for uniqueness. This function should only be used internally by DictList when it @@ -245,7 +249,7 @@ def _extend_nocheck(self, iterable: Iterable[Object]) -> None: for i, obj in enumerate(islice(self, current_length, None), current_length): _dict[obj.id] = i - def __sub__(self, other: Iterable[Object]) -> "DictList": + def __sub__(self, other: Iterable[Object_T]) -> "DictList": """Remove a value or values, and returns the new DictList. x.__sub__(y) <==> x - y @@ -265,7 +269,7 @@ def __sub__(self, other: Iterable[Object]) -> "DictList": total.remove(item) return total - def __isub__(self, other: Iterable[Object]) -> "DictList": + def __isub__(self, other: Iterable[Object_T]) -> "DictList": """Remove a value or values in place. x.__sub__(y) <==> x -= y @@ -279,7 +283,7 @@ def __isub__(self, other: Iterable[Object]) -> "DictList": self.remove(item) return self - def __add__(self, other: Iterable[Object]) -> "DictList": + def __add__(self, other: Iterable[Object_T]) -> "DictList": """Add item while returning a new DictList. x.__add__(y) <==> x + y @@ -295,7 +299,7 @@ def __add__(self, other: Iterable[Object]) -> "DictList": total.extend(other) return total - def __iadd__(self, other: Iterable[Object]) -> "DictList": + def __iadd__(self, other: Iterable[Object_T]) -> "DictList": """Add item while returning the same DictList. x.__iadd__(y) <==> x += y @@ -337,7 +341,7 @@ def __setstate__(self, state: dict) -> None: self._generate_index() # noinspection PyShadowingBuiltins - def index(self, id: Union[str, Object], *args) -> int: + def index(self, id: Union[str, Object_T], *args) -> int: """Determine the position in the list. Parameters @@ -361,7 +365,7 @@ def index(self, id: Union[str, Object], *args) -> int: except KeyError: raise ValueError(f"{str(id)} not found") - def __contains__(self, entity: Union[str, Object]) -> bool: + def __contains__(self, entity: Union[str, Object_T]) -> bool: """Ask if the DictList contain an entity. DictList.__contains__(entity) <==> entity in DictList @@ -385,7 +389,7 @@ def __copy__(self) -> "DictList": the_copy._dict = self._dict.copy() return the_copy - def insert(self, index: int, entity: Object) -> None: + def insert(self, index: int, entity: Object_T) -> None: """Insert entity before index.""" self._check(entity.id) list.insert(self, index, entity) @@ -396,7 +400,7 @@ def insert(self, index: int, entity: Object) -> None: _dict[i] = j + 1 _dict[entity.id] = index - def pop(self, *args) -> Object: + def pop(self, *args) -> Object_T: """Remove and return item at index (default last).""" value = list.pop(self, *args) index = self._dict.pop(value.id) @@ -410,11 +414,11 @@ def pop(self, *args) -> Object: _dict[i] = j - 1 return value - def add(self, x: Object) -> None: + def add(self, x: Object_T) -> None: """Opposite of `remove`. Mirrors set.add.""" self.extend([x]) - def remove(self, x: Union[str, Object]) -> None: + def remove(self, x: Union[str, Object_T]) -> None: """.. warning :: Internal use only. Each item is unique in the list which allows this @@ -446,8 +450,8 @@ def key(i): self._generate_index() def __getitem__( - self, i: Union[int, slice, Iterable, Object, "DictList"] - ) -> Union["DictList", Object]: + self, i: Union[int, slice, Iterable, Object_T, "DictList"] + ) -> Union["DictList", Object_T]: """Get item from DictList.""" if isinstance(i, int): return list.__getitem__(self, i) @@ -466,7 +470,7 @@ def __getitem__( else: return list.__getitem__(self, i) - def __setitem__(self, i: Union[slice, int], y: Union[list, Object]) -> None: + def __setitem__(self, i: Union[slice, int], y: Union[list, Object_T]) -> None: """Set an item via index or slice. Parameters @@ -495,7 +499,7 @@ def __setitem__(self, i: Union[slice, int], y: Union[list, Object]) -> None: list.__setitem__(self, i, y) self._dict[the_id] = i - def __delitem__(self, index: int) -> None: + def __delitem__(self, index: Union[int, slice]) -> None: """Remove item from DictList.""" removed = self[index] list.__delitem__(self, index) @@ -512,7 +516,7 @@ def __getslice__(self, i: int, j: int) -> "DictList": """Get a slice from it to j of DictList.""" return self.__getitem__(slice(i, j)) - def __setslice__(self, i: int, j: int, y: Union[list, Object]) -> None: + def __setslice__(self, i: int, j: int, y: Union[list, Object_T]) -> None: """Set slice, where y is an iterable.""" self.__setitem__(slice(i, j), y)