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