summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIlya Etingof <etingof@gmail.com>2019-07-12 22:23:28 +0200
committerIlya Etingof <etingof@gmail.com>2019-07-12 22:23:28 +0200
commit279e57ec0e569c91b59815bd77adf4bb2a8a35b3 (patch)
tree6942818a0fb1266825e93ce8b9f4aaf594b881f9
parentcf9b3f5f67501b85296c05456bbd324352177718 (diff)
downloadpyasn1-git-fix-setof-slicing.tar.gz
Add `SequenceOf`/`SetOf` list-like slicing supportfix-setof-slicing
-rw-r--r--CHANGES.rst3
-rw-r--r--pyasn1/type/univ.py28
-rw-r--r--tests/type/test_univ.py17
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'))