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