1#
2# This file is part of pyasn1 software.
3#
4# Copyright (c) 2005-2019, Ilya Etingof <etingof@gmail.com>
5# License: http://snmplabs.com/pyasn1/license.html
6#
7import math
8import sys
9
10from pyasn1 import error
11from pyasn1.codec.ber import eoo
12from pyasn1.compat import binary
13from pyasn1.compat import integer
14from pyasn1.compat import octets
15from pyasn1.type import base
16from pyasn1.type import constraint
17from pyasn1.type import namedtype
18from pyasn1.type import namedval
19from pyasn1.type import tag
20from pyasn1.type import tagmap
21
22NoValue = base.NoValue
23noValue = NoValue()
24
25__all__ = ['Integer', 'Boolean', 'BitString', 'OctetString', 'Null',
26           'ObjectIdentifier', 'Real', 'Enumerated',
27           'SequenceOfAndSetOfBase', 'SequenceOf', 'SetOf',
28           'SequenceAndSetBase', 'Sequence', 'Set', 'Choice', 'Any',
29           'NoValue', 'noValue']
30
31# "Simple" ASN.1 types (yet incomplete)
32
33
34class Integer(base.SimpleAsn1Type):
35    """Create |ASN.1| schema or value object.
36
37    |ASN.1| class is based on :class:`~pyasn1.type.base.SimpleAsn1Type`, its
38    objects are immutable and duck-type Python :class:`int` objects.
39
40    Keyword Args
41    ------------
42    value: :class:`int`, :class:`str` or |ASN.1| object
43        Python :class:`int` or :class:`str` literal or |ASN.1| class
44        instance. If `value` is not given, schema object will be created.
45
46    tagSet: :py:class:`~pyasn1.type.tag.TagSet`
47        Object representing non-default ASN.1 tag(s)
48
49    subtypeSpec: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection`
50        Object representing non-default ASN.1 subtype constraint(s). Constraints
51        verification for |ASN.1| type occurs automatically on object
52        instantiation.
53
54    namedValues: :py:class:`~pyasn1.type.namedval.NamedValues`
55        Object representing non-default symbolic aliases for numbers
56
57    Raises
58    ------
59    ~pyasn1.error.ValueConstraintError, ~pyasn1.error.PyAsn1Error
60        On constraint violation or bad initializer.
61
62    Examples
63    --------
64
65    .. code-block:: python
66
67        class ErrorCode(Integer):
68            '''
69            ASN.1 specification:
70
71            ErrorCode ::=
72                INTEGER { disk-full(1), no-disk(-1),
73                          disk-not-formatted(2) }
74
75            error ErrorCode ::= disk-full
76            '''
77            namedValues = NamedValues(
78                ('disk-full', 1), ('no-disk', -1),
79                ('disk-not-formatted', 2)
80            )
81
82        error = ErrorCode('disk-full')
83    """
84    #: Set (on class, not on instance) or return a
85    #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s)
86    #: associated with |ASN.1| type.
87    tagSet = tag.initTagSet(
88        tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 0x02)
89    )
90
91    #: Set (on class, not on instance) or return a
92    #: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection` object
93    #: imposing constraints on |ASN.1| type initialization values.
94    subtypeSpec = constraint.ConstraintsIntersection()
95
96    #: Default :py:class:`~pyasn1.type.namedval.NamedValues` object
97    #: representing symbolic aliases for numbers
98    namedValues = namedval.NamedValues()
99
100    # Optimization for faster codec lookup
101    typeId = base.SimpleAsn1Type.getTypeId()
102
103    def __init__(self, value=noValue, **kwargs):
104        if 'namedValues' not in kwargs:
105            kwargs['namedValues'] = self.namedValues
106
107        base.SimpleAsn1Type.__init__(self, value, **kwargs)
108
109    def __and__(self, value):
110        return self.clone(self._value & value)
111
112    def __rand__(self, value):
113        return self.clone(value & self._value)
114
115    def __or__(self, value):
116        return self.clone(self._value | value)
117
118    def __ror__(self, value):
119        return self.clone(value | self._value)
120
121    def __xor__(self, value):
122        return self.clone(self._value ^ value)
123
124    def __rxor__(self, value):
125        return self.clone(value ^ self._value)
126
127    def __lshift__(self, value):
128        return self.clone(self._value << value)
129
130    def __rshift__(self, value):
131        return self.clone(self._value >> value)
132
133    def __add__(self, value):
134        return self.clone(self._value + value)
135
136    def __radd__(self, value):
137        return self.clone(value + self._value)
138
139    def __sub__(self, value):
140        return self.clone(self._value - value)
141
142    def __rsub__(self, value):
143        return self.clone(value - self._value)
144
145    def __mul__(self, value):
146        return self.clone(self._value * value)
147
148    def __rmul__(self, value):
149        return self.clone(value * self._value)
150
151    def __mod__(self, value):
152        return self.clone(self._value % value)
153
154    def __rmod__(self, value):
155        return self.clone(value % self._value)
156
157    def __pow__(self, value, modulo=None):
158        return self.clone(pow(self._value, value, modulo))
159
160    def __rpow__(self, value):
161        return self.clone(pow(value, self._value))
162
163    def __floordiv__(self, value):
164        return self.clone(self._value // value)
165
166    def __rfloordiv__(self, value):
167        return self.clone(value // self._value)
168
169    if sys.version_info[0] <= 2:
170        def __div__(self, value):
171            if isinstance(value, float):
172                return Real(self._value / value)
173            else:
174                return self.clone(self._value / value)
175
176        def __rdiv__(self, value):
177            if isinstance(value, float):
178                return Real(value / self._value)
179            else:
180                return self.clone(value / self._value)
181    else:
182        def __truediv__(self, value):
183            return Real(self._value / value)
184
185        def __rtruediv__(self, value):
186            return Real(value / self._value)
187
188        def __divmod__(self, value):
189            return self.clone(divmod(self._value, value))
190
191        def __rdivmod__(self, value):
192            return self.clone(divmod(value, self._value))
193
194        __hash__ = base.SimpleAsn1Type.__hash__
195
196    def __int__(self):
197        return int(self._value)
198
199    if sys.version_info[0] <= 2:
200        def __long__(self):
201            return long(self._value)
202
203    def __float__(self):
204        return float(self._value)
205
206    def __abs__(self):
207        return self.clone(abs(self._value))
208
209    def __index__(self):
210        return int(self._value)
211
212    def __pos__(self):
213        return self.clone(+self._value)
214
215    def __neg__(self):
216        return self.clone(-self._value)
217
218    def __invert__(self):
219        return self.clone(~self._value)
220
221    def __round__(self, n=0):
222        r = round(self._value, n)
223        if n:
224            return self.clone(r)
225        else:
226            return r
227
228    def __floor__(self):
229        return math.floor(self._value)
230
231    def __ceil__(self):
232        return math.ceil(self._value)
233
234    if sys.version_info[0:2] > (2, 5):
235        def __trunc__(self):
236            return self.clone(math.trunc(self._value))
237
238    def __lt__(self, value):
239        return self._value < value
240
241    def __le__(self, value):
242        return self._value <= value
243
244    def __eq__(self, value):
245        return self._value == value
246
247    def __ne__(self, value):
248        return self._value != value
249
250    def __gt__(self, value):
251        return self._value > value
252
253    def __ge__(self, value):
254        return self._value >= value
255
256    def prettyIn(self, value):
257        try:
258            return int(value)
259
260        except ValueError:
261            try:
262                return self.namedValues[value]
263
264            except KeyError:
265                raise error.PyAsn1Error(
266                    'Can\'t coerce %r into integer: %s' % (value, sys.exc_info()[1])
267                )
268
269    def prettyOut(self, value):
270        try:
271            return str(self.namedValues[value])
272
273        except KeyError:
274            return str(value)
275
276    # backward compatibility
277
278    def getNamedValues(self):
279        return self.namedValues
280
281
282class Boolean(Integer):
283    """Create |ASN.1| schema or value object.
284
285    |ASN.1| class is based on :class:`~pyasn1.type.base.SimpleAsn1Type`, its
286    objects are immutable and duck-type Python :class:`int` objects.
287
288    Keyword Args
289    ------------
290    value: :class:`int`, :class:`str` or |ASN.1| object
291        Python :class:`int` or :class:`str` literal or |ASN.1| class
292        instance. If `value` is not given, schema object will be created.
293
294    tagSet: :py:class:`~pyasn1.type.tag.TagSet`
295        Object representing non-default ASN.1 tag(s)
296
297    subtypeSpec: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection`
298        Object representing non-default ASN.1 subtype constraint(s).Constraints
299        verification for |ASN.1| type occurs automatically on object
300        instantiation.
301
302    namedValues: :py:class:`~pyasn1.type.namedval.NamedValues`
303        Object representing non-default symbolic aliases for numbers
304
305    Raises
306    ------
307    ~pyasn1.error.ValueConstraintError, ~pyasn1.error.PyAsn1Error
308        On constraint violation or bad initializer.
309
310    Examples
311    --------
312    .. code-block:: python
313
314        class RoundResult(Boolean):
315            '''
316            ASN.1 specification:
317
318            RoundResult ::= BOOLEAN
319
320            ok RoundResult ::= TRUE
321            ko RoundResult ::= FALSE
322            '''
323        ok = RoundResult(True)
324        ko = RoundResult(False)
325    """
326    #: Set (on class, not on instance) or return a
327    #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s)
328    #: associated with |ASN.1| type.
329    tagSet = tag.initTagSet(
330        tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 0x01),
331    )
332
333    #: Set (on class, not on instance) or return a
334    #: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection` object
335    #: imposing constraints on |ASN.1| type initialization values.
336    subtypeSpec = Integer.subtypeSpec + constraint.SingleValueConstraint(0, 1)
337
338    #: Default :py:class:`~pyasn1.type.namedval.NamedValues` object
339    #: representing symbolic aliases for numbers
340    namedValues = namedval.NamedValues(('False', 0), ('True', 1))
341
342    # Optimization for faster codec lookup
343    typeId = Integer.getTypeId()
344
345if sys.version_info[0] < 3:
346    SizedIntegerBase = long
347else:
348    SizedIntegerBase = int
349
350
351class SizedInteger(SizedIntegerBase):
352    bitLength = leadingZeroBits = None
353
354    def setBitLength(self, bitLength):
355        self.bitLength = bitLength
356        self.leadingZeroBits = max(bitLength - integer.bitLength(self), 0)
357        return self
358
359    def __len__(self):
360        if self.bitLength is None:
361            self.setBitLength(integer.bitLength(self))
362
363        return self.bitLength
364
365
366class BitString(base.SimpleAsn1Type):
367    """Create |ASN.1| schema or value object.
368
369    |ASN.1| class is based on :class:`~pyasn1.type.base.SimpleAsn1Type`, its
370    objects are immutable and duck-type both Python :class:`tuple` (as a tuple
371    of bits) and :class:`int` objects.
372
373    Keyword Args
374    ------------
375    value: :class:`int`, :class:`str` or |ASN.1| object
376        Python :class:`int` or :class:`str` literal representing binary
377        or hexadecimal number or sequence of integer bits or |ASN.1| object.
378        If `value` is not given, schema object will be created.
379
380    tagSet: :py:class:`~pyasn1.type.tag.TagSet`
381        Object representing non-default ASN.1 tag(s)
382
383    subtypeSpec: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection`
384        Object representing non-default ASN.1 subtype constraint(s). Constraints
385        verification for |ASN.1| type occurs automatically on object
386        instantiation.
387
388    namedValues: :py:class:`~pyasn1.type.namedval.NamedValues`
389        Object representing non-default symbolic aliases for numbers
390
391    binValue: :py:class:`str`
392        Binary string initializer to use instead of the *value*.
393        Example: '10110011'.
394
395    hexValue: :py:class:`str`
396        Hexadecimal string initializer to use instead of the *value*.
397        Example: 'DEADBEEF'.
398
399    Raises
400    ------
401    ~pyasn1.error.ValueConstraintError, ~pyasn1.error.PyAsn1Error
402        On constraint violation or bad initializer.
403
404    Examples
405    --------
406    .. code-block:: python
407
408        class Rights(BitString):
409            '''
410            ASN.1 specification:
411
412            Rights ::= BIT STRING { user-read(0), user-write(1),
413                                    group-read(2), group-write(3),
414                                    other-read(4), other-write(5) }
415
416            group1 Rights ::= { group-read, group-write }
417            group2 Rights ::= '0011'B
418            group3 Rights ::= '3'H
419            '''
420            namedValues = NamedValues(
421                ('user-read', 0), ('user-write', 1),
422                ('group-read', 2), ('group-write', 3),
423                ('other-read', 4), ('other-write', 5)
424            )
425
426        group1 = Rights(('group-read', 'group-write'))
427        group2 = Rights('0011')
428        group3 = Rights(0x3)
429    """
430    #: Set (on class, not on instance) or return a
431    #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s)
432    #: associated with |ASN.1| type.
433    tagSet = tag.initTagSet(
434        tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 0x03)
435    )
436
437    #: Set (on class, not on instance) or return a
438    #: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection` object
439    #: imposing constraints on |ASN.1| type initialization values.
440    subtypeSpec = constraint.ConstraintsIntersection()
441
442    #: Default :py:class:`~pyasn1.type.namedval.NamedValues` object
443    #: representing symbolic aliases for numbers
444    namedValues = namedval.NamedValues()
445
446    # Optimization for faster codec lookup
447    typeId = base.SimpleAsn1Type.getTypeId()
448
449    defaultBinValue = defaultHexValue = noValue
450
451    def __init__(self, value=noValue, **kwargs):
452        if value is noValue:
453            if kwargs:
454                try:
455                    value = self.fromBinaryString(kwargs.pop('binValue'), internalFormat=True)
456
457                except KeyError:
458                    pass
459
460                try:
461                    value = self.fromHexString(kwargs.pop('hexValue'), internalFormat=True)
462
463                except KeyError:
464                    pass
465
466        if value is noValue:
467            if self.defaultBinValue is not noValue:
468                value = self.fromBinaryString(self.defaultBinValue, internalFormat=True)
469
470            elif self.defaultHexValue is not noValue:
471                value = self.fromHexString(self.defaultHexValue, internalFormat=True)
472
473        if 'namedValues' not in kwargs:
474            kwargs['namedValues'] = self.namedValues
475
476        base.SimpleAsn1Type.__init__(self, value, **kwargs)
477
478    def __str__(self):
479        return self.asBinary()
480
481    def __eq__(self, other):
482        other = self.prettyIn(other)
483        return self is other or self._value == other and len(self._value) == len(other)
484
485    def __ne__(self, other):
486        other = self.prettyIn(other)
487        return self._value != other or len(self._value) != len(other)
488
489    def __lt__(self, other):
490        other = self.prettyIn(other)
491        return len(self._value) < len(other) or len(self._value) == len(other) and self._value < other
492
493    def __le__(self, other):
494        other = self.prettyIn(other)
495        return len(self._value) <= len(other) or len(self._value) == len(other) and self._value <= other
496
497    def __gt__(self, other):
498        other = self.prettyIn(other)
499        return len(self._value) > len(other) or len(self._value) == len(other) and self._value > other
500
501    def __ge__(self, other):
502        other = self.prettyIn(other)
503        return len(self._value) >= len(other) or len(self._value) == len(other) and self._value >= other
504
505    # Immutable sequence object protocol
506
507    def __len__(self):
508        return len(self._value)
509
510    def __getitem__(self, i):
511        if i.__class__ is slice:
512            return self.clone([self[x] for x in range(*i.indices(len(self)))])
513        else:
514            length = len(self._value) - 1
515            if i > length or i < 0:
516                raise IndexError('bit index out of range')
517            return (self._value >> (length - i)) & 1
518
519    def __iter__(self):
520        length = len(self._value)
521        while length:
522            length -= 1
523            yield (self._value >> length) & 1
524
525    def __reversed__(self):
526        return reversed(tuple(self))
527
528    # arithmetic operators
529
530    def __add__(self, value):
531        value = self.prettyIn(value)
532        return self.clone(SizedInteger(self._value << len(value) | value).setBitLength(len(self._value) + len(value)))
533
534    def __radd__(self, value):
535        value = self.prettyIn(value)
536        return self.clone(SizedInteger(value << len(self._value) | self._value).setBitLength(len(self._value) + len(value)))
537
538    def __mul__(self, value):
539        bitString = self._value
540        while value > 1:
541            bitString <<= len(self._value)
542            bitString |= self._value
543            value -= 1
544        return self.clone(bitString)
545
546    def __rmul__(self, value):
547        return self * value
548
549    def __lshift__(self, count):
550        return self.clone(SizedInteger(self._value << count).setBitLength(len(self._value) + count))
551
552    def __rshift__(self, count):
553        return self.clone(SizedInteger(self._value >> count).setBitLength(max(0, len(self._value) - count)))
554
555    def __int__(self):
556        return self._value
557
558    def __float__(self):
559        return float(self._value)
560
561    if sys.version_info[0] < 3:
562        def __long__(self):
563            return self._value
564
565    def asNumbers(self):
566        """Get |ASN.1| value as a sequence of 8-bit integers.
567
568        If |ASN.1| object length is not a multiple of 8, result
569        will be left-padded with zeros.
570        """
571        return tuple(octets.octs2ints(self.asOctets()))
572
573    def asOctets(self):
574        """Get |ASN.1| value as a sequence of octets.
575
576        If |ASN.1| object length is not a multiple of 8, result
577        will be left-padded with zeros.
578        """
579        return integer.to_bytes(self._value, length=len(self))
580
581    def asInteger(self):
582        """Get |ASN.1| value as a single integer value.
583        """
584        return self._value
585
586    def asBinary(self):
587        """Get |ASN.1| value as a text string of bits.
588        """
589        binString = binary.bin(self._value)[2:]
590        return '0' * (len(self._value) - len(binString)) + binString
591
592    @classmethod
593    def fromHexString(cls, value, internalFormat=False, prepend=None):
594        """Create a |ASN.1| object initialized from the hex string.
595
596        Parameters
597        ----------
598        value: :class:`str`
599            Text string like 'DEADBEEF'
600        """
601        try:
602            value = SizedInteger(value, 16).setBitLength(len(value) * 4)
603
604        except ValueError:
605            raise error.PyAsn1Error('%s.fromHexString() error: %s' % (cls.__name__, sys.exc_info()[1]))
606
607        if prepend is not None:
608            value = SizedInteger(
609                (SizedInteger(prepend) << len(value)) | value
610            ).setBitLength(len(prepend) + len(value))
611
612        if not internalFormat:
613            value = cls(value)
614
615        return value
616
617    @classmethod
618    def fromBinaryString(cls, value, internalFormat=False, prepend=None):
619        """Create a |ASN.1| object initialized from a string of '0' and '1'.
620
621        Parameters
622        ----------
623        value: :class:`str`
624            Text string like '1010111'
625        """
626        try:
627            value = SizedInteger(value or '0', 2).setBitLength(len(value))
628
629        except ValueError:
630            raise error.PyAsn1Error('%s.fromBinaryString() error: %s' % (cls.__name__, sys.exc_info()[1]))
631
632        if prepend is not None:
633            value = SizedInteger(
634                (SizedInteger(prepend) << len(value)) | value
635            ).setBitLength(len(prepend) + len(value))
636
637        if not internalFormat:
638            value = cls(value)
639
640        return value
641
642    @classmethod
643    def fromOctetString(cls, value, internalFormat=False, prepend=None, padding=0):
644        """Create a |ASN.1| object initialized from a string.
645
646        Parameters
647        ----------
648        value: :class:`str` (Py2) or :class:`bytes` (Py3)
649            Text string like '\\\\x01\\\\xff' (Py2) or b'\\\\x01\\\\xff' (Py3)
650        """
651        value = SizedInteger(integer.from_bytes(value) >> padding).setBitLength(len(value) * 8 - padding)
652
653        if prepend is not None:
654            value = SizedInteger(
655                (SizedInteger(prepend) << len(value)) | value
656            ).setBitLength(len(prepend) + len(value))
657
658        if not internalFormat:
659            value = cls(value)
660
661        return value
662
663    def prettyIn(self, value):
664        if isinstance(value, SizedInteger):
665            return value
666        elif octets.isStringType(value):
667            if not value:
668                return SizedInteger(0).setBitLength(0)
669
670            elif value[0] == '\'':  # "'1011'B" -- ASN.1 schema representation (deprecated)
671                if value[-2:] == '\'B':
672                    return self.fromBinaryString(value[1:-2], internalFormat=True)
673                elif value[-2:] == '\'H':
674                    return self.fromHexString(value[1:-2], internalFormat=True)
675                else:
676                    raise error.PyAsn1Error(
677                        'Bad BIT STRING value notation %s' % (value,)
678                    )
679
680            elif self.namedValues and not value.isdigit():  # named bits like 'Urgent, Active'
681                names = [x.strip() for x in value.split(',')]
682
683                try:
684
685                    bitPositions = [self.namedValues[name] for name in names]
686
687                except KeyError:
688                    raise error.PyAsn1Error('unknown bit name(s) in %r' % (names,))
689
690                rightmostPosition = max(bitPositions)
691
692                number = 0
693                for bitPosition in bitPositions:
694                    number |= 1 << (rightmostPosition - bitPosition)
695
696                return SizedInteger(number).setBitLength(rightmostPosition + 1)
697
698            elif value.startswith('0x'):
699                return self.fromHexString(value[2:], internalFormat=True)
700
701            elif value.startswith('0b'):
702                return self.fromBinaryString(value[2:], internalFormat=True)
703
704            else:  # assume plain binary string like '1011'
705                return self.fromBinaryString(value, internalFormat=True)
706
707        elif isinstance(value, (tuple, list)):
708            return self.fromBinaryString(''.join([b and '1' or '0' for b in value]), internalFormat=True)
709
710        elif isinstance(value, BitString):
711            return SizedInteger(value).setBitLength(len(value))
712
713        elif isinstance(value, intTypes):
714            return SizedInteger(value)
715
716        else:
717            raise error.PyAsn1Error(
718                'Bad BitString initializer type \'%s\'' % (value,)
719            )
720
721
722try:
723    # noinspection PyStatementEffect
724    all
725
726except NameError:  # Python 2.4
727    # noinspection PyShadowingBuiltins
728    def all(iterable):
729        for element in iterable:
730            if not element:
731                return False
732        return True
733
734
735class OctetString(base.SimpleAsn1Type):
736    """Create |ASN.1| schema or value object.
737
738    |ASN.1| class is based on :class:`~pyasn1.type.base.SimpleAsn1Type`, its
739    objects are immutable and duck-type Python 2 :class:`str` or
740    Python 3 :class:`bytes`. When used in Unicode context, |ASN.1| type
741    assumes "|encoding|" serialisation.
742
743    Keyword Args
744    ------------
745    value: :class:`unicode`, :class:`str`, :class:`bytes` or |ASN.1| object
746        class:`str` (Python 2) or :class:`bytes` (Python 3), alternatively
747        class:`unicode` object (Python 2) or :class:`str` (Python 3)
748        representing character string to be serialised into octets
749        (note `encoding` parameter) or |ASN.1| object.
750        If `value` is not given, schema object will be created.
751
752    tagSet: :py:class:`~pyasn1.type.tag.TagSet`
753        Object representing non-default ASN.1 tag(s)
754
755    subtypeSpec: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection`
756        Object representing non-default ASN.1 subtype constraint(s). Constraints
757        verification for |ASN.1| type occurs automatically on object
758        instantiation.
759
760    encoding: :py:class:`str`
761        Unicode codec ID to encode/decode :class:`unicode` (Python 2) or
762        :class:`str` (Python 3) the payload when |ASN.1| object is used
763        in text string context.
764
765    binValue: :py:class:`str`
766        Binary string initializer to use instead of the *value*.
767        Example: '10110011'.
768
769    hexValue: :py:class:`str`
770        Hexadecimal string initializer to use instead of the *value*.
771        Example: 'DEADBEEF'.
772
773    Raises
774    ------
775    ~pyasn1.error.ValueConstraintError, ~pyasn1.error.PyAsn1Error
776        On constraint violation or bad initializer.
777
778    Examples
779    --------
780    .. code-block:: python
781
782        class Icon(OctetString):
783            '''
784            ASN.1 specification:
785
786            Icon ::= OCTET STRING
787
788            icon1 Icon ::= '001100010011001000110011'B
789            icon2 Icon ::= '313233'H
790            '''
791        icon1 = Icon.fromBinaryString('001100010011001000110011')
792        icon2 = Icon.fromHexString('313233')
793    """
794    #: Set (on class, not on instance) or return a
795    #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s)
796    #: associated with |ASN.1| type.
797    tagSet = tag.initTagSet(
798        tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 0x04)
799    )
800
801    #: Set (on class, not on instance) or return a
802    #: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection` object
803    #: imposing constraints on |ASN.1| type initialization values.
804    subtypeSpec = constraint.ConstraintsIntersection()
805
806    # Optimization for faster codec lookup
807    typeId = base.SimpleAsn1Type.getTypeId()
808
809    defaultBinValue = defaultHexValue = noValue
810    encoding = 'iso-8859-1'
811
812    def __init__(self, value=noValue, **kwargs):
813        if kwargs:
814            if value is noValue:
815                try:
816                    value = self.fromBinaryString(kwargs.pop('binValue'))
817
818                except KeyError:
819                    pass
820
821                try:
822                    value = self.fromHexString(kwargs.pop('hexValue'))
823
824                except KeyError:
825                    pass
826
827        if value is noValue:
828            if self.defaultBinValue is not noValue:
829                value = self.fromBinaryString(self.defaultBinValue)
830
831            elif self.defaultHexValue is not noValue:
832                value = self.fromHexString(self.defaultHexValue)
833
834        if 'encoding' not in kwargs:
835            kwargs['encoding'] = self.encoding
836
837        base.SimpleAsn1Type.__init__(self, value, **kwargs)
838
839    if sys.version_info[0] <= 2:
840        def prettyIn(self, value):
841            if isinstance(value, str):
842                return value
843
844            elif isinstance(value, unicode):
845                try:
846                    return value.encode(self.encoding)
847
848                except (LookupError, UnicodeEncodeError):
849                    exc = sys.exc_info()[1]
850                    raise error.PyAsn1UnicodeEncodeError(
851                        "Can't encode string '%s' with codec "
852                        "%s" % (value, self.encoding), exc
853                    )
854
855            elif isinstance(value, (tuple, list)):
856                try:
857                    return ''.join([chr(x) for x in value])
858
859                except ValueError:
860                    raise error.PyAsn1Error(
861                        "Bad %s initializer '%s'" % (self.__class__.__name__, value)
862                    )
863
864            else:
865                return str(value)
866
867        def __str__(self):
868            return str(self._value)
869
870        def __unicode__(self):
871            try:
872                return self._value.decode(self.encoding)
873
874            except UnicodeDecodeError:
875                exc = sys.exc_info()[1]
876                raise error.PyAsn1UnicodeDecodeError(
877                    "Can't decode string '%s' with codec "
878                    "%s" % (self._value, self.encoding), exc
879                )
880
881        def asOctets(self):
882            return str(self._value)
883
884        def asNumbers(self):
885            return tuple([ord(x) for x in self._value])
886
887    else:
888        def prettyIn(self, value):
889            if isinstance(value, bytes):
890                return value
891
892            elif isinstance(value, str):
893                try:
894                    return value.encode(self.encoding)
895
896                except UnicodeEncodeError:
897                    exc = sys.exc_info()[1]
898                    raise error.PyAsn1UnicodeEncodeError(
899                        "Can't encode string '%s' with '%s' "
900                        "codec" % (value, self.encoding), exc
901                    )
902            elif isinstance(value, OctetString):  # a shortcut, bytes() would work the same way
903                return value.asOctets()
904
905            elif isinstance(value, base.SimpleAsn1Type):  # this mostly targets Integer objects
906                return self.prettyIn(str(value))
907
908            elif isinstance(value, (tuple, list)):
909                return self.prettyIn(bytes(value))
910
911            else:
912                return bytes(value)
913
914        def __str__(self):
915            try:
916                return self._value.decode(self.encoding)
917
918            except UnicodeDecodeError:
919                exc = sys.exc_info()[1]
920                raise error.PyAsn1UnicodeDecodeError(
921                    "Can't decode string '%s' with '%s' codec at "
922                    "'%s'" % (self._value, self.encoding,
923                              self.__class__.__name__), exc
924                )
925
926        def __bytes__(self):
927            return bytes(self._value)
928
929        def asOctets(self):
930            return bytes(self._value)
931
932        def asNumbers(self):
933            return tuple(self._value)
934
935    #
936    # Normally, `.prettyPrint()` is called from `__str__()`. Historically,
937    # OctetString.prettyPrint() used to return hexified payload
938    # representation in cases when non-printable content is present. At the
939    # same time `str()` used to produce either octet-stream (Py2) or
940    # text (Py3) representations.
941    #
942    # Therefore `OctetString.__str__()` -> `.prettyPrint()` call chain is
943    # reversed to preserve the original behaviour.
944    #
945    # Eventually we should deprecate `.prettyPrint()` / `.prettyOut()` harness
946    # and end up with just `__str__()` producing hexified representation while
947    # both text and octet-stream representation should only be requested via
948    # the `.asOctets()` method.
949    #
950    # Note: ASN.1 OCTET STRING is never mean to contain text!
951    #
952
953    def prettyOut(self, value):
954        return value
955
956    def prettyPrint(self, scope=0):
957        # first see if subclass has its own .prettyOut()
958        value = self.prettyOut(self._value)
959
960        if value is not self._value:
961            return value
962
963        numbers = self.asNumbers()
964
965        for x in numbers:
966            # hexify if needed
967            if x < 32 or x > 126:
968                return '0x' + ''.join(('%.2x' % x for x in numbers))
969        else:
970            # this prevents infinite recursion
971            return OctetString.__str__(self)
972
973    @staticmethod
974    def fromBinaryString(value):
975        """Create a |ASN.1| object initialized from a string of '0' and '1'.
976
977        Parameters
978        ----------
979        value: :class:`str`
980            Text string like '1010111'
981        """
982        bitNo = 8
983        byte = 0
984        r = []
985        for v in value:
986            if bitNo:
987                bitNo -= 1
988            else:
989                bitNo = 7
990                r.append(byte)
991                byte = 0
992            if v in ('0', '1'):
993                v = int(v)
994            else:
995                raise error.PyAsn1Error(
996                    'Non-binary OCTET STRING initializer %s' % (v,)
997                )
998            byte |= v << bitNo
999
1000        r.append(byte)
1001
1002        return octets.ints2octs(r)
1003
1004    @staticmethod
1005    def fromHexString(value):
1006        """Create a |ASN.1| object initialized from the hex string.
1007
1008        Parameters
1009        ----------
1010        value: :class:`str`
1011            Text string like 'DEADBEEF'
1012        """
1013        r = []
1014        p = []
1015        for v in value:
1016            if p:
1017                r.append(int(p + v, 16))
1018                p = None
1019            else:
1020                p = v
1021        if p:
1022            r.append(int(p + '0', 16))
1023
1024        return octets.ints2octs(r)
1025
1026    # Immutable sequence object protocol
1027
1028    def __len__(self):
1029        return len(self._value)
1030
1031    def __getitem__(self, i):
1032        if i.__class__ is slice:
1033            return self.clone(self._value[i])
1034        else:
1035            return self._value[i]
1036
1037    def __iter__(self):
1038        return iter(self._value)
1039
1040    def __contains__(self, value):
1041        return value in self._value
1042
1043    def __add__(self, value):
1044        return self.clone(self._value + self.prettyIn(value))
1045
1046    def __radd__(self, value):
1047        return self.clone(self.prettyIn(value) + self._value)
1048
1049    def __mul__(self, value):
1050        return self.clone(self._value * value)
1051
1052    def __rmul__(self, value):
1053        return self * value
1054
1055    def __int__(self):
1056        return int(self._value)
1057
1058    def __float__(self):
1059        return float(self._value)
1060
1061    def __reversed__(self):
1062        return reversed(self._value)
1063
1064
1065class Null(OctetString):
1066    """Create |ASN.1| schema or value object.
1067
1068    |ASN.1| class is based on :class:`~pyasn1.type.base.SimpleAsn1Type`, its
1069    objects are immutable and duck-type Python :class:`str` objects
1070    (always empty).
1071
1072    Keyword Args
1073    ------------
1074    value: :class:`str` or |ASN.1| object
1075        Python empty :class:`str` literal or any object that evaluates to :obj:`False`
1076        If `value` is not given, schema object will be created.
1077
1078    tagSet: :py:class:`~pyasn1.type.tag.TagSet`
1079        Object representing non-default ASN.1 tag(s)
1080
1081    Raises
1082    ------
1083    ~pyasn1.error.ValueConstraintError, ~pyasn1.error.PyAsn1Error
1084        On constraint violation or bad initializer.
1085
1086    Examples
1087    --------
1088    .. code-block:: python
1089
1090        class Ack(Null):
1091            '''
1092            ASN.1 specification:
1093
1094            Ack ::= NULL
1095            '''
1096        ack = Ack('')
1097    """
1098
1099    #: Set (on class, not on instance) or return a
1100    #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s)
1101    #: associated with |ASN.1| type.
1102    tagSet = tag.initTagSet(
1103        tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 0x05)
1104    )
1105    subtypeSpec = OctetString.subtypeSpec + constraint.SingleValueConstraint(octets.str2octs(''))
1106
1107    # Optimization for faster codec lookup
1108    typeId = OctetString.getTypeId()
1109
1110    def prettyIn(self, value):
1111        if value:
1112            return value
1113
1114        return octets.str2octs('')
1115
1116if sys.version_info[0] <= 2:
1117    intTypes = (int, long)
1118else:
1119    intTypes = (int,)
1120
1121numericTypes = intTypes + (float,)
1122
1123
1124class ObjectIdentifier(base.SimpleAsn1Type):
1125    """Create |ASN.1| schema or value object.
1126
1127    |ASN.1| class is based on :class:`~pyasn1.type.base.SimpleAsn1Type`, its
1128    objects are immutable and duck-type Python :class:`tuple` objects
1129    (tuple of non-negative integers).
1130
1131    Keyword Args
1132    ------------
1133    value: :class:`tuple`, :class:`str` or |ASN.1| object
1134        Python sequence of :class:`int` or :class:`str` literal or |ASN.1| object.
1135        If `value` is not given, schema object will be created.
1136
1137    tagSet: :py:class:`~pyasn1.type.tag.TagSet`
1138        Object representing non-default ASN.1 tag(s)
1139
1140    subtypeSpec: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection`
1141        Object representing non-default ASN.1 subtype constraint(s). Constraints
1142        verification for |ASN.1| type occurs automatically on object
1143        instantiation.
1144
1145    Raises
1146    ------
1147    ~pyasn1.error.ValueConstraintError, ~pyasn1.error.PyAsn1Error
1148        On constraint violation or bad initializer.
1149
1150    Examples
1151    --------
1152    .. code-block:: python
1153
1154        class ID(ObjectIdentifier):
1155            '''
1156            ASN.1 specification:
1157
1158            ID ::= OBJECT IDENTIFIER
1159
1160            id-edims ID ::= { joint-iso-itu-t mhs-motif(6) edims(7) }
1161            id-bp ID ::= { id-edims 11 }
1162            '''
1163        id_edims = ID('2.6.7')
1164        id_bp = id_edims + (11,)
1165    """
1166    #: Set (on class, not on instance) or return a
1167    #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s)
1168    #: associated with |ASN.1| type.
1169    tagSet = tag.initTagSet(
1170        tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 0x06)
1171    )
1172
1173    #: Set (on class, not on instance) or return a
1174    #: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection` object
1175    #: imposing constraints on |ASN.1| type initialization values.
1176    subtypeSpec = constraint.ConstraintsIntersection()
1177
1178    # Optimization for faster codec lookup
1179    typeId = base.SimpleAsn1Type.getTypeId()
1180
1181    def __add__(self, other):
1182        return self.clone(self._value + other)
1183
1184    def __radd__(self, other):
1185        return self.clone(other + self._value)
1186
1187    def asTuple(self):
1188        return self._value
1189
1190    # Sequence object protocol
1191
1192    def __len__(self):
1193        return len(self._value)
1194
1195    def __getitem__(self, i):
1196        if i.__class__ is slice:
1197            return self.clone(self._value[i])
1198        else:
1199            return self._value[i]
1200
1201    def __iter__(self):
1202        return iter(self._value)
1203
1204    def __contains__(self, value):
1205        return value in self._value
1206
1207    def index(self, suboid):
1208        return self._value.index(suboid)
1209
1210    def isPrefixOf(self, other):
1211        """Indicate if this |ASN.1| object is a prefix of other |ASN.1| object.
1212
1213        Parameters
1214        ----------
1215        other: |ASN.1| object
1216            |ASN.1| object
1217
1218        Returns
1219        -------
1220        : :class:`bool`
1221            :obj:`True` if this |ASN.1| object is a parent (e.g. prefix) of the other |ASN.1| object
1222            or :obj:`False` otherwise.
1223        """
1224        l = len(self)
1225        if l <= len(other):
1226            if self._value[:l] == other[:l]:
1227                return True
1228        return False
1229
1230    def prettyIn(self, value):
1231        if isinstance(value, ObjectIdentifier):
1232            return tuple(value)
1233        elif octets.isStringType(value):
1234            if '-' in value:
1235                raise error.PyAsn1Error(
1236                    'Malformed Object ID %s at %s: %s' % (value, self.__class__.__name__, sys.exc_info()[1])
1237                )
1238            try:
1239                return tuple([int(subOid) for subOid in value.split('.') if subOid])
1240            except ValueError:
1241                raise error.PyAsn1Error(
1242                    'Malformed Object ID %s at %s: %s' % (value, self.__class__.__name__, sys.exc_info()[1])
1243                )
1244
1245        try:
1246            tupleOfInts = tuple([int(subOid) for subOid in value if subOid >= 0])
1247
1248        except (ValueError, TypeError):
1249            raise error.PyAsn1Error(
1250                'Malformed Object ID %s at %s: %s' % (value, self.__class__.__name__, sys.exc_info()[1])
1251            )
1252
1253        if len(tupleOfInts) == len(value):
1254            return tupleOfInts
1255
1256        raise error.PyAsn1Error('Malformed Object ID %s at %s' % (value, self.__class__.__name__))
1257
1258    def prettyOut(self, value):
1259        return '.'.join([str(x) for x in value])
1260
1261
1262class Real(base.SimpleAsn1Type):
1263    """Create |ASN.1| schema or value object.
1264
1265    |ASN.1| class is based on :class:`~pyasn1.type.base.SimpleAsn1Type`, its
1266    objects are immutable and duck-type Python :class:`float` objects.
1267    Additionally, |ASN.1| objects behave like a :class:`tuple` in which case its
1268    elements are mantissa, base and exponent.
1269
1270    Keyword Args
1271    ------------
1272    value: :class:`tuple`, :class:`float` or |ASN.1| object
1273        Python sequence of :class:`int` (representing mantissa, base and
1274        exponent) or :class:`float` instance or |ASN.1| object.
1275        If `value` is not given, schema object will be created.
1276
1277    tagSet: :py:class:`~pyasn1.type.tag.TagSet`
1278        Object representing non-default ASN.1 tag(s)
1279
1280    subtypeSpec: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection`
1281        Object representing non-default ASN.1 subtype constraint(s). Constraints
1282        verification for |ASN.1| type occurs automatically on object
1283        instantiation.
1284
1285    Raises
1286    ------
1287    ~pyasn1.error.ValueConstraintError, ~pyasn1.error.PyAsn1Error
1288        On constraint violation or bad initializer.
1289
1290    Examples
1291    --------
1292    .. code-block:: python
1293
1294        class Pi(Real):
1295            '''
1296            ASN.1 specification:
1297
1298            Pi ::= REAL
1299
1300            pi Pi ::= { mantissa 314159, base 10, exponent -5 }
1301
1302            '''
1303        pi = Pi((314159, 10, -5))
1304    """
1305    binEncBase = None  # binEncBase = 16 is recommended for large numbers
1306
1307    try:
1308        _plusInf = float('inf')
1309        _minusInf = float('-inf')
1310        _inf = _plusInf, _minusInf
1311
1312    except ValueError:
1313        # Infinity support is platform and Python dependent
1314        _plusInf = _minusInf = None
1315        _inf = ()
1316
1317    #: Set (on class, not on instance) or return a
1318    #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s)
1319    #: associated with |ASN.1| type.
1320    tagSet = tag.initTagSet(
1321        tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 0x09)
1322    )
1323
1324    #: Set (on class, not on instance) or return a
1325    #: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection` object
1326    #: imposing constraints on |ASN.1| type initialization values.
1327    subtypeSpec = constraint.ConstraintsIntersection()
1328
1329    # Optimization for faster codec lookup
1330    typeId = base.SimpleAsn1Type.getTypeId()
1331
1332    @staticmethod
1333    def __normalizeBase10(value):
1334        m, b, e = value
1335        while m and m % 10 == 0:
1336            m /= 10
1337            e += 1
1338        return m, b, e
1339
1340    def prettyIn(self, value):
1341        if isinstance(value, tuple) and len(value) == 3:
1342            if (not isinstance(value[0], numericTypes) or
1343                    not isinstance(value[1], intTypes) or
1344                    not isinstance(value[2], intTypes)):
1345                raise error.PyAsn1Error('Lame Real value syntax: %s' % (value,))
1346            if (isinstance(value[0], float) and
1347                    self._inf and value[0] in self._inf):
1348                return value[0]
1349            if value[1] not in (2, 10):
1350                raise error.PyAsn1Error(
1351                    'Prohibited base for Real value: %s' % (value[1],)
1352                )
1353            if value[1] == 10:
1354                value = self.__normalizeBase10(value)
1355            return value
1356        elif isinstance(value, intTypes):
1357            return self.__normalizeBase10((value, 10, 0))
1358        elif isinstance(value, float) or octets.isStringType(value):
1359            if octets.isStringType(value):
1360                try:
1361                    value = float(value)
1362                except ValueError:
1363                    raise error.PyAsn1Error(
1364                        'Bad real value syntax: %s' % (value,)
1365                    )
1366            if self._inf and value in self._inf:
1367                return value
1368            else:
1369                e = 0
1370                while int(value) != value:
1371                    value *= 10
1372                    e -= 1
1373                return self.__normalizeBase10((int(value), 10, e))
1374        elif isinstance(value, Real):
1375            return tuple(value)
1376        raise error.PyAsn1Error(
1377            'Bad real value syntax: %s' % (value,)
1378        )
1379
1380    def prettyPrint(self, scope=0):
1381        try:
1382            return self.prettyOut(float(self))
1383
1384        except OverflowError:
1385            return '<overflow>'
1386
1387    @property
1388    def isPlusInf(self):
1389        """Indicate PLUS-INFINITY object value
1390
1391        Returns
1392        -------
1393        : :class:`bool`
1394            :obj:`True` if calling object represents plus infinity
1395            or :obj:`False` otherwise.
1396
1397        """
1398        return self._value == self._plusInf
1399
1400    @property
1401    def isMinusInf(self):
1402        """Indicate MINUS-INFINITY object value
1403
1404        Returns
1405        -------
1406        : :class:`bool`
1407            :obj:`True` if calling object represents minus infinity
1408            or :obj:`False` otherwise.
1409        """
1410        return self._value == self._minusInf
1411
1412    @property
1413    def isInf(self):
1414        return self._value in self._inf
1415
1416    def __add__(self, value):
1417        return self.clone(float(self) + value)
1418
1419    def __radd__(self, value):
1420        return self + value
1421
1422    def __mul__(self, value):
1423        return self.clone(float(self) * value)
1424
1425    def __rmul__(self, value):
1426        return self * value
1427
1428    def __sub__(self, value):
1429        return self.clone(float(self) - value)
1430
1431    def __rsub__(self, value):
1432        return self.clone(value - float(self))
1433
1434    def __mod__(self, value):
1435        return self.clone(float(self) % value)
1436
1437    def __rmod__(self, value):
1438        return self.clone(value % float(self))
1439
1440    def __pow__(self, value, modulo=None):
1441        return self.clone(pow(float(self), value, modulo))
1442
1443    def __rpow__(self, value):
1444        return self.clone(pow(value, float(self)))
1445
1446    if sys.version_info[0] <= 2:
1447        def __div__(self, value):
1448            return self.clone(float(self) / value)
1449
1450        def __rdiv__(self, value):
1451            return self.clone(value / float(self))
1452    else:
1453        def __truediv__(self, value):
1454            return self.clone(float(self) / value)
1455
1456        def __rtruediv__(self, value):
1457            return self.clone(value / float(self))
1458
1459        def __divmod__(self, value):
1460            return self.clone(float(self) // value)
1461
1462        def __rdivmod__(self, value):
1463            return self.clone(value // float(self))
1464
1465    def __int__(self):
1466        return int(float(self))
1467
1468    if sys.version_info[0] <= 2:
1469        def __long__(self):
1470            return long(float(self))
1471
1472    def __float__(self):
1473        if self._value in self._inf:
1474            return self._value
1475        else:
1476            return float(
1477                self._value[0] * pow(self._value[1], self._value[2])
1478            )
1479
1480    def __abs__(self):
1481        return self.clone(abs(float(self)))
1482
1483    def __pos__(self):
1484        return self.clone(+float(self))
1485
1486    def __neg__(self):
1487        return self.clone(-float(self))
1488
1489    def __round__(self, n=0):
1490        r = round(float(self), n)
1491        if n:
1492            return self.clone(r)
1493        else:
1494            return r
1495
1496    def __floor__(self):
1497        return self.clone(math.floor(float(self)))
1498
1499    def __ceil__(self):
1500        return self.clone(math.ceil(float(self)))
1501
1502    if sys.version_info[0:2] > (2, 5):
1503        def __trunc__(self):
1504            return self.clone(math.trunc(float(self)))
1505
1506    def __lt__(self, value):
1507        return float(self) < value
1508
1509    def __le__(self, value):
1510        return float(self) <= value
1511
1512    def __eq__(self, value):
1513        return float(self) == value
1514
1515    def __ne__(self, value):
1516        return float(self) != value
1517
1518    def __gt__(self, value):
1519        return float(self) > value
1520
1521    def __ge__(self, value):
1522        return float(self) >= value
1523
1524    if sys.version_info[0] <= 2:
1525        def __nonzero__(self):
1526            return bool(float(self))
1527    else:
1528        def __bool__(self):
1529            return bool(float(self))
1530
1531        __hash__ = base.SimpleAsn1Type.__hash__
1532
1533    def __getitem__(self, idx):
1534        if self._value in self._inf:
1535            raise error.PyAsn1Error('Invalid infinite value operation')
1536        else:
1537            return self._value[idx]
1538
1539    # compatibility stubs
1540
1541    def isPlusInfinity(self):
1542        return self.isPlusInf
1543
1544    def isMinusInfinity(self):
1545        return self.isMinusInf
1546
1547    def isInfinity(self):
1548        return self.isInf
1549
1550
1551class Enumerated(Integer):
1552    """Create |ASN.1| schema or value object.
1553
1554    |ASN.1| class is based on :class:`~pyasn1.type.base.SimpleAsn1Type`, its
1555    objects are immutable and duck-type Python :class:`int` objects.
1556
1557    Keyword Args
1558    ------------
1559    value: :class:`int`, :class:`str` or |ASN.1| object
1560        Python :class:`int` or :class:`str` literal or |ASN.1| object.
1561        If `value` is not given, schema object will be created.
1562
1563    tagSet: :py:class:`~pyasn1.type.tag.TagSet`
1564        Object representing non-default ASN.1 tag(s)
1565
1566    subtypeSpec: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection`
1567        Object representing non-default ASN.1 subtype constraint(s). Constraints
1568        verification for |ASN.1| type occurs automatically on object
1569        instantiation.
1570
1571    namedValues: :py:class:`~pyasn1.type.namedval.NamedValues`
1572        Object representing non-default symbolic aliases for numbers
1573
1574    Raises
1575    ------
1576    ~pyasn1.error.ValueConstraintError, ~pyasn1.error.PyAsn1Error
1577        On constraint violation or bad initializer.
1578
1579    Examples
1580    --------
1581
1582    .. code-block:: python
1583
1584        class RadioButton(Enumerated):
1585            '''
1586            ASN.1 specification:
1587
1588            RadioButton ::= ENUMERATED { button1(0), button2(1),
1589                                         button3(2) }
1590
1591            selected-by-default RadioButton ::= button1
1592            '''
1593            namedValues = NamedValues(
1594                ('button1', 0), ('button2', 1),
1595                ('button3', 2)
1596            )
1597
1598        selected_by_default = RadioButton('button1')
1599    """
1600    #: Set (on class, not on instance) or return a
1601    #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s)
1602    #: associated with |ASN.1| type.
1603    tagSet = tag.initTagSet(
1604        tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 0x0A)
1605    )
1606
1607    #: Set (on class, not on instance) or return a
1608    #: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection` object
1609    #: imposing constraints on |ASN.1| type initialization values.
1610    subtypeSpec = constraint.ConstraintsIntersection()
1611
1612    # Optimization for faster codec lookup
1613    typeId = Integer.getTypeId()
1614
1615    #: Default :py:class:`~pyasn1.type.namedval.NamedValues` object
1616    #: representing symbolic aliases for numbers
1617    namedValues = namedval.NamedValues()
1618
1619
1620# "Structured" ASN.1 types
1621
1622class SequenceOfAndSetOfBase(base.ConstructedAsn1Type):
1623    """Create |ASN.1| schema or value object.
1624
1625    |ASN.1| class is based on :class:`~pyasn1.type.base.ConstructedAsn1Type`,
1626    its objects are mutable and duck-type Python :class:`list` objects.
1627
1628    Keyword Args
1629    ------------
1630    componentType : :py:class:`~pyasn1.type.base.PyAsn1Item` derivative
1631        A pyasn1 object representing ASN.1 type allowed within |ASN.1| type
1632
1633    tagSet: :py:class:`~pyasn1.type.tag.TagSet`
1634        Object representing non-default ASN.1 tag(s)
1635
1636    subtypeSpec: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection`
1637        Object representing non-default ASN.1 subtype constraint(s). Constraints
1638        verification for |ASN.1| type can only occur on explicit
1639        `.isInconsistent` call.
1640
1641    Examples
1642    --------
1643
1644    .. code-block:: python
1645
1646        class LotteryDraw(SequenceOf):  #  SetOf is similar
1647            '''
1648            ASN.1 specification:
1649
1650            LotteryDraw ::= SEQUENCE OF INTEGER
1651            '''
1652            componentType = Integer()
1653
1654        lotteryDraw = LotteryDraw()
1655        lotteryDraw.extend([123, 456, 789])
1656    """
1657    def __init__(self, *args, **kwargs):
1658        # support positional params for backward compatibility
1659        if args:
1660            for key, value in zip(('componentType', 'tagSet',
1661                                   'subtypeSpec'), args):
1662                if key in kwargs:
1663                    raise error.PyAsn1Error('Conflicting positional and keyword params!')
1664                kwargs['componentType'] = value
1665
1666        self._componentValues = noValue
1667
1668        base.ConstructedAsn1Type.__init__(self, **kwargs)
1669
1670    # Python list protocol
1671
1672    def __getitem__(self, idx):
1673        try:
1674            return self.getComponentByPosition(idx)
1675
1676        except error.PyAsn1Error:
1677            raise IndexError(sys.exc_info()[1])
1678
1679    def __setitem__(self, idx, value):
1680        try:
1681            self.setComponentByPosition(idx, value)
1682
1683        except error.PyAsn1Error:
1684            raise IndexError(sys.exc_info()[1])
1685
1686    def append(self, value):
1687        if self._componentValues is noValue:
1688            pos = 0
1689
1690        else:
1691            pos = len(self._componentValues)
1692
1693        self[pos] = value
1694
1695    def count(self, value):
1696        return list(self._componentValues.values()).count(value)
1697
1698    def extend(self, values):
1699        for value in values:
1700            self.append(value)
1701
1702        if self._componentValues is noValue:
1703            self._componentValues = {}
1704
1705    def index(self, value, start=0, stop=None):
1706        if stop is None:
1707            stop = len(self)
1708
1709        indices, values = zip(*self._componentValues.items())
1710
1711        # TODO: remove when Py2.5 support is gone
1712        values = list(values)
1713
1714        try:
1715            return indices[values.index(value, start, stop)]
1716
1717        except error.PyAsn1Error:
1718            raise ValueError(sys.exc_info()[1])
1719
1720    def reverse(self):
1721        self._componentValues.reverse()
1722
1723    def sort(self, key=None, reverse=False):
1724        self._componentValues = dict(
1725            enumerate(sorted(self._componentValues.values(),
1726                             key=key, reverse=reverse)))
1727
1728    def __len__(self):
1729        if self._componentValues is noValue or not self._componentValues:
1730            return 0
1731
1732        return max(self._componentValues) + 1
1733
1734    def __iter__(self):
1735        for idx in range(0, len(self)):
1736            yield self.getComponentByPosition(idx)
1737
1738    def _cloneComponentValues(self, myClone, cloneValueFlag):
1739        for idx, componentValue in self._componentValues.items():
1740            if componentValue is not noValue:
1741                if isinstance(componentValue, base.ConstructedAsn1Type):
1742                    myClone.setComponentByPosition(
1743                        idx, componentValue.clone(cloneValueFlag=cloneValueFlag)
1744                    )
1745                else:
1746                    myClone.setComponentByPosition(idx, componentValue.clone())
1747
1748    def getComponentByPosition(self, idx, default=noValue, instantiate=True):
1749        """Return |ASN.1| type component value by position.
1750
1751        Equivalent to Python sequence subscription operation (e.g. `[]`).
1752
1753        Parameters
1754        ----------
1755        idx : :class:`int`
1756            Component index (zero-based). Must either refer to an existing
1757            component or to N+1 component (if *componentType* is set). In the latter
1758            case a new component type gets instantiated and appended to the |ASN.1|
1759            sequence.
1760
1761        Keyword Args
1762        ------------
1763        default: :class:`object`
1764            If set and requested component is a schema object, return the `default`
1765            object instead of the requested component.
1766
1767        instantiate: :class:`bool`
1768            If :obj:`True` (default), inner component will be automatically instantiated.
1769            If :obj:`False` either existing component or the :class:`NoValue` object will be
1770            returned.
1771
1772        Returns
1773        -------
1774        : :py:class:`~pyasn1.type.base.PyAsn1Item`
1775            Instantiate |ASN.1| component type or return existing component value
1776
1777        Examples
1778        --------
1779
1780        .. code-block:: python
1781
1782            # can also be SetOf
1783            class MySequenceOf(SequenceOf):
1784                componentType = OctetString()
1785
1786            s = MySequenceOf()
1787
1788            # returns component #0 with `.isValue` property False
1789            s.getComponentByPosition(0)
1790
1791            # returns None
1792            s.getComponentByPosition(0, default=None)
1793
1794            s.clear()
1795
1796            # returns noValue
1797            s.getComponentByPosition(0, instantiate=False)
1798
1799            # sets component #0 to OctetString() ASN.1 schema
1800            # object and returns it
1801            s.getComponentByPosition(0, instantiate=True)
1802
1803            # sets component #0 to ASN.1 value object
1804            s.setComponentByPosition(0, 'ABCD')
1805
1806            # returns OctetString('ABCD') value object
1807            s.getComponentByPosition(0, instantiate=False)
1808
1809            s.clear()
1810
1811            # returns noValue
1812            s.getComponentByPosition(0, instantiate=False)
1813        """
1814        if isinstance(idx, slice):
1815            indices = tuple(range(len(self)))
1816            return [self.getComponentByPosition(subidx, default, instantiate)
1817                    for subidx in indices[idx]]
1818
1819        if idx < 0:
1820            idx = len(self) + idx
1821            if idx < 0:
1822                raise error.PyAsn1Error(
1823                    'SequenceOf/SetOf index is out of range')
1824
1825        try:
1826            componentValue = self._componentValues[idx]
1827
1828        except (KeyError, error.PyAsn1Error):
1829            if not instantiate:
1830                return default
1831
1832            self.setComponentByPosition(idx)
1833
1834            componentValue = self._componentValues[idx]
1835
1836        if default is noValue or componentValue.isValue:
1837            return componentValue
1838        else:
1839            return default
1840
1841    def setComponentByPosition(self, idx, value=noValue,
1842                               verifyConstraints=True,
1843                               matchTags=True,
1844                               matchConstraints=True):
1845        """Assign |ASN.1| type component by position.
1846
1847        Equivalent to Python sequence item assignment operation (e.g. `[]`)
1848        or list.append() (when idx == len(self)).
1849
1850        Parameters
1851        ----------
1852        idx: :class:`int`
1853            Component index (zero-based). Must either refer to existing
1854            component or to N+1 component. In the latter case a new component
1855            type gets instantiated (if *componentType* is set, or given ASN.1
1856            object is taken otherwise) and appended to the |ASN.1| sequence.
1857
1858        Keyword Args
1859        ------------
1860        value: :class:`object` or :py:class:`~pyasn1.type.base.PyAsn1Item` derivative
1861            A Python value to initialize |ASN.1| component with (if *componentType* is set)
1862            or ASN.1 value object to assign to |ASN.1| component.
1863            If `value` is not given, schema object will be set as a component.
1864
1865        verifyConstraints: :class:`bool`
1866             If :obj:`False`, skip constraints validation
1867
1868        matchTags: :class:`bool`
1869             If :obj:`False`, skip component tags matching
1870
1871        matchConstraints: :class:`bool`
1872             If :obj:`False`, skip component constraints matching
1873
1874        Returns
1875        -------
1876        self
1877
1878        Raises
1879        ------
1880        ~pyasn1.error.ValueConstraintError, ~pyasn1.error.PyAsn1Error
1881            On constraint violation or bad initializer
1882        IndexError
1883            When idx > len(self)
1884        """
1885        if isinstance(idx, slice):
1886            indices = tuple(range(len(self)))
1887            startIdx = indices and indices[idx][0] or 0
1888            for subIdx, subValue in enumerate(value):
1889                self.setComponentByPosition(
1890                    startIdx + subIdx, subValue, verifyConstraints,
1891                    matchTags, matchConstraints)
1892            return self
1893
1894        if idx < 0:
1895            idx = len(self) + idx
1896            if idx < 0:
1897                raise error.PyAsn1Error(
1898                    'SequenceOf/SetOf index is out of range')
1899
1900        componentType = self.componentType
1901
1902        if self._componentValues is noValue:
1903            componentValues = {}
1904
1905        else:
1906            componentValues = self._componentValues
1907
1908        currentValue = componentValues.get(idx, noValue)
1909
1910        if value is noValue:
1911            if componentType is not None:
1912                value = componentType.clone()
1913
1914            elif currentValue is noValue:
1915                raise error.PyAsn1Error('Component type not defined')
1916
1917        elif not isinstance(value, base.Asn1Item):
1918            if (componentType is not None and
1919                    isinstance(componentType, base.SimpleAsn1Type)):
1920                value = componentType.clone(value=value)
1921
1922            elif (currentValue is not noValue and
1923                    isinstance(currentValue, base.SimpleAsn1Type)):
1924                value = currentValue.clone(value=value)
1925
1926            else:
1927                raise error.PyAsn1Error(
1928                    'Non-ASN.1 value %r and undefined component'
1929                    ' type at %r' % (value, self))
1930
1931        elif componentType is not None and (matchTags or matchConstraints):
1932            subtypeChecker = (
1933                    self.strictConstraints and
1934                    componentType.isSameTypeWith or
1935                    componentType.isSuperTypeOf)
1936
1937            if not subtypeChecker(value, verifyConstraints and matchTags,
1938                                  verifyConstraints and matchConstraints):
1939                # TODO: we should wrap componentType with UnnamedType to carry
1940                # additional properties associated with componentType
1941                if componentType.typeId != Any.typeId:
1942                    raise error.PyAsn1Error(
1943                        'Component value is tag-incompatible: %r vs '
1944                        '%r' % (value, componentType))
1945
1946        componentValues[idx] = value
1947
1948        self._componentValues = componentValues
1949
1950        return self
1951
1952    @property
1953    def componentTagMap(self):
1954        if self.componentType is not None:
1955            return self.componentType.tagMap
1956
1957    @property
1958    def components(self):
1959        return [self._componentValues[idx]
1960                for idx in sorted(self._componentValues)]
1961
1962    def clear(self):
1963        """Remove all components and become an empty |ASN.1| value object.
1964
1965        Has the same effect on |ASN.1| object as it does on :class:`list`
1966        built-in.
1967        """
1968        self._componentValues = {}
1969        return self
1970
1971    def reset(self):
1972        """Remove all components and become a |ASN.1| schema object.
1973
1974        See :meth:`isValue` property for more information on the
1975        distinction between value and schema objects.
1976        """
1977        self._componentValues = noValue
1978        return self
1979
1980    def prettyPrint(self, scope=0):
1981        scope += 1
1982        representation = self.__class__.__name__ + ':\n'
1983
1984        if not self.isValue:
1985            return representation
1986
1987        for idx, componentValue in enumerate(self):
1988            representation += ' ' * scope
1989            if (componentValue is noValue and
1990                    self.componentType is not None):
1991                representation += '<empty>'
1992            else:
1993                representation += componentValue.prettyPrint(scope)
1994
1995        return representation
1996
1997    def prettyPrintType(self, scope=0):
1998        scope += 1
1999        representation = '%s -> %s {\n' % (self.tagSet, self.__class__.__name__)
2000        if self.componentType is not None:
2001            representation += ' ' * scope
2002            representation += self.componentType.prettyPrintType(scope)
2003        return representation + '\n' + ' ' * (scope - 1) + '}'
2004
2005
2006    @property
2007    def isValue(self):
2008        """Indicate that |ASN.1| object represents ASN.1 value.
2009
2010        If *isValue* is :obj:`False` then this object represents just ASN.1 schema.
2011
2012        If *isValue* is :obj:`True` then, in addition to its ASN.1 schema features,
2013        this object can also be used like a Python built-in object
2014        (e.g. :class:`int`, :class:`str`, :class:`dict` etc.).
2015
2016        Returns
2017        -------
2018        : :class:`bool`
2019            :obj:`False` if object represents just ASN.1 schema.
2020            :obj:`True` if object represents ASN.1 schema and can be used as a normal value.
2021
2022        Note
2023        ----
2024        There is an important distinction between PyASN1 schema and value objects.
2025        The PyASN1 schema objects can only participate in ASN.1 schema-related
2026        operations (e.g. defining or testing the structure of the data). Most
2027        obvious uses of ASN.1 schema is to guide serialisation codecs whilst
2028        encoding/decoding serialised ASN.1 contents.
2029
2030        The PyASN1 value objects can **additionally** participate in many operations
2031        involving regular Python objects (e.g. arithmetic, comprehension etc).
2032        """
2033        if self._componentValues is noValue:
2034            return False
2035
2036        if len(self._componentValues) != len(self):
2037            return False
2038
2039        for componentValue in self._componentValues.values():
2040            if componentValue is noValue or not componentValue.isValue:
2041                return False
2042
2043        return True
2044
2045    @property
2046    def isInconsistent(self):
2047        """Run necessary checks to ensure |ASN.1| object consistency.
2048
2049        Default action is to verify |ASN.1| object against constraints imposed
2050        by `subtypeSpec`.
2051
2052        Raises
2053        ------
2054        :py:class:`~pyasn1.error.PyAsn1tError` on any inconsistencies found
2055        """
2056        if self.componentType is noValue or not self.subtypeSpec:
2057            return False
2058
2059        if self._componentValues is noValue:
2060            return True
2061
2062        mapping = {}
2063
2064        for idx, value in self._componentValues.items():
2065            # Absent fields are not in the mapping
2066            if value is noValue:
2067                continue
2068
2069            mapping[idx] = value
2070
2071        try:
2072            # Represent SequenceOf/SetOf as a bare dict to constraints chain
2073            self.subtypeSpec(mapping)
2074
2075        except error.PyAsn1Error:
2076            exc = sys.exc_info()[1]
2077            return exc
2078
2079        return False
2080
2081class SequenceOf(SequenceOfAndSetOfBase):
2082    __doc__ = SequenceOfAndSetOfBase.__doc__
2083
2084    #: Set (on class, not on instance) or return a
2085    #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s)
2086    #: associated with |ASN.1| type.
2087    tagSet = tag.initTagSet(
2088        tag.Tag(tag.tagClassUniversal, tag.tagFormatConstructed, 0x10)
2089    )
2090
2091    #: Default :py:class:`~pyasn1.type.base.PyAsn1Item` derivative
2092    #: object representing ASN.1 type allowed within |ASN.1| type
2093    componentType = None
2094
2095    #: Set (on class, not on instance) or return a
2096    #: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection` object
2097    #: imposing constraints on |ASN.1| type initialization values.
2098    subtypeSpec = constraint.ConstraintsIntersection()
2099
2100    # Disambiguation ASN.1 types identification
2101    typeId = SequenceOfAndSetOfBase.getTypeId()
2102
2103
2104class SetOf(SequenceOfAndSetOfBase):
2105    __doc__ = SequenceOfAndSetOfBase.__doc__
2106
2107    #: Set (on class, not on instance) or return a
2108    #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s)
2109    #: associated with |ASN.1| type.
2110    tagSet = tag.initTagSet(
2111        tag.Tag(tag.tagClassUniversal, tag.tagFormatConstructed, 0x11)
2112    )
2113
2114    #: Default :py:class:`~pyasn1.type.base.PyAsn1Item` derivative
2115    #: object representing ASN.1 type allowed within |ASN.1| type
2116    componentType = None
2117
2118    #: Set (on class, not on instance) or return a
2119    #: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection` object
2120    #: imposing constraints on |ASN.1| type initialization values.
2121    subtypeSpec = constraint.ConstraintsIntersection()
2122
2123    # Disambiguation ASN.1 types identification
2124    typeId = SequenceOfAndSetOfBase.getTypeId()
2125
2126
2127class SequenceAndSetBase(base.ConstructedAsn1Type):
2128    """Create |ASN.1| schema or value object.
2129
2130    |ASN.1| class is based on :class:`~pyasn1.type.base.ConstructedAsn1Type`,
2131    its objects are mutable and duck-type Python :class:`dict` objects.
2132
2133    Keyword Args
2134    ------------
2135    componentType: :py:class:`~pyasn1.type.namedtype.NamedType`
2136        Object holding named ASN.1 types allowed within this collection
2137
2138    tagSet: :py:class:`~pyasn1.type.tag.TagSet`
2139        Object representing non-default ASN.1 tag(s)
2140
2141    subtypeSpec: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection`
2142        Object representing non-default ASN.1 subtype constraint(s).  Constraints
2143        verification for |ASN.1| type can only occur on explicit
2144        `.isInconsistent` call.
2145
2146    Examples
2147    --------
2148
2149    .. code-block:: python
2150
2151        class Description(Sequence):  #  Set is similar
2152            '''
2153            ASN.1 specification:
2154
2155            Description ::= SEQUENCE {
2156                surname    IA5String,
2157                first-name IA5String OPTIONAL,
2158                age        INTEGER DEFAULT 40
2159            }
2160            '''
2161            componentType = NamedTypes(
2162                NamedType('surname', IA5String()),
2163                OptionalNamedType('first-name', IA5String()),
2164                DefaultedNamedType('age', Integer(40))
2165            )
2166
2167        descr = Description()
2168        descr['surname'] = 'Smith'
2169        descr['first-name'] = 'John'
2170    """
2171    #: Default :py:class:`~pyasn1.type.namedtype.NamedTypes`
2172    #: object representing named ASN.1 types allowed within |ASN.1| type
2173    componentType = namedtype.NamedTypes()
2174
2175
2176    class DynamicNames(object):
2177        """Fields names/positions mapping for component-less objects"""
2178        def __init__(self):
2179            self._keyToIdxMap = {}
2180            self._idxToKeyMap = {}
2181
2182        def __len__(self):
2183            return len(self._keyToIdxMap)
2184
2185        def __contains__(self, item):
2186            return item in self._keyToIdxMap or item in self._idxToKeyMap
2187
2188        def __iter__(self):
2189            return (self._idxToKeyMap[idx] for idx in range(len(self._idxToKeyMap)))
2190
2191        def __getitem__(self, item):
2192            try:
2193                return self._keyToIdxMap[item]
2194
2195            except KeyError:
2196                return self._idxToKeyMap[item]
2197
2198        def getNameByPosition(self, idx):
2199            try:
2200                return self._idxToKeyMap[idx]
2201
2202            except KeyError:
2203                raise error.PyAsn1Error('Type position out of range')
2204
2205        def getPositionByName(self, name):
2206            try:
2207                return self._keyToIdxMap[name]
2208
2209            except KeyError:
2210                raise error.PyAsn1Error('Name %s not found' % (name,))
2211
2212        def addField(self, idx):
2213            self._keyToIdxMap['field-%d' % idx] = idx
2214            self._idxToKeyMap[idx] = 'field-%d' % idx
2215
2216
2217    def __init__(self, **kwargs):
2218        base.ConstructedAsn1Type.__init__(self, **kwargs)
2219        self._componentTypeLen = len(self.componentType)
2220        if self._componentTypeLen:
2221            self._componentValues = []
2222        else:
2223            self._componentValues = noValue
2224        self._dynamicNames = self._componentTypeLen or self.DynamicNames()
2225
2226    def __getitem__(self, idx):
2227        if octets.isStringType(idx):
2228            try:
2229                return self.getComponentByName(idx)
2230
2231            except error.PyAsn1Error:
2232                # duck-typing dict
2233                raise KeyError(sys.exc_info()[1])
2234
2235        else:
2236            try:
2237                return self.getComponentByPosition(idx)
2238
2239            except error.PyAsn1Error:
2240                # duck-typing list
2241                raise IndexError(sys.exc_info()[1])
2242
2243    def __setitem__(self, idx, value):
2244        if octets.isStringType(idx):
2245            try:
2246                self.setComponentByName(idx, value)
2247
2248            except error.PyAsn1Error:
2249                # duck-typing dict
2250                raise KeyError(sys.exc_info()[1])
2251
2252        else:
2253            try:
2254                self.setComponentByPosition(idx, value)
2255
2256            except error.PyAsn1Error:
2257                # duck-typing list
2258                raise IndexError(sys.exc_info()[1])
2259
2260    def __contains__(self, key):
2261        if self._componentTypeLen:
2262            return key in self.componentType
2263        else:
2264            return key in self._dynamicNames
2265
2266    def __len__(self):
2267        return len(self._componentValues)
2268
2269    def __iter__(self):
2270        return iter(self.componentType or self._dynamicNames)
2271
2272    # Python dict protocol
2273
2274    def values(self):
2275        for idx in range(self._componentTypeLen or len(self._dynamicNames)):
2276            yield self[idx]
2277
2278    def keys(self):
2279        return iter(self)
2280
2281    def items(self):
2282        for idx in range(self._componentTypeLen or len(self._dynamicNames)):
2283            if self._componentTypeLen:
2284                yield self.componentType[idx].name, self[idx]
2285            else:
2286                yield self._dynamicNames[idx], self[idx]
2287
2288    def update(self, *iterValue, **mappingValue):
2289        for k, v in iterValue:
2290            self[k] = v
2291        for k in mappingValue:
2292            self[k] = mappingValue[k]
2293
2294    def clear(self):
2295        """Remove all components and become an empty |ASN.1| value object.
2296
2297        Has the same effect on |ASN.1| object as it does on :class:`dict`
2298        built-in.
2299        """
2300        self._componentValues = []
2301        self._dynamicNames = self.DynamicNames()
2302        return self
2303
2304    def reset(self):
2305        """Remove all components and become a |ASN.1| schema object.
2306
2307        See :meth:`isValue` property for more information on the
2308        distinction between value and schema objects.
2309        """
2310        self._componentValues = noValue
2311        self._dynamicNames = self.DynamicNames()
2312        return self
2313
2314    @property
2315    def components(self):
2316        return self._componentValues
2317
2318    def _cloneComponentValues(self, myClone, cloneValueFlag):
2319        if self._componentValues is noValue:
2320            return
2321
2322        for idx, componentValue in enumerate(self._componentValues):
2323            if componentValue is not noValue:
2324                if isinstance(componentValue, base.ConstructedAsn1Type):
2325                    myClone.setComponentByPosition(
2326                        idx, componentValue.clone(cloneValueFlag=cloneValueFlag)
2327                    )
2328                else:
2329                    myClone.setComponentByPosition(idx, componentValue.clone())
2330
2331    def getComponentByName(self, name, default=noValue, instantiate=True):
2332        """Returns |ASN.1| type component by name.
2333
2334        Equivalent to Python :class:`dict` subscription operation (e.g. `[]`).
2335
2336        Parameters
2337        ----------
2338        name: :class:`str`
2339            |ASN.1| type component name
2340
2341        Keyword Args
2342        ------------
2343        default: :class:`object`
2344            If set and requested component is a schema object, return the `default`
2345            object instead of the requested component.
2346
2347        instantiate: :class:`bool`
2348            If :obj:`True` (default), inner component will be automatically
2349            instantiated.
2350            If :obj:`False` either existing component or the :class:`NoValue`
2351            object will be returned.
2352
2353        Returns
2354        -------
2355        : :py:class:`~pyasn1.type.base.PyAsn1Item`
2356            Instantiate |ASN.1| component type or return existing
2357            component value
2358        """
2359        if self._componentTypeLen:
2360            idx = self.componentType.getPositionByName(name)
2361        else:
2362            try:
2363                idx = self._dynamicNames.getPositionByName(name)
2364
2365            except KeyError:
2366                raise error.PyAsn1Error('Name %s not found' % (name,))
2367
2368        return self.getComponentByPosition(idx, default=default, instantiate=instantiate)
2369
2370    def setComponentByName(self, name, value=noValue,
2371                           verifyConstraints=True,
2372                           matchTags=True,
2373                           matchConstraints=True):
2374        """Assign |ASN.1| type component by name.
2375
2376        Equivalent to Python :class:`dict` item assignment operation (e.g. `[]`).
2377
2378        Parameters
2379        ----------
2380        name: :class:`str`
2381            |ASN.1| type component name
2382
2383        Keyword Args
2384        ------------
2385        value: :class:`object` or :py:class:`~pyasn1.type.base.PyAsn1Item` derivative
2386            A Python value to initialize |ASN.1| component with (if *componentType* is set)
2387            or ASN.1 value object to assign to |ASN.1| component.
2388            If `value` is not given, schema object will be set as a component.
2389
2390        verifyConstraints: :class:`bool`
2391             If :obj:`False`, skip constraints validation
2392
2393        matchTags: :class:`bool`
2394             If :obj:`False`, skip component tags matching
2395
2396        matchConstraints: :class:`bool`
2397             If :obj:`False`, skip component constraints matching
2398
2399        Returns
2400        -------
2401        self
2402        """
2403        if self._componentTypeLen:
2404            idx = self.componentType.getPositionByName(name)
2405        else:
2406            try:
2407                idx = self._dynamicNames.getPositionByName(name)
2408
2409            except KeyError:
2410                raise error.PyAsn1Error('Name %s not found' % (name,))
2411
2412        return self.setComponentByPosition(
2413            idx, value, verifyConstraints, matchTags, matchConstraints
2414        )
2415
2416    def getComponentByPosition(self, idx, default=noValue, instantiate=True):
2417        """Returns |ASN.1| type component by index.
2418
2419        Equivalent to Python sequence subscription operation (e.g. `[]`).
2420
2421        Parameters
2422        ----------
2423        idx: :class:`int`
2424            Component index (zero-based). Must either refer to an existing
2425            component or (if *componentType* is set) new ASN.1 schema object gets
2426            instantiated.
2427
2428        Keyword Args
2429        ------------
2430        default: :class:`object`
2431            If set and requested component is a schema object, return the `default`
2432            object instead of the requested component.
2433
2434        instantiate: :class:`bool`
2435            If :obj:`True` (default), inner component will be automatically
2436            instantiated.
2437            If :obj:`False` either existing component or the :class:`NoValue`
2438            object will be returned.
2439
2440        Returns
2441        -------
2442        : :py:class:`~pyasn1.type.base.PyAsn1Item`
2443            a PyASN1 object
2444
2445        Examples
2446        --------
2447
2448        .. code-block:: python
2449
2450            # can also be Set
2451            class MySequence(Sequence):
2452                componentType = NamedTypes(
2453                    NamedType('id', OctetString())
2454                )
2455
2456            s = MySequence()
2457
2458            # returns component #0 with `.isValue` property False
2459            s.getComponentByPosition(0)
2460
2461            # returns None
2462            s.getComponentByPosition(0, default=None)
2463
2464            s.clear()
2465
2466            # returns noValue
2467            s.getComponentByPosition(0, instantiate=False)
2468
2469            # sets component #0 to OctetString() ASN.1 schema
2470            # object and returns it
2471            s.getComponentByPosition(0, instantiate=True)
2472
2473            # sets component #0 to ASN.1 value object
2474            s.setComponentByPosition(0, 'ABCD')
2475
2476            # returns OctetString('ABCD') value object
2477            s.getComponentByPosition(0, instantiate=False)
2478
2479            s.clear()
2480
2481            # returns noValue
2482            s.getComponentByPosition(0, instantiate=False)
2483        """
2484        try:
2485            if self._componentValues is noValue:
2486                componentValue = noValue
2487
2488            else:
2489                componentValue = self._componentValues[idx]
2490
2491        except IndexError:
2492            componentValue = noValue
2493
2494        if not instantiate:
2495            if componentValue is noValue or not componentValue.isValue:
2496                return default
2497            else:
2498                return componentValue
2499
2500        if componentValue is noValue:
2501            self.setComponentByPosition(idx)
2502
2503        componentValue = self._componentValues[idx]
2504
2505        if default is noValue or componentValue.isValue:
2506            return componentValue
2507        else:
2508            return default
2509
2510    def setComponentByPosition(self, idx, value=noValue,
2511                               verifyConstraints=True,
2512                               matchTags=True,
2513                               matchConstraints=True):
2514        """Assign |ASN.1| type component by position.
2515
2516        Equivalent to Python sequence item assignment operation (e.g. `[]`).
2517
2518        Parameters
2519        ----------
2520        idx : :class:`int`
2521            Component index (zero-based). Must either refer to existing
2522            component (if *componentType* is set) or to N+1 component
2523            otherwise. In the latter case a new component of given ASN.1
2524            type gets instantiated and appended to |ASN.1| sequence.
2525
2526        Keyword Args
2527        ------------
2528        value: :class:`object` or :py:class:`~pyasn1.type.base.PyAsn1Item` derivative
2529            A Python value to initialize |ASN.1| component with (if *componentType* is set)
2530            or ASN.1 value object to assign to |ASN.1| component.
2531            If `value` is not given, schema object will be set as a component.
2532
2533        verifyConstraints : :class:`bool`
2534             If :obj:`False`, skip constraints validation
2535
2536        matchTags: :class:`bool`
2537             If :obj:`False`, skip component tags matching
2538
2539        matchConstraints: :class:`bool`
2540             If :obj:`False`, skip component constraints matching
2541
2542        Returns
2543        -------
2544        self
2545        """
2546        componentType = self.componentType
2547        componentTypeLen = self._componentTypeLen
2548
2549        if self._componentValues is noValue:
2550            componentValues = []
2551
2552        else:
2553            componentValues = self._componentValues
2554
2555        try:
2556            currentValue = componentValues[idx]
2557
2558        except IndexError:
2559            currentValue = noValue
2560            if componentTypeLen:
2561                if componentTypeLen < idx:
2562                    raise error.PyAsn1Error('component index out of range')
2563
2564                componentValues = [noValue] * componentTypeLen
2565
2566        if value is noValue:
2567            if componentTypeLen:
2568                value = componentType.getTypeByPosition(idx)
2569                if isinstance(value, base.ConstructedAsn1Type):
2570                    value = value.clone(cloneValueFlag=componentType[idx].isDefaulted)
2571
2572            elif currentValue is noValue:
2573                raise error.PyAsn1Error('Component type not defined')
2574
2575        elif not isinstance(value, base.Asn1Item):
2576            if componentTypeLen:
2577                subComponentType = componentType.getTypeByPosition(idx)
2578                if isinstance(subComponentType, base.SimpleAsn1Type):
2579                    value = subComponentType.clone(value=value)
2580
2581                else:
2582                    raise error.PyAsn1Error('%s can cast only scalar values' % componentType.__class__.__name__)
2583
2584            elif currentValue is not noValue and isinstance(currentValue, base.SimpleAsn1Type):
2585                value = currentValue.clone(value=value)
2586
2587            else:
2588                raise error.PyAsn1Error('%s undefined component type' % componentType.__class__.__name__)
2589
2590        elif ((verifyConstraints or matchTags or matchConstraints) and
2591              componentTypeLen):
2592            subComponentType = componentType.getTypeByPosition(idx)
2593            if subComponentType is not noValue:
2594                subtypeChecker = (self.strictConstraints and
2595                                  subComponentType.isSameTypeWith or
2596                                  subComponentType.isSuperTypeOf)
2597
2598                if not subtypeChecker(value, verifyConstraints and matchTags,
2599                                      verifyConstraints and matchConstraints):
2600                    if not componentType[idx].openType:
2601                        raise error.PyAsn1Error('Component value is tag-incompatible: %r vs %r' % (value, componentType))
2602
2603        if componentTypeLen or idx in self._dynamicNames:
2604            componentValues[idx] = value
2605
2606        elif len(componentValues) == idx:
2607            componentValues.append(value)
2608            self._dynamicNames.addField(idx)
2609
2610        else:
2611            raise error.PyAsn1Error('Component index out of range')
2612
2613        self._componentValues = componentValues
2614
2615        return self
2616
2617    @property
2618    def isValue(self):
2619        """Indicate that |ASN.1| object represents ASN.1 value.
2620
2621        If *isValue* is :obj:`False` then this object represents just ASN.1 schema.
2622
2623        If *isValue* is :obj:`True` then, in addition to its ASN.1 schema features,
2624        this object can also be used like a Python built-in object (e.g.
2625        :class:`int`, :class:`str`, :class:`dict` etc.).
2626
2627        Returns
2628        -------
2629        : :class:`bool`
2630            :obj:`False` if object represents just ASN.1 schema.
2631            :obj:`True` if object represents ASN.1 schema and can be used as a
2632            normal value.
2633
2634        Note
2635        ----
2636        There is an important distinction between PyASN1 schema and value objects.
2637        The PyASN1 schema objects can only participate in ASN.1 schema-related
2638        operations (e.g. defining or testing the structure of the data). Most
2639        obvious uses of ASN.1 schema is to guide serialisation codecs whilst
2640        encoding/decoding serialised ASN.1 contents.
2641
2642        The PyASN1 value objects can **additionally** participate in many operations
2643        involving regular Python objects (e.g. arithmetic, comprehension etc).
2644
2645        It is sufficient for |ASN.1| objects to have all non-optional and non-defaulted
2646        components being value objects to be considered as a value objects as a whole.
2647        In other words, even having one or more optional components not turned into
2648        value objects, |ASN.1| object is still considered as a value object. Defaulted
2649        components are normally value objects by default.
2650        """
2651        if self._componentValues is noValue:
2652            return False
2653
2654        componentType = self.componentType
2655
2656        if componentType:
2657            for idx, subComponentType in enumerate(componentType.namedTypes):
2658                if subComponentType.isDefaulted or subComponentType.isOptional:
2659                    continue
2660
2661                if not self._componentValues:
2662                    return False
2663
2664                componentValue = self._componentValues[idx]
2665                if componentValue is noValue or not componentValue.isValue:
2666                    return False
2667
2668        else:
2669            for componentValue in self._componentValues:
2670                if componentValue is noValue or not componentValue.isValue:
2671                    return False
2672
2673        return True
2674
2675    @property
2676    def isInconsistent(self):
2677        """Run necessary checks to ensure |ASN.1| object consistency.
2678
2679        Default action is to verify |ASN.1| object against constraints imposed
2680        by `subtypeSpec`.
2681
2682        Raises
2683        ------
2684        :py:class:`~pyasn1.error.PyAsn1tError` on any inconsistencies found
2685        """
2686        if self.componentType is noValue or not self.subtypeSpec:
2687            return False
2688
2689        if self._componentValues is noValue:
2690            return True
2691
2692        mapping = {}
2693
2694        for idx, value in enumerate(self._componentValues):
2695            # Absent fields are not in the mapping
2696            if value is noValue:
2697                continue
2698
2699            name = self.componentType.getNameByPosition(idx)
2700
2701            mapping[name] = value
2702
2703        try:
2704            # Represent Sequence/Set as a bare dict to constraints chain
2705            self.subtypeSpec(mapping)
2706
2707        except error.PyAsn1Error:
2708            exc = sys.exc_info()[1]
2709            return exc
2710
2711        return False
2712
2713    def prettyPrint(self, scope=0):
2714        """Return an object representation string.
2715
2716        Returns
2717        -------
2718        : :class:`str`
2719            Human-friendly object representation.
2720        """
2721        scope += 1
2722        representation = self.__class__.__name__ + ':\n'
2723        for idx, componentValue in enumerate(self._componentValues):
2724            if componentValue is not noValue and componentValue.isValue:
2725                representation += ' ' * scope
2726                if self.componentType:
2727                    representation += self.componentType.getNameByPosition(idx)
2728                else:
2729                    representation += self._dynamicNames.getNameByPosition(idx)
2730                representation = '%s=%s\n' % (
2731                    representation, componentValue.prettyPrint(scope)
2732                )
2733        return representation
2734
2735    def prettyPrintType(self, scope=0):
2736        scope += 1
2737        representation = '%s -> %s {\n' % (self.tagSet, self.__class__.__name__)
2738        for idx, componentType in enumerate(self.componentType.values() or self._componentValues):
2739            representation += ' ' * scope
2740            if self.componentType:
2741                representation += '"%s"' % self.componentType.getNameByPosition(idx)
2742            else:
2743                representation += '"%s"' % self._dynamicNames.getNameByPosition(idx)
2744            representation = '%s = %s\n' % (
2745                representation, componentType.prettyPrintType(scope)
2746            )
2747        return representation + '\n' + ' ' * (scope - 1) + '}'
2748
2749    # backward compatibility
2750
2751    def setDefaultComponents(self):
2752        return self
2753
2754    def getComponentType(self):
2755        if self._componentTypeLen:
2756            return self.componentType
2757
2758    def getNameByPosition(self, idx):
2759        if self._componentTypeLen:
2760            return self.componentType[idx].name
2761
2762class Sequence(SequenceAndSetBase):
2763    __doc__ = SequenceAndSetBase.__doc__
2764
2765    #: Set (on class, not on instance) or return a
2766    #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s)
2767    #: associated with |ASN.1| type.
2768    tagSet = tag.initTagSet(
2769        tag.Tag(tag.tagClassUniversal, tag.tagFormatConstructed, 0x10)
2770    )
2771
2772    #: Set (on class, not on instance) or return a
2773    #: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection` object
2774    #: imposing constraints on |ASN.1| type initialization values.
2775    subtypeSpec = constraint.ConstraintsIntersection()
2776
2777    #: Default collection of ASN.1 types of component (e.g. :py:class:`~pyasn1.type.namedtype.NamedType`)
2778    #: object imposing size constraint on |ASN.1| objects
2779    componentType = namedtype.NamedTypes()
2780
2781    # Disambiguation ASN.1 types identification
2782    typeId = SequenceAndSetBase.getTypeId()
2783
2784    # backward compatibility
2785
2786    def getComponentTagMapNearPosition(self, idx):
2787        if self.componentType:
2788            return self.componentType.getTagMapNearPosition(idx)
2789
2790    def getComponentPositionNearType(self, tagSet, idx):
2791        if self.componentType:
2792            return self.componentType.getPositionNearType(tagSet, idx)
2793        else:
2794            return idx
2795
2796
2797class Set(SequenceAndSetBase):
2798    __doc__ = SequenceAndSetBase.__doc__
2799
2800    #: Set (on class, not on instance) or return a
2801    #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s)
2802    #: associated with |ASN.1| type.
2803    tagSet = tag.initTagSet(
2804        tag.Tag(tag.tagClassUniversal, tag.tagFormatConstructed, 0x11)
2805    )
2806
2807    #: Default collection of ASN.1 types of component (e.g. :py:class:`~pyasn1.type.namedtype.NamedType`)
2808    #: object representing ASN.1 type allowed within |ASN.1| type
2809    componentType = namedtype.NamedTypes()
2810
2811    #: Set (on class, not on instance) or return a
2812    #: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection` object
2813    #: imposing constraints on |ASN.1| type initialization values.
2814    subtypeSpec = constraint.ConstraintsIntersection()
2815
2816    # Disambiguation ASN.1 types identification
2817    typeId = SequenceAndSetBase.getTypeId()
2818
2819    def getComponent(self, innerFlag=False):
2820        return self
2821
2822    def getComponentByType(self, tagSet, default=noValue,
2823                           instantiate=True, innerFlag=False):
2824        """Returns |ASN.1| type component by ASN.1 tag.
2825
2826        Parameters
2827        ----------
2828        tagSet : :py:class:`~pyasn1.type.tag.TagSet`
2829            Object representing ASN.1 tags to identify one of
2830            |ASN.1| object component
2831
2832        Keyword Args
2833        ------------
2834        default: :class:`object`
2835            If set and requested component is a schema object, return the `default`
2836            object instead of the requested component.
2837
2838        instantiate: :class:`bool`
2839            If :obj:`True` (default), inner component will be automatically
2840            instantiated.
2841            If :obj:`False` either existing component or the :class:`noValue`
2842            object will be returned.
2843
2844        Returns
2845        -------
2846        : :py:class:`~pyasn1.type.base.PyAsn1Item`
2847            a pyasn1 object
2848        """
2849        componentValue = self.getComponentByPosition(
2850            self.componentType.getPositionByType(tagSet),
2851            default=default, instantiate=instantiate
2852        )
2853        if innerFlag and isinstance(componentValue, Set):
2854            # get inner component by inner tagSet
2855            return componentValue.getComponent(innerFlag=True)
2856        else:
2857            # get outer component by inner tagSet
2858            return componentValue
2859
2860    def setComponentByType(self, tagSet, value=noValue,
2861                           verifyConstraints=True,
2862                           matchTags=True,
2863                           matchConstraints=True,
2864                           innerFlag=False):
2865        """Assign |ASN.1| type component by ASN.1 tag.
2866
2867        Parameters
2868        ----------
2869        tagSet : :py:class:`~pyasn1.type.tag.TagSet`
2870            Object representing ASN.1 tags to identify one of
2871            |ASN.1| object component
2872
2873        Keyword Args
2874        ------------
2875        value: :class:`object` or :py:class:`~pyasn1.type.base.PyAsn1Item` derivative
2876            A Python value to initialize |ASN.1| component with (if *componentType* is set)
2877            or ASN.1 value object to assign to |ASN.1| component.
2878            If `value` is not given, schema object will be set as a component.
2879
2880        verifyConstraints : :class:`bool`
2881            If :obj:`False`, skip constraints validation
2882
2883        matchTags: :class:`bool`
2884            If :obj:`False`, skip component tags matching
2885
2886        matchConstraints: :class:`bool`
2887            If :obj:`False`, skip component constraints matching
2888
2889        innerFlag: :class:`bool`
2890            If :obj:`True`, search for matching *tagSet* recursively.
2891
2892        Returns
2893        -------
2894        self
2895        """
2896        idx = self.componentType.getPositionByType(tagSet)
2897
2898        if innerFlag:  # set inner component by inner tagSet
2899            componentType = self.componentType.getTypeByPosition(idx)
2900
2901            if componentType.tagSet:
2902                return self.setComponentByPosition(
2903                    idx, value, verifyConstraints, matchTags, matchConstraints
2904                )
2905            else:
2906                componentType = self.getComponentByPosition(idx)
2907                return componentType.setComponentByType(
2908                    tagSet, value, verifyConstraints, matchTags, matchConstraints, innerFlag=innerFlag
2909                )
2910        else:  # set outer component by inner tagSet
2911            return self.setComponentByPosition(
2912                idx, value, verifyConstraints, matchTags, matchConstraints
2913            )
2914
2915    @property
2916    def componentTagMap(self):
2917        if self.componentType:
2918            return self.componentType.tagMapUnique
2919
2920
2921class Choice(Set):
2922    """Create |ASN.1| schema or value object.
2923
2924    |ASN.1| class is based on :class:`~pyasn1.type.base.ConstructedAsn1Type`,
2925    its objects are mutable and duck-type Python :class:`list` objects.
2926
2927    Keyword Args
2928    ------------
2929    componentType: :py:class:`~pyasn1.type.namedtype.NamedType`
2930        Object holding named ASN.1 types allowed within this collection
2931
2932    tagSet: :py:class:`~pyasn1.type.tag.TagSet`
2933        Object representing non-default ASN.1 tag(s)
2934
2935    subtypeSpec: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection`
2936        Object representing non-default ASN.1 subtype constraint(s).  Constraints
2937        verification for |ASN.1| type can only occur on explicit
2938        `.isInconsistent` call.
2939
2940    Examples
2941    --------
2942
2943    .. code-block:: python
2944
2945        class Afters(Choice):
2946            '''
2947            ASN.1 specification:
2948
2949            Afters ::= CHOICE {
2950                cheese  [0] IA5String,
2951                dessert [1] IA5String
2952            }
2953            '''
2954            componentType = NamedTypes(
2955                NamedType('cheese', IA5String().subtype(
2956                    implicitTag=Tag(tagClassContext, tagFormatSimple, 0)
2957                ),
2958                NamedType('dessert', IA5String().subtype(
2959                    implicitTag=Tag(tagClassContext, tagFormatSimple, 1)
2960                )
2961            )
2962
2963        afters = Afters()
2964        afters['cheese'] = 'Mascarpone'
2965    """
2966    #: Set (on class, not on instance) or return a
2967    #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s)
2968    #: associated with |ASN.1| type.
2969    tagSet = tag.TagSet()  # untagged
2970
2971    #: Default collection of ASN.1 types of component (e.g. :py:class:`~pyasn1.type.namedtype.NamedType`)
2972    #: object representing ASN.1 type allowed within |ASN.1| type
2973    componentType = namedtype.NamedTypes()
2974
2975    #: Set (on class, not on instance) or return a
2976    #: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection` object
2977    #: imposing constraints on |ASN.1| type initialization values.
2978    subtypeSpec = constraint.ConstraintsIntersection(
2979        constraint.ValueSizeConstraint(1, 1)
2980    )
2981
2982    # Disambiguation ASN.1 types identification
2983    typeId = Set.getTypeId()
2984
2985    _currentIdx = None
2986
2987    def __eq__(self, other):
2988        if self._componentValues:
2989            return self._componentValues[self._currentIdx] == other
2990        return NotImplemented
2991
2992    def __ne__(self, other):
2993        if self._componentValues:
2994            return self._componentValues[self._currentIdx] != other
2995        return NotImplemented
2996
2997    def __lt__(self, other):
2998        if self._componentValues:
2999            return self._componentValues[self._currentIdx] < other
3000        return NotImplemented
3001
3002    def __le__(self, other):
3003        if self._componentValues:
3004            return self._componentValues[self._currentIdx] <= other
3005        return NotImplemented
3006
3007    def __gt__(self, other):
3008        if self._componentValues:
3009            return self._componentValues[self._currentIdx] > other
3010        return NotImplemented
3011
3012    def __ge__(self, other):
3013        if self._componentValues:
3014            return self._componentValues[self._currentIdx] >= other
3015        return NotImplemented
3016
3017    if sys.version_info[0] <= 2:
3018        def __nonzero__(self):
3019            return self._componentValues and True or False
3020    else:
3021        def __bool__(self):
3022            return self._componentValues and True or False
3023
3024    def __len__(self):
3025        return self._currentIdx is not None and 1 or 0
3026
3027    def __contains__(self, key):
3028        if self._currentIdx is None:
3029            return False
3030        return key == self.componentType[self._currentIdx].getName()
3031
3032    def __iter__(self):
3033        if self._currentIdx is None:
3034            raise StopIteration
3035        yield self.componentType[self._currentIdx].getName()
3036
3037    # Python dict protocol
3038
3039    def values(self):
3040        if self._currentIdx is not None:
3041            yield self._componentValues[self._currentIdx]
3042
3043    def keys(self):
3044        if self._currentIdx is not None:
3045            yield self.componentType[self._currentIdx].getName()
3046
3047    def items(self):
3048        if self._currentIdx is not None:
3049            yield self.componentType[self._currentIdx].getName(), self[self._currentIdx]
3050
3051    def checkConsistency(self):
3052        if self._currentIdx is None:
3053            raise error.PyAsn1Error('Component not chosen')
3054
3055    def _cloneComponentValues(self, myClone, cloneValueFlag):
3056        try:
3057            component = self.getComponent()
3058        except error.PyAsn1Error:
3059            pass
3060        else:
3061            if isinstance(component, Choice):
3062                tagSet = component.effectiveTagSet
3063            else:
3064                tagSet = component.tagSet
3065            if isinstance(component, base.ConstructedAsn1Type):
3066                myClone.setComponentByType(
3067                    tagSet, component.clone(cloneValueFlag=cloneValueFlag)
3068                )
3069            else:
3070                myClone.setComponentByType(tagSet, component.clone())
3071
3072    def getComponentByPosition(self, idx, default=noValue, instantiate=True):
3073        __doc__ = Set.__doc__
3074
3075        if self._currentIdx is None or self._currentIdx != idx:
3076            return Set.getComponentByPosition(self, idx, default=default,
3077                                              instantiate=instantiate)
3078
3079        return self._componentValues[idx]
3080
3081    def setComponentByPosition(self, idx, value=noValue,
3082                               verifyConstraints=True,
3083                               matchTags=True,
3084                               matchConstraints=True):
3085        """Assign |ASN.1| type component by position.
3086
3087        Equivalent to Python sequence item assignment operation (e.g. `[]`).
3088
3089        Parameters
3090        ----------
3091        idx: :class:`int`
3092            Component index (zero-based). Must either refer to existing
3093            component or to N+1 component. In the latter case a new component
3094            type gets instantiated (if *componentType* is set, or given ASN.1
3095            object is taken otherwise) and appended to the |ASN.1| sequence.
3096
3097        Keyword Args
3098        ------------
3099        value: :class:`object` or :py:class:`~pyasn1.type.base.PyAsn1Item` derivative
3100            A Python value to initialize |ASN.1| component with (if *componentType* is set)
3101            or ASN.1 value object to assign to |ASN.1| component. Once a new value is
3102            set to *idx* component, previous value is dropped.
3103            If `value` is not given, schema object will be set as a component.
3104
3105        verifyConstraints : :class:`bool`
3106            If :obj:`False`, skip constraints validation
3107
3108        matchTags: :class:`bool`
3109            If :obj:`False`, skip component tags matching
3110
3111        matchConstraints: :class:`bool`
3112            If :obj:`False`, skip component constraints matching
3113
3114        Returns
3115        -------
3116        self
3117        """
3118        oldIdx = self._currentIdx
3119        Set.setComponentByPosition(self, idx, value, verifyConstraints, matchTags, matchConstraints)
3120        self._currentIdx = idx
3121        if oldIdx is not None and oldIdx != idx:
3122            self._componentValues[oldIdx] = noValue
3123        return self
3124
3125    @property
3126    def effectiveTagSet(self):
3127        """Return a :class:`~pyasn1.type.tag.TagSet` object of the currently initialized component or self (if |ASN.1| is tagged)."""
3128        if self.tagSet:
3129            return self.tagSet
3130        else:
3131            component = self.getComponent()
3132            return component.effectiveTagSet
3133
3134    @property
3135    def tagMap(self):
3136        """"Return a :class:`~pyasn1.type.tagmap.TagMap` object mapping
3137            ASN.1 tags to ASN.1 objects contained within callee.
3138        """
3139        if self.tagSet:
3140            return Set.tagMap.fget(self)
3141        else:
3142            return self.componentType.tagMapUnique
3143
3144    def getComponent(self, innerFlag=False):
3145        """Return currently assigned component of the |ASN.1| object.
3146
3147        Returns
3148        -------
3149        : :py:class:`~pyasn1.type.base.PyAsn1Item`
3150            a PyASN1 object
3151        """
3152        if self._currentIdx is None:
3153            raise error.PyAsn1Error('Component not chosen')
3154        else:
3155            c = self._componentValues[self._currentIdx]
3156            if innerFlag and isinstance(c, Choice):
3157                return c.getComponent(innerFlag)
3158            else:
3159                return c
3160
3161    def getName(self, innerFlag=False):
3162        """Return the name of currently assigned component of the |ASN.1| object.
3163
3164        Returns
3165        -------
3166        : :py:class:`str`
3167            |ASN.1| component name
3168        """
3169        if self._currentIdx is None:
3170            raise error.PyAsn1Error('Component not chosen')
3171        else:
3172            if innerFlag:
3173                c = self._componentValues[self._currentIdx]
3174                if isinstance(c, Choice):
3175                    return c.getName(innerFlag)
3176            return self.componentType.getNameByPosition(self._currentIdx)
3177
3178    @property
3179    def isValue(self):
3180        """Indicate that |ASN.1| object represents ASN.1 value.
3181
3182        If *isValue* is :obj:`False` then this object represents just ASN.1 schema.
3183
3184        If *isValue* is :obj:`True` then, in addition to its ASN.1 schema features,
3185        this object can also be used like a Python built-in object (e.g.
3186        :class:`int`, :class:`str`, :class:`dict` etc.).
3187
3188        Returns
3189        -------
3190        : :class:`bool`
3191            :obj:`False` if object represents just ASN.1 schema.
3192            :obj:`True` if object represents ASN.1 schema and can be used as a normal
3193            value.
3194
3195        Note
3196        ----
3197        There is an important distinction between PyASN1 schema and value objects.
3198        The PyASN1 schema objects can only participate in ASN.1 schema-related
3199        operations (e.g. defining or testing the structure of the data). Most
3200        obvious uses of ASN.1 schema is to guide serialisation codecs whilst
3201        encoding/decoding serialised ASN.1 contents.
3202
3203        The PyASN1 value objects can **additionally** participate in many operations
3204        involving regular Python objects (e.g. arithmetic, comprehension etc).
3205        """
3206        if self._currentIdx is None:
3207            return False
3208
3209        componentValue = self._componentValues[self._currentIdx]
3210
3211        return componentValue is not noValue and componentValue.isValue
3212
3213    def clear(self):
3214        self._currentIdx = None
3215        return Set.clear(self)
3216
3217    # compatibility stubs
3218
3219    def getMinTagSet(self):
3220        return self.minTagSet
3221
3222
3223class Any(OctetString):
3224    """Create |ASN.1| schema or value object.
3225
3226    |ASN.1| class is based on :class:`~pyasn1.type.base.SimpleAsn1Type`,
3227    its objects are immutable and duck-type Python 2 :class:`str` or Python 3
3228    :class:`bytes`. When used in Unicode context, |ASN.1| type assumes
3229    "|encoding|" serialisation.
3230
3231    Keyword Args
3232    ------------
3233    value: :class:`unicode`, :class:`str`, :class:`bytes` or |ASN.1| object
3234        :class:`str` (Python 2) or :class:`bytes` (Python 3), alternatively
3235        :class:`unicode` object (Python 2) or :class:`str` (Python 3)
3236        representing character string to be serialised into octets (note
3237        `encoding` parameter) or |ASN.1| object.
3238        If `value` is not given, schema object will be created.
3239
3240    tagSet: :py:class:`~pyasn1.type.tag.TagSet`
3241        Object representing non-default ASN.1 tag(s)
3242
3243    subtypeSpec: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection`
3244        Object representing non-default ASN.1 subtype constraint(s). Constraints
3245        verification for |ASN.1| type occurs automatically on object
3246        instantiation.
3247
3248    encoding: :py:class:`str`
3249        Unicode codec ID to encode/decode :class:`unicode` (Python 2) or
3250        :class:`str` (Python 3) the payload when |ASN.1| object is used
3251        in text string context.
3252
3253    binValue: :py:class:`str`
3254        Binary string initializer to use instead of the *value*.
3255        Example: '10110011'.
3256
3257    hexValue: :py:class:`str`
3258        Hexadecimal string initializer to use instead of the *value*.
3259        Example: 'DEADBEEF'.
3260
3261    Raises
3262    ------
3263    ~pyasn1.error.ValueConstraintError, ~pyasn1.error.PyAsn1Error
3264        On constraint violation or bad initializer.
3265
3266    Examples
3267    --------
3268    .. code-block:: python
3269
3270        class Error(Sequence):
3271            '''
3272            ASN.1 specification:
3273
3274            Error ::= SEQUENCE {
3275                code      INTEGER,
3276                parameter ANY DEFINED BY code  -- Either INTEGER or REAL
3277            }
3278            '''
3279            componentType=NamedTypes(
3280                NamedType('code', Integer()),
3281                NamedType('parameter', Any(),
3282                          openType=OpenType('code', {1: Integer(),
3283                                                     2: Real()}))
3284            )
3285
3286        error = Error()
3287        error['code'] = 1
3288        error['parameter'] = Integer(1234)
3289    """
3290    #: Set (on class, not on instance) or return a
3291    #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s)
3292    #: associated with |ASN.1| type.
3293    tagSet = tag.TagSet()  # untagged
3294
3295    #: Set (on class, not on instance) or return a
3296    #: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection` object
3297    #: imposing constraints on |ASN.1| type initialization values.
3298    subtypeSpec = constraint.ConstraintsIntersection()
3299
3300    # Disambiguation ASN.1 types identification
3301    typeId = OctetString.getTypeId()
3302
3303    @property
3304    def tagMap(self):
3305        """"Return a :class:`~pyasn1.type.tagmap.TagMap` object mapping
3306            ASN.1 tags to ASN.1 objects contained within callee.
3307        """
3308        try:
3309            return self._tagMap
3310
3311        except AttributeError:
3312            self._tagMap = tagmap.TagMap(
3313                {self.tagSet: self},
3314                {eoo.endOfOctets.tagSet: eoo.endOfOctets},
3315                self
3316            )
3317
3318            return self._tagMap
3319
3320# XXX
3321# coercion rules?
3322