from datashape import dshape, discover
from datashape.dispatch import dispatch
from odo import convert, append, odo
class TypedList(list):
"""A list with type checked values.
Paramaters
----------
dtype : dshape
The type of the valus in the list.
data : iterable of dtype, optional
The values to initialize the list with.
"""
def __init__(self, dtype, data=None):
super().__init__(())
self.dtype = dshape(dtype).measure
if data:
self.extend(data)
def _checktype(self, value):
if discover(value) != self.dtype:
raise TypeError(
"value '%s' is of type '%s', not type '%s'" % (
value,
discover(value).measure,
self.dtype,
),
)
def __setitem__(self, idx, value):
self._checktype(value)
super().__setitem__(idx, value)
def append(self, value):
self._checktype(value)
super().append(value)
def extend(self, vs):
for v in vs:
self.append(v)
def __repr__(self):
return '%s::%s' % (super().__repr__(), self.dtype)
tl = TypedList('int64', [1, 2, 3])
tl
[1, 2, 3]::int64
tl.append('a')
--------------------------------------------------------------------------- TypeError Traceback (most recent call last) <ipython-input-4-891aa13888c0> in <module>() ----> 1 tl.append('a') <ipython-input-2-80db5ac2dc8c> in append(self, value) 30 31 def append(self, value): ---> 32 self._checktype(value) 33 super().append(value) 34 <ipython-input-2-80db5ac2dc8c> in _checktype(self, value) 21 value, 22 discover(value).measure, ---> 23 self.dtype, 24 ), 25 ) TypeError: value 'a' is of type 'string', not type 'int64'
tl.append(3)
tl
[1, 2, 3, 3]::int64
@dispatch(TypedList)
def discover(tl):
return len(tl) * tl.dtype
discover(tl)
dshape("4 * int64")
@convert.register(TypedList, list)
def list_to_typed_list(ds, dshape=None, **kwargs):
if dshape is None:
dshape = discover(ds).measure.measure
return TypedList(dshape, ds)
@convert.register(list, TypedList)
def list_to_typed_list(ds, **kwargs):
return list(ds)
odo(tl, list)
[1, 2, 3, 3]
odo(tl, set)
{1, 2, 3}
odo(tl, tuple)
(1, 2, 3, 3)
import numpy as np
odo(tl, np.ndarray)
array([1, 2, 3, 3])
odo(TypedList('float64', [1.2, 1.3, 1.4]), np.ndarray)
array([ 1.2, 1.3, 1.4])
odo([1, 2, 3], TypedList, dtype='int64')
[1, 2, 3]::int64
odo(np.array([1, 2, 3]), TypedList('int64'))
[1, 2, 3]::int64
@append.register(list, TypedList)
def append_list_to_typed_list(ds, tl, **kwargs):
tl.extend(ds)
odo([1, 2, 3], tl)
[1, 2, 3, 3, 1, 2, 3]::int64
tl
[1, 2, 3, 3, 1, 2, 3]::int64