Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/pyasn1/type/univ.py: 35%
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
1494 mantissa, base, exponent = self._value
1496 if not mantissa:
1497 return 0.0
1499 if base == 2:
1500 return math.ldexp(float(mantissa), exponent)
1502 # base is 10 (prettyIn() rejects everything else); refuse to
1503 # materialize astronomically large integers via pow()
1504 if exponent > sys.float_info.max_10_exp:
1505 raise OverflowError('Real value too large to convert to float')
1507 return float(mantissa * pow(base, exponent))
1509 def __abs__(self):
1510 return self.clone(abs(float(self)))
1512 def __pos__(self):
1513 return self.clone(+float(self))
1515 def __neg__(self):
1516 return self.clone(-float(self))
1518 def __round__(self, n=0):
1519 r = round(float(self), n)
1520 if n:
1521 return self.clone(r)
1522 else:
1523 return r
1525 def __floor__(self):
1526 return self.clone(math.floor(float(self)))
1528 def __ceil__(self):
1529 return self.clone(math.ceil(float(self)))
1531 def __trunc__(self):
1532 return self.clone(math.trunc(float(self)))
1534 def __lt__(self, value):
1535 return float(self) < value
1537 def __le__(self, value):
1538 return float(self) <= value
1540 def __eq__(self, value):
1541 return float(self) == value
1543 def __ne__(self, value):
1544 return float(self) != value
1546 def __gt__(self, value):
1547 return float(self) > value
1549 def __ge__(self, value):
1550 return float(self) >= value
1552 def __bool__(self):
1553 return bool(float(self))
1555 __hash__ = base.SimpleAsn1Type.__hash__
1557 def __getitem__(self, idx):
1558 if self._value in self._inf:
1559 raise error.PyAsn1Error('Invalid infinite value operation')
1560 else:
1561 return self._value[idx]
1563 # compatibility stubs
1565 def isPlusInfinity(self):
1566 return self.isPlusInf
1568 def isMinusInfinity(self):
1569 return self.isMinusInf
1571 def isInfinity(self):
1572 return self.isInf
1575class Enumerated(Integer):
1576 """Create |ASN.1| schema or value object.
1578 |ASN.1| class is based on :class:`~pyasn1.type.base.SimpleAsn1Type`, its
1579 objects are immutable and duck-type Python :class:`int` objects.
1581 Keyword Args
1582 ------------
1583 value: :class:`int`, :class:`str` or |ASN.1| object
1584 Python :class:`int` or :class:`str` literal or |ASN.1| object.
1585 If `value` is not given, schema object will be created.
1587 tagSet: :py:class:`~pyasn1.type.tag.TagSet`
1588 Object representing non-default ASN.1 tag(s)
1590 subtypeSpec: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection`
1591 Object representing non-default ASN.1 subtype constraint(s). Constraints
1592 verification for |ASN.1| type occurs automatically on object
1593 instantiation.
1595 namedValues: :py:class:`~pyasn1.type.namedval.NamedValues`
1596 Object representing non-default symbolic aliases for numbers
1598 Raises
1599 ------
1600 ~pyasn1.error.ValueConstraintError, ~pyasn1.error.PyAsn1Error
1601 On constraint violation or bad initializer.
1603 Examples
1604 --------
1606 .. code-block:: python
1608 class RadioButton(Enumerated):
1609 '''
1610 ASN.1 specification:
1612 RadioButton ::= ENUMERATED { button1(0), button2(1),
1613 button3(2) }
1615 selected-by-default RadioButton ::= button1
1616 '''
1617 namedValues = NamedValues(
1618 ('button1', 0), ('button2', 1),
1619 ('button3', 2)
1620 )
1622 selected_by_default = RadioButton('button1')
1623 """
1624 #: Set (on class, not on instance) or return a
1625 #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s)
1626 #: associated with |ASN.1| type.
1627 tagSet = tag.initTagSet(
1628 tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 0x0A)
1629 )
1631 #: Set (on class, not on instance) or return a
1632 #: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection` object
1633 #: imposing constraints on |ASN.1| type initialization values.
1634 subtypeSpec = constraint.ConstraintsIntersection()
1636 # Optimization for faster codec lookup
1637 typeId = Integer.getTypeId()
1639 #: Default :py:class:`~pyasn1.type.namedval.NamedValues` object
1640 #: representing symbolic aliases for numbers
1641 namedValues = namedval.NamedValues()
1644# "Structured" ASN.1 types
1646class SequenceOfAndSetOfBase(base.ConstructedAsn1Type):
1647 """Create |ASN.1| schema or value object.
1649 |ASN.1| class is based on :class:`~pyasn1.type.base.ConstructedAsn1Type`,
1650 its objects are mutable and duck-type Python :class:`list` objects.
1652 Keyword Args
1653 ------------
1654 componentType : :py:class:`~pyasn1.type.base.PyAsn1Item` derivative
1655 A pyasn1 object representing ASN.1 type allowed within |ASN.1| type
1657 tagSet: :py:class:`~pyasn1.type.tag.TagSet`
1658 Object representing non-default ASN.1 tag(s)
1660 subtypeSpec: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection`
1661 Object representing non-default ASN.1 subtype constraint(s). Constraints
1662 verification for |ASN.1| type can only occur on explicit
1663 `.isInconsistent` call.
1665 Examples
1666 --------
1668 .. code-block:: python
1670 class LotteryDraw(SequenceOf): # SetOf is similar
1671 '''
1672 ASN.1 specification:
1674 LotteryDraw ::= SEQUENCE OF INTEGER
1675 '''
1676 componentType = Integer()
1678 lotteryDraw = LotteryDraw()
1679 lotteryDraw.extend([123, 456, 789])
1680 """
1681 def __init__(self, *args, **kwargs):
1682 # support positional params for backward compatibility
1683 if args:
1684 for key, value in zip(('componentType', 'tagSet',
1685 'subtypeSpec'), args):
1686 if key in kwargs:
1687 raise error.PyAsn1Error('Conflicting positional and keyword params!')
1688 kwargs['componentType'] = value
1690 self._componentValues = noValue
1692 base.ConstructedAsn1Type.__init__(self, **kwargs)
1694 # Python list protocol
1696 def __getitem__(self, idx):
1697 try:
1698 return self.getComponentByPosition(idx)
1700 except error.PyAsn1Error as exc:
1701 raise IndexError(exc)
1703 def __setitem__(self, idx, value):
1704 try:
1705 self.setComponentByPosition(idx, value)
1707 except error.PyAsn1Error as exc:
1708 raise IndexError(exc)
1710 def append(self, value):
1711 if self._componentValues is noValue:
1712 pos = 0
1714 else:
1715 pos = len(self._componentValues)
1717 self[pos] = value
1719 def count(self, value):
1720 return list(self._componentValues.values()).count(value)
1722 def extend(self, values):
1723 for value in values:
1724 self.append(value)
1726 if self._componentValues is noValue:
1727 self._componentValues = {}
1729 def index(self, value, start=0, stop=None):
1730 if stop is None:
1731 stop = len(self)
1733 indices, values = zip(*self._componentValues.items())
1735 # TODO: remove when Py2.5 support is gone
1736 values = list(values)
1738 try:
1739 return indices[values.index(value, start, stop)]
1741 except error.PyAsn1Error as exc:
1742 raise ValueError(exc)
1744 def reverse(self):
1745 self._componentValues.reverse()
1747 def sort(self, key=None, reverse=False):
1748 self._componentValues = dict(
1749 enumerate(sorted(self._componentValues.values(),
1750 key=key, reverse=reverse)))
1752 def __len__(self):
1753 if self._componentValues is noValue or not self._componentValues:
1754 return 0
1756 return max(self._componentValues) + 1
1758 def __iter__(self):
1759 for idx in range(0, len(self)):
1760 yield self.getComponentByPosition(idx)
1762 def _cloneComponentValues(self, myClone, cloneValueFlag):
1763 for idx, componentValue in self._componentValues.items():
1764 if componentValue is not noValue:
1765 if isinstance(componentValue, base.ConstructedAsn1Type):
1766 myClone.setComponentByPosition(
1767 idx, componentValue.clone(cloneValueFlag=cloneValueFlag)
1768 )
1769 else:
1770 myClone.setComponentByPosition(idx, componentValue.clone())
1772 def getComponentByPosition(self, idx, default=noValue, instantiate=True):
1773 """Return |ASN.1| type component value by position.
1775 Equivalent to Python sequence subscription operation (e.g. `[]`).
1777 Parameters
1778 ----------
1779 idx : :class:`int`
1780 Component index (zero-based). Must either refer to an existing
1781 component or to N+1 component (if *componentType* is set). In the latter
1782 case a new component type gets instantiated and appended to the |ASN.1|
1783 sequence.
1785 Keyword Args
1786 ------------
1787 default: :class:`object`
1788 If set and requested component is a schema object, return the `default`
1789 object instead of the requested component.
1791 instantiate: :class:`bool`
1792 If :obj:`True` (default), inner component will be automatically instantiated.
1793 If :obj:`False` either existing component or the :class:`NoValue` object will be
1794 returned.
1796 Returns
1797 -------
1798 : :py:class:`~pyasn1.type.base.PyAsn1Item`
1799 Instantiate |ASN.1| component type or return existing component value
1801 Examples
1802 --------
1804 .. code-block:: python
1806 # can also be SetOf
1807 class MySequenceOf(SequenceOf):
1808 componentType = OctetString()
1810 s = MySequenceOf()
1812 # returns component #0 with `.isValue` property False
1813 s.getComponentByPosition(0)
1815 # returns None
1816 s.getComponentByPosition(0, default=None)
1818 s.clear()
1820 # returns noValue
1821 s.getComponentByPosition(0, instantiate=False)
1823 # sets component #0 to OctetString() ASN.1 schema
1824 # object and returns it
1825 s.getComponentByPosition(0, instantiate=True)
1827 # sets component #0 to ASN.1 value object
1828 s.setComponentByPosition(0, 'ABCD')
1830 # returns OctetString('ABCD') value object
1831 s.getComponentByPosition(0, instantiate=False)
1833 s.clear()
1835 # returns noValue
1836 s.getComponentByPosition(0, instantiate=False)
1837 """
1838 if isinstance(idx, slice):
1839 indices = tuple(range(len(self)))
1840 return [self.getComponentByPosition(subidx, default, instantiate)
1841 for subidx in indices[idx]]
1843 if idx < 0:
1844 idx = len(self) + idx
1845 if idx < 0:
1846 raise error.PyAsn1Error(
1847 'SequenceOf/SetOf index is out of range')
1849 try:
1850 componentValue = self._componentValues[idx]
1852 except (KeyError, error.PyAsn1Error):
1853 if not instantiate:
1854 return default
1856 self.setComponentByPosition(idx)
1858 componentValue = self._componentValues[idx]
1860 if default is noValue or componentValue.isValue:
1861 return componentValue
1862 else:
1863 return default
1865 def setComponentByPosition(self, idx, value=noValue,
1866 verifyConstraints=True,
1867 matchTags=True,
1868 matchConstraints=True):
1869 """Assign |ASN.1| type component by position.
1871 Equivalent to Python sequence item assignment operation (e.g. `[]`)
1872 or list.append() (when idx == len(self)).
1874 Parameters
1875 ----------
1876 idx: :class:`int`
1877 Component index (zero-based). Must either refer to existing
1878 component or to N+1 component. In the latter case a new component
1879 type gets instantiated (if *componentType* is set, or given ASN.1
1880 object is taken otherwise) and appended to the |ASN.1| sequence.
1882 Keyword Args
1883 ------------
1884 value: :class:`object` or :py:class:`~pyasn1.type.base.PyAsn1Item` derivative
1885 A Python value to initialize |ASN.1| component with (if *componentType* is set)
1886 or ASN.1 value object to assign to |ASN.1| component.
1887 If `value` is not given, schema object will be set as a component.
1889 verifyConstraints: :class:`bool`
1890 If :obj:`False`, skip constraints validation
1892 matchTags: :class:`bool`
1893 If :obj:`False`, skip component tags matching
1895 matchConstraints: :class:`bool`
1896 If :obj:`False`, skip component constraints matching
1898 Returns
1899 -------
1900 self
1902 Raises
1903 ------
1904 ~pyasn1.error.ValueConstraintError, ~pyasn1.error.PyAsn1Error
1905 On constraint violation or bad initializer
1906 IndexError
1907 When idx > len(self)
1908 """
1909 if isinstance(idx, slice):
1910 indices = tuple(range(len(self)))
1911 startIdx = indices and indices[idx][0] or 0
1912 for subIdx, subValue in enumerate(value):
1913 self.setComponentByPosition(
1914 startIdx + subIdx, subValue, verifyConstraints,
1915 matchTags, matchConstraints)
1916 return self
1918 if idx < 0:
1919 idx = len(self) + idx
1920 if idx < 0:
1921 raise error.PyAsn1Error(
1922 'SequenceOf/SetOf index is out of range')
1924 componentType = self.componentType
1926 if self._componentValues is noValue:
1927 componentValues = {}
1929 else:
1930 componentValues = self._componentValues
1932 currentValue = componentValues.get(idx, noValue)
1934 if value is noValue:
1935 if componentType is not None:
1936 value = componentType.clone()
1938 elif currentValue is noValue:
1939 raise error.PyAsn1Error('Component type not defined')
1941 elif not isinstance(value, base.Asn1Item):
1942 if (componentType is not None and
1943 isinstance(componentType, base.SimpleAsn1Type)):
1944 value = componentType.clone(value=value)
1946 elif (currentValue is not noValue and
1947 isinstance(currentValue, base.SimpleAsn1Type)):
1948 value = currentValue.clone(value=value)
1950 else:
1951 raise error.PyAsn1Error(
1952 'Non-ASN.1 value %r and undefined component'
1953 ' type at %r' % (value, self))
1955 elif componentType is not None and (matchTags or matchConstraints):
1956 subtypeChecker = (
1957 self.strictConstraints and
1958 componentType.isSameTypeWith or
1959 componentType.isSuperTypeOf)
1961 if not subtypeChecker(value, verifyConstraints and matchTags,
1962 verifyConstraints and matchConstraints):
1963 # TODO: we should wrap componentType with UnnamedType to carry
1964 # additional properties associated with componentType
1965 if componentType.typeId != Any.typeId:
1966 raise error.PyAsn1Error(
1967 'Component value is tag-incompatible: %r vs '
1968 '%r' % (value, componentType))
1970 componentValues[idx] = value
1972 self._componentValues = componentValues
1974 return self
1976 @property
1977 def componentTagMap(self):
1978 if self.componentType is not None:
1979 return self.componentType.tagMap
1981 @property
1982 def components(self):
1983 return [self._componentValues[idx]
1984 for idx in sorted(self._componentValues)]
1986 def clear(self):
1987 """Remove all components and become an empty |ASN.1| value object.
1989 Has the same effect on |ASN.1| object as it does on :class:`list`
1990 built-in.
1991 """
1992 self._componentValues = {}
1993 return self
1995 def reset(self):
1996 """Remove all components and become a |ASN.1| schema object.
1998 See :meth:`isValue` property for more information on the
1999 distinction between value and schema objects.
2000 """
2001 self._componentValues = noValue
2002 return self
2004 def prettyPrint(self, scope=0):
2005 scope += 1
2006 representation = self.__class__.__name__ + ':\n'
2008 if not self.isValue:
2009 return representation
2011 for idx, componentValue in enumerate(self):
2012 representation += ' ' * scope
2013 if (componentValue is noValue and
2014 self.componentType is not None):
2015 representation += '<empty>'
2016 else:
2017 representation += componentValue.prettyPrint(scope)
2019 return representation
2021 def prettyPrintType(self, scope=0):
2022 scope += 1
2023 representation = '%s -> %s {\n' % (self.tagSet, self.__class__.__name__)
2024 if self.componentType is not None:
2025 representation += ' ' * scope
2026 representation += self.componentType.prettyPrintType(scope)
2027 return representation + '\n' + ' ' * (scope - 1) + '}'
2030 @property
2031 def isValue(self):
2032 """Indicate that |ASN.1| object represents ASN.1 value.
2034 If *isValue* is :obj:`False` then this object represents just ASN.1 schema.
2036 If *isValue* is :obj:`True` then, in addition to its ASN.1 schema features,
2037 this object can also be used like a Python built-in object
2038 (e.g. :class:`int`, :class:`str`, :class:`dict` etc.).
2040 Returns
2041 -------
2042 : :class:`bool`
2043 :obj:`False` if object represents just ASN.1 schema.
2044 :obj:`True` if object represents ASN.1 schema and can be used as a normal value.
2046 Note
2047 ----
2048 There is an important distinction between PyASN1 schema and value objects.
2049 The PyASN1 schema objects can only participate in ASN.1 schema-related
2050 operations (e.g. defining or testing the structure of the data). Most
2051 obvious uses of ASN.1 schema is to guide serialisation codecs whilst
2052 encoding/decoding serialised ASN.1 contents.
2054 The PyASN1 value objects can **additionally** participate in many operations
2055 involving regular Python objects (e.g. arithmetic, comprehension etc).
2056 """
2057 if self._componentValues is noValue:
2058 return False
2060 if len(self._componentValues) != len(self):
2061 return False
2063 for componentValue in self._componentValues.values():
2064 if componentValue is noValue or not componentValue.isValue:
2065 return False
2067 return True
2069 @property
2070 def isInconsistent(self):
2071 """Run necessary checks to ensure |ASN.1| object consistency.
2073 Default action is to verify |ASN.1| object against constraints imposed
2074 by `subtypeSpec`.
2076 Raises
2077 ------
2078 :py:class:`~pyasn1.error.PyAsn1tError` on any inconsistencies found
2079 """
2080 if self.componentType is noValue or not self.subtypeSpec:
2081 return False
2083 if self._componentValues is noValue:
2084 return True
2086 mapping = {}
2088 for idx, value in self._componentValues.items():
2089 # Absent fields are not in the mapping
2090 if value is noValue:
2091 continue
2093 mapping[idx] = value
2095 try:
2096 # Represent SequenceOf/SetOf as a bare dict to constraints chain
2097 self.subtypeSpec(mapping)
2099 except error.PyAsn1Error as exc:
2100 return exc
2102 return False
2104class SequenceOf(SequenceOfAndSetOfBase):
2105 __doc__ = SequenceOfAndSetOfBase.__doc__
2107 #: Set (on class, not on instance) or return a
2108 #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s)
2109 #: associated with |ASN.1| type.
2110 tagSet = tag.initTagSet(
2111 tag.Tag(tag.tagClassUniversal, tag.tagFormatConstructed, 0x10)
2112 )
2114 #: Default :py:class:`~pyasn1.type.base.PyAsn1Item` derivative
2115 #: object representing ASN.1 type allowed within |ASN.1| type
2116 componentType = None
2118 #: Set (on class, not on instance) or return a
2119 #: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection` object
2120 #: imposing constraints on |ASN.1| type initialization values.
2121 subtypeSpec = constraint.ConstraintsIntersection()
2123 # Disambiguation ASN.1 types identification
2124 typeId = SequenceOfAndSetOfBase.getTypeId()
2127class SetOf(SequenceOfAndSetOfBase):
2128 __doc__ = SequenceOfAndSetOfBase.__doc__
2130 #: Set (on class, not on instance) or return a
2131 #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s)
2132 #: associated with |ASN.1| type.
2133 tagSet = tag.initTagSet(
2134 tag.Tag(tag.tagClassUniversal, tag.tagFormatConstructed, 0x11)
2135 )
2137 #: Default :py:class:`~pyasn1.type.base.PyAsn1Item` derivative
2138 #: object representing ASN.1 type allowed within |ASN.1| type
2139 componentType = None
2141 #: Set (on class, not on instance) or return a
2142 #: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection` object
2143 #: imposing constraints on |ASN.1| type initialization values.
2144 subtypeSpec = constraint.ConstraintsIntersection()
2146 # Disambiguation ASN.1 types identification
2147 typeId = SequenceOfAndSetOfBase.getTypeId()
2150class SequenceAndSetBase(base.ConstructedAsn1Type):
2151 """Create |ASN.1| schema or value object.
2153 |ASN.1| class is based on :class:`~pyasn1.type.base.ConstructedAsn1Type`,
2154 its objects are mutable and duck-type Python :class:`dict` objects.
2156 Keyword Args
2157 ------------
2158 componentType: :py:class:`~pyasn1.type.namedtype.NamedType`
2159 Object holding named ASN.1 types allowed within this collection
2161 tagSet: :py:class:`~pyasn1.type.tag.TagSet`
2162 Object representing non-default ASN.1 tag(s)
2164 subtypeSpec: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection`
2165 Object representing non-default ASN.1 subtype constraint(s). Constraints
2166 verification for |ASN.1| type can only occur on explicit
2167 `.isInconsistent` call.
2169 Examples
2170 --------
2172 .. code-block:: python
2174 class Description(Sequence): # Set is similar
2175 '''
2176 ASN.1 specification:
2178 Description ::= SEQUENCE {
2179 surname IA5String,
2180 first-name IA5String OPTIONAL,
2181 age INTEGER DEFAULT 40
2182 }
2183 '''
2184 componentType = NamedTypes(
2185 NamedType('surname', IA5String()),
2186 OptionalNamedType('first-name', IA5String()),
2187 DefaultedNamedType('age', Integer(40))
2188 )
2190 descr = Description()
2191 descr['surname'] = 'Smith'
2192 descr['first-name'] = 'John'
2193 """
2194 #: Default :py:class:`~pyasn1.type.namedtype.NamedTypes`
2195 #: object representing named ASN.1 types allowed within |ASN.1| type
2196 componentType = namedtype.NamedTypes()
2199 class DynamicNames(object):
2200 """Fields names/positions mapping for component-less objects"""
2201 def __init__(self):
2202 self._keyToIdxMap = {}
2203 self._idxToKeyMap = {}
2205 def __len__(self):
2206 return len(self._keyToIdxMap)
2208 def __contains__(self, item):
2209 return item in self._keyToIdxMap or item in self._idxToKeyMap
2211 def __iter__(self):
2212 return (self._idxToKeyMap[idx] for idx in range(len(self._idxToKeyMap)))
2214 def __getitem__(self, item):
2215 try:
2216 return self._keyToIdxMap[item]
2218 except KeyError:
2219 return self._idxToKeyMap[item]
2221 def getNameByPosition(self, idx):
2222 try:
2223 return self._idxToKeyMap[idx]
2225 except KeyError:
2226 raise error.PyAsn1Error('Type position out of range')
2228 def getPositionByName(self, name):
2229 try:
2230 return self._keyToIdxMap[name]
2232 except KeyError:
2233 raise error.PyAsn1Error('Name %s not found' % (name,))
2235 def addField(self, idx):
2236 self._keyToIdxMap['field-%d' % idx] = idx
2237 self._idxToKeyMap[idx] = 'field-%d' % idx
2240 def __init__(self, **kwargs):
2241 base.ConstructedAsn1Type.__init__(self, **kwargs)
2242 self._componentTypeLen = len(self.componentType)
2243 if self._componentTypeLen:
2244 self._componentValues = []
2245 else:
2246 self._componentValues = noValue
2247 self._dynamicNames = self._componentTypeLen or self.DynamicNames()
2249 def __getitem__(self, idx):
2250 if isinstance(idx, str):
2251 try:
2252 return self.getComponentByName(idx)
2254 except error.PyAsn1Error as exc:
2255 # duck-typing dict
2256 raise KeyError(exc)
2258 else:
2259 try:
2260 return self.getComponentByPosition(idx)
2262 except error.PyAsn1Error as exc:
2263 # duck-typing list
2264 raise IndexError(exc)
2266 def __setitem__(self, idx, value):
2267 if isinstance(idx, str):
2268 try:
2269 self.setComponentByName(idx, value)
2271 except error.PyAsn1Error as exc:
2272 # duck-typing dict
2273 raise KeyError(exc)
2275 else:
2276 try:
2277 self.setComponentByPosition(idx, value)
2279 except error.PyAsn1Error as exc:
2280 # duck-typing list
2281 raise IndexError(exc)
2283 def __contains__(self, key):
2284 if self._componentTypeLen:
2285 return key in self.componentType
2286 else:
2287 return key in self._dynamicNames
2289 def __len__(self):
2290 return len(self._componentValues)
2292 def __iter__(self):
2293 return iter(self.componentType or self._dynamicNames)
2295 # Python dict protocol
2297 def values(self):
2298 for idx in range(self._componentTypeLen or len(self._dynamicNames)):
2299 yield self[idx]
2301 def keys(self):
2302 return iter(self)
2304 def items(self):
2305 for idx in range(self._componentTypeLen or len(self._dynamicNames)):
2306 if self._componentTypeLen:
2307 yield self.componentType[idx].name, self[idx]
2308 else:
2309 yield self._dynamicNames[idx], self[idx]
2311 def update(self, *iterValue, **mappingValue):
2312 for k, v in iterValue:
2313 self[k] = v
2314 for k in mappingValue:
2315 self[k] = mappingValue[k]
2317 def clear(self):
2318 """Remove all components and become an empty |ASN.1| value object.
2320 Has the same effect on |ASN.1| object as it does on :class:`dict`
2321 built-in.
2322 """
2323 self._componentValues = []
2324 self._dynamicNames = self.DynamicNames()
2325 return self
2327 def reset(self):
2328 """Remove all components and become a |ASN.1| schema object.
2330 See :meth:`isValue` property for more information on the
2331 distinction between value and schema objects.
2332 """
2333 self._componentValues = noValue
2334 self._dynamicNames = self.DynamicNames()
2335 return self
2337 @property
2338 def components(self):
2339 return self._componentValues
2341 def _cloneComponentValues(self, myClone, cloneValueFlag):
2342 if self._componentValues is noValue:
2343 return
2345 for idx, componentValue in enumerate(self._componentValues):
2346 if componentValue is not noValue:
2347 if isinstance(componentValue, base.ConstructedAsn1Type):
2348 myClone.setComponentByPosition(
2349 idx, componentValue.clone(cloneValueFlag=cloneValueFlag)
2350 )
2351 else:
2352 myClone.setComponentByPosition(idx, componentValue.clone())
2354 def getComponentByName(self, name, default=noValue, instantiate=True):
2355 """Returns |ASN.1| type component by name.
2357 Equivalent to Python :class:`dict` subscription operation (e.g. `[]`).
2359 Parameters
2360 ----------
2361 name: :class:`str`
2362 |ASN.1| type component name
2364 Keyword Args
2365 ------------
2366 default: :class:`object`
2367 If set and requested component is a schema object, return the `default`
2368 object instead of the requested component.
2370 instantiate: :class:`bool`
2371 If :obj:`True` (default), inner component will be automatically
2372 instantiated.
2373 If :obj:`False` either existing component or the :class:`NoValue`
2374 object will be returned.
2376 Returns
2377 -------
2378 : :py:class:`~pyasn1.type.base.PyAsn1Item`
2379 Instantiate |ASN.1| component type or return existing
2380 component value
2381 """
2382 if self._componentTypeLen:
2383 idx = self.componentType.getPositionByName(name)
2384 else:
2385 try:
2386 idx = self._dynamicNames.getPositionByName(name)
2388 except KeyError:
2389 raise error.PyAsn1Error('Name %s not found' % (name,))
2391 return self.getComponentByPosition(idx, default=default, instantiate=instantiate)
2393 def setComponentByName(self, name, value=noValue,
2394 verifyConstraints=True,
2395 matchTags=True,
2396 matchConstraints=True):
2397 """Assign |ASN.1| type component by name.
2399 Equivalent to Python :class:`dict` item assignment operation (e.g. `[]`).
2401 Parameters
2402 ----------
2403 name: :class:`str`
2404 |ASN.1| type component name
2406 Keyword Args
2407 ------------
2408 value: :class:`object` or :py:class:`~pyasn1.type.base.PyAsn1Item` derivative
2409 A Python value to initialize |ASN.1| component with (if *componentType* is set)
2410 or ASN.1 value object to assign to |ASN.1| component.
2411 If `value` is not given, schema object will be set as a component.
2413 verifyConstraints: :class:`bool`
2414 If :obj:`False`, skip constraints validation
2416 matchTags: :class:`bool`
2417 If :obj:`False`, skip component tags matching
2419 matchConstraints: :class:`bool`
2420 If :obj:`False`, skip component constraints matching
2422 Returns
2423 -------
2424 self
2425 """
2426 if self._componentTypeLen:
2427 idx = self.componentType.getPositionByName(name)
2428 else:
2429 try:
2430 idx = self._dynamicNames.getPositionByName(name)
2432 except KeyError:
2433 raise error.PyAsn1Error('Name %s not found' % (name,))
2435 return self.setComponentByPosition(
2436 idx, value, verifyConstraints, matchTags, matchConstraints
2437 )
2439 def getComponentByPosition(self, idx, default=noValue, instantiate=True):
2440 """Returns |ASN.1| type component by index.
2442 Equivalent to Python sequence subscription operation (e.g. `[]`).
2444 Parameters
2445 ----------
2446 idx: :class:`int`
2447 Component index (zero-based). Must either refer to an existing
2448 component or (if *componentType* is set) new ASN.1 schema object gets
2449 instantiated.
2451 Keyword Args
2452 ------------
2453 default: :class:`object`
2454 If set and requested component is a schema object, return the `default`
2455 object instead of the requested component.
2457 instantiate: :class:`bool`
2458 If :obj:`True` (default), inner component will be automatically
2459 instantiated.
2460 If :obj:`False` either existing component or the :class:`NoValue`
2461 object will be returned.
2463 Returns
2464 -------
2465 : :py:class:`~pyasn1.type.base.PyAsn1Item`
2466 a PyASN1 object
2468 Examples
2469 --------
2471 .. code-block:: python
2473 # can also be Set
2474 class MySequence(Sequence):
2475 componentType = NamedTypes(
2476 NamedType('id', OctetString())
2477 )
2479 s = MySequence()
2481 # returns component #0 with `.isValue` property False
2482 s.getComponentByPosition(0)
2484 # returns None
2485 s.getComponentByPosition(0, default=None)
2487 s.clear()
2489 # returns noValue
2490 s.getComponentByPosition(0, instantiate=False)
2492 # sets component #0 to OctetString() ASN.1 schema
2493 # object and returns it
2494 s.getComponentByPosition(0, instantiate=True)
2496 # sets component #0 to ASN.1 value object
2497 s.setComponentByPosition(0, 'ABCD')
2499 # returns OctetString('ABCD') value object
2500 s.getComponentByPosition(0, instantiate=False)
2502 s.clear()
2504 # returns noValue
2505 s.getComponentByPosition(0, instantiate=False)
2506 """
2507 try:
2508 if self._componentValues is noValue:
2509 componentValue = noValue
2511 else:
2512 componentValue = self._componentValues[idx]
2514 except IndexError:
2515 componentValue = noValue
2517 if not instantiate:
2518 if componentValue is noValue or not componentValue.isValue:
2519 return default
2520 else:
2521 return componentValue
2523 if componentValue is noValue:
2524 self.setComponentByPosition(idx)
2526 componentValue = self._componentValues[idx]
2528 if default is noValue or componentValue.isValue:
2529 return componentValue
2530 else:
2531 return default
2533 def setComponentByPosition(self, idx, value=noValue,
2534 verifyConstraints=True,
2535 matchTags=True,
2536 matchConstraints=True):
2537 """Assign |ASN.1| type component by position.
2539 Equivalent to Python sequence item assignment operation (e.g. `[]`).
2541 Parameters
2542 ----------
2543 idx : :class:`int`
2544 Component index (zero-based). Must either refer to existing
2545 component (if *componentType* is set) or to N+1 component
2546 otherwise. In the latter case a new component of given ASN.1
2547 type gets instantiated and appended to |ASN.1| sequence.
2549 Keyword Args
2550 ------------
2551 value: :class:`object` or :py:class:`~pyasn1.type.base.PyAsn1Item` derivative
2552 A Python value to initialize |ASN.1| component with (if *componentType* is set)
2553 or ASN.1 value object to assign to |ASN.1| component.
2554 If `value` is not given, schema object will be set as a component.
2556 verifyConstraints : :class:`bool`
2557 If :obj:`False`, skip constraints validation
2559 matchTags: :class:`bool`
2560 If :obj:`False`, skip component tags matching
2562 matchConstraints: :class:`bool`
2563 If :obj:`False`, skip component constraints matching
2565 Returns
2566 -------
2567 self
2568 """
2569 componentType = self.componentType
2570 componentTypeLen = self._componentTypeLen
2572 if self._componentValues is noValue:
2573 componentValues = []
2575 else:
2576 componentValues = self._componentValues
2578 try:
2579 currentValue = componentValues[idx]
2581 except IndexError:
2582 currentValue = noValue
2583 if componentTypeLen:
2584 if componentTypeLen < idx:
2585 raise error.PyAsn1Error('component index out of range')
2587 componentValues = [noValue] * componentTypeLen
2589 if value is noValue:
2590 if componentTypeLen:
2591 value = componentType.getTypeByPosition(idx)
2592 if isinstance(value, base.ConstructedAsn1Type):
2593 value = value.clone(cloneValueFlag=componentType[idx].isDefaulted)
2595 elif currentValue is noValue:
2596 raise error.PyAsn1Error('Component type not defined')
2598 elif not isinstance(value, base.Asn1Item):
2599 if componentTypeLen:
2600 subComponentType = componentType.getTypeByPosition(idx)
2601 if isinstance(subComponentType, base.SimpleAsn1Type):
2602 value = subComponentType.clone(value=value)
2604 else:
2605 raise error.PyAsn1Error('%s can cast only scalar values' % componentType.__class__.__name__)
2607 elif currentValue is not noValue and isinstance(currentValue, base.SimpleAsn1Type):
2608 value = currentValue.clone(value=value)
2610 else:
2611 raise error.PyAsn1Error('%s undefined component type' % componentType.__class__.__name__)
2613 elif ((verifyConstraints or matchTags or matchConstraints) and
2614 componentTypeLen):
2615 subComponentType = componentType.getTypeByPosition(idx)
2616 if subComponentType is not noValue:
2617 subtypeChecker = (self.strictConstraints and
2618 subComponentType.isSameTypeWith or
2619 subComponentType.isSuperTypeOf)
2621 if not subtypeChecker(value, verifyConstraints and matchTags,
2622 verifyConstraints and matchConstraints):
2623 if not componentType[idx].openType:
2624 raise error.PyAsn1Error('Component value is tag-incompatible: %r vs %r' % (value, componentType))
2626 if componentTypeLen or idx in self._dynamicNames:
2627 componentValues[idx] = value
2629 elif len(componentValues) == idx:
2630 componentValues.append(value)
2631 self._dynamicNames.addField(idx)
2633 else:
2634 raise error.PyAsn1Error('Component index out of range')
2636 self._componentValues = componentValues
2638 return self
2640 @property
2641 def isValue(self):
2642 """Indicate that |ASN.1| object represents ASN.1 value.
2644 If *isValue* is :obj:`False` then this object represents just ASN.1 schema.
2646 If *isValue* is :obj:`True` then, in addition to its ASN.1 schema features,
2647 this object can also be used like a Python built-in object (e.g.
2648 :class:`int`, :class:`str`, :class:`dict` etc.).
2650 Returns
2651 -------
2652 : :class:`bool`
2653 :obj:`False` if object represents just ASN.1 schema.
2654 :obj:`True` if object represents ASN.1 schema and can be used as a
2655 normal value.
2657 Note
2658 ----
2659 There is an important distinction between PyASN1 schema and value objects.
2660 The PyASN1 schema objects can only participate in ASN.1 schema-related
2661 operations (e.g. defining or testing the structure of the data). Most
2662 obvious uses of ASN.1 schema is to guide serialisation codecs whilst
2663 encoding/decoding serialised ASN.1 contents.
2665 The PyASN1 value objects can **additionally** participate in many operations
2666 involving regular Python objects (e.g. arithmetic, comprehension etc).
2668 It is sufficient for |ASN.1| objects to have all non-optional and non-defaulted
2669 components being value objects to be considered as a value objects as a whole.
2670 In other words, even having one or more optional components not turned into
2671 value objects, |ASN.1| object is still considered as a value object. Defaulted
2672 components are normally value objects by default.
2673 """
2674 if self._componentValues is noValue:
2675 return False
2677 componentType = self.componentType
2679 if componentType:
2680 for idx, subComponentType in enumerate(componentType.namedTypes):
2681 if subComponentType.isDefaulted or subComponentType.isOptional:
2682 continue
2684 if not self._componentValues:
2685 return False
2687 componentValue = self._componentValues[idx]
2688 if componentValue is noValue or not componentValue.isValue:
2689 return False
2691 else:
2692 for componentValue in self._componentValues:
2693 if componentValue is noValue or not componentValue.isValue:
2694 return False
2696 return True
2698 @property
2699 def isInconsistent(self):
2700 """Run necessary checks to ensure |ASN.1| object consistency.
2702 Default action is to verify |ASN.1| object against constraints imposed
2703 by `subtypeSpec`.
2705 Raises
2706 ------
2707 :py:class:`~pyasn1.error.PyAsn1tError` on any inconsistencies found
2708 """
2709 if self.componentType is noValue or not self.subtypeSpec:
2710 return False
2712 if self._componentValues is noValue:
2713 return True
2715 mapping = {}
2717 for idx, value in enumerate(self._componentValues):
2718 # Absent fields are not in the mapping
2719 if value is noValue:
2720 continue
2722 name = self.componentType.getNameByPosition(idx)
2724 mapping[name] = value
2726 try:
2727 # Represent Sequence/Set as a bare dict to constraints chain
2728 self.subtypeSpec(mapping)
2730 except error.PyAsn1Error as exc:
2731 return exc
2733 return False
2735 def prettyPrint(self, scope=0):
2736 """Return an object representation string.
2738 Returns
2739 -------
2740 : :class:`str`
2741 Human-friendly object representation.
2742 """
2743 scope += 1
2744 representation = self.__class__.__name__ + ':\n'
2745 for idx, componentValue in enumerate(self._componentValues):
2746 if componentValue is not noValue and componentValue.isValue:
2747 representation += ' ' * scope
2748 if self.componentType:
2749 representation += self.componentType.getNameByPosition(idx)
2750 else:
2751 representation += self._dynamicNames.getNameByPosition(idx)
2752 representation = '%s=%s\n' % (
2753 representation, componentValue.prettyPrint(scope)
2754 )
2755 return representation
2757 def prettyPrintType(self, scope=0):
2758 scope += 1
2759 representation = '%s -> %s {\n' % (self.tagSet, self.__class__.__name__)
2760 for idx, componentType in enumerate(self.componentType.values() or self._componentValues):
2761 representation += ' ' * scope
2762 if self.componentType:
2763 representation += '"%s"' % self.componentType.getNameByPosition(idx)
2764 else:
2765 representation += '"%s"' % self._dynamicNames.getNameByPosition(idx)
2766 representation = '%s = %s\n' % (
2767 representation, componentType.prettyPrintType(scope)
2768 )
2769 return representation + '\n' + ' ' * (scope - 1) + '}'
2771 # backward compatibility
2773 def setDefaultComponents(self):
2774 return self
2776 def getComponentType(self):
2777 if self._componentTypeLen:
2778 return self.componentType
2780 def getNameByPosition(self, idx):
2781 if self._componentTypeLen:
2782 return self.componentType[idx].name
2784class Sequence(SequenceAndSetBase):
2785 __doc__ = SequenceAndSetBase.__doc__
2787 #: Set (on class, not on instance) or return a
2788 #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s)
2789 #: associated with |ASN.1| type.
2790 tagSet = tag.initTagSet(
2791 tag.Tag(tag.tagClassUniversal, tag.tagFormatConstructed, 0x10)
2792 )
2794 #: Set (on class, not on instance) or return a
2795 #: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection` object
2796 #: imposing constraints on |ASN.1| type initialization values.
2797 subtypeSpec = constraint.ConstraintsIntersection()
2799 #: Default collection of ASN.1 types of component (e.g. :py:class:`~pyasn1.type.namedtype.NamedType`)
2800 #: object imposing size constraint on |ASN.1| objects
2801 componentType = namedtype.NamedTypes()
2803 # Disambiguation ASN.1 types identification
2804 typeId = SequenceAndSetBase.getTypeId()
2806 # backward compatibility
2808 def getComponentTagMapNearPosition(self, idx):
2809 if self.componentType:
2810 return self.componentType.getTagMapNearPosition(idx)
2812 def getComponentPositionNearType(self, tagSet, idx):
2813 if self.componentType:
2814 return self.componentType.getPositionNearType(tagSet, idx)
2815 else:
2816 return idx
2819class Set(SequenceAndSetBase):
2820 __doc__ = SequenceAndSetBase.__doc__
2822 #: Set (on class, not on instance) or return a
2823 #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s)
2824 #: associated with |ASN.1| type.
2825 tagSet = tag.initTagSet(
2826 tag.Tag(tag.tagClassUniversal, tag.tagFormatConstructed, 0x11)
2827 )
2829 #: Default collection of ASN.1 types of component (e.g. :py:class:`~pyasn1.type.namedtype.NamedType`)
2830 #: object representing ASN.1 type allowed within |ASN.1| type
2831 componentType = namedtype.NamedTypes()
2833 #: Set (on class, not on instance) or return a
2834 #: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection` object
2835 #: imposing constraints on |ASN.1| type initialization values.
2836 subtypeSpec = constraint.ConstraintsIntersection()
2838 # Disambiguation ASN.1 types identification
2839 typeId = SequenceAndSetBase.getTypeId()
2841 def getComponent(self, innerFlag=False):
2842 return self
2844 def getComponentByType(self, tagSet, default=noValue,
2845 instantiate=True, innerFlag=False):
2846 """Returns |ASN.1| type component by ASN.1 tag.
2848 Parameters
2849 ----------
2850 tagSet : :py:class:`~pyasn1.type.tag.TagSet`
2851 Object representing ASN.1 tags to identify one of
2852 |ASN.1| object component
2854 Keyword Args
2855 ------------
2856 default: :class:`object`
2857 If set and requested component is a schema object, return the `default`
2858 object instead of the requested component.
2860 instantiate: :class:`bool`
2861 If :obj:`True` (default), inner component will be automatically
2862 instantiated.
2863 If :obj:`False` either existing component or the :class:`noValue`
2864 object will be returned.
2866 Returns
2867 -------
2868 : :py:class:`~pyasn1.type.base.PyAsn1Item`
2869 a pyasn1 object
2870 """
2871 componentValue = self.getComponentByPosition(
2872 self.componentType.getPositionByType(tagSet),
2873 default=default, instantiate=instantiate
2874 )
2875 if innerFlag and isinstance(componentValue, Set):
2876 # get inner component by inner tagSet
2877 return componentValue.getComponent(innerFlag=True)
2878 else:
2879 # get outer component by inner tagSet
2880 return componentValue
2882 def setComponentByType(self, tagSet, value=noValue,
2883 verifyConstraints=True,
2884 matchTags=True,
2885 matchConstraints=True,
2886 innerFlag=False):
2887 """Assign |ASN.1| type component by ASN.1 tag.
2889 Parameters
2890 ----------
2891 tagSet : :py:class:`~pyasn1.type.tag.TagSet`
2892 Object representing ASN.1 tags to identify one of
2893 |ASN.1| object component
2895 Keyword Args
2896 ------------
2897 value: :class:`object` or :py:class:`~pyasn1.type.base.PyAsn1Item` derivative
2898 A Python value to initialize |ASN.1| component with (if *componentType* is set)
2899 or ASN.1 value object to assign to |ASN.1| component.
2900 If `value` is not given, schema object will be set as a component.
2902 verifyConstraints : :class:`bool`
2903 If :obj:`False`, skip constraints validation
2905 matchTags: :class:`bool`
2906 If :obj:`False`, skip component tags matching
2908 matchConstraints: :class:`bool`
2909 If :obj:`False`, skip component constraints matching
2911 innerFlag: :class:`bool`
2912 If :obj:`True`, search for matching *tagSet* recursively.
2914 Returns
2915 -------
2916 self
2917 """
2918 idx = self.componentType.getPositionByType(tagSet)
2920 if innerFlag: # set inner component by inner tagSet
2921 componentType = self.componentType.getTypeByPosition(idx)
2923 if componentType.tagSet:
2924 return self.setComponentByPosition(
2925 idx, value, verifyConstraints, matchTags, matchConstraints
2926 )
2927 else:
2928 componentType = self.getComponentByPosition(idx)
2929 return componentType.setComponentByType(
2930 tagSet, value, verifyConstraints, matchTags, matchConstraints, innerFlag=innerFlag
2931 )
2932 else: # set outer component by inner tagSet
2933 return self.setComponentByPosition(
2934 idx, value, verifyConstraints, matchTags, matchConstraints
2935 )
2937 @property
2938 def componentTagMap(self):
2939 if self.componentType:
2940 return self.componentType.tagMapUnique
2943class Choice(Set):
2944 """Create |ASN.1| schema or value object.
2946 |ASN.1| class is based on :class:`~pyasn1.type.base.ConstructedAsn1Type`,
2947 its objects are mutable and duck-type Python :class:`list` objects.
2949 Keyword Args
2950 ------------
2951 componentType: :py:class:`~pyasn1.type.namedtype.NamedType`
2952 Object holding named ASN.1 types allowed within this collection
2954 tagSet: :py:class:`~pyasn1.type.tag.TagSet`
2955 Object representing non-default ASN.1 tag(s)
2957 subtypeSpec: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection`
2958 Object representing non-default ASN.1 subtype constraint(s). Constraints
2959 verification for |ASN.1| type can only occur on explicit
2960 `.isInconsistent` call.
2962 Examples
2963 --------
2965 .. code-block:: python
2967 class Afters(Choice):
2968 '''
2969 ASN.1 specification:
2971 Afters ::= CHOICE {
2972 cheese [0] IA5String,
2973 dessert [1] IA5String
2974 }
2975 '''
2976 componentType = NamedTypes(
2977 NamedType('cheese', IA5String().subtype(
2978 implicitTag=Tag(tagClassContext, tagFormatSimple, 0)
2979 ),
2980 NamedType('dessert', IA5String().subtype(
2981 implicitTag=Tag(tagClassContext, tagFormatSimple, 1)
2982 )
2983 )
2985 afters = Afters()
2986 afters['cheese'] = 'Mascarpone'
2987 """
2988 #: Set (on class, not on instance) or return a
2989 #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s)
2990 #: associated with |ASN.1| type.
2991 tagSet = tag.TagSet() # untagged
2993 #: Default collection of ASN.1 types of component (e.g. :py:class:`~pyasn1.type.namedtype.NamedType`)
2994 #: object representing ASN.1 type allowed within |ASN.1| type
2995 componentType = namedtype.NamedTypes()
2997 #: Set (on class, not on instance) or return a
2998 #: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection` object
2999 #: imposing constraints on |ASN.1| type initialization values.
3000 subtypeSpec = constraint.ConstraintsIntersection(
3001 constraint.ValueSizeConstraint(1, 1)
3002 )
3004 # Disambiguation ASN.1 types identification
3005 typeId = Set.getTypeId()
3007 _currentIdx = None
3009 def __eq__(self, other):
3010 if self._componentValues:
3011 return self._componentValues[self._currentIdx] == other
3012 return NotImplemented
3014 def __ne__(self, other):
3015 if self._componentValues:
3016 return self._componentValues[self._currentIdx] != other
3017 return NotImplemented
3019 def __lt__(self, other):
3020 if self._componentValues:
3021 return self._componentValues[self._currentIdx] < other
3022 return NotImplemented
3024 def __le__(self, other):
3025 if self._componentValues:
3026 return self._componentValues[self._currentIdx] <= other
3027 return NotImplemented
3029 def __gt__(self, other):
3030 if self._componentValues:
3031 return self._componentValues[self._currentIdx] > other
3032 return NotImplemented
3034 def __ge__(self, other):
3035 if self._componentValues:
3036 return self._componentValues[self._currentIdx] >= other
3037 return NotImplemented
3039 def __bool__(self):
3040 return bool(self._componentValues)
3042 def __len__(self):
3043 return self._currentIdx is not None and 1 or 0
3045 def __contains__(self, key):
3046 if self._currentIdx is None:
3047 return False
3048 return key == self.componentType[self._currentIdx].getName()
3050 def __iter__(self):
3051 if self._currentIdx is None:
3052 raise StopIteration
3053 yield self.componentType[self._currentIdx].getName()
3055 # Python dict protocol
3057 def values(self):
3058 if self._currentIdx is not None:
3059 yield self._componentValues[self._currentIdx]
3061 def keys(self):
3062 if self._currentIdx is not None:
3063 yield self.componentType[self._currentIdx].getName()
3065 def items(self):
3066 if self._currentIdx is not None:
3067 yield self.componentType[self._currentIdx].getName(), self[self._currentIdx]
3069 def checkConsistency(self):
3070 if self._currentIdx is None:
3071 raise error.PyAsn1Error('Component not chosen')
3073 def _cloneComponentValues(self, myClone, cloneValueFlag):
3074 try:
3075 component = self.getComponent()
3076 except error.PyAsn1Error:
3077 pass
3078 else:
3079 if isinstance(component, Choice):
3080 tagSet = component.effectiveTagSet
3081 else:
3082 tagSet = component.tagSet
3083 if isinstance(component, base.ConstructedAsn1Type):
3084 myClone.setComponentByType(
3085 tagSet, component.clone(cloneValueFlag=cloneValueFlag)
3086 )
3087 else:
3088 myClone.setComponentByType(tagSet, component.clone())
3090 def getComponentByPosition(self, idx, default=noValue, instantiate=True):
3091 __doc__ = Set.__doc__
3093 if self._currentIdx is None or self._currentIdx != idx:
3094 return Set.getComponentByPosition(self, idx, default=default,
3095 instantiate=instantiate)
3097 return self._componentValues[idx]
3099 def setComponentByPosition(self, idx, value=noValue,
3100 verifyConstraints=True,
3101 matchTags=True,
3102 matchConstraints=True):
3103 """Assign |ASN.1| type component by position.
3105 Equivalent to Python sequence item assignment operation (e.g. `[]`).
3107 Parameters
3108 ----------
3109 idx: :class:`int`
3110 Component index (zero-based). Must either refer to existing
3111 component or to N+1 component. In the latter case a new component
3112 type gets instantiated (if *componentType* is set, or given ASN.1
3113 object is taken otherwise) and appended to the |ASN.1| sequence.
3115 Keyword Args
3116 ------------
3117 value: :class:`object` or :py:class:`~pyasn1.type.base.PyAsn1Item` derivative
3118 A Python value to initialize |ASN.1| component with (if *componentType* is set)
3119 or ASN.1 value object to assign to |ASN.1| component. Once a new value is
3120 set to *idx* component, previous value is dropped.
3121 If `value` is not given, schema object will be set as a component.
3123 verifyConstraints : :class:`bool`
3124 If :obj:`False`, skip constraints validation
3126 matchTags: :class:`bool`
3127 If :obj:`False`, skip component tags matching
3129 matchConstraints: :class:`bool`
3130 If :obj:`False`, skip component constraints matching
3132 Returns
3133 -------
3134 self
3135 """
3136 oldIdx = self._currentIdx
3137 Set.setComponentByPosition(self, idx, value, verifyConstraints, matchTags, matchConstraints)
3138 self._currentIdx = idx
3139 if oldIdx is not None and oldIdx != idx:
3140 self._componentValues[oldIdx] = noValue
3141 return self
3143 @property
3144 def effectiveTagSet(self):
3145 """Return a :class:`~pyasn1.type.tag.TagSet` object of the currently initialized component or self (if |ASN.1| is tagged)."""
3146 if self.tagSet:
3147 return self.tagSet
3148 else:
3149 component = self.getComponent()
3150 return component.effectiveTagSet
3152 @property
3153 def tagMap(self):
3154 """"Return a :class:`~pyasn1.type.tagmap.TagMap` object mapping
3155 ASN.1 tags to ASN.1 objects contained within callee.
3156 """
3157 if self.tagSet:
3158 return Set.tagMap.fget(self)
3159 else:
3160 return self.componentType.tagMapUnique
3162 def getComponent(self, innerFlag=False):
3163 """Return currently assigned component of the |ASN.1| object.
3165 Returns
3166 -------
3167 : :py:class:`~pyasn1.type.base.PyAsn1Item`
3168 a PyASN1 object
3169 """
3170 if self._currentIdx is None:
3171 raise error.PyAsn1Error('Component not chosen')
3172 else:
3173 c = self._componentValues[self._currentIdx]
3174 if innerFlag and isinstance(c, Choice):
3175 return c.getComponent(innerFlag)
3176 else:
3177 return c
3179 def getName(self, innerFlag=False):
3180 """Return the name of currently assigned component of the |ASN.1| object.
3182 Returns
3183 -------
3184 : :py:class:`str`
3185 |ASN.1| component name
3186 """
3187 if self._currentIdx is None:
3188 raise error.PyAsn1Error('Component not chosen')
3189 else:
3190 if innerFlag:
3191 c = self._componentValues[self._currentIdx]
3192 if isinstance(c, Choice):
3193 return c.getName(innerFlag)
3194 return self.componentType.getNameByPosition(self._currentIdx)
3196 @property
3197 def isValue(self):
3198 """Indicate that |ASN.1| object represents ASN.1 value.
3200 If *isValue* is :obj:`False` then this object represents just ASN.1 schema.
3202 If *isValue* is :obj:`True` then, in addition to its ASN.1 schema features,
3203 this object can also be used like a Python built-in object (e.g.
3204 :class:`int`, :class:`str`, :class:`dict` etc.).
3206 Returns
3207 -------
3208 : :class:`bool`
3209 :obj:`False` if object represents just ASN.1 schema.
3210 :obj:`True` if object represents ASN.1 schema and can be used as a normal
3211 value.
3213 Note
3214 ----
3215 There is an important distinction between PyASN1 schema and value objects.
3216 The PyASN1 schema objects can only participate in ASN.1 schema-related
3217 operations (e.g. defining or testing the structure of the data). Most
3218 obvious uses of ASN.1 schema is to guide serialisation codecs whilst
3219 encoding/decoding serialised ASN.1 contents.
3221 The PyASN1 value objects can **additionally** participate in many operations
3222 involving regular Python objects (e.g. arithmetic, comprehension etc).
3223 """
3224 if self._currentIdx is None:
3225 return False
3227 componentValue = self._componentValues[self._currentIdx]
3229 return componentValue is not noValue and componentValue.isValue
3231 def clear(self):
3232 self._currentIdx = None
3233 return Set.clear(self)
3235 # compatibility stubs
3237 def getMinTagSet(self):
3238 return self.minTagSet
3241class Any(OctetString):
3242 """Create |ASN.1| schema or value object.
3244 |ASN.1| class is based on :class:`~pyasn1.type.base.SimpleAsn1Type`,
3245 its objects are immutable and duck-type :class:`bytes`.
3246 When used in Unicode context, |ASN.1| type assumes
3247 "|encoding|" serialisation.
3249 Keyword Args
3250 ------------
3251 value: :class:`unicode`, :class:`str`, :class:`bytes` or |ASN.1| object
3252 :class:`bytes`, alternatively :class:`str`
3253 representing character string to be serialised into octets (note
3254 `encoding` parameter) or |ASN.1| object.
3255 If `value` is not given, schema object will be created.
3257 tagSet: :py:class:`~pyasn1.type.tag.TagSet`
3258 Object representing non-default ASN.1 tag(s)
3260 subtypeSpec: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection`
3261 Object representing non-default ASN.1 subtype constraint(s). Constraints
3262 verification for |ASN.1| type occurs automatically on object
3263 instantiation.
3265 encoding: :py:class:`str`
3266 Unicode codec ID to encode/decode
3267 :class:`str` the payload when |ASN.1| object is used
3268 in text string context.
3270 binValue: :py:class:`str`
3271 Binary string initializer to use instead of the *value*.
3272 Example: '10110011'.
3274 hexValue: :py:class:`str`
3275 Hexadecimal string initializer to use instead of the *value*.
3276 Example: 'DEADBEEF'.
3278 Raises
3279 ------
3280 ~pyasn1.error.ValueConstraintError, ~pyasn1.error.PyAsn1Error
3281 On constraint violation or bad initializer.
3283 Examples
3284 --------
3285 .. code-block:: python
3287 class Error(Sequence):
3288 '''
3289 ASN.1 specification:
3291 Error ::= SEQUENCE {
3292 code INTEGER,
3293 parameter ANY DEFINED BY code -- Either INTEGER or REAL
3294 }
3295 '''
3296 componentType=NamedTypes(
3297 NamedType('code', Integer()),
3298 NamedType('parameter', Any(),
3299 openType=OpenType('code', {1: Integer(),
3300 2: Real()}))
3301 )
3303 error = Error()
3304 error['code'] = 1
3305 error['parameter'] = Integer(1234)
3306 """
3307 #: Set (on class, not on instance) or return a
3308 #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s)
3309 #: associated with |ASN.1| type.
3310 tagSet = tag.TagSet() # untagged
3312 #: Set (on class, not on instance) or return a
3313 #: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection` object
3314 #: imposing constraints on |ASN.1| type initialization values.
3315 subtypeSpec = constraint.ConstraintsIntersection()
3317 # Disambiguation ASN.1 types identification
3318 typeId = OctetString.getTypeId()
3320 @property
3321 def tagMap(self):
3322 """"Return a :class:`~pyasn1.type.tagmap.TagMap` object mapping
3323 ASN.1 tags to ASN.1 objects contained within callee.
3324 """
3325 try:
3326 return self._tagMap
3328 except AttributeError:
3329 self._tagMap = tagmap.TagMap(
3330 {self.tagSet: self},
3331 {eoo.endOfOctets.tagSet: eoo.endOfOctets},
3332 self
3333 )
3335 return self._tagMap
3337# XXX
3338# coercion rules?