diff options
author | Anthon van der Neut <anthon@mnt.org> | 2018-08-14 17:53:12 +0200 |
---|---|---|
committer | Anthon van der Neut <anthon@mnt.org> | 2018-08-14 17:53:12 +0200 |
commit | ecd5f8dbaf580fa618205845374256a301d0675f (patch) | |
tree | c90362a9922031e9fdf49a3dcfaabe8291e337b5 /compat.py | |
parent | 0923c2a691f57f9e095f5c4b9a8f06fa78bb46d2 (diff) | |
download | ruamel.yaml-ecd5f8dbaf580fa618205845374256a301d0675f.tar.gz |
fix issue #176 CommentedSeq does not support slice assignment
I implemented slicing in an intermediate baseclass ruamel.yaml.compat.MutableSliceableSequence,
on top of collections.{,abc.}.MutableSequence. I'm not sure if I tested all possibilities but
CommentedSeq **should** now support all (extended) slicing operations.
Test were added in _test/test_issues.py
*When this change indeed resolves your problem, please **Close** this issue*.
*(You can do so using the WorkFlow pull-down (close to the top right of this page))*
Diffstat (limited to 'compat.py')
-rw-r--r-- | compat.py | 61 |
1 files changed, 61 insertions, 0 deletions
@@ -7,6 +7,7 @@ from __future__ import print_function import sys import os import types +from abc import abstractmethod # fmt: off if False: # MYPY @@ -220,3 +221,63 @@ def version_tnf(t1, t2=None): if t2 is not None and version_info < t2: return None return False + + +class MutableSliceableSequence(MutableSequence): + __slots__ = () + + def __getitem__(self, index): + # type: (Any) -> Any + if not isinstance(index, slice): + return self.__getsingleitem__(index) + return type(self)([self[i] for i in range(*index.indices(len(self)))]) # type: ignore + + def __setitem__(self, index, value): + # type: (Any, Any) -> None + if not isinstance(index, slice): + return self.__setsingleitem__(index, value) + assert iter(value) + print(index.start, index.stop, index.step, index.indices(len(self))) + if index.step is None: + del self[index.start : index.stop] + for elem in reversed(value): + self.insert(0 if index.start is None else index.start, elem) + else: + range_parms = index.indices(len(self)) + nr_assigned_items = (range_parms[1] - range_parms[0] - 1) // range_parms[2] + 1 + # need to test before changing, in case TypeError is caught + if nr_assigned_items < len(value): + raise TypeError( + 'too many elements in value {} < {}'.format(nr_assigned_items, len(value)) + ) + elif nr_assigned_items > len(value): + raise TypeError( + 'not enough elements in value {} > {}'.format( + nr_assigned_items, len(value) + ) + ) + for idx, i in enumerate(range(*range_parms)): + self[i] = value[idx] + + def __delitem__(self, index): + # type: (Any) -> None + if not isinstance(index, slice): + return self.__delsingleitem__(index) + print(index.start, index.stop, index.step, index.indices(len(self))) + for i in reversed(range(*index.indices(len(self)))): + del self[i] + + @abstractmethod + def __getsingleitem__(self, index): + # type: (Any) -> Any + raise IndexError + + @abstractmethod + def __setsingleitem__(self, index, value): + # type: (Any, Any) -> None + raise IndexError + + @abstractmethod + def __delsingleitem__(self, index): + # type: (Any) -> None + raise IndexError |