Skip to content

Commit

Permalink
Add index_to_slice
Browse files Browse the repository at this point in the history
Provides a simple formatting function that allows an integer index to be
converted to a slice. It is worth noting that a single integer index
does not behave the same as slice containing one index. The former
results in reduction of a dimension; whereas, the latter keeps the
dimension, but reduces it to a singleton dimension.
  • Loading branch information
jakirkham committed Feb 17, 2017
1 parent 5e4ef5e commit d4b1e05
Show file tree
Hide file tree
Showing 2 changed files with 112 additions and 0 deletions.
34 changes: 34 additions & 0 deletions kenjutsu/format.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,40 @@
import numbers


def index_to_slice(index):
"""
Convert an index to a slice.
Note:
A single index behaves differently from a length 1 slice. When
applying the former one reduces that dimension; whereas, applying
the latter results in a singleton dimension being retained.
Args:
index(int): an index to convert to a slice
Returns:
(slice): a slice corresponding to the index
Examples:
>>> index_to_slice(1)
slice(1, 2, 1)
>>> index_to_slice(-1)
slice(-1, -2, -1)
"""

if not isinstance(index, numbers.Integral):
raise TypeError(
"Expected an integral type. Instead got `%s`." % str(index)
)

step = -1 if index < 0 else 1

return slice(index, index + step, step)


def reformat_slice(a_slice, a_length=None):
"""
Takes a slice and reformats it to fill in as many undefined values as
Expand Down
78 changes: 78 additions & 0 deletions tests/test_format.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,84 @@ def setUp(self):
pass


def test_index_to_slice(self):
with self.assertRaises(TypeError) as e:
format.index_to_slice(None)

self.assertEqual(
str(e.exception),
"Expected an integral type. Instead got `None`."
)

with self.assertRaises(TypeError) as e:
format.index_to_slice(2.5)

self.assertEqual(
str(e.exception),
"Expected an integral type. Instead got `2.5`."
)

with self.assertRaises(TypeError) as e:
format.index_to_slice((0,))

self.assertEqual(
str(e.exception),
"Expected an integral type. Instead got `(0,)`."
)

with self.assertRaises(TypeError) as e:
format.index_to_slice([0, 1])

self.assertEqual(
str(e.exception),
"Expected an integral type. Instead got `[0, 1]`."
)

with self.assertRaises(TypeError) as e:
format.index_to_slice(slice(None))

self.assertEqual(
str(e.exception),
"Expected an integral type. Instead got `slice(None, None, None)`."
)

with self.assertRaises(TypeError) as e:
format.index_to_slice(Ellipsis)

self.assertEqual(
str(e.exception),
"Expected an integral type. Instead got `Ellipsis`."
)

for size in [10, 11, 12]:
excess = size + 3
each_range = range(size)

for index in itertools.chain(irange(-excess, excess)):
expected_result = []
try:
expected_result = [each_range[index]]
except IndexError:
pass

rf_slice = format.index_to_slice(index)

self.assertIsInstance(rf_slice, slice)

result = each_range[rf_slice]
self.assertEqual(result, expected_result)

start = rf_slice.start
stop = rf_slice.stop
step = rf_slice.step

l = float(stop - start)/float(step)
self.assertEqual(
int(math.ceil(l)),
1
)


def test_reformat_slice(self):
with self.assertRaises(ValueError) as e:
format.reformat_slice(None)
Expand Down

0 comments on commit d4b1e05

Please sign in to comment.