diff options
-rw-r--r-- | CHANGES.rst | 3 | ||||
-rw-r--r-- | pyasn1/type/univ.py | 28 | ||||
-rw-r--r-- | tests/type/test_univ.py | 17 |
3 files changed, 44 insertions, 4 deletions
diff --git a/CHANGES.rst b/CHANGES.rst index 26d4978..f631be5 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -1,5 +1,5 @@ -Revision 0.4.6, released XX-06-2019 +Revision 0.4.6, released XX-07-2019 ----------------------------------- - Added previously missing `SET OF ANY` construct encoding/decoding support. @@ -9,6 +9,7 @@ Revision 0.4.6, released XX-06-2019 - New elements to `SequenceOf`/`SetOf` objects can now be added at any position - the requirement for the new elements to reside at the end of the existing ones (i.e. s[len(s)] = 123) is removed. +- List-like slicing support added to `SequenceOf`/`SetOf` objects. - Removed default initializer from `SequenceOf`/`SetOf` types to ensure consistent behaviour with the rest of ASN.1 types. Before this change, `SequenceOf`/`SetOf` instances immediately become value objects behaving diff --git a/pyasn1/type/univ.py b/pyasn1/type/univ.py index 5634f94..0ba59a7 100644 --- a/pyasn1/type/univ.py +++ b/pyasn1/type/univ.py @@ -1677,7 +1677,7 @@ class SequenceOfAndSetOfBase(base.AbstractConstructedAsn1Item): key=key, reverse=reverse))) def __len__(self): - if not self._componentValues: + if self._componentValues is noValue or not self._componentValues: return 0 return max(self._componentValues) + 1 @@ -1762,6 +1762,17 @@ class SequenceOfAndSetOfBase(base.AbstractConstructedAsn1Item): # returns noValue s.getComponentByPosition(0, instantiate=False) """ + if isinstance(idx, slice): + indices = tuple(range(len(self))) + return [self.getComponentByPosition(subidx, default, instantiate) + for subidx in indices[idx]] + + if idx < 0: + idx = len(self) + idx + if idx < 0: + raise error.PyAsn1Error( + 'SequenceOf/SetOf index is out of range') + try: componentValue = self._componentValues[idx] @@ -1819,9 +1830,20 @@ class SequenceOfAndSetOfBase(base.AbstractConstructedAsn1Item): IndexError: When idx > len(self) """ + if isinstance(idx, slice): + indices = tuple(range(len(self))) + startIdx = indices and indices[idx][0] or 0 + for subIdx, subValue in enumerate(value): + self.setComponentByPosition( + startIdx + subIdx, subValue, verifyConstraints, + matchTags, matchConstraints) + return self + if idx < 0: - raise error.PyAsn1Error( - 'SequenceOf/SetOf index must not be negative') + idx = len(self) + idx + if idx < 0: + raise error.PyAsn1Error( + 'SequenceOf/SetOf index is out of range') componentType = self.componentType diff --git a/tests/type/test_univ.py b/tests/type/test_univ.py index 169b73e..de7cdee 100644 --- a/tests/type/test_univ.py +++ b/tests/type/test_univ.py @@ -1090,6 +1090,13 @@ class SequenceOf(BaseTestCase): # this is a deviation from standard sequence protocol assert not s[2] + def testGetItemSlice(self): + s = self.s1.clone() + s.extend(['xxx', 'yyy', 'zzz']) + assert s[:1] == [str2octs('xxx')] + assert s[-2:] == [str2octs('yyy'), str2octs('zzz')] + assert s[1:2] == [str2octs('yyy')] + def testSetItem(self): s = self.s1.clone() s.append('xxx') @@ -1097,6 +1104,16 @@ class SequenceOf(BaseTestCase): assert len(s) == 3 assert s[1] == str2octs('') + def testSetItemSlice(self): + s = self.s1.clone() + s[:1] = ['xxx'] + assert s == [str2octs('xxx')] + s[-2:] = ['yyy', 'zzz'] + assert s == [str2octs('yyy'), str2octs('zzz')] + s[1:2] = ['yyy'] + assert s == [str2octs('yyy'), str2octs('yyy')] + assert len(s) == 2 + def testAppend(self): self.s1.clear() self.s1.setComponentByPosition(0, univ.OctetString('abc')) |