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