Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/pyasn1/type/univ.py: 38%
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1#
2# This file is part of pyasn1 software.
3#
4# Copyright (c) 2005-2020, Ilya Etingof <etingof@gmail.com>
5# License: https://pyasn1.readthedocs.io/en/latest/license.html
6#
7import math
8import sys
10from pyasn1 import error
11from pyasn1.codec.ber import eoo
12from pyasn1.compat import integer
13from pyasn1.compat import octets
14from pyasn1.type import base
15from pyasn1.type import constraint
16from pyasn1.type import namedtype
17from pyasn1.type import namedval
18from pyasn1.type import tag
19from pyasn1.type import tagmap
21NoValue = base.NoValue
22noValue = NoValue()
24__all__ = ['Integer', 'Boolean', 'BitString', 'OctetString', 'Null',
25 'ObjectIdentifier', 'Real', 'Enumerated',
26 'SequenceOfAndSetOfBase', 'SequenceOf', 'SetOf',
27 'SequenceAndSetBase', 'Sequence', 'Set', 'Choice', 'Any',
28 'NoValue', 'noValue']
30# "Simple" ASN.1 types (yet incomplete)
33class Integer(base.SimpleAsn1Type):
34 """Create |ASN.1| schema or value object.
36 |ASN.1| class is based on :class:`~pyasn1.type.base.SimpleAsn1Type`, its
37 objects are immutable and duck-type Python :class:`int` objects.
39 Keyword Args
40 ------------
41 value: :class:`int`, :class:`str` or |ASN.1| object
42 Python :class:`int` or :class:`str` literal or |ASN.1| class
43 instance. If `value` is not given, schema object will be created.
45 tagSet: :py:class:`~pyasn1.type.tag.TagSet`
46 Object representing non-default ASN.1 tag(s)
48 subtypeSpec: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection`
49 Object representing non-default ASN.1 subtype constraint(s). Constraints
50 verification for |ASN.1| type occurs automatically on object
51 instantiation.
53 namedValues: :py:class:`~pyasn1.type.namedval.NamedValues`
54 Object representing non-default symbolic aliases for numbers
56 Raises
57 ------
58 ~pyasn1.error.ValueConstraintError, ~pyasn1.error.PyAsn1Error
59 On constraint violation or bad initializer.
61 Examples
62 --------
64 .. code-block:: python
66 class ErrorCode(Integer):
67 '''
68 ASN.1 specification:
70 ErrorCode ::=
71 INTEGER { disk-full(1), no-disk(-1),
72 disk-not-formatted(2) }
74 error ErrorCode ::= disk-full
75 '''
76 namedValues = NamedValues(
77 ('disk-full', 1), ('no-disk', -1),
78 ('disk-not-formatted', 2)
79 )
81 error = ErrorCode('disk-full')
82 """
83 #: Set (on class, not on instance) or return a
84 #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s)
85 #: associated with |ASN.1| type.
86 tagSet = tag.initTagSet(
87 tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 0x02)
88 )
90 #: Set (on class, not on instance) or return a
91 #: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection` object
92 #: imposing constraints on |ASN.1| type initialization values.
93 subtypeSpec = constraint.ConstraintsIntersection()
95 #: Default :py:class:`~pyasn1.type.namedval.NamedValues` object
96 #: representing symbolic aliases for numbers
97 namedValues = namedval.NamedValues()
99 # Optimization for faster codec lookup
100 typeId = base.SimpleAsn1Type.getTypeId()
102 def __init__(self, value=noValue, **kwargs):
103 if 'namedValues' not in kwargs:
104 kwargs['namedValues'] = self.namedValues
106 base.SimpleAsn1Type.__init__(self, value, **kwargs)
108 def __and__(self, value):
109 return self.clone(self._value & value)
111 def __rand__(self, value):
112 return self.clone(value & self._value)
114 def __or__(self, value):
115 return self.clone(self._value | value)
117 def __ror__(self, value):
118 return self.clone(value | self._value)
120 def __xor__(self, value):
121 return self.clone(self._value ^ value)
123 def __rxor__(self, value):
124 return self.clone(value ^ self._value)
126 def __lshift__(self, value):
127 return self.clone(self._value << value)
129 def __rshift__(self, value):
130 return self.clone(self._value >> value)
132 def __add__(self, value):
133 return self.clone(self._value + value)
135 def __radd__(self, value):
136 return self.clone(value + self._value)
138 def __sub__(self, value):
139 return self.clone(self._value - value)
141 def __rsub__(self, value):
142 return self.clone(value - self._value)
144 def __mul__(self, value):
145 return self.clone(self._value * value)
147 def __rmul__(self, value):
148 return self.clone(value * self._value)
150 def __mod__(self, value):
151 return self.clone(self._value % value)
153 def __rmod__(self, value):
154 return self.clone(value % self._value)
156 def __pow__(self, value, modulo=None):
157 return self.clone(pow(self._value, value, modulo))
159 def __rpow__(self, value):
160 return self.clone(pow(value, self._value))
162 def __floordiv__(self, value):
163 return self.clone(self._value // value)
165 def __rfloordiv__(self, value):
166 return self.clone(value // self._value)
168 if sys.version_info[0] <= 2:
169 def __div__(self, value):
170 if isinstance(value, float):
171 return Real(self._value / value)
172 else:
173 return self.clone(self._value / value)
175 def __rdiv__(self, value):
176 if isinstance(value, float):
177 return Real(value / self._value)
178 else:
179 return self.clone(value / self._value)
180 else:
181 def __truediv__(self, value):
182 return Real(self._value / value)
184 def __rtruediv__(self, value):
185 return Real(value / self._value)
187 def __divmod__(self, value):
188 return self.clone(divmod(self._value, value))
190 def __rdivmod__(self, value):
191 return self.clone(divmod(value, self._value))
193 __hash__ = base.SimpleAsn1Type.__hash__
195 def __int__(self):
196 return int(self._value)
198 if sys.version_info[0] <= 2:
199 def __long__(self):
200 return long(self._value)
202 def __float__(self):
203 return float(self._value)
205 def __abs__(self):
206 return self.clone(abs(self._value))
208 def __index__(self):
209 return int(self._value)
211 def __pos__(self):
212 return self.clone(+self._value)
214 def __neg__(self):
215 return self.clone(-self._value)
217 def __invert__(self):
218 return self.clone(~self._value)
220 def __round__(self, n=0):
221 r = round(self._value, n)
222 if n:
223 return self.clone(r)
224 else:
225 return r
227 def __floor__(self):
228 return math.floor(self._value)
230 def __ceil__(self):
231 return math.ceil(self._value)
233 def __trunc__(self):
234 return self.clone(math.trunc(self._value))
236 def __lt__(self, value):
237 return self._value < value
239 def __le__(self, value):
240 return self._value <= value
242 def __eq__(self, value):
243 return self._value == value
245 def __ne__(self, value):
246 return self._value != value
248 def __gt__(self, value):
249 return self._value > value
251 def __ge__(self, value):
252 return self._value >= value
254 def prettyIn(self, value):
255 try:
256 return int(value)
258 except ValueError:
259 try:
260 return self.namedValues[value]
262 except KeyError:
263 raise error.PyAsn1Error(
264 'Can\'t coerce %r into integer: %s' % (value, sys.exc_info()[1])
265 )
267 def prettyOut(self, value):
268 try:
269 return str(self.namedValues[value])
271 except KeyError:
272 return str(value)
274 # backward compatibility
276 def getNamedValues(self):
277 return self.namedValues
280class Boolean(Integer):
281 """Create |ASN.1| schema or value object.
283 |ASN.1| class is based on :class:`~pyasn1.type.base.SimpleAsn1Type`, its
284 objects are immutable and duck-type Python :class:`int` objects.
286 Keyword Args
287 ------------
288 value: :class:`int`, :class:`str` or |ASN.1| object
289 Python :class:`int` or :class:`str` literal or |ASN.1| class
290 instance. If `value` is not given, schema object will be created.
292 tagSet: :py:class:`~pyasn1.type.tag.TagSet`
293 Object representing non-default ASN.1 tag(s)
295 subtypeSpec: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection`
296 Object representing non-default ASN.1 subtype constraint(s).Constraints
297 verification for |ASN.1| type occurs automatically on object
298 instantiation.
300 namedValues: :py:class:`~pyasn1.type.namedval.NamedValues`
301 Object representing non-default symbolic aliases for numbers
303 Raises
304 ------
305 ~pyasn1.error.ValueConstraintError, ~pyasn1.error.PyAsn1Error
306 On constraint violation or bad initializer.
308 Examples
309 --------
310 .. code-block:: python
312 class RoundResult(Boolean):
313 '''
314 ASN.1 specification:
316 RoundResult ::= BOOLEAN
318 ok RoundResult ::= TRUE
319 ko RoundResult ::= FALSE
320 '''
321 ok = RoundResult(True)
322 ko = RoundResult(False)
323 """
324 #: Set (on class, not on instance) or return a
325 #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s)
326 #: associated with |ASN.1| type.
327 tagSet = tag.initTagSet(
328 tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 0x01),
329 )
331 #: Set (on class, not on instance) or return a
332 #: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection` object
333 #: imposing constraints on |ASN.1| type initialization values.
334 subtypeSpec = Integer.subtypeSpec + constraint.SingleValueConstraint(0, 1)
336 #: Default :py:class:`~pyasn1.type.namedval.NamedValues` object
337 #: representing symbolic aliases for numbers
338 namedValues = namedval.NamedValues(('False', 0), ('True', 1))
340 # Optimization for faster codec lookup
341 typeId = Integer.getTypeId()
343if sys.version_info[0] < 3:
344 SizedIntegerBase = long
345else:
346 SizedIntegerBase = int
349class SizedInteger(SizedIntegerBase):
350 bitLength = leadingZeroBits = None
352 def setBitLength(self, bitLength):
353 self.bitLength = bitLength
354 self.leadingZeroBits = max(bitLength - integer.bitLength(self), 0)
355 return self
357 def __len__(self):
358 if self.bitLength is None:
359 self.setBitLength(integer.bitLength(self))
361 return self.bitLength
364class BitString(base.SimpleAsn1Type):
365 """Create |ASN.1| schema or value object.
367 |ASN.1| class is based on :class:`~pyasn1.type.base.SimpleAsn1Type`, its
368 objects are immutable and duck-type both Python :class:`tuple` (as a tuple
369 of bits) and :class:`int` objects.
371 Keyword Args
372 ------------
373 value: :class:`int`, :class:`str` or |ASN.1| object
374 Python :class:`int` or :class:`str` literal representing binary
375 or hexadecimal number or sequence of integer bits or |ASN.1| object.
376 If `value` is not given, schema object will be created.
378 tagSet: :py:class:`~pyasn1.type.tag.TagSet`
379 Object representing non-default ASN.1 tag(s)
381 subtypeSpec: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection`
382 Object representing non-default ASN.1 subtype constraint(s). Constraints
383 verification for |ASN.1| type occurs automatically on object
384 instantiation.
386 namedValues: :py:class:`~pyasn1.type.namedval.NamedValues`
387 Object representing non-default symbolic aliases for numbers
389 binValue: :py:class:`str`
390 Binary string initializer to use instead of the *value*.
391 Example: '10110011'.
393 hexValue: :py:class:`str`
394 Hexadecimal string initializer to use instead of the *value*.
395 Example: 'DEADBEEF'.
397 Raises
398 ------
399 ~pyasn1.error.ValueConstraintError, ~pyasn1.error.PyAsn1Error
400 On constraint violation or bad initializer.
402 Examples
403 --------
404 .. code-block:: python
406 class Rights(BitString):
407 '''
408 ASN.1 specification:
410 Rights ::= BIT STRING { user-read(0), user-write(1),
411 group-read(2), group-write(3),
412 other-read(4), other-write(5) }
414 group1 Rights ::= { group-read, group-write }
415 group2 Rights ::= '0011'B
416 group3 Rights ::= '3'H
417 '''
418 namedValues = NamedValues(
419 ('user-read', 0), ('user-write', 1),
420 ('group-read', 2), ('group-write', 3),
421 ('other-read', 4), ('other-write', 5)
422 )
424 group1 = Rights(('group-read', 'group-write'))
425 group2 = Rights('0011')
426 group3 = Rights(0x3)
427 """
428 #: Set (on class, not on instance) or return a
429 #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s)
430 #: associated with |ASN.1| type.
431 tagSet = tag.initTagSet(
432 tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 0x03)
433 )
435 #: Set (on class, not on instance) or return a
436 #: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection` object
437 #: imposing constraints on |ASN.1| type initialization values.
438 subtypeSpec = constraint.ConstraintsIntersection()
440 #: Default :py:class:`~pyasn1.type.namedval.NamedValues` object
441 #: representing symbolic aliases for numbers
442 namedValues = namedval.NamedValues()
444 # Optimization for faster codec lookup
445 typeId = base.SimpleAsn1Type.getTypeId()
447 defaultBinValue = defaultHexValue = noValue
449 def __init__(self, value=noValue, **kwargs):
450 if value is noValue:
451 if kwargs:
452 try:
453 value = self.fromBinaryString(kwargs.pop('binValue'), internalFormat=True)
455 except KeyError:
456 pass
458 try:
459 value = self.fromHexString(kwargs.pop('hexValue'), internalFormat=True)
461 except KeyError:
462 pass
464 if value is noValue:
465 if self.defaultBinValue is not noValue:
466 value = self.fromBinaryString(self.defaultBinValue, internalFormat=True)
468 elif self.defaultHexValue is not noValue:
469 value = self.fromHexString(self.defaultHexValue, internalFormat=True)
471 if 'namedValues' not in kwargs:
472 kwargs['namedValues'] = self.namedValues
474 base.SimpleAsn1Type.__init__(self, value, **kwargs)
476 def __str__(self):
477 return self.asBinary()
479 def __eq__(self, other):
480 other = self.prettyIn(other)
481 return self is other or self._value == other and len(self._value) == len(other)
483 def __ne__(self, other):
484 other = self.prettyIn(other)
485 return self._value != other or len(self._value) != len(other)
487 def __lt__(self, other):
488 other = self.prettyIn(other)
489 return len(self._value) < len(other) or len(self._value) == len(other) and self._value < other
491 def __le__(self, other):
492 other = self.prettyIn(other)
493 return len(self._value) <= len(other) or len(self._value) == len(other) and self._value <= other
495 def __gt__(self, other):
496 other = self.prettyIn(other)
497 return len(self._value) > len(other) or len(self._value) == len(other) and self._value > other
499 def __ge__(self, other):
500 other = self.prettyIn(other)
501 return len(self._value) >= len(other) or len(self._value) == len(other) and self._value >= other
503 # Immutable sequence object protocol
505 def __len__(self):
506 return len(self._value)
508 def __getitem__(self, i):
509 if i.__class__ is slice:
510 return self.clone([self[x] for x in range(*i.indices(len(self)))])
511 else:
512 length = len(self._value) - 1
513 if i > length or i < 0:
514 raise IndexError('bit index out of range')
515 return (self._value >> (length - i)) & 1
517 def __iter__(self):
518 length = len(self._value)
519 while length:
520 length -= 1
521 yield (self._value >> length) & 1
523 def __reversed__(self):
524 return reversed(tuple(self))
526 # arithmetic operators
528 def __add__(self, value):
529 value = self.prettyIn(value)
530 return self.clone(SizedInteger(self._value << len(value) | value).setBitLength(len(self._value) + len(value)))
532 def __radd__(self, value):
533 value = self.prettyIn(value)
534 return self.clone(SizedInteger(value << len(self._value) | self._value).setBitLength(len(self._value) + len(value)))
536 def __mul__(self, value):
537 bitString = self._value
538 while value > 1:
539 bitString <<= len(self._value)
540 bitString |= self._value
541 value -= 1
542 return self.clone(bitString)
544 def __rmul__(self, value):
545 return self * value
547 def __lshift__(self, count):
548 return self.clone(SizedInteger(self._value << count).setBitLength(len(self._value) + count))
550 def __rshift__(self, count):
551 return self.clone(SizedInteger(self._value >> count).setBitLength(max(0, len(self._value) - count)))
553 def __int__(self):
554 return int(self._value)
556 def __float__(self):
557 return float(self._value)
559 if sys.version_info[0] < 3:
560 def __long__(self):
561 return self._value
563 def asNumbers(self):
564 """Get |ASN.1| value as a sequence of 8-bit integers.
566 If |ASN.1| object length is not a multiple of 8, result
567 will be left-padded with zeros.
568 """
569 return tuple(octets.octs2ints(self.asOctets()))
571 def asOctets(self):
572 """Get |ASN.1| value as a sequence of octets.
574 If |ASN.1| object length is not a multiple of 8, result
575 will be left-padded with zeros.
576 """
577 return integer.to_bytes(self._value, length=len(self))
579 def asInteger(self):
580 """Get |ASN.1| value as a single integer value.
581 """
582 return self._value
584 def asBinary(self):
585 """Get |ASN.1| value as a text string of bits.
586 """
587 binString = bin(self._value)[2:]
588 return '0' * (len(self._value) - len(binString)) + binString
590 @classmethod
591 def fromHexString(cls, value, internalFormat=False, prepend=None):
592 """Create a |ASN.1| object initialized from the hex string.
594 Parameters
595 ----------
596 value: :class:`str`
597 Text string like 'DEADBEEF'
598 """
599 try:
600 value = SizedInteger(value, 16).setBitLength(len(value) * 4)
602 except ValueError:
603 raise error.PyAsn1Error('%s.fromHexString() error: %s' % (cls.__name__, sys.exc_info()[1]))
605 if prepend is not None:
606 value = SizedInteger(
607 (SizedInteger(prepend) << len(value)) | value
608 ).setBitLength(len(prepend) + len(value))
610 if not internalFormat:
611 value = cls(value)
613 return value
615 @classmethod
616 def fromBinaryString(cls, value, internalFormat=False, prepend=None):
617 """Create a |ASN.1| object initialized from a string of '0' and '1'.
619 Parameters
620 ----------
621 value: :class:`str`
622 Text string like '1010111'
623 """
624 try:
625 value = SizedInteger(value or '0', 2).setBitLength(len(value))
627 except ValueError:
628 raise error.PyAsn1Error('%s.fromBinaryString() error: %s' % (cls.__name__, sys.exc_info()[1]))
630 if prepend is not None:
631 value = SizedInteger(
632 (SizedInteger(prepend) << len(value)) | value
633 ).setBitLength(len(prepend) + len(value))
635 if not internalFormat:
636 value = cls(value)
638 return value
640 @classmethod
641 def fromOctetString(cls, value, internalFormat=False, prepend=None, padding=0):
642 """Create a |ASN.1| object initialized from a string.
644 Parameters
645 ----------
646 value: :class:`str` (Py2) or :class:`bytes` (Py3)
647 Text string like '\\\\x01\\\\xff' (Py2) or b'\\\\x01\\\\xff' (Py3)
648 """
649 value = SizedInteger(integer.from_bytes(value) >> padding).setBitLength(len(value) * 8 - padding)
651 if prepend is not None:
652 value = SizedInteger(
653 (SizedInteger(prepend) << len(value)) | value
654 ).setBitLength(len(prepend) + len(value))
656 if not internalFormat:
657 value = cls(value)
659 return value
661 def prettyIn(self, value):
662 if isinstance(value, SizedInteger):
663 return value
664 elif octets.isStringType(value):
665 if not value:
666 return SizedInteger(0).setBitLength(0)
668 elif value[0] == '\'': # "'1011'B" -- ASN.1 schema representation (deprecated)
669 if value[-2:] == '\'B':
670 return self.fromBinaryString(value[1:-2], internalFormat=True)
671 elif value[-2:] == '\'H':
672 return self.fromHexString(value[1:-2], internalFormat=True)
673 else:
674 raise error.PyAsn1Error(
675 'Bad BIT STRING value notation %s' % (value,)
676 )
678 elif self.namedValues and not value.isdigit(): # named bits like 'Urgent, Active'
679 names = [x.strip() for x in value.split(',')]
681 try:
683 bitPositions = [self.namedValues[name] for name in names]
685 except KeyError:
686 raise error.PyAsn1Error('unknown bit name(s) in %r' % (names,))
688 rightmostPosition = max(bitPositions)
690 number = 0
691 for bitPosition in bitPositions:
692 number |= 1 << (rightmostPosition - bitPosition)
694 return SizedInteger(number).setBitLength(rightmostPosition + 1)
696 elif value.startswith('0x'):
697 return self.fromHexString(value[2:], internalFormat=True)
699 elif value.startswith('0b'):
700 return self.fromBinaryString(value[2:], internalFormat=True)
702 else: # assume plain binary string like '1011'
703 return self.fromBinaryString(value, internalFormat=True)
705 elif isinstance(value, (tuple, list)):
706 return self.fromBinaryString(''.join([b and '1' or '0' for b in value]), internalFormat=True)
708 elif isinstance(value, BitString):
709 return SizedInteger(value).setBitLength(len(value))
711 elif isinstance(value, intTypes):
712 return SizedInteger(value)
714 else:
715 raise error.PyAsn1Error(
716 'Bad BitString initializer type \'%s\'' % (value,)
717 )
720class OctetString(base.SimpleAsn1Type):
721 """Create |ASN.1| schema or value object.
723 |ASN.1| class is based on :class:`~pyasn1.type.base.SimpleAsn1Type`, its
724 objects are immutable and duck-type Python 2 :class:`str` or
725 Python 3 :class:`bytes`. When used in Unicode context, |ASN.1| type
726 assumes "|encoding|" serialisation.
728 Keyword Args
729 ------------
730 value: :class:`unicode`, :class:`str`, :class:`bytes` or |ASN.1| object
731 class:`str` (Python 2) or :class:`bytes` (Python 3), alternatively
732 class:`unicode` object (Python 2) or :class:`str` (Python 3)
733 representing character string to be serialised into octets
734 (note `encoding` parameter) or |ASN.1| object.
735 If `value` is not given, schema object will be created.
737 tagSet: :py:class:`~pyasn1.type.tag.TagSet`
738 Object representing non-default ASN.1 tag(s)
740 subtypeSpec: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection`
741 Object representing non-default ASN.1 subtype constraint(s). Constraints
742 verification for |ASN.1| type occurs automatically on object
743 instantiation.
745 encoding: :py:class:`str`
746 Unicode codec ID to encode/decode :class:`unicode` (Python 2) or
747 :class:`str` (Python 3) the payload when |ASN.1| object is used
748 in text string context.
750 binValue: :py:class:`str`
751 Binary string initializer to use instead of the *value*.
752 Example: '10110011'.
754 hexValue: :py:class:`str`
755 Hexadecimal string initializer to use instead of the *value*.
756 Example: 'DEADBEEF'.
758 Raises
759 ------
760 ~pyasn1.error.ValueConstraintError, ~pyasn1.error.PyAsn1Error
761 On constraint violation or bad initializer.
763 Examples
764 --------
765 .. code-block:: python
767 class Icon(OctetString):
768 '''
769 ASN.1 specification:
771 Icon ::= OCTET STRING
773 icon1 Icon ::= '001100010011001000110011'B
774 icon2 Icon ::= '313233'H
775 '''
776 icon1 = Icon.fromBinaryString('001100010011001000110011')
777 icon2 = Icon.fromHexString('313233')
778 """
779 #: Set (on class, not on instance) or return a
780 #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s)
781 #: associated with |ASN.1| type.
782 tagSet = tag.initTagSet(
783 tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 0x04)
784 )
786 #: Set (on class, not on instance) or return a
787 #: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection` object
788 #: imposing constraints on |ASN.1| type initialization values.
789 subtypeSpec = constraint.ConstraintsIntersection()
791 # Optimization for faster codec lookup
792 typeId = base.SimpleAsn1Type.getTypeId()
794 defaultBinValue = defaultHexValue = noValue
795 encoding = 'iso-8859-1'
797 def __init__(self, value=noValue, **kwargs):
798 if kwargs:
799 if value is noValue:
800 try:
801 value = self.fromBinaryString(kwargs.pop('binValue'))
803 except KeyError:
804 pass
806 try:
807 value = self.fromHexString(kwargs.pop('hexValue'))
809 except KeyError:
810 pass
812 if value is noValue:
813 if self.defaultBinValue is not noValue:
814 value = self.fromBinaryString(self.defaultBinValue)
816 elif self.defaultHexValue is not noValue:
817 value = self.fromHexString(self.defaultHexValue)
819 if 'encoding' not in kwargs:
820 kwargs['encoding'] = self.encoding
822 base.SimpleAsn1Type.__init__(self, value, **kwargs)
824 if sys.version_info[0] <= 2:
825 def prettyIn(self, value):
826 if isinstance(value, str):
827 return value
829 elif isinstance(value, unicode):
830 try:
831 return value.encode(self.encoding)
833 except (LookupError, UnicodeEncodeError):
834 exc = sys.exc_info()[1]
835 raise error.PyAsn1UnicodeEncodeError(
836 "Can't encode string '%s' with codec "
837 "%s" % (value, self.encoding), exc
838 )
840 elif isinstance(value, (tuple, list)):
841 try:
842 return ''.join([chr(x) for x in value])
844 except ValueError:
845 raise error.PyAsn1Error(
846 "Bad %s initializer '%s'" % (self.__class__.__name__, value)
847 )
849 else:
850 return str(value)
852 def __str__(self):
853 return str(self._value)
855 def __unicode__(self):
856 try:
857 return self._value.decode(self.encoding)
859 except UnicodeDecodeError:
860 exc = sys.exc_info()[1]
861 raise error.PyAsn1UnicodeDecodeError(
862 "Can't decode string '%s' with codec "
863 "%s" % (self._value, self.encoding), exc
864 )
866 def asOctets(self):
867 return str(self._value)
869 def asNumbers(self):
870 return tuple([ord(x) for x in self._value])
872 else:
873 def prettyIn(self, value):
874 if isinstance(value, bytes):
875 return value
877 elif isinstance(value, str):
878 try:
879 return value.encode(self.encoding)
881 except UnicodeEncodeError:
882 exc = sys.exc_info()[1]
883 raise error.PyAsn1UnicodeEncodeError(
884 "Can't encode string '%s' with '%s' "
885 "codec" % (value, self.encoding), exc
886 )
887 elif isinstance(value, OctetString): # a shortcut, bytes() would work the same way
888 return value.asOctets()
890 elif isinstance(value, base.SimpleAsn1Type): # this mostly targets Integer objects
891 return self.prettyIn(str(value))
893 elif isinstance(value, (tuple, list)):
894 return self.prettyIn(bytes(value))
896 else:
897 return bytes(value)
899 def __str__(self):
900 try:
901 return self._value.decode(self.encoding)
903 except UnicodeDecodeError:
904 exc = sys.exc_info()[1]
905 raise error.PyAsn1UnicodeDecodeError(
906 "Can't decode string '%s' with '%s' codec at "
907 "'%s'" % (self._value, self.encoding,
908 self.__class__.__name__), exc
909 )
911 def __bytes__(self):
912 return bytes(self._value)
914 def asOctets(self):
915 return bytes(self._value)
917 def asNumbers(self):
918 return tuple(self._value)
920 #
921 # Normally, `.prettyPrint()` is called from `__str__()`. Historically,
922 # OctetString.prettyPrint() used to return hexified payload
923 # representation in cases when non-printable content is present. At the
924 # same time `str()` used to produce either octet-stream (Py2) or
925 # text (Py3) representations.
926 #
927 # Therefore `OctetString.__str__()` -> `.prettyPrint()` call chain is
928 # reversed to preserve the original behaviour.
929 #
930 # Eventually we should deprecate `.prettyPrint()` / `.prettyOut()` harness
931 # and end up with just `__str__()` producing hexified representation while
932 # both text and octet-stream representation should only be requested via
933 # the `.asOctets()` method.
934 #
935 # Note: ASN.1 OCTET STRING is never mean to contain text!
936 #
938 def prettyOut(self, value):
939 return value
941 def prettyPrint(self, scope=0):
942 # first see if subclass has its own .prettyOut()
943 value = self.prettyOut(self._value)
945 if value is not self._value:
946 return value
948 numbers = self.asNumbers()
950 for x in numbers:
951 # hexify if needed
952 if x < 32 or x > 126:
953 return '0x' + ''.join(('%.2x' % x for x in numbers))
954 else:
955 # this prevents infinite recursion
956 return OctetString.__str__(self)
958 @staticmethod
959 def fromBinaryString(value):
960 """Create a |ASN.1| object initialized from a string of '0' and '1'.
962 Parameters
963 ----------
964 value: :class:`str`
965 Text string like '1010111'
966 """
967 bitNo = 8
968 byte = 0
969 r = []
970 for v in value:
971 if bitNo:
972 bitNo -= 1
973 else:
974 bitNo = 7
975 r.append(byte)
976 byte = 0
977 if v in ('0', '1'):
978 v = int(v)
979 else:
980 raise error.PyAsn1Error(
981 'Non-binary OCTET STRING initializer %s' % (v,)
982 )
983 byte |= v << bitNo
985 r.append(byte)
987 return octets.ints2octs(r)
989 @staticmethod
990 def fromHexString(value):
991 """Create a |ASN.1| object initialized from the hex string.
993 Parameters
994 ----------
995 value: :class:`str`
996 Text string like 'DEADBEEF'
997 """
998 r = []
999 p = []
1000 for v in value:
1001 if p:
1002 r.append(int(p + v, 16))
1003 p = None
1004 else:
1005 p = v
1006 if p:
1007 r.append(int(p + '0', 16))
1009 return octets.ints2octs(r)
1011 # Immutable sequence object protocol
1013 def __len__(self):
1014 return len(self._value)
1016 def __getitem__(self, i):
1017 if i.__class__ is slice:
1018 return self.clone(self._value[i])
1019 else:
1020 return self._value[i]
1022 def __iter__(self):
1023 return iter(self._value)
1025 def __contains__(self, value):
1026 return value in self._value
1028 def __add__(self, value):
1029 return self.clone(self._value + self.prettyIn(value))
1031 def __radd__(self, value):
1032 return self.clone(self.prettyIn(value) + self._value)
1034 def __mul__(self, value):
1035 return self.clone(self._value * value)
1037 def __rmul__(self, value):
1038 return self * value
1040 def __int__(self):
1041 return int(self._value)
1043 def __float__(self):
1044 return float(self._value)
1046 def __reversed__(self):
1047 return reversed(self._value)
1050class Null(OctetString):
1051 """Create |ASN.1| schema or value object.
1053 |ASN.1| class is based on :class:`~pyasn1.type.base.SimpleAsn1Type`, its
1054 objects are immutable and duck-type Python :class:`str` objects
1055 (always empty).
1057 Keyword Args
1058 ------------
1059 value: :class:`str` or |ASN.1| object
1060 Python empty :class:`str` literal or any object that evaluates to :obj:`False`
1061 If `value` is not given, schema object will be created.
1063 tagSet: :py:class:`~pyasn1.type.tag.TagSet`
1064 Object representing non-default ASN.1 tag(s)
1066 Raises
1067 ------
1068 ~pyasn1.error.ValueConstraintError, ~pyasn1.error.PyAsn1Error
1069 On constraint violation or bad initializer.
1071 Examples
1072 --------
1073 .. code-block:: python
1075 class Ack(Null):
1076 '''
1077 ASN.1 specification:
1079 Ack ::= NULL
1080 '''
1081 ack = Ack('')
1082 """
1084 #: Set (on class, not on instance) or return a
1085 #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s)
1086 #: associated with |ASN.1| type.
1087 tagSet = tag.initTagSet(
1088 tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 0x05)
1089 )
1090 subtypeSpec = OctetString.subtypeSpec + constraint.SingleValueConstraint(octets.str2octs(''))
1092 # Optimization for faster codec lookup
1093 typeId = OctetString.getTypeId()
1095 def prettyIn(self, value):
1096 if value:
1097 return value
1099 return octets.str2octs('')
1101if sys.version_info[0] <= 2:
1102 intTypes = (int, long)
1103else:
1104 intTypes = (int,)
1106numericTypes = intTypes + (float,)
1109class ObjectIdentifier(base.SimpleAsn1Type):
1110 """Create |ASN.1| schema or value object.
1112 |ASN.1| class is based on :class:`~pyasn1.type.base.SimpleAsn1Type`, its
1113 objects are immutable and duck-type Python :class:`tuple` objects
1114 (tuple of non-negative integers).
1116 Keyword Args
1117 ------------
1118 value: :class:`tuple`, :class:`str` or |ASN.1| object
1119 Python sequence of :class:`int` or :class:`str` literal or |ASN.1| object.
1120 If `value` is not given, schema object will be created.
1122 tagSet: :py:class:`~pyasn1.type.tag.TagSet`
1123 Object representing non-default ASN.1 tag(s)
1125 subtypeSpec: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection`
1126 Object representing non-default ASN.1 subtype constraint(s). Constraints
1127 verification for |ASN.1| type occurs automatically on object
1128 instantiation.
1130 Raises
1131 ------
1132 ~pyasn1.error.ValueConstraintError, ~pyasn1.error.PyAsn1Error
1133 On constraint violation or bad initializer.
1135 Examples
1136 --------
1137 .. code-block:: python
1139 class ID(ObjectIdentifier):
1140 '''
1141 ASN.1 specification:
1143 ID ::= OBJECT IDENTIFIER
1145 id-edims ID ::= { joint-iso-itu-t mhs-motif(6) edims(7) }
1146 id-bp ID ::= { id-edims 11 }
1147 '''
1148 id_edims = ID('2.6.7')
1149 id_bp = id_edims + (11,)
1150 """
1151 #: Set (on class, not on instance) or return a
1152 #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s)
1153 #: associated with |ASN.1| type.
1154 tagSet = tag.initTagSet(
1155 tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 0x06)
1156 )
1158 #: Set (on class, not on instance) or return a
1159 #: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection` object
1160 #: imposing constraints on |ASN.1| type initialization values.
1161 subtypeSpec = constraint.ConstraintsIntersection()
1163 # Optimization for faster codec lookup
1164 typeId = base.SimpleAsn1Type.getTypeId()
1166 def __add__(self, other):
1167 return self.clone(self._value + other)
1169 def __radd__(self, other):
1170 return self.clone(other + self._value)
1172 def asTuple(self):
1173 return self._value
1175 # Sequence object protocol
1177 def __len__(self):
1178 return len(self._value)
1180 def __getitem__(self, i):
1181 if i.__class__ is slice:
1182 return self.clone(self._value[i])
1183 else:
1184 return self._value[i]
1186 def __iter__(self):
1187 return iter(self._value)
1189 def __contains__(self, value):
1190 return value in self._value
1192 def index(self, suboid):
1193 return self._value.index(suboid)
1195 def isPrefixOf(self, other):
1196 """Indicate if this |ASN.1| object is a prefix of other |ASN.1| object.
1198 Parameters
1199 ----------
1200 other: |ASN.1| object
1201 |ASN.1| object
1203 Returns
1204 -------
1205 : :class:`bool`
1206 :obj:`True` if this |ASN.1| object is a parent (e.g. prefix) of the other |ASN.1| object
1207 or :obj:`False` otherwise.
1208 """
1209 l = len(self)
1210 if l <= len(other):
1211 if self._value[:l] == other[:l]:
1212 return True
1213 return False
1215 def prettyIn(self, value):
1216 if isinstance(value, ObjectIdentifier):
1217 return tuple(value)
1218 elif octets.isStringType(value):
1219 if '-' in value:
1220 raise error.PyAsn1Error(
1221 'Malformed Object ID %s at %s: %s' % (value, self.__class__.__name__, sys.exc_info()[1])
1222 )
1223 try:
1224 return tuple([int(subOid) for subOid in value.split('.') if subOid])
1225 except ValueError:
1226 raise error.PyAsn1Error(
1227 'Malformed Object ID %s at %s: %s' % (value, self.__class__.__name__, sys.exc_info()[1])
1228 )
1230 try:
1231 tupleOfInts = tuple([int(subOid) for subOid in value if subOid >= 0])
1233 except (ValueError, TypeError):
1234 raise error.PyAsn1Error(
1235 'Malformed Object ID %s at %s: %s' % (value, self.__class__.__name__, sys.exc_info()[1])
1236 )
1238 if len(tupleOfInts) == len(value):
1239 return tupleOfInts
1241 raise error.PyAsn1Error('Malformed Object ID %s at %s' % (value, self.__class__.__name__))
1243 def prettyOut(self, value):
1244 return '.'.join([str(x) for x in value])
1247class RelativeOID(base.SimpleAsn1Type):
1248 """Create |ASN.1| schema or value object.
1249 |ASN.1| class is based on :class:`~pyasn1.type.base.SimpleAsn1Type`, its
1250 objects are immutable and duck-type Python :class:`tuple` objects
1251 (tuple of non-negative integers).
1252 Keyword Args
1253 ------------
1254 value: :class:`tuple`, :class:`str` or |ASN.1| object
1255 Python sequence of :class:`int` or :class:`str` literal or |ASN.1| object.
1256 If `value` is not given, schema object will be created.
1257 tagSet: :py:class:`~pyasn1.type.tag.TagSet`
1258 Object representing non-default ASN.1 tag(s)
1259 subtypeSpec: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection`
1260 Object representing non-default ASN.1 subtype constraint(s). Constraints
1261 verification for |ASN.1| type occurs automatically on object
1262 instantiation.
1263 Raises
1264 ------
1265 ~pyasn1.error.ValueConstraintError, ~pyasn1.error.PyAsn1Error
1266 On constraint violation or bad initializer.
1267 Examples
1268 --------
1269 .. code-block:: python
1270 class RelOID(RelativeOID):
1271 '''
1272 ASN.1 specification:
1273 id-pad-null RELATIVE-OID ::= { 0 }
1274 id-pad-once RELATIVE-OID ::= { 5 6 }
1275 id-pad-twice RELATIVE-OID ::= { 5 6 7 }
1276 '''
1277 id_pad_null = RelOID('0')
1278 id_pad_once = RelOID('5.6')
1279 id_pad_twice = id_pad_once + (7,)
1280 """
1281 #: Set (on class, not on instance) or return a
1282 #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s)
1283 #: associated with |ASN.1| type.
1284 tagSet = tag.initTagSet(
1285 tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 0x0d)
1286 )
1288 #: Set (on class, not on instance) or return a
1289 #: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection` object
1290 #: imposing constraints on |ASN.1| type initialization values.
1291 subtypeSpec = constraint.ConstraintsIntersection()
1293 # Optimization for faster codec lookup
1294 typeId = base.SimpleAsn1Type.getTypeId()
1296 def __add__(self, other):
1297 return self.clone(self._value + other)
1299 def __radd__(self, other):
1300 return self.clone(other + self._value)
1302 def asTuple(self):
1303 return self._value
1305 # Sequence object protocol
1307 def __len__(self):
1308 return len(self._value)
1310 def __getitem__(self, i):
1311 if i.__class__ is slice:
1312 return self.clone(self._value[i])
1313 else:
1314 return self._value[i]
1316 def __iter__(self):
1317 return iter(self._value)
1319 def __contains__(self, value):
1320 return value in self._value
1322 def index(self, suboid):
1323 return self._value.index(suboid)
1325 def isPrefixOf(self, other):
1326 """Indicate if this |ASN.1| object is a prefix of other |ASN.1| object.
1327 Parameters
1328 ----------
1329 other: |ASN.1| object
1330 |ASN.1| object
1331 Returns
1332 -------
1333 : :class:`bool`
1334 :obj:`True` if this |ASN.1| object is a parent (e.g. prefix) of the other |ASN.1| object
1335 or :obj:`False` otherwise.
1336 """
1337 l = len(self)
1338 if l <= len(other):
1339 if self._value[:l] == other[:l]:
1340 return True
1341 return False
1343 def prettyIn(self, value):
1344 if isinstance(value, RelativeOID):
1345 return tuple(value)
1346 elif octets.isStringType(value):
1347 if '-' in value:
1348 raise error.PyAsn1Error(
1349 'Malformed RELATIVE-OID %s at %s: %s' % (value, self.__class__.__name__, sys.exc_info()[1])
1350 )
1351 try:
1352 return tuple([int(subOid) for subOid in value.split('.') if subOid])
1353 except ValueError:
1354 raise error.PyAsn1Error(
1355 'Malformed RELATIVE-OID %s at %s: %s' % (value, self.__class__.__name__, sys.exc_info()[1])
1356 )
1358 try:
1359 tupleOfInts = tuple([int(subOid) for subOid in value if subOid >= 0])
1361 except (ValueError, TypeError):
1362 raise error.PyAsn1Error(
1363 'Malformed RELATIVE-OID %s at %s: %s' % (value, self.__class__.__name__, sys.exc_info()[1])
1364 )
1366 if len(tupleOfInts) == len(value):
1367 return tupleOfInts
1369 raise error.PyAsn1Error('Malformed RELATIVE-OID %s at %s' % (value, self.__class__.__name__))
1371 def prettyOut(self, value):
1372 return '.'.join([str(x) for x in value])
1375class Real(base.SimpleAsn1Type):
1376 """Create |ASN.1| schema or value object.
1378 |ASN.1| class is based on :class:`~pyasn1.type.base.SimpleAsn1Type`, its
1379 objects are immutable and duck-type Python :class:`float` objects.
1380 Additionally, |ASN.1| objects behave like a :class:`tuple` in which case its
1381 elements are mantissa, base and exponent.
1383 Keyword Args
1384 ------------
1385 value: :class:`tuple`, :class:`float` or |ASN.1| object
1386 Python sequence of :class:`int` (representing mantissa, base and
1387 exponent) or :class:`float` instance or |ASN.1| object.
1388 If `value` is not given, schema object will be created.
1390 tagSet: :py:class:`~pyasn1.type.tag.TagSet`
1391 Object representing non-default ASN.1 tag(s)
1393 subtypeSpec: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection`
1394 Object representing non-default ASN.1 subtype constraint(s). Constraints
1395 verification for |ASN.1| type occurs automatically on object
1396 instantiation.
1398 Raises
1399 ------
1400 ~pyasn1.error.ValueConstraintError, ~pyasn1.error.PyAsn1Error
1401 On constraint violation or bad initializer.
1403 Examples
1404 --------
1405 .. code-block:: python
1407 class Pi(Real):
1408 '''
1409 ASN.1 specification:
1411 Pi ::= REAL
1413 pi Pi ::= { mantissa 314159, base 10, exponent -5 }
1415 '''
1416 pi = Pi((314159, 10, -5))
1417 """
1418 binEncBase = None # binEncBase = 16 is recommended for large numbers
1420 try:
1421 _plusInf = float('inf')
1422 _minusInf = float('-inf')
1423 _inf = _plusInf, _minusInf
1425 except ValueError:
1426 # Infinity support is platform and Python dependent
1427 _plusInf = _minusInf = None
1428 _inf = ()
1430 #: Set (on class, not on instance) or return a
1431 #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s)
1432 #: associated with |ASN.1| type.
1433 tagSet = tag.initTagSet(
1434 tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 0x09)
1435 )
1437 #: Set (on class, not on instance) or return a
1438 #: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection` object
1439 #: imposing constraints on |ASN.1| type initialization values.
1440 subtypeSpec = constraint.ConstraintsIntersection()
1442 # Optimization for faster codec lookup
1443 typeId = base.SimpleAsn1Type.getTypeId()
1445 @staticmethod
1446 def __normalizeBase10(value):
1447 m, b, e = value
1448 while m and m % 10 == 0:
1449 m /= 10
1450 e += 1
1451 return m, b, e
1453 def prettyIn(self, value):
1454 if isinstance(value, tuple) and len(value) == 3:
1455 if (not isinstance(value[0], numericTypes) or
1456 not isinstance(value[1], intTypes) or
1457 not isinstance(value[2], intTypes)):
1458 raise error.PyAsn1Error('Lame Real value syntax: %s' % (value,))
1459 if (isinstance(value[0], float) and
1460 self._inf and value[0] in self._inf):
1461 return value[0]
1462 if value[1] not in (2, 10):
1463 raise error.PyAsn1Error(
1464 'Prohibited base for Real value: %s' % (value[1],)
1465 )
1466 if value[1] == 10:
1467 value = self.__normalizeBase10(value)
1468 return value
1469 elif isinstance(value, intTypes):
1470 return self.__normalizeBase10((value, 10, 0))
1471 elif isinstance(value, float) or octets.isStringType(value):
1472 if octets.isStringType(value):
1473 try:
1474 value = float(value)
1475 except ValueError:
1476 raise error.PyAsn1Error(
1477 'Bad real value syntax: %s' % (value,)
1478 )
1479 if self._inf and value in self._inf:
1480 return value
1481 else:
1482 e = 0
1483 while int(value) != value:
1484 value *= 10
1485 e -= 1
1486 return self.__normalizeBase10((int(value), 10, e))
1487 elif isinstance(value, Real):
1488 return tuple(value)
1489 raise error.PyAsn1Error(
1490 'Bad real value syntax: %s' % (value,)
1491 )
1493 def prettyPrint(self, scope=0):
1494 try:
1495 return self.prettyOut(float(self))
1497 except OverflowError:
1498 return '<overflow>'
1500 @property
1501 def isPlusInf(self):
1502 """Indicate PLUS-INFINITY object value
1504 Returns
1505 -------
1506 : :class:`bool`
1507 :obj:`True` if calling object represents plus infinity
1508 or :obj:`False` otherwise.
1510 """
1511 return self._value == self._plusInf
1513 @property
1514 def isMinusInf(self):
1515 """Indicate MINUS-INFINITY object value
1517 Returns
1518 -------
1519 : :class:`bool`
1520 :obj:`True` if calling object represents minus infinity
1521 or :obj:`False` otherwise.
1522 """
1523 return self._value == self._minusInf
1525 @property
1526 def isInf(self):
1527 return self._value in self._inf
1529 def __add__(self, value):
1530 return self.clone(float(self) + value)
1532 def __radd__(self, value):
1533 return self + value
1535 def __mul__(self, value):
1536 return self.clone(float(self) * value)
1538 def __rmul__(self, value):
1539 return self * value
1541 def __sub__(self, value):
1542 return self.clone(float(self) - value)
1544 def __rsub__(self, value):
1545 return self.clone(value - float(self))
1547 def __mod__(self, value):
1548 return self.clone(float(self) % value)
1550 def __rmod__(self, value):
1551 return self.clone(value % float(self))
1553 def __pow__(self, value, modulo=None):
1554 return self.clone(pow(float(self), value, modulo))
1556 def __rpow__(self, value):
1557 return self.clone(pow(value, float(self)))
1559 if sys.version_info[0] <= 2:
1560 def __div__(self, value):
1561 return self.clone(float(self) / value)
1563 def __rdiv__(self, value):
1564 return self.clone(value / float(self))
1565 else:
1566 def __truediv__(self, value):
1567 return self.clone(float(self) / value)
1569 def __rtruediv__(self, value):
1570 return self.clone(value / float(self))
1572 def __divmod__(self, value):
1573 return self.clone(float(self) // value)
1575 def __rdivmod__(self, value):
1576 return self.clone(value // float(self))
1578 def __int__(self):
1579 return int(float(self))
1581 if sys.version_info[0] <= 2:
1582 def __long__(self):
1583 return long(float(self))
1585 def __float__(self):
1586 if self._value in self._inf:
1587 return self._value
1588 else:
1589 return float(
1590 self._value[0] * pow(self._value[1], self._value[2])
1591 )
1593 def __abs__(self):
1594 return self.clone(abs(float(self)))
1596 def __pos__(self):
1597 return self.clone(+float(self))
1599 def __neg__(self):
1600 return self.clone(-float(self))
1602 def __round__(self, n=0):
1603 r = round(float(self), n)
1604 if n:
1605 return self.clone(r)
1606 else:
1607 return r
1609 def __floor__(self):
1610 return self.clone(math.floor(float(self)))
1612 def __ceil__(self):
1613 return self.clone(math.ceil(float(self)))
1615 def __trunc__(self):
1616 return self.clone(math.trunc(float(self)))
1618 def __lt__(self, value):
1619 return float(self) < value
1621 def __le__(self, value):
1622 return float(self) <= value
1624 def __eq__(self, value):
1625 return float(self) == value
1627 def __ne__(self, value):
1628 return float(self) != value
1630 def __gt__(self, value):
1631 return float(self) > value
1633 def __ge__(self, value):
1634 return float(self) >= value
1636 if sys.version_info[0] <= 2:
1637 def __nonzero__(self):
1638 return bool(float(self))
1639 else:
1640 def __bool__(self):
1641 return bool(float(self))
1643 __hash__ = base.SimpleAsn1Type.__hash__
1645 def __getitem__(self, idx):
1646 if self._value in self._inf:
1647 raise error.PyAsn1Error('Invalid infinite value operation')
1648 else:
1649 return self._value[idx]
1651 # compatibility stubs
1653 def isPlusInfinity(self):
1654 return self.isPlusInf
1656 def isMinusInfinity(self):
1657 return self.isMinusInf
1659 def isInfinity(self):
1660 return self.isInf
1663class Enumerated(Integer):
1664 """Create |ASN.1| schema or value object.
1666 |ASN.1| class is based on :class:`~pyasn1.type.base.SimpleAsn1Type`, its
1667 objects are immutable and duck-type Python :class:`int` objects.
1669 Keyword Args
1670 ------------
1671 value: :class:`int`, :class:`str` or |ASN.1| object
1672 Python :class:`int` or :class:`str` literal or |ASN.1| object.
1673 If `value` is not given, schema object will be created.
1675 tagSet: :py:class:`~pyasn1.type.tag.TagSet`
1676 Object representing non-default ASN.1 tag(s)
1678 subtypeSpec: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection`
1679 Object representing non-default ASN.1 subtype constraint(s). Constraints
1680 verification for |ASN.1| type occurs automatically on object
1681 instantiation.
1683 namedValues: :py:class:`~pyasn1.type.namedval.NamedValues`
1684 Object representing non-default symbolic aliases for numbers
1686 Raises
1687 ------
1688 ~pyasn1.error.ValueConstraintError, ~pyasn1.error.PyAsn1Error
1689 On constraint violation or bad initializer.
1691 Examples
1692 --------
1694 .. code-block:: python
1696 class RadioButton(Enumerated):
1697 '''
1698 ASN.1 specification:
1700 RadioButton ::= ENUMERATED { button1(0), button2(1),
1701 button3(2) }
1703 selected-by-default RadioButton ::= button1
1704 '''
1705 namedValues = NamedValues(
1706 ('button1', 0), ('button2', 1),
1707 ('button3', 2)
1708 )
1710 selected_by_default = RadioButton('button1')
1711 """
1712 #: Set (on class, not on instance) or return a
1713 #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s)
1714 #: associated with |ASN.1| type.
1715 tagSet = tag.initTagSet(
1716 tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 0x0A)
1717 )
1719 #: Set (on class, not on instance) or return a
1720 #: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection` object
1721 #: imposing constraints on |ASN.1| type initialization values.
1722 subtypeSpec = constraint.ConstraintsIntersection()
1724 # Optimization for faster codec lookup
1725 typeId = Integer.getTypeId()
1727 #: Default :py:class:`~pyasn1.type.namedval.NamedValues` object
1728 #: representing symbolic aliases for numbers
1729 namedValues = namedval.NamedValues()
1732# "Structured" ASN.1 types
1734class SequenceOfAndSetOfBase(base.ConstructedAsn1Type):
1735 """Create |ASN.1| schema or value object.
1737 |ASN.1| class is based on :class:`~pyasn1.type.base.ConstructedAsn1Type`,
1738 its objects are mutable and duck-type Python :class:`list` objects.
1740 Keyword Args
1741 ------------
1742 componentType : :py:class:`~pyasn1.type.base.PyAsn1Item` derivative
1743 A pyasn1 object representing ASN.1 type allowed within |ASN.1| type
1745 tagSet: :py:class:`~pyasn1.type.tag.TagSet`
1746 Object representing non-default ASN.1 tag(s)
1748 subtypeSpec: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection`
1749 Object representing non-default ASN.1 subtype constraint(s). Constraints
1750 verification for |ASN.1| type can only occur on explicit
1751 `.isInconsistent` call.
1753 Examples
1754 --------
1756 .. code-block:: python
1758 class LotteryDraw(SequenceOf): # SetOf is similar
1759 '''
1760 ASN.1 specification:
1762 LotteryDraw ::= SEQUENCE OF INTEGER
1763 '''
1764 componentType = Integer()
1766 lotteryDraw = LotteryDraw()
1767 lotteryDraw.extend([123, 456, 789])
1768 """
1769 def __init__(self, *args, **kwargs):
1770 # support positional params for backward compatibility
1771 if args:
1772 for key, value in zip(('componentType', 'tagSet',
1773 'subtypeSpec'), args):
1774 if key in kwargs:
1775 raise error.PyAsn1Error('Conflicting positional and keyword params!')
1776 kwargs['componentType'] = value
1778 self._componentValues = noValue
1780 base.ConstructedAsn1Type.__init__(self, **kwargs)
1782 # Python list protocol
1784 def __getitem__(self, idx):
1785 try:
1786 return self.getComponentByPosition(idx)
1788 except error.PyAsn1Error:
1789 raise IndexError(sys.exc_info()[1])
1791 def __setitem__(self, idx, value):
1792 try:
1793 self.setComponentByPosition(idx, value)
1795 except error.PyAsn1Error:
1796 raise IndexError(sys.exc_info()[1])
1798 def append(self, value):
1799 if self._componentValues is noValue:
1800 pos = 0
1802 else:
1803 pos = len(self._componentValues)
1805 self[pos] = value
1807 def count(self, value):
1808 return list(self._componentValues.values()).count(value)
1810 def extend(self, values):
1811 for value in values:
1812 self.append(value)
1814 if self._componentValues is noValue:
1815 self._componentValues = {}
1817 def index(self, value, start=0, stop=None):
1818 if stop is None:
1819 stop = len(self)
1821 indices, values = zip(*self._componentValues.items())
1823 # TODO: remove when Py2.5 support is gone
1824 values = list(values)
1826 try:
1827 return indices[values.index(value, start, stop)]
1829 except error.PyAsn1Error:
1830 raise ValueError(sys.exc_info()[1])
1832 def reverse(self):
1833 self._componentValues.reverse()
1835 def sort(self, key=None, reverse=False):
1836 self._componentValues = dict(
1837 enumerate(sorted(self._componentValues.values(),
1838 key=key, reverse=reverse)))
1840 def __len__(self):
1841 if self._componentValues is noValue or not self._componentValues:
1842 return 0
1844 return max(self._componentValues) + 1
1846 def __iter__(self):
1847 for idx in range(0, len(self)):
1848 yield self.getComponentByPosition(idx)
1850 def _cloneComponentValues(self, myClone, cloneValueFlag):
1851 for idx, componentValue in self._componentValues.items():
1852 if componentValue is not noValue:
1853 if isinstance(componentValue, base.ConstructedAsn1Type):
1854 myClone.setComponentByPosition(
1855 idx, componentValue.clone(cloneValueFlag=cloneValueFlag)
1856 )
1857 else:
1858 myClone.setComponentByPosition(idx, componentValue.clone())
1860 def getComponentByPosition(self, idx, default=noValue, instantiate=True):
1861 """Return |ASN.1| type component value by position.
1863 Equivalent to Python sequence subscription operation (e.g. `[]`).
1865 Parameters
1866 ----------
1867 idx : :class:`int`
1868 Component index (zero-based). Must either refer to an existing
1869 component or to N+1 component (if *componentType* is set). In the latter
1870 case a new component type gets instantiated and appended to the |ASN.1|
1871 sequence.
1873 Keyword Args
1874 ------------
1875 default: :class:`object`
1876 If set and requested component is a schema object, return the `default`
1877 object instead of the requested component.
1879 instantiate: :class:`bool`
1880 If :obj:`True` (default), inner component will be automatically instantiated.
1881 If :obj:`False` either existing component or the :class:`NoValue` object will be
1882 returned.
1884 Returns
1885 -------
1886 : :py:class:`~pyasn1.type.base.PyAsn1Item`
1887 Instantiate |ASN.1| component type or return existing component value
1889 Examples
1890 --------
1892 .. code-block:: python
1894 # can also be SetOf
1895 class MySequenceOf(SequenceOf):
1896 componentType = OctetString()
1898 s = MySequenceOf()
1900 # returns component #0 with `.isValue` property False
1901 s.getComponentByPosition(0)
1903 # returns None
1904 s.getComponentByPosition(0, default=None)
1906 s.clear()
1908 # returns noValue
1909 s.getComponentByPosition(0, instantiate=False)
1911 # sets component #0 to OctetString() ASN.1 schema
1912 # object and returns it
1913 s.getComponentByPosition(0, instantiate=True)
1915 # sets component #0 to ASN.1 value object
1916 s.setComponentByPosition(0, 'ABCD')
1918 # returns OctetString('ABCD') value object
1919 s.getComponentByPosition(0, instantiate=False)
1921 s.clear()
1923 # returns noValue
1924 s.getComponentByPosition(0, instantiate=False)
1925 """
1926 if isinstance(idx, slice):
1927 indices = tuple(range(len(self)))
1928 return [self.getComponentByPosition(subidx, default, instantiate)
1929 for subidx in indices[idx]]
1931 if idx < 0:
1932 idx = len(self) + idx
1933 if idx < 0:
1934 raise error.PyAsn1Error(
1935 'SequenceOf/SetOf index is out of range')
1937 try:
1938 componentValue = self._componentValues[idx]
1940 except (KeyError, error.PyAsn1Error):
1941 if not instantiate:
1942 return default
1944 self.setComponentByPosition(idx)
1946 componentValue = self._componentValues[idx]
1948 if default is noValue or componentValue.isValue:
1949 return componentValue
1950 else:
1951 return default
1953 def setComponentByPosition(self, idx, value=noValue,
1954 verifyConstraints=True,
1955 matchTags=True,
1956 matchConstraints=True):
1957 """Assign |ASN.1| type component by position.
1959 Equivalent to Python sequence item assignment operation (e.g. `[]`)
1960 or list.append() (when idx == len(self)).
1962 Parameters
1963 ----------
1964 idx: :class:`int`
1965 Component index (zero-based). Must either refer to existing
1966 component or to N+1 component. In the latter case a new component
1967 type gets instantiated (if *componentType* is set, or given ASN.1
1968 object is taken otherwise) and appended to the |ASN.1| sequence.
1970 Keyword Args
1971 ------------
1972 value: :class:`object` or :py:class:`~pyasn1.type.base.PyAsn1Item` derivative
1973 A Python value to initialize |ASN.1| component with (if *componentType* is set)
1974 or ASN.1 value object to assign to |ASN.1| component.
1975 If `value` is not given, schema object will be set as a component.
1977 verifyConstraints: :class:`bool`
1978 If :obj:`False`, skip constraints validation
1980 matchTags: :class:`bool`
1981 If :obj:`False`, skip component tags matching
1983 matchConstraints: :class:`bool`
1984 If :obj:`False`, skip component constraints matching
1986 Returns
1987 -------
1988 self
1990 Raises
1991 ------
1992 ~pyasn1.error.ValueConstraintError, ~pyasn1.error.PyAsn1Error
1993 On constraint violation or bad initializer
1994 IndexError
1995 When idx > len(self)
1996 """
1997 if isinstance(idx, slice):
1998 indices = tuple(range(len(self)))
1999 startIdx = indices and indices[idx][0] or 0
2000 for subIdx, subValue in enumerate(value):
2001 self.setComponentByPosition(
2002 startIdx + subIdx, subValue, verifyConstraints,
2003 matchTags, matchConstraints)
2004 return self
2006 if idx < 0:
2007 idx = len(self) + idx
2008 if idx < 0:
2009 raise error.PyAsn1Error(
2010 'SequenceOf/SetOf index is out of range')
2012 componentType = self.componentType
2014 if self._componentValues is noValue:
2015 componentValues = {}
2017 else:
2018 componentValues = self._componentValues
2020 currentValue = componentValues.get(idx, noValue)
2022 if value is noValue:
2023 if componentType is not None:
2024 value = componentType.clone()
2026 elif currentValue is noValue:
2027 raise error.PyAsn1Error('Component type not defined')
2029 elif not isinstance(value, base.Asn1Item):
2030 if (componentType is not None and
2031 isinstance(componentType, base.SimpleAsn1Type)):
2032 value = componentType.clone(value=value)
2034 elif (currentValue is not noValue and
2035 isinstance(currentValue, base.SimpleAsn1Type)):
2036 value = currentValue.clone(value=value)
2038 else:
2039 raise error.PyAsn1Error(
2040 'Non-ASN.1 value %r and undefined component'
2041 ' type at %r' % (value, self))
2043 elif componentType is not None and (matchTags or matchConstraints):
2044 subtypeChecker = (
2045 self.strictConstraints and
2046 componentType.isSameTypeWith or
2047 componentType.isSuperTypeOf)
2049 if not subtypeChecker(value, verifyConstraints and matchTags,
2050 verifyConstraints and matchConstraints):
2051 # TODO: we should wrap componentType with UnnamedType to carry
2052 # additional properties associated with componentType
2053 if componentType.typeId != Any.typeId:
2054 raise error.PyAsn1Error(
2055 'Component value is tag-incompatible: %r vs '
2056 '%r' % (value, componentType))
2058 componentValues[idx] = value
2060 self._componentValues = componentValues
2062 return self
2064 @property
2065 def componentTagMap(self):
2066 if self.componentType is not None:
2067 return self.componentType.tagMap
2069 @property
2070 def components(self):
2071 return [self._componentValues[idx]
2072 for idx in sorted(self._componentValues)]
2074 def clear(self):
2075 """Remove all components and become an empty |ASN.1| value object.
2077 Has the same effect on |ASN.1| object as it does on :class:`list`
2078 built-in.
2079 """
2080 self._componentValues = {}
2081 return self
2083 def reset(self):
2084 """Remove all components and become a |ASN.1| schema object.
2086 See :meth:`isValue` property for more information on the
2087 distinction between value and schema objects.
2088 """
2089 self._componentValues = noValue
2090 return self
2092 def prettyPrint(self, scope=0):
2093 scope += 1
2094 representation = self.__class__.__name__ + ':\n'
2096 if not self.isValue:
2097 return representation
2099 for idx, componentValue in enumerate(self):
2100 representation += ' ' * scope
2101 if (componentValue is noValue and
2102 self.componentType is not None):
2103 representation += '<empty>'
2104 else:
2105 representation += componentValue.prettyPrint(scope)
2107 return representation
2109 def prettyPrintType(self, scope=0):
2110 scope += 1
2111 representation = '%s -> %s {\n' % (self.tagSet, self.__class__.__name__)
2112 if self.componentType is not None:
2113 representation += ' ' * scope
2114 representation += self.componentType.prettyPrintType(scope)
2115 return representation + '\n' + ' ' * (scope - 1) + '}'
2118 @property
2119 def isValue(self):
2120 """Indicate that |ASN.1| object represents ASN.1 value.
2122 If *isValue* is :obj:`False` then this object represents just ASN.1 schema.
2124 If *isValue* is :obj:`True` then, in addition to its ASN.1 schema features,
2125 this object can also be used like a Python built-in object
2126 (e.g. :class:`int`, :class:`str`, :class:`dict` etc.).
2128 Returns
2129 -------
2130 : :class:`bool`
2131 :obj:`False` if object represents just ASN.1 schema.
2132 :obj:`True` if object represents ASN.1 schema and can be used as a normal value.
2134 Note
2135 ----
2136 There is an important distinction between PyASN1 schema and value objects.
2137 The PyASN1 schema objects can only participate in ASN.1 schema-related
2138 operations (e.g. defining or testing the structure of the data). Most
2139 obvious uses of ASN.1 schema is to guide serialisation codecs whilst
2140 encoding/decoding serialised ASN.1 contents.
2142 The PyASN1 value objects can **additionally** participate in many operations
2143 involving regular Python objects (e.g. arithmetic, comprehension etc).
2144 """
2145 if self._componentValues is noValue:
2146 return False
2148 if len(self._componentValues) != len(self):
2149 return False
2151 for componentValue in self._componentValues.values():
2152 if componentValue is noValue or not componentValue.isValue:
2153 return False
2155 return True
2157 @property
2158 def isInconsistent(self):
2159 """Run necessary checks to ensure |ASN.1| object consistency.
2161 Default action is to verify |ASN.1| object against constraints imposed
2162 by `subtypeSpec`.
2164 Raises
2165 ------
2166 :py:class:`~pyasn1.error.PyAsn1tError` on any inconsistencies found
2167 """
2168 if self.componentType is noValue or not self.subtypeSpec:
2169 return False
2171 if self._componentValues is noValue:
2172 return True
2174 mapping = {}
2176 for idx, value in self._componentValues.items():
2177 # Absent fields are not in the mapping
2178 if value is noValue:
2179 continue
2181 mapping[idx] = value
2183 try:
2184 # Represent SequenceOf/SetOf as a bare dict to constraints chain
2185 self.subtypeSpec(mapping)
2187 except error.PyAsn1Error:
2188 exc = sys.exc_info()[1]
2189 return exc
2191 return False
2193class SequenceOf(SequenceOfAndSetOfBase):
2194 __doc__ = SequenceOfAndSetOfBase.__doc__
2196 #: Set (on class, not on instance) or return a
2197 #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s)
2198 #: associated with |ASN.1| type.
2199 tagSet = tag.initTagSet(
2200 tag.Tag(tag.tagClassUniversal, tag.tagFormatConstructed, 0x10)
2201 )
2203 #: Default :py:class:`~pyasn1.type.base.PyAsn1Item` derivative
2204 #: object representing ASN.1 type allowed within |ASN.1| type
2205 componentType = None
2207 #: Set (on class, not on instance) or return a
2208 #: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection` object
2209 #: imposing constraints on |ASN.1| type initialization values.
2210 subtypeSpec = constraint.ConstraintsIntersection()
2212 # Disambiguation ASN.1 types identification
2213 typeId = SequenceOfAndSetOfBase.getTypeId()
2216class SetOf(SequenceOfAndSetOfBase):
2217 __doc__ = SequenceOfAndSetOfBase.__doc__
2219 #: Set (on class, not on instance) or return a
2220 #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s)
2221 #: associated with |ASN.1| type.
2222 tagSet = tag.initTagSet(
2223 tag.Tag(tag.tagClassUniversal, tag.tagFormatConstructed, 0x11)
2224 )
2226 #: Default :py:class:`~pyasn1.type.base.PyAsn1Item` derivative
2227 #: object representing ASN.1 type allowed within |ASN.1| type
2228 componentType = None
2230 #: Set (on class, not on instance) or return a
2231 #: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection` object
2232 #: imposing constraints on |ASN.1| type initialization values.
2233 subtypeSpec = constraint.ConstraintsIntersection()
2235 # Disambiguation ASN.1 types identification
2236 typeId = SequenceOfAndSetOfBase.getTypeId()
2239class SequenceAndSetBase(base.ConstructedAsn1Type):
2240 """Create |ASN.1| schema or value object.
2242 |ASN.1| class is based on :class:`~pyasn1.type.base.ConstructedAsn1Type`,
2243 its objects are mutable and duck-type Python :class:`dict` objects.
2245 Keyword Args
2246 ------------
2247 componentType: :py:class:`~pyasn1.type.namedtype.NamedType`
2248 Object holding named ASN.1 types allowed within this collection
2250 tagSet: :py:class:`~pyasn1.type.tag.TagSet`
2251 Object representing non-default ASN.1 tag(s)
2253 subtypeSpec: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection`
2254 Object representing non-default ASN.1 subtype constraint(s). Constraints
2255 verification for |ASN.1| type can only occur on explicit
2256 `.isInconsistent` call.
2258 Examples
2259 --------
2261 .. code-block:: python
2263 class Description(Sequence): # Set is similar
2264 '''
2265 ASN.1 specification:
2267 Description ::= SEQUENCE {
2268 surname IA5String,
2269 first-name IA5String OPTIONAL,
2270 age INTEGER DEFAULT 40
2271 }
2272 '''
2273 componentType = NamedTypes(
2274 NamedType('surname', IA5String()),
2275 OptionalNamedType('first-name', IA5String()),
2276 DefaultedNamedType('age', Integer(40))
2277 )
2279 descr = Description()
2280 descr['surname'] = 'Smith'
2281 descr['first-name'] = 'John'
2282 """
2283 #: Default :py:class:`~pyasn1.type.namedtype.NamedTypes`
2284 #: object representing named ASN.1 types allowed within |ASN.1| type
2285 componentType = namedtype.NamedTypes()
2288 class DynamicNames(object):
2289 """Fields names/positions mapping for component-less objects"""
2290 def __init__(self):
2291 self._keyToIdxMap = {}
2292 self._idxToKeyMap = {}
2294 def __len__(self):
2295 return len(self._keyToIdxMap)
2297 def __contains__(self, item):
2298 return item in self._keyToIdxMap or item in self._idxToKeyMap
2300 def __iter__(self):
2301 return (self._idxToKeyMap[idx] for idx in range(len(self._idxToKeyMap)))
2303 def __getitem__(self, item):
2304 try:
2305 return self._keyToIdxMap[item]
2307 except KeyError:
2308 return self._idxToKeyMap[item]
2310 def getNameByPosition(self, idx):
2311 try:
2312 return self._idxToKeyMap[idx]
2314 except KeyError:
2315 raise error.PyAsn1Error('Type position out of range')
2317 def getPositionByName(self, name):
2318 try:
2319 return self._keyToIdxMap[name]
2321 except KeyError:
2322 raise error.PyAsn1Error('Name %s not found' % (name,))
2324 def addField(self, idx):
2325 self._keyToIdxMap['field-%d' % idx] = idx
2326 self._idxToKeyMap[idx] = 'field-%d' % idx
2329 def __init__(self, **kwargs):
2330 base.ConstructedAsn1Type.__init__(self, **kwargs)
2331 self._componentTypeLen = len(self.componentType)
2332 if self._componentTypeLen:
2333 self._componentValues = []
2334 else:
2335 self._componentValues = noValue
2336 self._dynamicNames = self._componentTypeLen or self.DynamicNames()
2338 def __getitem__(self, idx):
2339 if octets.isStringType(idx):
2340 try:
2341 return self.getComponentByName(idx)
2343 except error.PyAsn1Error:
2344 # duck-typing dict
2345 raise KeyError(sys.exc_info()[1])
2347 else:
2348 try:
2349 return self.getComponentByPosition(idx)
2351 except error.PyAsn1Error:
2352 # duck-typing list
2353 raise IndexError(sys.exc_info()[1])
2355 def __setitem__(self, idx, value):
2356 if octets.isStringType(idx):
2357 try:
2358 self.setComponentByName(idx, value)
2360 except error.PyAsn1Error:
2361 # duck-typing dict
2362 raise KeyError(sys.exc_info()[1])
2364 else:
2365 try:
2366 self.setComponentByPosition(idx, value)
2368 except error.PyAsn1Error:
2369 # duck-typing list
2370 raise IndexError(sys.exc_info()[1])
2372 def __contains__(self, key):
2373 if self._componentTypeLen:
2374 return key in self.componentType
2375 else:
2376 return key in self._dynamicNames
2378 def __len__(self):
2379 return len(self._componentValues)
2381 def __iter__(self):
2382 return iter(self.componentType or self._dynamicNames)
2384 # Python dict protocol
2386 def values(self):
2387 for idx in range(self._componentTypeLen or len(self._dynamicNames)):
2388 yield self[idx]
2390 def keys(self):
2391 return iter(self)
2393 def items(self):
2394 for idx in range(self._componentTypeLen or len(self._dynamicNames)):
2395 if self._componentTypeLen:
2396 yield self.componentType[idx].name, self[idx]
2397 else:
2398 yield self._dynamicNames[idx], self[idx]
2400 def update(self, *iterValue, **mappingValue):
2401 for k, v in iterValue:
2402 self[k] = v
2403 for k in mappingValue:
2404 self[k] = mappingValue[k]
2406 def clear(self):
2407 """Remove all components and become an empty |ASN.1| value object.
2409 Has the same effect on |ASN.1| object as it does on :class:`dict`
2410 built-in.
2411 """
2412 self._componentValues = []
2413 self._dynamicNames = self.DynamicNames()
2414 return self
2416 def reset(self):
2417 """Remove all components and become a |ASN.1| schema object.
2419 See :meth:`isValue` property for more information on the
2420 distinction between value and schema objects.
2421 """
2422 self._componentValues = noValue
2423 self._dynamicNames = self.DynamicNames()
2424 return self
2426 @property
2427 def components(self):
2428 return self._componentValues
2430 def _cloneComponentValues(self, myClone, cloneValueFlag):
2431 if self._componentValues is noValue:
2432 return
2434 for idx, componentValue in enumerate(self._componentValues):
2435 if componentValue is not noValue:
2436 if isinstance(componentValue, base.ConstructedAsn1Type):
2437 myClone.setComponentByPosition(
2438 idx, componentValue.clone(cloneValueFlag=cloneValueFlag)
2439 )
2440 else:
2441 myClone.setComponentByPosition(idx, componentValue.clone())
2443 def getComponentByName(self, name, default=noValue, instantiate=True):
2444 """Returns |ASN.1| type component by name.
2446 Equivalent to Python :class:`dict` subscription operation (e.g. `[]`).
2448 Parameters
2449 ----------
2450 name: :class:`str`
2451 |ASN.1| type component name
2453 Keyword Args
2454 ------------
2455 default: :class:`object`
2456 If set and requested component is a schema object, return the `default`
2457 object instead of the requested component.
2459 instantiate: :class:`bool`
2460 If :obj:`True` (default), inner component will be automatically
2461 instantiated.
2462 If :obj:`False` either existing component or the :class:`NoValue`
2463 object will be returned.
2465 Returns
2466 -------
2467 : :py:class:`~pyasn1.type.base.PyAsn1Item`
2468 Instantiate |ASN.1| component type or return existing
2469 component value
2470 """
2471 if self._componentTypeLen:
2472 idx = self.componentType.getPositionByName(name)
2473 else:
2474 try:
2475 idx = self._dynamicNames.getPositionByName(name)
2477 except KeyError:
2478 raise error.PyAsn1Error('Name %s not found' % (name,))
2480 return self.getComponentByPosition(idx, default=default, instantiate=instantiate)
2482 def setComponentByName(self, name, value=noValue,
2483 verifyConstraints=True,
2484 matchTags=True,
2485 matchConstraints=True):
2486 """Assign |ASN.1| type component by name.
2488 Equivalent to Python :class:`dict` item assignment operation (e.g. `[]`).
2490 Parameters
2491 ----------
2492 name: :class:`str`
2493 |ASN.1| type component name
2495 Keyword Args
2496 ------------
2497 value: :class:`object` or :py:class:`~pyasn1.type.base.PyAsn1Item` derivative
2498 A Python value to initialize |ASN.1| component with (if *componentType* is set)
2499 or ASN.1 value object to assign to |ASN.1| component.
2500 If `value` is not given, schema object will be set as a component.
2502 verifyConstraints: :class:`bool`
2503 If :obj:`False`, skip constraints validation
2505 matchTags: :class:`bool`
2506 If :obj:`False`, skip component tags matching
2508 matchConstraints: :class:`bool`
2509 If :obj:`False`, skip component constraints matching
2511 Returns
2512 -------
2513 self
2514 """
2515 if self._componentTypeLen:
2516 idx = self.componentType.getPositionByName(name)
2517 else:
2518 try:
2519 idx = self._dynamicNames.getPositionByName(name)
2521 except KeyError:
2522 raise error.PyAsn1Error('Name %s not found' % (name,))
2524 return self.setComponentByPosition(
2525 idx, value, verifyConstraints, matchTags, matchConstraints
2526 )
2528 def getComponentByPosition(self, idx, default=noValue, instantiate=True):
2529 """Returns |ASN.1| type component by index.
2531 Equivalent to Python sequence subscription operation (e.g. `[]`).
2533 Parameters
2534 ----------
2535 idx: :class:`int`
2536 Component index (zero-based). Must either refer to an existing
2537 component or (if *componentType* is set) new ASN.1 schema object gets
2538 instantiated.
2540 Keyword Args
2541 ------------
2542 default: :class:`object`
2543 If set and requested component is a schema object, return the `default`
2544 object instead of the requested component.
2546 instantiate: :class:`bool`
2547 If :obj:`True` (default), inner component will be automatically
2548 instantiated.
2549 If :obj:`False` either existing component or the :class:`NoValue`
2550 object will be returned.
2552 Returns
2553 -------
2554 : :py:class:`~pyasn1.type.base.PyAsn1Item`
2555 a PyASN1 object
2557 Examples
2558 --------
2560 .. code-block:: python
2562 # can also be Set
2563 class MySequence(Sequence):
2564 componentType = NamedTypes(
2565 NamedType('id', OctetString())
2566 )
2568 s = MySequence()
2570 # returns component #0 with `.isValue` property False
2571 s.getComponentByPosition(0)
2573 # returns None
2574 s.getComponentByPosition(0, default=None)
2576 s.clear()
2578 # returns noValue
2579 s.getComponentByPosition(0, instantiate=False)
2581 # sets component #0 to OctetString() ASN.1 schema
2582 # object and returns it
2583 s.getComponentByPosition(0, instantiate=True)
2585 # sets component #0 to ASN.1 value object
2586 s.setComponentByPosition(0, 'ABCD')
2588 # returns OctetString('ABCD') value object
2589 s.getComponentByPosition(0, instantiate=False)
2591 s.clear()
2593 # returns noValue
2594 s.getComponentByPosition(0, instantiate=False)
2595 """
2596 try:
2597 if self._componentValues is noValue:
2598 componentValue = noValue
2600 else:
2601 componentValue = self._componentValues[idx]
2603 except IndexError:
2604 componentValue = noValue
2606 if not instantiate:
2607 if componentValue is noValue or not componentValue.isValue:
2608 return default
2609 else:
2610 return componentValue
2612 if componentValue is noValue:
2613 self.setComponentByPosition(idx)
2615 componentValue = self._componentValues[idx]
2617 if default is noValue or componentValue.isValue:
2618 return componentValue
2619 else:
2620 return default
2622 def setComponentByPosition(self, idx, value=noValue,
2623 verifyConstraints=True,
2624 matchTags=True,
2625 matchConstraints=True):
2626 """Assign |ASN.1| type component by position.
2628 Equivalent to Python sequence item assignment operation (e.g. `[]`).
2630 Parameters
2631 ----------
2632 idx : :class:`int`
2633 Component index (zero-based). Must either refer to existing
2634 component (if *componentType* is set) or to N+1 component
2635 otherwise. In the latter case a new component of given ASN.1
2636 type gets instantiated and appended to |ASN.1| sequence.
2638 Keyword Args
2639 ------------
2640 value: :class:`object` or :py:class:`~pyasn1.type.base.PyAsn1Item` derivative
2641 A Python value to initialize |ASN.1| component with (if *componentType* is set)
2642 or ASN.1 value object to assign to |ASN.1| component.
2643 If `value` is not given, schema object will be set as a component.
2645 verifyConstraints : :class:`bool`
2646 If :obj:`False`, skip constraints validation
2648 matchTags: :class:`bool`
2649 If :obj:`False`, skip component tags matching
2651 matchConstraints: :class:`bool`
2652 If :obj:`False`, skip component constraints matching
2654 Returns
2655 -------
2656 self
2657 """
2658 componentType = self.componentType
2659 componentTypeLen = self._componentTypeLen
2661 if self._componentValues is noValue:
2662 componentValues = []
2664 else:
2665 componentValues = self._componentValues
2667 try:
2668 currentValue = componentValues[idx]
2670 except IndexError:
2671 currentValue = noValue
2672 if componentTypeLen:
2673 if componentTypeLen < idx:
2674 raise error.PyAsn1Error('component index out of range')
2676 componentValues = [noValue] * componentTypeLen
2678 if value is noValue:
2679 if componentTypeLen:
2680 value = componentType.getTypeByPosition(idx)
2681 if isinstance(value, base.ConstructedAsn1Type):
2682 value = value.clone(cloneValueFlag=componentType[idx].isDefaulted)
2684 elif currentValue is noValue:
2685 raise error.PyAsn1Error('Component type not defined')
2687 elif not isinstance(value, base.Asn1Item):
2688 if componentTypeLen:
2689 subComponentType = componentType.getTypeByPosition(idx)
2690 if isinstance(subComponentType, base.SimpleAsn1Type):
2691 value = subComponentType.clone(value=value)
2693 else:
2694 raise error.PyAsn1Error('%s can cast only scalar values' % componentType.__class__.__name__)
2696 elif currentValue is not noValue and isinstance(currentValue, base.SimpleAsn1Type):
2697 value = currentValue.clone(value=value)
2699 else:
2700 raise error.PyAsn1Error('%s undefined component type' % componentType.__class__.__name__)
2702 elif ((verifyConstraints or matchTags or matchConstraints) and
2703 componentTypeLen):
2704 subComponentType = componentType.getTypeByPosition(idx)
2705 if subComponentType is not noValue:
2706 subtypeChecker = (self.strictConstraints and
2707 subComponentType.isSameTypeWith or
2708 subComponentType.isSuperTypeOf)
2710 if not subtypeChecker(value, verifyConstraints and matchTags,
2711 verifyConstraints and matchConstraints):
2712 if not componentType[idx].openType:
2713 raise error.PyAsn1Error('Component value is tag-incompatible: %r vs %r' % (value, componentType))
2715 if componentTypeLen or idx in self._dynamicNames:
2716 componentValues[idx] = value
2718 elif len(componentValues) == idx:
2719 componentValues.append(value)
2720 self._dynamicNames.addField(idx)
2722 else:
2723 raise error.PyAsn1Error('Component index out of range')
2725 self._componentValues = componentValues
2727 return self
2729 @property
2730 def isValue(self):
2731 """Indicate that |ASN.1| object represents ASN.1 value.
2733 If *isValue* is :obj:`False` then this object represents just ASN.1 schema.
2735 If *isValue* is :obj:`True` then, in addition to its ASN.1 schema features,
2736 this object can also be used like a Python built-in object (e.g.
2737 :class:`int`, :class:`str`, :class:`dict` etc.).
2739 Returns
2740 -------
2741 : :class:`bool`
2742 :obj:`False` if object represents just ASN.1 schema.
2743 :obj:`True` if object represents ASN.1 schema and can be used as a
2744 normal value.
2746 Note
2747 ----
2748 There is an important distinction between PyASN1 schema and value objects.
2749 The PyASN1 schema objects can only participate in ASN.1 schema-related
2750 operations (e.g. defining or testing the structure of the data). Most
2751 obvious uses of ASN.1 schema is to guide serialisation codecs whilst
2752 encoding/decoding serialised ASN.1 contents.
2754 The PyASN1 value objects can **additionally** participate in many operations
2755 involving regular Python objects (e.g. arithmetic, comprehension etc).
2757 It is sufficient for |ASN.1| objects to have all non-optional and non-defaulted
2758 components being value objects to be considered as a value objects as a whole.
2759 In other words, even having one or more optional components not turned into
2760 value objects, |ASN.1| object is still considered as a value object. Defaulted
2761 components are normally value objects by default.
2762 """
2763 if self._componentValues is noValue:
2764 return False
2766 componentType = self.componentType
2768 if componentType:
2769 for idx, subComponentType in enumerate(componentType.namedTypes):
2770 if subComponentType.isDefaulted or subComponentType.isOptional:
2771 continue
2773 if not self._componentValues:
2774 return False
2776 componentValue = self._componentValues[idx]
2777 if componentValue is noValue or not componentValue.isValue:
2778 return False
2780 else:
2781 for componentValue in self._componentValues:
2782 if componentValue is noValue or not componentValue.isValue:
2783 return False
2785 return True
2787 @property
2788 def isInconsistent(self):
2789 """Run necessary checks to ensure |ASN.1| object consistency.
2791 Default action is to verify |ASN.1| object against constraints imposed
2792 by `subtypeSpec`.
2794 Raises
2795 ------
2796 :py:class:`~pyasn1.error.PyAsn1tError` on any inconsistencies found
2797 """
2798 if self.componentType is noValue or not self.subtypeSpec:
2799 return False
2801 if self._componentValues is noValue:
2802 return True
2804 mapping = {}
2806 for idx, value in enumerate(self._componentValues):
2807 # Absent fields are not in the mapping
2808 if value is noValue:
2809 continue
2811 name = self.componentType.getNameByPosition(idx)
2813 mapping[name] = value
2815 try:
2816 # Represent Sequence/Set as a bare dict to constraints chain
2817 self.subtypeSpec(mapping)
2819 except error.PyAsn1Error:
2820 exc = sys.exc_info()[1]
2821 return exc
2823 return False
2825 def prettyPrint(self, scope=0):
2826 """Return an object representation string.
2828 Returns
2829 -------
2830 : :class:`str`
2831 Human-friendly object representation.
2832 """
2833 scope += 1
2834 representation = self.__class__.__name__ + ':\n'
2835 for idx, componentValue in enumerate(self._componentValues):
2836 if componentValue is not noValue and componentValue.isValue:
2837 representation += ' ' * scope
2838 if self.componentType:
2839 representation += self.componentType.getNameByPosition(idx)
2840 else:
2841 representation += self._dynamicNames.getNameByPosition(idx)
2842 representation = '%s=%s\n' % (
2843 representation, componentValue.prettyPrint(scope)
2844 )
2845 return representation
2847 def prettyPrintType(self, scope=0):
2848 scope += 1
2849 representation = '%s -> %s {\n' % (self.tagSet, self.__class__.__name__)
2850 for idx, componentType in enumerate(self.componentType.values() or self._componentValues):
2851 representation += ' ' * scope
2852 if self.componentType:
2853 representation += '"%s"' % self.componentType.getNameByPosition(idx)
2854 else:
2855 representation += '"%s"' % self._dynamicNames.getNameByPosition(idx)
2856 representation = '%s = %s\n' % (
2857 representation, componentType.prettyPrintType(scope)
2858 )
2859 return representation + '\n' + ' ' * (scope - 1) + '}'
2861 # backward compatibility
2863 def setDefaultComponents(self):
2864 return self
2866 def getComponentType(self):
2867 if self._componentTypeLen:
2868 return self.componentType
2870 def getNameByPosition(self, idx):
2871 if self._componentTypeLen:
2872 return self.componentType[idx].name
2874class Sequence(SequenceAndSetBase):
2875 __doc__ = SequenceAndSetBase.__doc__
2877 #: Set (on class, not on instance) or return a
2878 #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s)
2879 #: associated with |ASN.1| type.
2880 tagSet = tag.initTagSet(
2881 tag.Tag(tag.tagClassUniversal, tag.tagFormatConstructed, 0x10)
2882 )
2884 #: Set (on class, not on instance) or return a
2885 #: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection` object
2886 #: imposing constraints on |ASN.1| type initialization values.
2887 subtypeSpec = constraint.ConstraintsIntersection()
2889 #: Default collection of ASN.1 types of component (e.g. :py:class:`~pyasn1.type.namedtype.NamedType`)
2890 #: object imposing size constraint on |ASN.1| objects
2891 componentType = namedtype.NamedTypes()
2893 # Disambiguation ASN.1 types identification
2894 typeId = SequenceAndSetBase.getTypeId()
2896 # backward compatibility
2898 def getComponentTagMapNearPosition(self, idx):
2899 if self.componentType:
2900 return self.componentType.getTagMapNearPosition(idx)
2902 def getComponentPositionNearType(self, tagSet, idx):
2903 if self.componentType:
2904 return self.componentType.getPositionNearType(tagSet, idx)
2905 else:
2906 return idx
2909class Set(SequenceAndSetBase):
2910 __doc__ = SequenceAndSetBase.__doc__
2912 #: Set (on class, not on instance) or return a
2913 #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s)
2914 #: associated with |ASN.1| type.
2915 tagSet = tag.initTagSet(
2916 tag.Tag(tag.tagClassUniversal, tag.tagFormatConstructed, 0x11)
2917 )
2919 #: Default collection of ASN.1 types of component (e.g. :py:class:`~pyasn1.type.namedtype.NamedType`)
2920 #: object representing ASN.1 type allowed within |ASN.1| type
2921 componentType = namedtype.NamedTypes()
2923 #: Set (on class, not on instance) or return a
2924 #: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection` object
2925 #: imposing constraints on |ASN.1| type initialization values.
2926 subtypeSpec = constraint.ConstraintsIntersection()
2928 # Disambiguation ASN.1 types identification
2929 typeId = SequenceAndSetBase.getTypeId()
2931 def getComponent(self, innerFlag=False):
2932 return self
2934 def getComponentByType(self, tagSet, default=noValue,
2935 instantiate=True, innerFlag=False):
2936 """Returns |ASN.1| type component by ASN.1 tag.
2938 Parameters
2939 ----------
2940 tagSet : :py:class:`~pyasn1.type.tag.TagSet`
2941 Object representing ASN.1 tags to identify one of
2942 |ASN.1| object component
2944 Keyword Args
2945 ------------
2946 default: :class:`object`
2947 If set and requested component is a schema object, return the `default`
2948 object instead of the requested component.
2950 instantiate: :class:`bool`
2951 If :obj:`True` (default), inner component will be automatically
2952 instantiated.
2953 If :obj:`False` either existing component or the :class:`noValue`
2954 object will be returned.
2956 Returns
2957 -------
2958 : :py:class:`~pyasn1.type.base.PyAsn1Item`
2959 a pyasn1 object
2960 """
2961 componentValue = self.getComponentByPosition(
2962 self.componentType.getPositionByType(tagSet),
2963 default=default, instantiate=instantiate
2964 )
2965 if innerFlag and isinstance(componentValue, Set):
2966 # get inner component by inner tagSet
2967 return componentValue.getComponent(innerFlag=True)
2968 else:
2969 # get outer component by inner tagSet
2970 return componentValue
2972 def setComponentByType(self, tagSet, value=noValue,
2973 verifyConstraints=True,
2974 matchTags=True,
2975 matchConstraints=True,
2976 innerFlag=False):
2977 """Assign |ASN.1| type component by ASN.1 tag.
2979 Parameters
2980 ----------
2981 tagSet : :py:class:`~pyasn1.type.tag.TagSet`
2982 Object representing ASN.1 tags to identify one of
2983 |ASN.1| object component
2985 Keyword Args
2986 ------------
2987 value: :class:`object` or :py:class:`~pyasn1.type.base.PyAsn1Item` derivative
2988 A Python value to initialize |ASN.1| component with (if *componentType* is set)
2989 or ASN.1 value object to assign to |ASN.1| component.
2990 If `value` is not given, schema object will be set as a component.
2992 verifyConstraints : :class:`bool`
2993 If :obj:`False`, skip constraints validation
2995 matchTags: :class:`bool`
2996 If :obj:`False`, skip component tags matching
2998 matchConstraints: :class:`bool`
2999 If :obj:`False`, skip component constraints matching
3001 innerFlag: :class:`bool`
3002 If :obj:`True`, search for matching *tagSet* recursively.
3004 Returns
3005 -------
3006 self
3007 """
3008 idx = self.componentType.getPositionByType(tagSet)
3010 if innerFlag: # set inner component by inner tagSet
3011 componentType = self.componentType.getTypeByPosition(idx)
3013 if componentType.tagSet:
3014 return self.setComponentByPosition(
3015 idx, value, verifyConstraints, matchTags, matchConstraints
3016 )
3017 else:
3018 componentType = self.getComponentByPosition(idx)
3019 return componentType.setComponentByType(
3020 tagSet, value, verifyConstraints, matchTags, matchConstraints, innerFlag=innerFlag
3021 )
3022 else: # set outer component by inner tagSet
3023 return self.setComponentByPosition(
3024 idx, value, verifyConstraints, matchTags, matchConstraints
3025 )
3027 @property
3028 def componentTagMap(self):
3029 if self.componentType:
3030 return self.componentType.tagMapUnique
3033class Choice(Set):
3034 """Create |ASN.1| schema or value object.
3036 |ASN.1| class is based on :class:`~pyasn1.type.base.ConstructedAsn1Type`,
3037 its objects are mutable and duck-type Python :class:`list` objects.
3039 Keyword Args
3040 ------------
3041 componentType: :py:class:`~pyasn1.type.namedtype.NamedType`
3042 Object holding named ASN.1 types allowed within this collection
3044 tagSet: :py:class:`~pyasn1.type.tag.TagSet`
3045 Object representing non-default ASN.1 tag(s)
3047 subtypeSpec: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection`
3048 Object representing non-default ASN.1 subtype constraint(s). Constraints
3049 verification for |ASN.1| type can only occur on explicit
3050 `.isInconsistent` call.
3052 Examples
3053 --------
3055 .. code-block:: python
3057 class Afters(Choice):
3058 '''
3059 ASN.1 specification:
3061 Afters ::= CHOICE {
3062 cheese [0] IA5String,
3063 dessert [1] IA5String
3064 }
3065 '''
3066 componentType = NamedTypes(
3067 NamedType('cheese', IA5String().subtype(
3068 implicitTag=Tag(tagClassContext, tagFormatSimple, 0)
3069 ),
3070 NamedType('dessert', IA5String().subtype(
3071 implicitTag=Tag(tagClassContext, tagFormatSimple, 1)
3072 )
3073 )
3075 afters = Afters()
3076 afters['cheese'] = 'Mascarpone'
3077 """
3078 #: Set (on class, not on instance) or return a
3079 #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s)
3080 #: associated with |ASN.1| type.
3081 tagSet = tag.TagSet() # untagged
3083 #: Default collection of ASN.1 types of component (e.g. :py:class:`~pyasn1.type.namedtype.NamedType`)
3084 #: object representing ASN.1 type allowed within |ASN.1| type
3085 componentType = namedtype.NamedTypes()
3087 #: Set (on class, not on instance) or return a
3088 #: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection` object
3089 #: imposing constraints on |ASN.1| type initialization values.
3090 subtypeSpec = constraint.ConstraintsIntersection(
3091 constraint.ValueSizeConstraint(1, 1)
3092 )
3094 # Disambiguation ASN.1 types identification
3095 typeId = Set.getTypeId()
3097 _currentIdx = None
3099 def __eq__(self, other):
3100 if self._componentValues:
3101 return self._componentValues[self._currentIdx] == other
3102 return NotImplemented
3104 def __ne__(self, other):
3105 if self._componentValues:
3106 return self._componentValues[self._currentIdx] != other
3107 return NotImplemented
3109 def __lt__(self, other):
3110 if self._componentValues:
3111 return self._componentValues[self._currentIdx] < other
3112 return NotImplemented
3114 def __le__(self, other):
3115 if self._componentValues:
3116 return self._componentValues[self._currentIdx] <= other
3117 return NotImplemented
3119 def __gt__(self, other):
3120 if self._componentValues:
3121 return self._componentValues[self._currentIdx] > other
3122 return NotImplemented
3124 def __ge__(self, other):
3125 if self._componentValues:
3126 return self._componentValues[self._currentIdx] >= other
3127 return NotImplemented
3129 if sys.version_info[0] <= 2:
3130 def __nonzero__(self):
3131 return self._componentValues and True or False
3132 else:
3133 def __bool__(self):
3134 return self._componentValues and True or False
3136 def __len__(self):
3137 return self._currentIdx is not None and 1 or 0
3139 def __contains__(self, key):
3140 if self._currentIdx is None:
3141 return False
3142 return key == self.componentType[self._currentIdx].getName()
3144 def __iter__(self):
3145 if self._currentIdx is None:
3146 raise StopIteration
3147 yield self.componentType[self._currentIdx].getName()
3149 # Python dict protocol
3151 def values(self):
3152 if self._currentIdx is not None:
3153 yield self._componentValues[self._currentIdx]
3155 def keys(self):
3156 if self._currentIdx is not None:
3157 yield self.componentType[self._currentIdx].getName()
3159 def items(self):
3160 if self._currentIdx is not None:
3161 yield self.componentType[self._currentIdx].getName(), self[self._currentIdx]
3163 def checkConsistency(self):
3164 if self._currentIdx is None:
3165 raise error.PyAsn1Error('Component not chosen')
3167 def _cloneComponentValues(self, myClone, cloneValueFlag):
3168 try:
3169 component = self.getComponent()
3170 except error.PyAsn1Error:
3171 pass
3172 else:
3173 if isinstance(component, Choice):
3174 tagSet = component.effectiveTagSet
3175 else:
3176 tagSet = component.tagSet
3177 if isinstance(component, base.ConstructedAsn1Type):
3178 myClone.setComponentByType(
3179 tagSet, component.clone(cloneValueFlag=cloneValueFlag)
3180 )
3181 else:
3182 myClone.setComponentByType(tagSet, component.clone())
3184 def getComponentByPosition(self, idx, default=noValue, instantiate=True):
3185 __doc__ = Set.__doc__
3187 if self._currentIdx is None or self._currentIdx != idx:
3188 return Set.getComponentByPosition(self, idx, default=default,
3189 instantiate=instantiate)
3191 return self._componentValues[idx]
3193 def setComponentByPosition(self, idx, value=noValue,
3194 verifyConstraints=True,
3195 matchTags=True,
3196 matchConstraints=True):
3197 """Assign |ASN.1| type component by position.
3199 Equivalent to Python sequence item assignment operation (e.g. `[]`).
3201 Parameters
3202 ----------
3203 idx: :class:`int`
3204 Component index (zero-based). Must either refer to existing
3205 component or to N+1 component. In the latter case a new component
3206 type gets instantiated (if *componentType* is set, or given ASN.1
3207 object is taken otherwise) and appended to the |ASN.1| sequence.
3209 Keyword Args
3210 ------------
3211 value: :class:`object` or :py:class:`~pyasn1.type.base.PyAsn1Item` derivative
3212 A Python value to initialize |ASN.1| component with (if *componentType* is set)
3213 or ASN.1 value object to assign to |ASN.1| component. Once a new value is
3214 set to *idx* component, previous value is dropped.
3215 If `value` is not given, schema object will be set as a component.
3217 verifyConstraints : :class:`bool`
3218 If :obj:`False`, skip constraints validation
3220 matchTags: :class:`bool`
3221 If :obj:`False`, skip component tags matching
3223 matchConstraints: :class:`bool`
3224 If :obj:`False`, skip component constraints matching
3226 Returns
3227 -------
3228 self
3229 """
3230 oldIdx = self._currentIdx
3231 Set.setComponentByPosition(self, idx, value, verifyConstraints, matchTags, matchConstraints)
3232 self._currentIdx = idx
3233 if oldIdx is not None and oldIdx != idx:
3234 self._componentValues[oldIdx] = noValue
3235 return self
3237 @property
3238 def effectiveTagSet(self):
3239 """Return a :class:`~pyasn1.type.tag.TagSet` object of the currently initialized component or self (if |ASN.1| is tagged)."""
3240 if self.tagSet:
3241 return self.tagSet
3242 else:
3243 component = self.getComponent()
3244 return component.effectiveTagSet
3246 @property
3247 def tagMap(self):
3248 """"Return a :class:`~pyasn1.type.tagmap.TagMap` object mapping
3249 ASN.1 tags to ASN.1 objects contained within callee.
3250 """
3251 if self.tagSet:
3252 return Set.tagMap.fget(self)
3253 else:
3254 return self.componentType.tagMapUnique
3256 def getComponent(self, innerFlag=False):
3257 """Return currently assigned component of the |ASN.1| object.
3259 Returns
3260 -------
3261 : :py:class:`~pyasn1.type.base.PyAsn1Item`
3262 a PyASN1 object
3263 """
3264 if self._currentIdx is None:
3265 raise error.PyAsn1Error('Component not chosen')
3266 else:
3267 c = self._componentValues[self._currentIdx]
3268 if innerFlag and isinstance(c, Choice):
3269 return c.getComponent(innerFlag)
3270 else:
3271 return c
3273 def getName(self, innerFlag=False):
3274 """Return the name of currently assigned component of the |ASN.1| object.
3276 Returns
3277 -------
3278 : :py:class:`str`
3279 |ASN.1| component name
3280 """
3281 if self._currentIdx is None:
3282 raise error.PyAsn1Error('Component not chosen')
3283 else:
3284 if innerFlag:
3285 c = self._componentValues[self._currentIdx]
3286 if isinstance(c, Choice):
3287 return c.getName(innerFlag)
3288 return self.componentType.getNameByPosition(self._currentIdx)
3290 @property
3291 def isValue(self):
3292 """Indicate that |ASN.1| object represents ASN.1 value.
3294 If *isValue* is :obj:`False` then this object represents just ASN.1 schema.
3296 If *isValue* is :obj:`True` then, in addition to its ASN.1 schema features,
3297 this object can also be used like a Python built-in object (e.g.
3298 :class:`int`, :class:`str`, :class:`dict` etc.).
3300 Returns
3301 -------
3302 : :class:`bool`
3303 :obj:`False` if object represents just ASN.1 schema.
3304 :obj:`True` if object represents ASN.1 schema and can be used as a normal
3305 value.
3307 Note
3308 ----
3309 There is an important distinction between PyASN1 schema and value objects.
3310 The PyASN1 schema objects can only participate in ASN.1 schema-related
3311 operations (e.g. defining or testing the structure of the data). Most
3312 obvious uses of ASN.1 schema is to guide serialisation codecs whilst
3313 encoding/decoding serialised ASN.1 contents.
3315 The PyASN1 value objects can **additionally** participate in many operations
3316 involving regular Python objects (e.g. arithmetic, comprehension etc).
3317 """
3318 if self._currentIdx is None:
3319 return False
3321 componentValue = self._componentValues[self._currentIdx]
3323 return componentValue is not noValue and componentValue.isValue
3325 def clear(self):
3326 self._currentIdx = None
3327 return Set.clear(self)
3329 # compatibility stubs
3331 def getMinTagSet(self):
3332 return self.minTagSet
3335class Any(OctetString):
3336 """Create |ASN.1| schema or value object.
3338 |ASN.1| class is based on :class:`~pyasn1.type.base.SimpleAsn1Type`,
3339 its objects are immutable and duck-type Python 2 :class:`str` or Python 3
3340 :class:`bytes`. When used in Unicode context, |ASN.1| type assumes
3341 "|encoding|" serialisation.
3343 Keyword Args
3344 ------------
3345 value: :class:`unicode`, :class:`str`, :class:`bytes` or |ASN.1| object
3346 :class:`str` (Python 2) or :class:`bytes` (Python 3), alternatively
3347 :class:`unicode` object (Python 2) or :class:`str` (Python 3)
3348 representing character string to be serialised into octets (note
3349 `encoding` parameter) or |ASN.1| object.
3350 If `value` is not given, schema object will be created.
3352 tagSet: :py:class:`~pyasn1.type.tag.TagSet`
3353 Object representing non-default ASN.1 tag(s)
3355 subtypeSpec: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection`
3356 Object representing non-default ASN.1 subtype constraint(s). Constraints
3357 verification for |ASN.1| type occurs automatically on object
3358 instantiation.
3360 encoding: :py:class:`str`
3361 Unicode codec ID to encode/decode :class:`unicode` (Python 2) or
3362 :class:`str` (Python 3) the payload when |ASN.1| object is used
3363 in text string context.
3365 binValue: :py:class:`str`
3366 Binary string initializer to use instead of the *value*.
3367 Example: '10110011'.
3369 hexValue: :py:class:`str`
3370 Hexadecimal string initializer to use instead of the *value*.
3371 Example: 'DEADBEEF'.
3373 Raises
3374 ------
3375 ~pyasn1.error.ValueConstraintError, ~pyasn1.error.PyAsn1Error
3376 On constraint violation or bad initializer.
3378 Examples
3379 --------
3380 .. code-block:: python
3382 class Error(Sequence):
3383 '''
3384 ASN.1 specification:
3386 Error ::= SEQUENCE {
3387 code INTEGER,
3388 parameter ANY DEFINED BY code -- Either INTEGER or REAL
3389 }
3390 '''
3391 componentType=NamedTypes(
3392 NamedType('code', Integer()),
3393 NamedType('parameter', Any(),
3394 openType=OpenType('code', {1: Integer(),
3395 2: Real()}))
3396 )
3398 error = Error()
3399 error['code'] = 1
3400 error['parameter'] = Integer(1234)
3401 """
3402 #: Set (on class, not on instance) or return a
3403 #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s)
3404 #: associated with |ASN.1| type.
3405 tagSet = tag.TagSet() # untagged
3407 #: Set (on class, not on instance) or return a
3408 #: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection` object
3409 #: imposing constraints on |ASN.1| type initialization values.
3410 subtypeSpec = constraint.ConstraintsIntersection()
3412 # Disambiguation ASN.1 types identification
3413 typeId = OctetString.getTypeId()
3415 @property
3416 def tagMap(self):
3417 """"Return a :class:`~pyasn1.type.tagmap.TagMap` object mapping
3418 ASN.1 tags to ASN.1 objects contained within callee.
3419 """
3420 try:
3421 return self._tagMap
3423 except AttributeError:
3424 self._tagMap = tagmap.TagMap(
3425 {self.tagSet: self},
3426 {eoo.endOfOctets.tagSet: eoo.endOfOctets},
3427 self
3428 )
3430 return self._tagMap
3432# XXX
3433# coercion rules?