import ruamel.yaml
from six.moves import zip
from .round_trip_data import RoundTripData
from .yamlizable import Yamlizable, Dynamic, Typed
from .yamlizing_error import YamlizingError
class Sequence(Yamlizable):
item_type = Dynamic
__slots__ = ('__items', '__round_trip_data')
def __init__(self, items=()):
Yamlizable.__init__(self)
self.__round_trip_data = RoundTripData(None)
self.__items = []
self.extend(items)
def __getstate__(self):
return list(self.__items)
def __setstate__(self, state):
self.__init__(state)
def __iter__(self):
return iter(self.__items)
def __repr__(self):
return repr(self.__items)
def __str__(self):
return str(self.__items)
def __len__(self):
return len(self.__items)
def __getitem__(self, index):
return self.__items[index]
def __setitem__(self, index, value):
self.__items[index] = value
def __delitem__(self, index):
del self.__items[index]
def __eq__(self, other):
try:
if not isinstance(other, (self.__class__, list)):
return False
if len(self) != len(other):
return False
for mine, theirs in zip(self, other):
# only uses the == comparison
if mine == theirs:
continue
return False
return True
except Exception:
return False
def __ne__(self, other):
try:
if not isinstance(other, (self.__class__, list)):
return True
if len(self) != len(other):
return True
for mine, theirs in zip(self, other):
# only uses the != comparison
if mine != theirs:
return True
return False
except Exception:
return True
def __iadd__(self, other):
self.__items += other
return self
def append(self, item):
if not isinstance(item, self.item_type):
item = self.item_type(item)
self.__items.append(item)
def extend(self, items):
if not isinstance(items, (list, tuple, Sequence)):
raise TypeError('Cannot extend items in a {} with {}'
.format(self.__class__, type(items)))
for item in items:
self.append(item)
@classmethod
def from_yaml(cls, loader, node, _rtd=None):
if not isinstance(node, ruamel.yaml.SequenceNode):
raise YamlizingError('Expected a SequenceNode', node)
if node in loader.constructed_objects:
return loader.constructed_objects[node]
self = cls()
self.__round_trip_data = RoundTripData(node)
loader.constructed_objects[node] = self
# node.value list of values
for item_node in node.value:
value = cls.item_type.from_yaml(loader, item_node, self.__round_trip_data)
self.append(value)
return self
@classmethod
def to_yaml(cls, dumper, self, _rtd=None):
# grab the id of the item before we try anything else, that way we can
# easily track the original id
self_id = id(self)
if not isinstance(self, cls):
try:
# this makes it possible to do IntList.dump(range(4))
self = cls(self)
except Exception:
raise YamlizingError('Expected instance of {}, got: {}'.format(cls, self))
if self_id in dumper.represented_objects:
return dumper.represented_objects[self_id]
items = []
node = ruamel.yaml.SequenceNode(
ruamel.yaml.resolver.BaseResolver.DEFAULT_SEQUENCE_TAG, items)
self.__round_trip_data.apply(node)
dumper.represented_objects[self_id] = node
for item in self:
item_node = self.item_type.to_yaml(dumper, item, self.__round_trip_data)
items.append(item_node)
return node
class FloatList(Sequence):
item_type = Typed(float)
class IntList(Sequence):
item_type = Typed(int)
class StrList(Sequence):
item_type = Typed(str)