[Python-checkins] r54679 - sandbox/trunk/abc/abc.py sandbox/trunk/abc/test_abc.py
guido.van.rossum
python-checkins at python.org
Wed Apr 4 02:17:13 CEST 2007
Author: guido.van.rossum
Date: Wed Apr 4 02:17:12 2007
New Revision: 54679
Modified:
sandbox/trunk/abc/abc.py
sandbox/trunk/abc/test_abc.py
Log:
Move the index and slice helpers to global functions.
Add proper slice support for AdaptToSequence.
Modified: sandbox/trunk/abc/abc.py
==============================================================================
--- sandbox/trunk/abc/abc.py (original)
+++ sandbox/trunk/abc/abc.py Wed Apr 4 02:17:12 2007
@@ -406,6 +406,56 @@
### SEQUENCES ###
+def _index(i):
+ # Internal helper to raise TypeError for non-integer(-castable) values
+ if not isinstance(i, int):
+ if not hasattr(i, "__index__"):
+ raise TypeError
+ i = i.__index__()
+ if not isinstance(i, int):
+ raise TypeError
+ return i
+
+
+def _slice(slc, size):
+ # Internal helper to normalize a slice into start, stop, step
+ # ints; arguments are a slice object and the length of the
+ # sequence.
+ # XXX A problem this shares with Python 2: a[n-1:-1:-1] (where n
+ # is len(a)) returns an empty slice because the stop value is
+ # normalized to n-1.
+ start, stop, step = slc.start, slc.stop, slc.step
+
+ if start is not None:
+ start = _index(start)
+ if start < 0:
+ start += size
+ if stop is not None:
+ stop = _index(stop)
+ if stop < 0:
+ stop += size
+ if step is not None:
+ step = _index(step)
+
+ if step is None:
+ step = 1
+ if step == 0:
+ raise ValueError
+ if step < 0:
+ if start is None:
+ start = size - 1
+ if stop is None:
+ stop = -1
+ else:
+ if start is None:
+ start = 0
+ if stop is None:
+ stop = size
+
+ return start, stop, step
+
+
+
class Sequence(Sizeable, Iterable):
"""A minimal sequence.
@@ -418,44 +468,14 @@
giving an iterable providing the elements.
"""
- def __index(self, i):
- # Internal helper to raise TypeError for non-integer(-castable) values
- if not isinstance(i, int):
- if not hasattr(i, "__index__"):
- raise TypeError
- i = i.__index__()
- if not isinstance(i, int):
- raise TypeError
- return i
-
@abstractmethod
def __getitem__(self, index):
if isinstance(index, slice):
- return self.__getslice(index)
- index = self.__index(index)
- raise IndexError
-
- def __getslice(self, slc):
- # XXX Would be nice to make this generally available?
- start, stop, step = slc.start, slc.stop, slc.step
- for index in start, stop, step:
- if index is not None:
- self.__index(index)
- if step is None:
- step = 1
- if step == 0:
- raise ValueError
- if step < 0:
- if start is None:
- start = len(self) - 1
- if stop is None:
- stop = -1
+ start, stop, step = _slice(index, len(self))
+ return self.__class__(self[i] for i in range(start, stop, step))
else:
- if start is None:
- start = 0
- if stop is None:
- stop = len(self)
- return self.__class__(self[i] for i in range(start, stop, step))
+ index = _index(index)
+ raise IndexError
@abstractmethod
def __len__(self):
@@ -491,7 +511,7 @@
# XXX Looks like we need an ABC to indicate integer-ness...
if not isinstance(repeat, int) and not hasattr(repeat, "__index__"):
return NotImplemented
- repeat = self.__index(repeat)
+ repeat = _index(repeat)
return self.__class__(elem for i in range(repeat) for elem in self)
def __eq__(self, other):
@@ -555,12 +575,17 @@
class AdaptToSequence(Sequence):
def __new__(cls, adaptee):
- self = Sequence.__new__(cls)
- self.adaptee = adaptee
- return self
+ if not hasattr(adaptee, "__getitem__"):
+ # Hack so that the self.__class__(<generator>) calls above work
+ adaptee = list(adaptee)
+ obj = Sequence.__new__(cls)
+ obj.adaptee = adaptee
+ return obj
def __getitem__(self, index):
- return self.adaptee[index]
+ if isinstance(index, slice):
+ return super(AdaptToSequence, self).__getitem__(index)
+ return self.adaptee[_index(index)]
def __len__(self):
return len(self.adaptee)
Modified: sandbox/trunk/abc/test_abc.py
==============================================================================
--- sandbox/trunk/abc/test_abc.py (original)
+++ sandbox/trunk/abc/test_abc.py Wed Apr 4 02:17:12 2007
@@ -46,7 +46,9 @@
self.assertEqual(a[-1], 9)
self.assertEqual(list(a), range(10))
#self.assertEqual(a, range(10))
- # Slicing isn't implemented correctly
+ b = a[1:-1]
+ self.assertEqual(b.__class__, abc.AdaptToSequence)
+ self.assertEqual(list(b), range(1, 9))
def test_adapt_to_mapping(self):
a = abc.AdaptToMapping({1: 10, 2: 20})
More information about the Python-checkins
mailing list