Skip to content

Commit

Permalink
Use @OVERRIDES much more within the ranged dict code.
Browse files Browse the repository at this point in the history
Required some extension to @OVERRIDES to make that work.
  • Loading branch information
dkfellows committed Mar 2, 2018
1 parent cf2f430 commit 650de9a
Show file tree
Hide file tree
Showing 11 changed files with 176 additions and 196 deletions.
22 changes: 14 additions & 8 deletions spinn_utilities/overrides.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,15 @@ class overrides(object):
# True if the doc string is to be extended, False to set if not set
"_extend_doc",
# Any additional arguments required by the subclass method
"_additional_arguments"
"_additional_arguments",
# True if the subclass method may have additional defaults
"_extend_defaults"
]

def __init__(
self, super_class_method, extend_doc=True,
additional_arguments=None):
additional_arguments=None, extend_defaults=False):
"""
:param super_class_method: The method to override in the superclass
:param extend_doc:\
True the method doc string should be appended to the super-method\
Expand All @@ -30,21 +31,26 @@ def __init__(
:param additional_arguments:\
Additional arguments taken by the subclass method over the\
superclass method, e.g., that are to be injected
:param extend_defaults: \
Whether the subclass may specify extra defaults for the parameters
"""
self._superclass_method = super_class_method
self._extend_doc = extend_doc
self._additional_arguments = additional_arguments
self._extend_defaults = extend_defaults
if additional_arguments is None:
self._additional_arguments = {}
if isinstance(super_class_method, property):
self._superclass_method = super_class_method.fget

@staticmethod
def __match_defaults(default_args, super_defaults):
def __match_defaults(default_args, super_defaults, extend_ok):
if default_args is None:
return super_defaults is None
elif super_defaults is None:
return False
return extend_ok
if extend_ok:
return len(default_args) >= len(super_defaults)
return len(default_args) == len(super_defaults)

def __verify_method_arguments(self, method):
Expand All @@ -68,7 +74,8 @@ def __verify_method_arguments(self, method):
if arg != super_arg:
raise AttributeError(
"Missing argument {}".format(super_arg))
if not self.__match_defaults(default_args, super_args.defaults):
if not self.__match_defaults(
default_args, super_args.defaults, self._extend_defaults):
raise AttributeError(
"Default arguments don't match super class method")

Expand Down Expand Up @@ -99,6 +106,5 @@ def __call__(self, method):
elif (self._extend_doc and
self._superclass_method.__doc__ is not None):
method.__doc__ = (
self._superclass_method.__doc__ +
method.__doc__)
self._superclass_method.__doc__ + method.__doc__)
return method
7 changes: 0 additions & 7 deletions spinn_utilities/ranged/abstract_dict.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,13 @@ def get_value(self, key):
If even one of the keys has multiple values set.\
But not if other keys not asked for have multiple values
"""
pass

@abstractmethod
def keys(self):
""" Returns the keys in the dictionary
:return: keys in the dict
"""
pass

@abstractmethod
def set_value(self, key, value):
Expand All @@ -54,7 +52,6 @@ def set_value(self, key, value):
:param value: any object
:raise KeyError: If a new key is being used.
"""
pass

@abstractmethod
def ids(self):
Expand All @@ -71,7 +68,6 @@ def ids(self):
:return: list of IDs
:rtype: list(int)
"""
pass

@abstractmethod
def iter_all_values(self, key, update_save=False):
Expand All @@ -90,7 +86,6 @@ def iter_all_values(self, key, update_save=False):
If key is iterable (list, tuple, set, etc) of str (or None)\
yields dictionary objects
"""
pass

def get_ranges(self, key=None):
""" Lists the ranges(s) for all IDs covered by this view
Expand Down Expand Up @@ -134,7 +129,6 @@ def iter_ranges(self, key=None):
If key is iterable (list, tuple, set, etc) of str (or None)\
value is a dictionary object
"""
pass

@abstractmethod
def get_default(self, key):
Expand All @@ -150,7 +144,6 @@ def get_default(self, key):
:type key: str
:return: default for this key.
"""
pass

def items(self):
""" Returns a list of (key, value) tuples
Expand Down
47 changes: 24 additions & 23 deletions spinn_utilities/ranged/abstract_list.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import numbers
from spinn_utilities.overrides import overrides
from spinn_utilities.ranged.multiple_values_exception \
import MultipleValuesException
from spinn_utilities.ranged.abstract_sized import AbstractSized
Expand Down Expand Up @@ -34,8 +35,7 @@ class AbstractList(AbstractSized):
"_key"]

def __init__(self, size, key=None):
"""
Constructor for a ranged list.
""" Constructor for a ranged list.
:param size: Fixed length of the list
:param key: The dict key this list covers.\
Expand All @@ -56,7 +56,6 @@ def range_based(self):
:return: True if and only if Ranged based calls are recommended.
"""
pass

def __len__(self):
""" Size of the list, irrespective of actual values
Expand Down Expand Up @@ -101,7 +100,6 @@ def get_value_by_id(self, id): # @ReservedAssignment
:type id: int
:return: The value of that element
"""
pass

@abstractmethod
def get_value_by_slice(self, slice_start, slice_stop):
Expand All @@ -115,7 +113,6 @@ def get_value_by_slice(self, slice_start, slice_stop):
value. \
Not thrown if elements outside of the slice have a different value
"""
pass

def __getslice__(self, start, stop):
return list(self.iter_by_slice(start, stop))
Expand All @@ -133,7 +130,6 @@ def get_value_by_ids(self, ids):
Not thrown if elements outside of the IDs have a different value,\
even if these elements are between the ones pointed to by IDs
"""
pass

def __getitem__(self, key):
""" Supports the list[x] to return an element or slice of the list
Expand Down Expand Up @@ -292,15 +288,14 @@ def iter_ranges_by_id(self, id): # @ReservedAssignment

@abstractmethod
def iter_ranges_by_slice(self, slice_start, slice_stop):
"""
Fast NOT update safe iterator of the ranges covered by this slice
""" Fast NOT update safe iterator of the ranges covered by this slice
Note: The start and stop of the range will be reduced to just the\
ids inside the slice
.. note::
The start and stop of the range will be reduced to just the\
IDs inside the slice
:return: yields each range one by one
"""
pass
:return: yields each range one by one
"""

def iter_ranges_by_ids(self, ids):
""" Fast NOT update safe iterator of the ranges covered by these IDs
Expand Down Expand Up @@ -344,7 +339,6 @@ def get_default(self):
:return: Default value
"""
pass

def __add__(self, other):
""" Support for new_list = list1 + list2
Expand Down Expand Up @@ -453,8 +447,7 @@ def __floordiv__(self, other):
"RangedLists and numerical Values")

def apply_operation(self, operation):
"""
Applies a function on the list to create a new one
""" Applies a function on the list to create a new one
The values of the new list are created on the fly so any changes to\
the original lists are reflected.
Expand Down Expand Up @@ -489,26 +482,33 @@ def __init__(self, a_list, operation, key=None):
self._a_list = a_list
self._operation = operation

@overrides(AbstractList.range_based)
def range_based(self):
return self._a_list.range_based()

@overrides(AbstractList.get_value_by_id)
def get_value_by_id(self, id): # @ReservedAssignment
return self._operation(self._a_list.get_value_by_id(id))

@overrides(AbstractList.get_value_by_slice)
def get_value_by_slice(self, slice_start, slice_stop):
return self._operation(self._a_list.get_value_by_slice(
slice_start, slice_stop))

@overrides(AbstractList.get_value_by_ids)
def get_value_by_ids(self, ids):
return self._operation(self._a_list.get_value_by_ids(ids))

@overrides(AbstractList.iter_ranges)
def iter_ranges(self):
for (start, stop, value) in self._a_list.iter_ranges():
yield (start, stop, self._operation(value))

@overrides(AbstractList.get_default)
def get_default(self):
self._operation(self._a_list.get_default())

@overrides(AbstractList.iter_ranges_by_slice)
def iter_ranges_by_slice(self, slice_start, slice_stop):
for (start, stop, value) in \
self._a_list.iter_ranges_by_slice(slice_start, slice_stop):
Expand Down Expand Up @@ -540,31 +540,29 @@ def __init__(self, left, right, operation, key=None):
self._right = right
self._operation = operation

@overrides(AbstractList.range_based)
def range_based(self):
return self._left.range_based() and self._right.range_based()

@overrides(AbstractList.get_value_by_id)
def get_value_by_id(self, id): # @ReservedAssignment
return self._operation(
self._left.get_value_by_id(id), self._right.get_value_by_id(id))

@overrides(AbstractList.get_value_by_slice)
def get_value_by_slice(self, slice_start, slice_stop):
return self._operation(
self._left.get_value_by_slice(slice_start, slice_stop),
self._right.get_value_by_slice(slice_start, slice_stop))

@overrides(AbstractList.get_value_by_ids)
def get_value_by_ids(self, ids):
return self._operation(
self._left.get_value_by_ids(ids),
self._right.get_value_by_ids(ids))

@overrides(AbstractList.iter_by_slice)
def iter_by_slice(self, slice_start, slice_stop):
""" Fast NOT update safe iterator of all elements in the slice
.. note::
Duplicate/Repeated elements are yielded for each ID
:return: yields each element one by one
"""
slice_start, slice_stop = self._check_slice_in_range(
slice_start, slice_stop)
if self._left.range_based():
Expand Down Expand Up @@ -603,11 +601,13 @@ def iter_by_slice(self, slice_start, slice_stop):
while True:
yield self._operation(left_iter.next(), right_iter.next())

@overrides(AbstractList.iter_ranges)
def iter_ranges(self):
left_iter = self._left.iter_ranges()
right_iter = self._right.iter_ranges()
return self._merge_ranges(left_iter, right_iter)

@overrides(AbstractList.iter_ranges_by_slice)
def iter_ranges_by_slice(self, slice_start, slice_stop):
left_iter = self._left.iter_ranges_by_slice(slice_start, slice_stop)
right_iter = self._right.iter_ranges_by_slice(slice_start, slice_stop)
Expand All @@ -628,5 +628,6 @@ def _merge_ranges(self, left_iter, right_iter):
(left_start, left_stop, left_value) = left_iter.next()
(right_start, right_stop, right_value) = right_iter.next()

@overrides(AbstractList.get_default)
def get_default(self):
self._operation(self._left.get_default(), self._right.get_default())
20 changes: 12 additions & 8 deletions spinn_utilities/ranged/abstract_sized.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@


class AbstractSized(object):
"""
Base class for slice and id checking against size.
""" Base class for slice and ID checking against size.
"""

__slots__ = [
Expand All @@ -24,14 +23,19 @@ def __len__(self):
"""
return self._size

@staticmethod
def _is_id_type(id): # @ReservedAssignment
""" Check if the given ID has a type acceptable for IDs. """
return isinstance(id, (int, long))

def _check_id_in_range(self, id): # @ReservedAssignment
if id < 0:
if isinstance(id, (int, long)):
if self._is_id_type(id):
raise IndexError(
"The index {} is out of range.".format(id))
raise TypeError("Invalid argument type {}.".format(type(id)))
if id >= self._size:
if isinstance(id, (int, long)):
if self._is_id_type(id):
raise IndexError(
"The index {0!d} is out of range.".format(id))
raise TypeError("Invalid argument type {}.".format(type(id)))
Expand All @@ -42,7 +46,7 @@ def _check_slice_in_range(self, slice_start, slice_stop):
elif slice_start < 0:
slice_start = self._size + slice_start
if slice_start < 0:
if isinstance(slice_start, (int, long)):
if self._is_id_type(slice_start):
raise IndexError(
"The range_start {} is out of range.".format(
slice_start))
Expand All @@ -53,17 +57,17 @@ def _check_slice_in_range(self, slice_start, slice_stop):
elif slice_stop < 0:
slice_stop = self._size + slice_stop
if slice_start > slice_stop:
if not isinstance(slice_start, (int, long)):
if not self._is_id_type(slice_start):
raise TypeError("Invalid argument type {}.".format(
type(slice_start)))
if not isinstance(slice_stop, (int, long)):
if not self._is_id_type(slice_stop):
raise TypeError("Invalid argument type {}.".format(
type(slice_start)))
raise IndexError(
"The range_start {} is after the range stop {}.".format(
slice_start, slice_stop))
if slice_stop > len(self):
if isinstance(slice_stop, (int, long)):
if self._is_id_type(slice_stop):
raise IndexError("The range_stop {} is out of range.".format(
slice_stop))
raise TypeError("Invalid argument type {}.".format(
Expand Down

0 comments on commit 650de9a

Please sign in to comment.