Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/pyasn1/type/univ.py: 45%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1249 statements  

1# 

2# This file is part of pyasn1 software. 

3# 

4# Copyright (c) 2005-2020, Ilya Etingof <etingof@gmail.com> 

5# License: https://pyasn1.readthedocs.io/en/latest/license.html 

6# 

7import math 

8import sys 

9 

10from pyasn1 import error 

11from pyasn1.codec.ber import eoo 

12from pyasn1.compat import integer 

13from pyasn1.type import base 

14from pyasn1.type import constraint 

15from pyasn1.type import namedtype 

16from pyasn1.type import namedval 

17from pyasn1.type import tag 

18from pyasn1.type import tagmap 

19 

20NoValue = base.NoValue 

21noValue = NoValue() 

22 

23__all__ = ['Integer', 'Boolean', 'BitString', 'OctetString', 'Null', 

24 'ObjectIdentifier', 'Real', 'Enumerated', 

25 'SequenceOfAndSetOfBase', 'SequenceOf', 'SetOf', 

26 'SequenceAndSetBase', 'Sequence', 'Set', 'Choice', 'Any', 

27 'NoValue', 'noValue'] 

28 

29# "Simple" ASN.1 types (yet incomplete) 

30 

31 

32class Integer(base.SimpleAsn1Type): 

33 """Create |ASN.1| schema or value object. 

34 

35 |ASN.1| class is based on :class:`~pyasn1.type.base.SimpleAsn1Type`, its 

36 objects are immutable and duck-type Python :class:`int` objects. 

37 

38 Keyword Args 

39 ------------ 

40 value: :class:`int`, :class:`str` or |ASN.1| object 

41 Python :class:`int` or :class:`str` literal or |ASN.1| class 

42 instance. If `value` is not given, schema object will be created. 

43 

44 tagSet: :py:class:`~pyasn1.type.tag.TagSet` 

45 Object representing non-default ASN.1 tag(s) 

46 

47 subtypeSpec: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection` 

48 Object representing non-default ASN.1 subtype constraint(s). Constraints 

49 verification for |ASN.1| type occurs automatically on object 

50 instantiation. 

51 

52 namedValues: :py:class:`~pyasn1.type.namedval.NamedValues` 

53 Object representing non-default symbolic aliases for numbers 

54 

55 Raises 

56 ------ 

57 ~pyasn1.error.ValueConstraintError, ~pyasn1.error.PyAsn1Error 

58 On constraint violation or bad initializer. 

59 

60 Examples 

61 -------- 

62 

63 .. code-block:: python 

64 

65 class ErrorCode(Integer): 

66 ''' 

67 ASN.1 specification: 

68 

69 ErrorCode ::= 

70 INTEGER { disk-full(1), no-disk(-1), 

71 disk-not-formatted(2) } 

72 

73 error ErrorCode ::= disk-full 

74 ''' 

75 namedValues = NamedValues( 

76 ('disk-full', 1), ('no-disk', -1), 

77 ('disk-not-formatted', 2) 

78 ) 

79 

80 error = ErrorCode('disk-full') 

81 """ 

82 #: Set (on class, not on instance) or return a 

83 #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s) 

84 #: associated with |ASN.1| type. 

85 tagSet = tag.initTagSet( 

86 tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 0x02) 

87 ) 

88 

89 #: Set (on class, not on instance) or return a 

90 #: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection` object 

91 #: imposing constraints on |ASN.1| type initialization values. 

92 subtypeSpec = constraint.ConstraintsIntersection() 

93 

94 #: Default :py:class:`~pyasn1.type.namedval.NamedValues` object 

95 #: representing symbolic aliases for numbers 

96 namedValues = namedval.NamedValues() 

97 

98 # Optimization for faster codec lookup 

99 typeId = base.SimpleAsn1Type.getTypeId() 

100 

101 def __init__(self, value=noValue, **kwargs): 

102 if 'namedValues' not in kwargs: 

103 kwargs['namedValues'] = self.namedValues 

104 

105 base.SimpleAsn1Type.__init__(self, value, **kwargs) 

106 

107 def __and__(self, value): 

108 return self.clone(self._value & value) 

109 

110 def __rand__(self, value): 

111 return self.clone(value & self._value) 

112 

113 def __or__(self, value): 

114 return self.clone(self._value | value) 

115 

116 def __ror__(self, value): 

117 return self.clone(value | self._value) 

118 

119 def __xor__(self, value): 

120 return self.clone(self._value ^ value) 

121 

122 def __rxor__(self, value): 

123 return self.clone(value ^ self._value) 

124 

125 def __lshift__(self, value): 

126 return self.clone(self._value << value) 

127 

128 def __rshift__(self, value): 

129 return self.clone(self._value >> value) 

130 

131 def __add__(self, value): 

132 return self.clone(self._value + value) 

133 

134 def __radd__(self, value): 

135 return self.clone(value + self._value) 

136 

137 def __sub__(self, value): 

138 return self.clone(self._value - value) 

139 

140 def __rsub__(self, value): 

141 return self.clone(value - self._value) 

142 

143 def __mul__(self, value): 

144 return self.clone(self._value * value) 

145 

146 def __rmul__(self, value): 

147 return self.clone(value * self._value) 

148 

149 def __mod__(self, value): 

150 return self.clone(self._value % value) 

151 

152 def __rmod__(self, value): 

153 return self.clone(value % self._value) 

154 

155 def __pow__(self, value, modulo=None): 

156 return self.clone(pow(self._value, value, modulo)) 

157 

158 def __rpow__(self, value): 

159 return self.clone(pow(value, self._value)) 

160 

161 def __floordiv__(self, value): 

162 return self.clone(self._value // value) 

163 

164 def __rfloordiv__(self, value): 

165 return self.clone(value // self._value) 

166 

167 def __truediv__(self, value): 

168 return Real(self._value / value) 

169 

170 def __rtruediv__(self, value): 

171 return Real(value / self._value) 

172 

173 def __divmod__(self, value): 

174 return self.clone(divmod(self._value, value)) 

175 

176 def __rdivmod__(self, value): 

177 return self.clone(divmod(value, self._value)) 

178 

179 __hash__ = base.SimpleAsn1Type.__hash__ 

180 

181 def __int__(self): 

182 return int(self._value) 

183 

184 def __float__(self): 

185 return float(self._value) 

186 

187 def __abs__(self): 

188 return self.clone(abs(self._value)) 

189 

190 def __index__(self): 

191 return int(self._value) 

192 

193 def __pos__(self): 

194 return self.clone(+self._value) 

195 

196 def __neg__(self): 

197 return self.clone(-self._value) 

198 

199 def __invert__(self): 

200 return self.clone(~self._value) 

201 

202 def __round__(self, n=0): 

203 r = round(self._value, n) 

204 if n: 

205 return self.clone(r) 

206 else: 

207 return r 

208 

209 def __floor__(self): 

210 return math.floor(self._value) 

211 

212 def __ceil__(self): 

213 return math.ceil(self._value) 

214 

215 def __trunc__(self): 

216 return self.clone(math.trunc(self._value)) 

217 

218 def __lt__(self, value): 

219 return self._value < value 

220 

221 def __le__(self, value): 

222 return self._value <= value 

223 

224 def __eq__(self, value): 

225 return self._value == value 

226 

227 def __ne__(self, value): 

228 return self._value != value 

229 

230 def __gt__(self, value): 

231 return self._value > value 

232 

233 def __ge__(self, value): 

234 return self._value >= value 

235 

236 def prettyIn(self, value): 

237 try: 

238 return int(value) 

239 

240 except ValueError: 

241 try: 

242 return self.namedValues[value] 

243 

244 except KeyError as exc: 

245 raise error.PyAsn1Error( 

246 'Can\'t coerce %r into integer: %s' % (value, exc) 

247 ) 

248 

249 def prettyOut(self, value): 

250 try: 

251 return str(self.namedValues[value]) 

252 

253 except KeyError: 

254 return str(value) 

255 

256 # backward compatibility 

257 

258 def getNamedValues(self): 

259 return self.namedValues 

260 

261 

262class Boolean(Integer): 

263 """Create |ASN.1| schema or value object. 

264 

265 |ASN.1| class is based on :class:`~pyasn1.type.base.SimpleAsn1Type`, its 

266 objects are immutable and duck-type Python :class:`int` objects. 

267 

268 Keyword Args 

269 ------------ 

270 value: :class:`int`, :class:`str` or |ASN.1| object 

271 Python :class:`int` or :class:`str` literal or |ASN.1| class 

272 instance. If `value` is not given, schema object will be created. 

273 

274 tagSet: :py:class:`~pyasn1.type.tag.TagSet` 

275 Object representing non-default ASN.1 tag(s) 

276 

277 subtypeSpec: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection` 

278 Object representing non-default ASN.1 subtype constraint(s).Constraints 

279 verification for |ASN.1| type occurs automatically on object 

280 instantiation. 

281 

282 namedValues: :py:class:`~pyasn1.type.namedval.NamedValues` 

283 Object representing non-default symbolic aliases for numbers 

284 

285 Raises 

286 ------ 

287 ~pyasn1.error.ValueConstraintError, ~pyasn1.error.PyAsn1Error 

288 On constraint violation or bad initializer. 

289 

290 Examples 

291 -------- 

292 .. code-block:: python 

293 

294 class RoundResult(Boolean): 

295 ''' 

296 ASN.1 specification: 

297 

298 RoundResult ::= BOOLEAN 

299 

300 ok RoundResult ::= TRUE 

301 ko RoundResult ::= FALSE 

302 ''' 

303 ok = RoundResult(True) 

304 ko = RoundResult(False) 

305 """ 

306 #: Set (on class, not on instance) or return a 

307 #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s) 

308 #: associated with |ASN.1| type. 

309 tagSet = tag.initTagSet( 

310 tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 0x01), 

311 ) 

312 

313 #: Set (on class, not on instance) or return a 

314 #: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection` object 

315 #: imposing constraints on |ASN.1| type initialization values. 

316 subtypeSpec = Integer.subtypeSpec + constraint.SingleValueConstraint(0, 1) 

317 

318 #: Default :py:class:`~pyasn1.type.namedval.NamedValues` object 

319 #: representing symbolic aliases for numbers 

320 namedValues = namedval.NamedValues(('False', 0), ('True', 1)) 

321 

322 # Optimization for faster codec lookup 

323 typeId = Integer.getTypeId() 

324 

325 

326class SizedInteger(int): 

327 bitLength = leadingZeroBits = None 

328 

329 def setBitLength(self, bitLength): 

330 self.bitLength = bitLength 

331 self.leadingZeroBits = max(bitLength - self.bit_length(), 0) 

332 return self 

333 

334 def __len__(self): 

335 if self.bitLength is None: 

336 self.setBitLength(self.bit_length()) 

337 

338 return self.bitLength 

339 

340 

341class BitString(base.SimpleAsn1Type): 

342 """Create |ASN.1| schema or value object. 

343 

344 |ASN.1| class is based on :class:`~pyasn1.type.base.SimpleAsn1Type`, its 

345 objects are immutable and duck-type both Python :class:`tuple` (as a tuple 

346 of bits) and :class:`int` objects. 

347 

348 Keyword Args 

349 ------------ 

350 value: :class:`int`, :class:`str` or |ASN.1| object 

351 Python :class:`int` or :class:`str` literal representing binary 

352 or hexadecimal number or sequence of integer bits or |ASN.1| object. 

353 If `value` is not given, schema object will be created. 

354 

355 tagSet: :py:class:`~pyasn1.type.tag.TagSet` 

356 Object representing non-default ASN.1 tag(s) 

357 

358 subtypeSpec: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection` 

359 Object representing non-default ASN.1 subtype constraint(s). Constraints 

360 verification for |ASN.1| type occurs automatically on object 

361 instantiation. 

362 

363 namedValues: :py:class:`~pyasn1.type.namedval.NamedValues` 

364 Object representing non-default symbolic aliases for numbers 

365 

366 binValue: :py:class:`str` 

367 Binary string initializer to use instead of the *value*. 

368 Example: '10110011'. 

369 

370 hexValue: :py:class:`str` 

371 Hexadecimal string initializer to use instead of the *value*. 

372 Example: 'DEADBEEF'. 

373 

374 Raises 

375 ------ 

376 ~pyasn1.error.ValueConstraintError, ~pyasn1.error.PyAsn1Error 

377 On constraint violation or bad initializer. 

378 

379 Examples 

380 -------- 

381 .. code-block:: python 

382 

383 class Rights(BitString): 

384 ''' 

385 ASN.1 specification: 

386 

387 Rights ::= BIT STRING { user-read(0), user-write(1), 

388 group-read(2), group-write(3), 

389 other-read(4), other-write(5) } 

390 

391 group1 Rights ::= { group-read, group-write } 

392 group2 Rights ::= '0011'B 

393 group3 Rights ::= '3'H 

394 ''' 

395 namedValues = NamedValues( 

396 ('user-read', 0), ('user-write', 1), 

397 ('group-read', 2), ('group-write', 3), 

398 ('other-read', 4), ('other-write', 5) 

399 ) 

400 

401 group1 = Rights(('group-read', 'group-write')) 

402 group2 = Rights('0011') 

403 group3 = Rights(0x3) 

404 """ 

405 #: Set (on class, not on instance) or return a 

406 #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s) 

407 #: associated with |ASN.1| type. 

408 tagSet = tag.initTagSet( 

409 tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 0x03) 

410 ) 

411 

412 #: Set (on class, not on instance) or return a 

413 #: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection` object 

414 #: imposing constraints on |ASN.1| type initialization values. 

415 subtypeSpec = constraint.ConstraintsIntersection() 

416 

417 #: Default :py:class:`~pyasn1.type.namedval.NamedValues` object 

418 #: representing symbolic aliases for numbers 

419 namedValues = namedval.NamedValues() 

420 

421 # Optimization for faster codec lookup 

422 typeId = base.SimpleAsn1Type.getTypeId() 

423 

424 defaultBinValue = defaultHexValue = noValue 

425 

426 def __init__(self, value=noValue, **kwargs): 

427 if value is noValue: 

428 if kwargs: 

429 try: 

430 value = self.fromBinaryString(kwargs.pop('binValue'), internalFormat=True) 

431 

432 except KeyError: 

433 pass 

434 

435 try: 

436 value = self.fromHexString(kwargs.pop('hexValue'), internalFormat=True) 

437 

438 except KeyError: 

439 pass 

440 

441 if value is noValue: 

442 if self.defaultBinValue is not noValue: 

443 value = self.fromBinaryString(self.defaultBinValue, internalFormat=True) 

444 

445 elif self.defaultHexValue is not noValue: 

446 value = self.fromHexString(self.defaultHexValue, internalFormat=True) 

447 

448 if 'namedValues' not in kwargs: 

449 kwargs['namedValues'] = self.namedValues 

450 

451 base.SimpleAsn1Type.__init__(self, value, **kwargs) 

452 

453 def __str__(self): 

454 return self.asBinary() 

455 

456 def __eq__(self, other): 

457 other = self.prettyIn(other) 

458 return self is other or self._value == other and len(self._value) == len(other) 

459 

460 def __ne__(self, other): 

461 other = self.prettyIn(other) 

462 return self._value != other or len(self._value) != len(other) 

463 

464 def __lt__(self, other): 

465 other = self.prettyIn(other) 

466 return len(self._value) < len(other) or len(self._value) == len(other) and self._value < other 

467 

468 def __le__(self, other): 

469 other = self.prettyIn(other) 

470 return len(self._value) <= len(other) or len(self._value) == len(other) and self._value <= other 

471 

472 def __gt__(self, other): 

473 other = self.prettyIn(other) 

474 return len(self._value) > len(other) or len(self._value) == len(other) and self._value > other 

475 

476 def __ge__(self, other): 

477 other = self.prettyIn(other) 

478 return len(self._value) >= len(other) or len(self._value) == len(other) and self._value >= other 

479 

480 # Immutable sequence object protocol 

481 

482 def __len__(self): 

483 return len(self._value) 

484 

485 def __getitem__(self, i): 

486 if i.__class__ is slice: 

487 return self.clone([self[x] for x in range(*i.indices(len(self)))]) 

488 else: 

489 length = len(self._value) - 1 

490 if i > length or i < 0: 

491 raise IndexError('bit index out of range') 

492 return (self._value >> (length - i)) & 1 

493 

494 def __iter__(self): 

495 length = len(self._value) 

496 while length: 

497 length -= 1 

498 yield (self._value >> length) & 1 

499 

500 def __reversed__(self): 

501 return reversed(tuple(self)) 

502 

503 # arithmetic operators 

504 

505 def __add__(self, value): 

506 value = self.prettyIn(value) 

507 return self.clone(SizedInteger(self._value << len(value) | value).setBitLength(len(self._value) + len(value))) 

508 

509 def __radd__(self, value): 

510 value = self.prettyIn(value) 

511 return self.clone(SizedInteger(value << len(self._value) | self._value).setBitLength(len(self._value) + len(value))) 

512 

513 def __mul__(self, value): 

514 bitString = self._value 

515 while value > 1: 

516 bitString <<= len(self._value) 

517 bitString |= self._value 

518 value -= 1 

519 return self.clone(bitString) 

520 

521 def __rmul__(self, value): 

522 return self * value 

523 

524 def __lshift__(self, count): 

525 return self.clone(SizedInteger(self._value << count).setBitLength(len(self._value) + count)) 

526 

527 def __rshift__(self, count): 

528 return self.clone(SizedInteger(self._value >> count).setBitLength(max(0, len(self._value) - count))) 

529 

530 def __int__(self): 

531 return int(self._value) 

532 

533 def __float__(self): 

534 return float(self._value) 

535 

536 def asNumbers(self): 

537 """Get |ASN.1| value as a sequence of 8-bit integers. 

538 

539 If |ASN.1| object length is not a multiple of 8, result 

540 will be left-padded with zeros. 

541 """ 

542 return tuple(self.asOctets()) 

543 

544 def asOctets(self): 

545 """Get |ASN.1| value as a sequence of octets. 

546 

547 If |ASN.1| object length is not a multiple of 8, result 

548 will be left-padded with zeros. 

549 """ 

550 return integer.to_bytes(self._value, length=len(self)) 

551 

552 def asInteger(self): 

553 """Get |ASN.1| value as a single integer value. 

554 """ 

555 return self._value 

556 

557 def asBinary(self): 

558 """Get |ASN.1| value as a text string of bits. 

559 """ 

560 binString = bin(self._value)[2:] 

561 return '0' * (len(self._value) - len(binString)) + binString 

562 

563 @classmethod 

564 def fromHexString(cls, value, internalFormat=False, prepend=None): 

565 """Create a |ASN.1| object initialized from the hex string. 

566 

567 Parameters 

568 ---------- 

569 value: :class:`str` 

570 Text string like 'DEADBEEF' 

571 """ 

572 try: 

573 value = SizedInteger(value, 16).setBitLength(len(value) * 4) 

574 

575 except ValueError as exc: 

576 raise error.PyAsn1Error('%s.fromHexString() error: %s' % (cls.__name__, exc)) 

577 

578 if prepend is not None: 

579 value = SizedInteger( 

580 (SizedInteger(prepend) << len(value)) | value 

581 ).setBitLength(len(prepend) + len(value)) 

582 

583 if not internalFormat: 

584 value = cls(value) 

585 

586 return value 

587 

588 @classmethod 

589 def fromBinaryString(cls, value, internalFormat=False, prepend=None): 

590 """Create a |ASN.1| object initialized from a string of '0' and '1'. 

591 

592 Parameters 

593 ---------- 

594 value: :class:`str` 

595 Text string like '1010111' 

596 """ 

597 try: 

598 value = SizedInteger(value or '0', 2).setBitLength(len(value)) 

599 

600 except ValueError as exc: 

601 raise error.PyAsn1Error('%s.fromBinaryString() error: %s' % (cls.__name__, exc)) 

602 

603 if prepend is not None: 

604 value = SizedInteger( 

605 (SizedInteger(prepend) << len(value)) | value 

606 ).setBitLength(len(prepend) + len(value)) 

607 

608 if not internalFormat: 

609 value = cls(value) 

610 

611 return value 

612 

613 @classmethod 

614 def fromOctetString(cls, value, internalFormat=False, prepend=None, padding=0): 

615 """Create a |ASN.1| object initialized from a string. 

616 

617 Parameters 

618 ---------- 

619 value: :class:`bytes` 

620 Text string like b'\\\\x01\\\\xff' 

621 """ 

622 value = SizedInteger(int.from_bytes(bytes(value), 'big') >> padding).setBitLength(len(value) * 8 - padding) 

623 

624 if prepend is not None: 

625 value = SizedInteger( 

626 (SizedInteger(prepend) << len(value)) | value 

627 ).setBitLength(len(prepend) + len(value)) 

628 

629 if not internalFormat: 

630 value = cls(value) 

631 

632 return value 

633 

634 def prettyIn(self, value): 

635 if isinstance(value, SizedInteger): 

636 return value 

637 elif isinstance(value, str): 

638 if not value: 

639 return SizedInteger(0).setBitLength(0) 

640 

641 elif value[0] == '\'': # "'1011'B" -- ASN.1 schema representation (deprecated) 

642 if value[-2:] == '\'B': 

643 return self.fromBinaryString(value[1:-2], internalFormat=True) 

644 elif value[-2:] == '\'H': 

645 return self.fromHexString(value[1:-2], internalFormat=True) 

646 else: 

647 raise error.PyAsn1Error( 

648 'Bad BIT STRING value notation %s' % (value,) 

649 ) 

650 

651 elif self.namedValues and not value.isdigit(): # named bits like 'Urgent, Active' 

652 names = [x.strip() for x in value.split(',')] 

653 

654 try: 

655 

656 bitPositions = [self.namedValues[name] for name in names] 

657 

658 except KeyError: 

659 raise error.PyAsn1Error('unknown bit name(s) in %r' % (names,)) 

660 

661 rightmostPosition = max(bitPositions) 

662 

663 number = 0 

664 for bitPosition in bitPositions: 

665 number |= 1 << (rightmostPosition - bitPosition) 

666 

667 return SizedInteger(number).setBitLength(rightmostPosition + 1) 

668 

669 elif value.startswith('0x'): 

670 return self.fromHexString(value[2:], internalFormat=True) 

671 

672 elif value.startswith('0b'): 

673 return self.fromBinaryString(value[2:], internalFormat=True) 

674 

675 else: # assume plain binary string like '1011' 

676 return self.fromBinaryString(value, internalFormat=True) 

677 

678 elif isinstance(value, (tuple, list)): 

679 return self.fromBinaryString(''.join([b and '1' or '0' for b in value]), internalFormat=True) 

680 

681 elif isinstance(value, BitString): 

682 return SizedInteger(value).setBitLength(len(value)) 

683 

684 elif isinstance(value, int): 

685 return SizedInteger(value) 

686 

687 else: 

688 raise error.PyAsn1Error( 

689 'Bad BitString initializer type \'%s\'' % (value,) 

690 ) 

691 

692 

693class OctetString(base.SimpleAsn1Type): 

694 """Create |ASN.1| schema or value object. 

695 

696 |ASN.1| class is based on :class:`~pyasn1.type.base.SimpleAsn1Type`, its 

697 objects are immutable and duck-type :class:`bytes`. 

698 When used in Unicode context, |ASN.1| type 

699 assumes "|encoding|" serialisation. 

700 

701 Keyword Args 

702 ------------ 

703 value: :class:`unicode`, :class:`str`, :class:`bytes` or |ASN.1| object 

704 :class:`bytes`, alternatively :class:`str` 

705 representing character string to be serialised into octets 

706 (note `encoding` parameter) or |ASN.1| object. 

707 If `value` is not given, schema object will be created. 

708 

709 tagSet: :py:class:`~pyasn1.type.tag.TagSet` 

710 Object representing non-default ASN.1 tag(s) 

711 

712 subtypeSpec: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection` 

713 Object representing non-default ASN.1 subtype constraint(s). Constraints 

714 verification for |ASN.1| type occurs automatically on object 

715 instantiation. 

716 

717 encoding: :py:class:`str` 

718 Unicode codec ID to encode/decode 

719 :class:`str` the payload when |ASN.1| object is used 

720 in text string context. 

721 

722 binValue: :py:class:`str` 

723 Binary string initializer to use instead of the *value*. 

724 Example: '10110011'. 

725 

726 hexValue: :py:class:`str` 

727 Hexadecimal string initializer to use instead of the *value*. 

728 Example: 'DEADBEEF'. 

729 

730 Raises 

731 ------ 

732 ~pyasn1.error.ValueConstraintError, ~pyasn1.error.PyAsn1Error 

733 On constraint violation or bad initializer. 

734 

735 Examples 

736 -------- 

737 .. code-block:: python 

738 

739 class Icon(OctetString): 

740 ''' 

741 ASN.1 specification: 

742 

743 Icon ::= OCTET STRING 

744 

745 icon1 Icon ::= '001100010011001000110011'B 

746 icon2 Icon ::= '313233'H 

747 ''' 

748 icon1 = Icon.fromBinaryString('001100010011001000110011') 

749 icon2 = Icon.fromHexString('313233') 

750 """ 

751 #: Set (on class, not on instance) or return a 

752 #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s) 

753 #: associated with |ASN.1| type. 

754 tagSet = tag.initTagSet( 

755 tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 0x04) 

756 ) 

757 

758 #: Set (on class, not on instance) or return a 

759 #: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection` object 

760 #: imposing constraints on |ASN.1| type initialization values. 

761 subtypeSpec = constraint.ConstraintsIntersection() 

762 

763 # Optimization for faster codec lookup 

764 typeId = base.SimpleAsn1Type.getTypeId() 

765 

766 defaultBinValue = defaultHexValue = noValue 

767 encoding = 'iso-8859-1' 

768 

769 def __init__(self, value=noValue, **kwargs): 

770 if kwargs: 

771 if value is noValue: 

772 try: 

773 value = self.fromBinaryString(kwargs.pop('binValue')) 

774 

775 except KeyError: 

776 pass 

777 

778 try: 

779 value = self.fromHexString(kwargs.pop('hexValue')) 

780 

781 except KeyError: 

782 pass 

783 

784 if value is noValue: 

785 if self.defaultBinValue is not noValue: 

786 value = self.fromBinaryString(self.defaultBinValue) 

787 

788 elif self.defaultHexValue is not noValue: 

789 value = self.fromHexString(self.defaultHexValue) 

790 

791 if 'encoding' not in kwargs: 

792 kwargs['encoding'] = self.encoding 

793 

794 base.SimpleAsn1Type.__init__(self, value, **kwargs) 

795 

796 def prettyIn(self, value): 

797 if isinstance(value, bytes): 

798 return value 

799 

800 elif isinstance(value, str): 

801 try: 

802 return value.encode(self.encoding) 

803 

804 except UnicodeEncodeError as exc: 

805 raise error.PyAsn1UnicodeEncodeError( 

806 "Can't encode string '%s' with '%s' " 

807 "codec" % (value, self.encoding), exc 

808 ) 

809 elif isinstance(value, OctetString): # a shortcut, bytes() would work the same way 

810 return value.asOctets() 

811 

812 elif isinstance(value, base.SimpleAsn1Type): # this mostly targets Integer objects 

813 return self.prettyIn(str(value)) 

814 

815 elif isinstance(value, (tuple, list)): 

816 return self.prettyIn(bytes(value)) 

817 

818 else: 

819 return bytes(value) 

820 

821 def __str__(self): 

822 try: 

823 return self._value.decode(self.encoding) 

824 

825 except UnicodeDecodeError as exc: 

826 raise error.PyAsn1UnicodeDecodeError( 

827 "Can't decode string '%s' with '%s' codec at " 

828 "'%s'" % (self._value, self.encoding, 

829 self.__class__.__name__), exc 

830 ) 

831 

832 def __bytes__(self): 

833 return bytes(self._value) 

834 

835 def asOctets(self): 

836 return bytes(self._value) 

837 

838 def asNumbers(self): 

839 return tuple(self._value) 

840 

841 # 

842 # Normally, `.prettyPrint()` is called from `__str__()`. Historically, 

843 # OctetString.prettyPrint() used to return hexified payload 

844 # representation in cases when non-printable content is present. At the 

845 # same time `str()` used to produce either octet-stream (Py2) or 

846 # text (Py3) representations. 

847 # 

848 # Therefore `OctetString.__str__()` -> `.prettyPrint()` call chain is 

849 # reversed to preserve the original behaviour. 

850 # 

851 # Eventually we should deprecate `.prettyPrint()` / `.prettyOut()` harness 

852 # and end up with just `__str__()` producing hexified representation while 

853 # both text and octet-stream representation should only be requested via 

854 # the `.asOctets()` method. 

855 # 

856 # Note: ASN.1 OCTET STRING is never mean to contain text! 

857 # 

858 

859 def prettyOut(self, value): 

860 return value 

861 

862 def prettyPrint(self, scope=0): 

863 # first see if subclass has its own .prettyOut() 

864 value = self.prettyOut(self._value) 

865 

866 if value is not self._value: 

867 return value 

868 

869 numbers = self.asNumbers() 

870 

871 for x in numbers: 

872 # hexify if needed 

873 if x < 32 or x > 126: 

874 return '0x' + ''.join(('%.2x' % x for x in numbers)) 

875 else: 

876 # this prevents infinite recursion 

877 return OctetString.__str__(self) 

878 

879 @staticmethod 

880 def fromBinaryString(value): 

881 """Create a |ASN.1| object initialized from a string of '0' and '1'. 

882 

883 Parameters 

884 ---------- 

885 value: :class:`str` 

886 Text string like '1010111' 

887 """ 

888 bitNo = 8 

889 byte = 0 

890 r = [] 

891 for v in value: 

892 if bitNo: 

893 bitNo -= 1 

894 else: 

895 bitNo = 7 

896 r.append(byte) 

897 byte = 0 

898 if v in ('0', '1'): 

899 v = int(v) 

900 else: 

901 raise error.PyAsn1Error( 

902 'Non-binary OCTET STRING initializer %s' % (v,) 

903 ) 

904 byte |= v << bitNo 

905 

906 r.append(byte) 

907 

908 return bytes(r) 

909 

910 @staticmethod 

911 def fromHexString(value): 

912 """Create a |ASN.1| object initialized from the hex string. 

913 

914 Parameters 

915 ---------- 

916 value: :class:`str` 

917 Text string like 'DEADBEEF' 

918 """ 

919 r = [] 

920 p = [] 

921 for v in value: 

922 if p: 

923 r.append(int(p + v, 16)) 

924 p = None 

925 else: 

926 p = v 

927 if p: 

928 r.append(int(p + '0', 16)) 

929 

930 return bytes(r) 

931 

932 # Immutable sequence object protocol 

933 

934 def __len__(self): 

935 return len(self._value) 

936 

937 def __getitem__(self, i): 

938 if i.__class__ is slice: 

939 return self.clone(self._value[i]) 

940 else: 

941 return self._value[i] 

942 

943 def __iter__(self): 

944 return iter(self._value) 

945 

946 def __contains__(self, value): 

947 return value in self._value 

948 

949 def __add__(self, value): 

950 return self.clone(self._value + self.prettyIn(value)) 

951 

952 def __radd__(self, value): 

953 return self.clone(self.prettyIn(value) + self._value) 

954 

955 def __mul__(self, value): 

956 return self.clone(self._value * value) 

957 

958 def __rmul__(self, value): 

959 return self * value 

960 

961 def __int__(self): 

962 return int(self._value) 

963 

964 def __float__(self): 

965 return float(self._value) 

966 

967 def __reversed__(self): 

968 return reversed(self._value) 

969 

970 

971class Null(OctetString): 

972 """Create |ASN.1| schema or value object. 

973 

974 |ASN.1| class is based on :class:`~pyasn1.type.base.SimpleAsn1Type`, its 

975 objects are immutable and duck-type Python :class:`str` objects 

976 (always empty). 

977 

978 Keyword Args 

979 ------------ 

980 value: :class:`str` or |ASN.1| object 

981 Python empty :class:`str` literal or any object that evaluates to :obj:`False` 

982 If `value` is not given, schema object will be created. 

983 

984 tagSet: :py:class:`~pyasn1.type.tag.TagSet` 

985 Object representing non-default ASN.1 tag(s) 

986 

987 Raises 

988 ------ 

989 ~pyasn1.error.ValueConstraintError, ~pyasn1.error.PyAsn1Error 

990 On constraint violation or bad initializer. 

991 

992 Examples 

993 -------- 

994 .. code-block:: python 

995 

996 class Ack(Null): 

997 ''' 

998 ASN.1 specification: 

999 

1000 Ack ::= NULL 

1001 ''' 

1002 ack = Ack('') 

1003 """ 

1004 

1005 #: Set (on class, not on instance) or return a 

1006 #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s) 

1007 #: associated with |ASN.1| type. 

1008 tagSet = tag.initTagSet( 

1009 tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 0x05) 

1010 ) 

1011 subtypeSpec = OctetString.subtypeSpec + constraint.SingleValueConstraint(b'') 

1012 

1013 # Optimization for faster codec lookup 

1014 typeId = OctetString.getTypeId() 

1015 

1016 def prettyIn(self, value): 

1017 if value: 

1018 return value 

1019 

1020 return b'' 

1021 

1022 

1023class ObjectIdentifier(base.SimpleAsn1Type): 

1024 """Create |ASN.1| schema or value object. 

1025 

1026 |ASN.1| class is based on :class:`~pyasn1.type.base.SimpleAsn1Type`, its 

1027 objects are immutable and duck-type Python :class:`tuple` objects 

1028 (tuple of non-negative integers). 

1029 

1030 Keyword Args 

1031 ------------ 

1032 value: :class:`tuple`, :class:`str` or |ASN.1| object 

1033 Python sequence of :class:`int` or :class:`str` literal or |ASN.1| object. 

1034 If `value` is not given, schema object will be created. 

1035 

1036 tagSet: :py:class:`~pyasn1.type.tag.TagSet` 

1037 Object representing non-default ASN.1 tag(s) 

1038 

1039 subtypeSpec: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection` 

1040 Object representing non-default ASN.1 subtype constraint(s). Constraints 

1041 verification for |ASN.1| type occurs automatically on object 

1042 instantiation. 

1043 

1044 Raises 

1045 ------ 

1046 ~pyasn1.error.ValueConstraintError, ~pyasn1.error.PyAsn1Error 

1047 On constraint violation or bad initializer. 

1048 

1049 Examples 

1050 -------- 

1051 .. code-block:: python 

1052 

1053 class ID(ObjectIdentifier): 

1054 ''' 

1055 ASN.1 specification: 

1056 

1057 ID ::= OBJECT IDENTIFIER 

1058 

1059 id-edims ID ::= { joint-iso-itu-t mhs-motif(6) edims(7) } 

1060 id-bp ID ::= { id-edims 11 } 

1061 ''' 

1062 id_edims = ID('2.6.7') 

1063 id_bp = id_edims + (11,) 

1064 """ 

1065 #: Set (on class, not on instance) or return a 

1066 #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s) 

1067 #: associated with |ASN.1| type. 

1068 tagSet = tag.initTagSet( 

1069 tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 0x06) 

1070 ) 

1071 

1072 #: Set (on class, not on instance) or return a 

1073 #: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection` object 

1074 #: imposing constraints on |ASN.1| type initialization values. 

1075 subtypeSpec = constraint.ConstraintsIntersection() 

1076 

1077 # Optimization for faster codec lookup 

1078 typeId = base.SimpleAsn1Type.getTypeId() 

1079 

1080 def __add__(self, other): 

1081 return self.clone(self._value + other) 

1082 

1083 def __radd__(self, other): 

1084 return self.clone(other + self._value) 

1085 

1086 def asTuple(self): 

1087 return self._value 

1088 

1089 # Sequence object protocol 

1090 

1091 def __len__(self): 

1092 return len(self._value) 

1093 

1094 def __getitem__(self, i): 

1095 if i.__class__ is slice: 

1096 return self.clone(self._value[i]) 

1097 else: 

1098 return self._value[i] 

1099 

1100 def __iter__(self): 

1101 return iter(self._value) 

1102 

1103 def __contains__(self, value): 

1104 return value in self._value 

1105 

1106 def index(self, suboid): 

1107 return self._value.index(suboid) 

1108 

1109 def isPrefixOf(self, other): 

1110 """Indicate if this |ASN.1| object is a prefix of other |ASN.1| object. 

1111 

1112 Parameters 

1113 ---------- 

1114 other: |ASN.1| object 

1115 |ASN.1| object 

1116 

1117 Returns 

1118 ------- 

1119 : :class:`bool` 

1120 :obj:`True` if this |ASN.1| object is a parent (e.g. prefix) of the other |ASN.1| object 

1121 or :obj:`False` otherwise. 

1122 """ 

1123 l = len(self) 

1124 if l <= len(other): 

1125 if self._value[:l] == other[:l]: 

1126 return True 

1127 return False 

1128 

1129 def prettyIn(self, value): 

1130 if isinstance(value, ObjectIdentifier): 

1131 return tuple(value) 

1132 elif isinstance(value, str): 

1133 if '-' in value: 

1134 raise error.PyAsn1Error( 

1135 # sys.exc_info in case prettyIn was called while handling an exception 

1136 'Malformed Object ID %s at %s: %s' % (value, self.__class__.__name__, sys.exc_info()[1]) 

1137 ) 

1138 try: 

1139 return tuple([int(subOid) for subOid in value.split('.') if subOid]) 

1140 except ValueError as exc: 

1141 raise error.PyAsn1Error( 

1142 'Malformed Object ID %s at %s: %s' % (value, self.__class__.__name__, exc) 

1143 ) 

1144 

1145 try: 

1146 tupleOfInts = tuple([int(subOid) for subOid in value if subOid >= 0]) 

1147 

1148 except (ValueError, TypeError) as exc: 

1149 raise error.PyAsn1Error( 

1150 'Malformed Object ID %s at %s: %s' % (value, self.__class__.__name__, exc) 

1151 ) 

1152 

1153 if len(tupleOfInts) == len(value): 

1154 return tupleOfInts 

1155 

1156 raise error.PyAsn1Error('Malformed Object ID %s at %s' % (value, self.__class__.__name__)) 

1157 

1158 def prettyOut(self, value): 

1159 return '.'.join([str(x) for x in value]) 

1160 

1161 

1162class RelativeOID(base.SimpleAsn1Type): 

1163 """Create |ASN.1| schema or value object. 

1164 |ASN.1| class is based on :class:`~pyasn1.type.base.SimpleAsn1Type`, its 

1165 objects are immutable and duck-type Python :class:`tuple` objects 

1166 (tuple of non-negative integers). 

1167 Keyword Args 

1168 ------------ 

1169 value: :class:`tuple`, :class:`str` or |ASN.1| object 

1170 Python sequence of :class:`int` or :class:`str` literal or |ASN.1| object. 

1171 If `value` is not given, schema object will be created. 

1172 tagSet: :py:class:`~pyasn1.type.tag.TagSet` 

1173 Object representing non-default ASN.1 tag(s) 

1174 subtypeSpec: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection` 

1175 Object representing non-default ASN.1 subtype constraint(s). Constraints 

1176 verification for |ASN.1| type occurs automatically on object 

1177 instantiation. 

1178 Raises 

1179 ------ 

1180 ~pyasn1.error.ValueConstraintError, ~pyasn1.error.PyAsn1Error 

1181 On constraint violation or bad initializer. 

1182 Examples 

1183 -------- 

1184 .. code-block:: python 

1185 class RelOID(RelativeOID): 

1186 ''' 

1187 ASN.1 specification: 

1188 id-pad-null RELATIVE-OID ::= { 0 } 

1189 id-pad-once RELATIVE-OID ::= { 5 6 } 

1190 id-pad-twice RELATIVE-OID ::= { 5 6 7 } 

1191 ''' 

1192 id_pad_null = RelOID('0') 

1193 id_pad_once = RelOID('5.6') 

1194 id_pad_twice = id_pad_once + (7,) 

1195 """ 

1196 #: Set (on class, not on instance) or return a 

1197 #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s) 

1198 #: associated with |ASN.1| type. 

1199 tagSet = tag.initTagSet( 

1200 tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 0x0d) 

1201 ) 

1202 

1203 #: Set (on class, not on instance) or return a 

1204 #: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection` object 

1205 #: imposing constraints on |ASN.1| type initialization values. 

1206 subtypeSpec = constraint.ConstraintsIntersection() 

1207 

1208 # Optimization for faster codec lookup 

1209 typeId = base.SimpleAsn1Type.getTypeId() 

1210 

1211 def __add__(self, other): 

1212 return self.clone(self._value + other) 

1213 

1214 def __radd__(self, other): 

1215 return self.clone(other + self._value) 

1216 

1217 def asTuple(self): 

1218 return self._value 

1219 

1220 # Sequence object protocol 

1221 

1222 def __len__(self): 

1223 return len(self._value) 

1224 

1225 def __getitem__(self, i): 

1226 if i.__class__ is slice: 

1227 return self.clone(self._value[i]) 

1228 else: 

1229 return self._value[i] 

1230 

1231 def __iter__(self): 

1232 return iter(self._value) 

1233 

1234 def __contains__(self, value): 

1235 return value in self._value 

1236 

1237 def index(self, suboid): 

1238 return self._value.index(suboid) 

1239 

1240 def isPrefixOf(self, other): 

1241 """Indicate if this |ASN.1| object is a prefix of other |ASN.1| object. 

1242 Parameters 

1243 ---------- 

1244 other: |ASN.1| object 

1245 |ASN.1| object 

1246 Returns 

1247 ------- 

1248 : :class:`bool` 

1249 :obj:`True` if this |ASN.1| object is a parent (e.g. prefix) of the other |ASN.1| object 

1250 or :obj:`False` otherwise. 

1251 """ 

1252 l = len(self) 

1253 if l <= len(other): 

1254 if self._value[:l] == other[:l]: 

1255 return True 

1256 return False 

1257 

1258 def prettyIn(self, value): 

1259 if isinstance(value, RelativeOID): 

1260 return tuple(value) 

1261 elif isinstance(value, str): 

1262 if '-' in value: 

1263 raise error.PyAsn1Error( 

1264 # sys.exc_info in case prettyIn was called while handling an exception 

1265 'Malformed RELATIVE-OID %s at %s: %s' % (value, self.__class__.__name__, sys.exc_info()[1]) 

1266 ) 

1267 try: 

1268 return tuple([int(subOid) for subOid in value.split('.') if subOid]) 

1269 except ValueError as exc: 

1270 raise error.PyAsn1Error( 

1271 'Malformed RELATIVE-OID %s at %s: %s' % (value, self.__class__.__name__, exc) 

1272 ) 

1273 

1274 try: 

1275 tupleOfInts = tuple([int(subOid) for subOid in value if subOid >= 0]) 

1276 

1277 except (ValueError, TypeError) as exc: 

1278 raise error.PyAsn1Error( 

1279 'Malformed RELATIVE-OID %s at %s: %s' % (value, self.__class__.__name__, exc) 

1280 ) 

1281 

1282 if len(tupleOfInts) == len(value): 

1283 return tupleOfInts 

1284 

1285 raise error.PyAsn1Error('Malformed RELATIVE-OID %s at %s' % (value, self.__class__.__name__)) 

1286 

1287 def prettyOut(self, value): 

1288 return '.'.join([str(x) for x in value]) 

1289 

1290 

1291class Real(base.SimpleAsn1Type): 

1292 """Create |ASN.1| schema or value object. 

1293 

1294 |ASN.1| class is based on :class:`~pyasn1.type.base.SimpleAsn1Type`, its 

1295 objects are immutable and duck-type Python :class:`float` objects. 

1296 Additionally, |ASN.1| objects behave like a :class:`tuple` in which case its 

1297 elements are mantissa, base and exponent. 

1298 

1299 Keyword Args 

1300 ------------ 

1301 value: :class:`tuple`, :class:`float` or |ASN.1| object 

1302 Python sequence of :class:`int` (representing mantissa, base and 

1303 exponent) or :class:`float` instance or |ASN.1| object. 

1304 If `value` is not given, schema object will be created. 

1305 

1306 tagSet: :py:class:`~pyasn1.type.tag.TagSet` 

1307 Object representing non-default ASN.1 tag(s) 

1308 

1309 subtypeSpec: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection` 

1310 Object representing non-default ASN.1 subtype constraint(s). Constraints 

1311 verification for |ASN.1| type occurs automatically on object 

1312 instantiation. 

1313 

1314 Raises 

1315 ------ 

1316 ~pyasn1.error.ValueConstraintError, ~pyasn1.error.PyAsn1Error 

1317 On constraint violation or bad initializer. 

1318 

1319 Examples 

1320 -------- 

1321 .. code-block:: python 

1322 

1323 class Pi(Real): 

1324 ''' 

1325 ASN.1 specification: 

1326 

1327 Pi ::= REAL 

1328 

1329 pi Pi ::= { mantissa 314159, base 10, exponent -5 } 

1330 

1331 ''' 

1332 pi = Pi((314159, 10, -5)) 

1333 """ 

1334 binEncBase = None # binEncBase = 16 is recommended for large numbers 

1335 

1336 try: 

1337 _plusInf = float('inf') 

1338 _minusInf = float('-inf') 

1339 _inf = _plusInf, _minusInf 

1340 

1341 except ValueError: 

1342 # Infinity support is platform and Python dependent 

1343 _plusInf = _minusInf = None 

1344 _inf = () 

1345 

1346 #: Set (on class, not on instance) or return a 

1347 #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s) 

1348 #: associated with |ASN.1| type. 

1349 tagSet = tag.initTagSet( 

1350 tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 0x09) 

1351 ) 

1352 

1353 #: Set (on class, not on instance) or return a 

1354 #: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection` object 

1355 #: imposing constraints on |ASN.1| type initialization values. 

1356 subtypeSpec = constraint.ConstraintsIntersection() 

1357 

1358 # Optimization for faster codec lookup 

1359 typeId = base.SimpleAsn1Type.getTypeId() 

1360 

1361 @staticmethod 

1362 def __normalizeBase10(value): 

1363 m, b, e = value 

1364 while m and m % 10 == 0: 

1365 m //= 10 

1366 e += 1 

1367 return m, b, e 

1368 

1369 def prettyIn(self, value): 

1370 if isinstance(value, tuple) and len(value) == 3: 

1371 if (not isinstance(value[0], (int, float)) or 

1372 not isinstance(value[1], int) or 

1373 not isinstance(value[2], int)): 

1374 raise error.PyAsn1Error('Lame Real value syntax: %s' % (value,)) 

1375 if (isinstance(value[0], float) and 

1376 self._inf and value[0] in self._inf): 

1377 return value[0] 

1378 if value[1] not in (2, 10): 

1379 raise error.PyAsn1Error( 

1380 'Prohibited base for Real value: %s' % (value[1],) 

1381 ) 

1382 if value[1] == 10: 

1383 value = self.__normalizeBase10(value) 

1384 return value 

1385 elif isinstance(value, int): 

1386 return self.__normalizeBase10((value, 10, 0)) 

1387 elif isinstance(value, float) or isinstance(value, str): 

1388 if isinstance(value, str): 

1389 try: 

1390 value = float(value) 

1391 except ValueError: 

1392 raise error.PyAsn1Error( 

1393 'Bad real value syntax: %s' % (value,) 

1394 ) 

1395 if self._inf and value in self._inf: 

1396 return value 

1397 else: 

1398 e = 0 

1399 while int(value) != value: 

1400 value *= 10 

1401 e -= 1 

1402 return self.__normalizeBase10((int(value), 10, e)) 

1403 elif isinstance(value, Real): 

1404 return tuple(value) 

1405 raise error.PyAsn1Error( 

1406 'Bad real value syntax: %s' % (value,) 

1407 ) 

1408 

1409 def prettyPrint(self, scope=0): 

1410 try: 

1411 return self.prettyOut(float(self)) 

1412 

1413 except OverflowError: 

1414 return '<overflow>' 

1415 

1416 @property 

1417 def isPlusInf(self): 

1418 """Indicate PLUS-INFINITY object value 

1419 

1420 Returns 

1421 ------- 

1422 : :class:`bool` 

1423 :obj:`True` if calling object represents plus infinity 

1424 or :obj:`False` otherwise. 

1425 

1426 """ 

1427 return self._value == self._plusInf 

1428 

1429 @property 

1430 def isMinusInf(self): 

1431 """Indicate MINUS-INFINITY object value 

1432 

1433 Returns 

1434 ------- 

1435 : :class:`bool` 

1436 :obj:`True` if calling object represents minus infinity 

1437 or :obj:`False` otherwise. 

1438 """ 

1439 return self._value == self._minusInf 

1440 

1441 @property 

1442 def isInf(self): 

1443 return self._value in self._inf 

1444 

1445 def __add__(self, value): 

1446 return self.clone(float(self) + value) 

1447 

1448 def __radd__(self, value): 

1449 return self + value 

1450 

1451 def __mul__(self, value): 

1452 return self.clone(float(self) * value) 

1453 

1454 def __rmul__(self, value): 

1455 return self * value 

1456 

1457 def __sub__(self, value): 

1458 return self.clone(float(self) - value) 

1459 

1460 def __rsub__(self, value): 

1461 return self.clone(value - float(self)) 

1462 

1463 def __mod__(self, value): 

1464 return self.clone(float(self) % value) 

1465 

1466 def __rmod__(self, value): 

1467 return self.clone(value % float(self)) 

1468 

1469 def __pow__(self, value, modulo=None): 

1470 return self.clone(pow(float(self), value, modulo)) 

1471 

1472 def __rpow__(self, value): 

1473 return self.clone(pow(value, float(self))) 

1474 

1475 def __truediv__(self, value): 

1476 return self.clone(float(self) / value) 

1477 

1478 def __rtruediv__(self, value): 

1479 return self.clone(value / float(self)) 

1480 

1481 def __divmod__(self, value): 

1482 return self.clone(float(self) // value) 

1483 

1484 def __rdivmod__(self, value): 

1485 return self.clone(value // float(self)) 

1486 

1487 def __int__(self): 

1488 return int(float(self)) 

1489 

1490 def __float__(self): 

1491 if self._value in self._inf: 

1492 return self._value 

1493 

1494 mantissa, base, exponent = self._value 

1495 

1496 if not mantissa: 

1497 return 0.0 

1498 

1499 if base == 2: 

1500 return math.ldexp(float(mantissa), exponent) 

1501 

1502 # base is 10 (prettyIn() rejects everything else); refuse to 

1503 # materialize astronomically large integers via pow() 

1504 if exponent > sys.float_info.max_10_exp: 

1505 raise OverflowError('Real value too large to convert to float') 

1506 

1507 return float(mantissa * pow(base, exponent)) 

1508 

1509 def __abs__(self): 

1510 return self.clone(abs(float(self))) 

1511 

1512 def __pos__(self): 

1513 return self.clone(+float(self)) 

1514 

1515 def __neg__(self): 

1516 return self.clone(-float(self)) 

1517 

1518 def __round__(self, n=0): 

1519 r = round(float(self), n) 

1520 if n: 

1521 return self.clone(r) 

1522 else: 

1523 return r 

1524 

1525 def __floor__(self): 

1526 return self.clone(math.floor(float(self))) 

1527 

1528 def __ceil__(self): 

1529 return self.clone(math.ceil(float(self))) 

1530 

1531 def __trunc__(self): 

1532 return self.clone(math.trunc(float(self))) 

1533 

1534 def __lt__(self, value): 

1535 return float(self) < value 

1536 

1537 def __le__(self, value): 

1538 return float(self) <= value 

1539 

1540 def __eq__(self, value): 

1541 return float(self) == value 

1542 

1543 def __ne__(self, value): 

1544 return float(self) != value 

1545 

1546 def __gt__(self, value): 

1547 return float(self) > value 

1548 

1549 def __ge__(self, value): 

1550 return float(self) >= value 

1551 

1552 def __bool__(self): 

1553 return bool(float(self)) 

1554 

1555 __hash__ = base.SimpleAsn1Type.__hash__ 

1556 

1557 def __getitem__(self, idx): 

1558 if self._value in self._inf: 

1559 raise error.PyAsn1Error('Invalid infinite value operation') 

1560 else: 

1561 return self._value[idx] 

1562 

1563 # compatibility stubs 

1564 

1565 def isPlusInfinity(self): 

1566 return self.isPlusInf 

1567 

1568 def isMinusInfinity(self): 

1569 return self.isMinusInf 

1570 

1571 def isInfinity(self): 

1572 return self.isInf 

1573 

1574 

1575class Enumerated(Integer): 

1576 """Create |ASN.1| schema or value object. 

1577 

1578 |ASN.1| class is based on :class:`~pyasn1.type.base.SimpleAsn1Type`, its 

1579 objects are immutable and duck-type Python :class:`int` objects. 

1580 

1581 Keyword Args 

1582 ------------ 

1583 value: :class:`int`, :class:`str` or |ASN.1| object 

1584 Python :class:`int` or :class:`str` literal or |ASN.1| object. 

1585 If `value` is not given, schema object will be created. 

1586 

1587 tagSet: :py:class:`~pyasn1.type.tag.TagSet` 

1588 Object representing non-default ASN.1 tag(s) 

1589 

1590 subtypeSpec: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection` 

1591 Object representing non-default ASN.1 subtype constraint(s). Constraints 

1592 verification for |ASN.1| type occurs automatically on object 

1593 instantiation. 

1594 

1595 namedValues: :py:class:`~pyasn1.type.namedval.NamedValues` 

1596 Object representing non-default symbolic aliases for numbers 

1597 

1598 Raises 

1599 ------ 

1600 ~pyasn1.error.ValueConstraintError, ~pyasn1.error.PyAsn1Error 

1601 On constraint violation or bad initializer. 

1602 

1603 Examples 

1604 -------- 

1605 

1606 .. code-block:: python 

1607 

1608 class RadioButton(Enumerated): 

1609 ''' 

1610 ASN.1 specification: 

1611 

1612 RadioButton ::= ENUMERATED { button1(0), button2(1), 

1613 button3(2) } 

1614 

1615 selected-by-default RadioButton ::= button1 

1616 ''' 

1617 namedValues = NamedValues( 

1618 ('button1', 0), ('button2', 1), 

1619 ('button3', 2) 

1620 ) 

1621 

1622 selected_by_default = RadioButton('button1') 

1623 """ 

1624 #: Set (on class, not on instance) or return a 

1625 #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s) 

1626 #: associated with |ASN.1| type. 

1627 tagSet = tag.initTagSet( 

1628 tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 0x0A) 

1629 ) 

1630 

1631 #: Set (on class, not on instance) or return a 

1632 #: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection` object 

1633 #: imposing constraints on |ASN.1| type initialization values. 

1634 subtypeSpec = constraint.ConstraintsIntersection() 

1635 

1636 # Optimization for faster codec lookup 

1637 typeId = Integer.getTypeId() 

1638 

1639 #: Default :py:class:`~pyasn1.type.namedval.NamedValues` object 

1640 #: representing symbolic aliases for numbers 

1641 namedValues = namedval.NamedValues() 

1642 

1643 

1644# "Structured" ASN.1 types 

1645 

1646class SequenceOfAndSetOfBase(base.ConstructedAsn1Type): 

1647 """Create |ASN.1| schema or value object. 

1648 

1649 |ASN.1| class is based on :class:`~pyasn1.type.base.ConstructedAsn1Type`, 

1650 its objects are mutable and duck-type Python :class:`list` objects. 

1651 

1652 Keyword Args 

1653 ------------ 

1654 componentType : :py:class:`~pyasn1.type.base.PyAsn1Item` derivative 

1655 A pyasn1 object representing ASN.1 type allowed within |ASN.1| type 

1656 

1657 tagSet: :py:class:`~pyasn1.type.tag.TagSet` 

1658 Object representing non-default ASN.1 tag(s) 

1659 

1660 subtypeSpec: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection` 

1661 Object representing non-default ASN.1 subtype constraint(s). Constraints 

1662 verification for |ASN.1| type can only occur on explicit 

1663 `.isInconsistent` call. 

1664 

1665 Examples 

1666 -------- 

1667 

1668 .. code-block:: python 

1669 

1670 class LotteryDraw(SequenceOf): # SetOf is similar 

1671 ''' 

1672 ASN.1 specification: 

1673 

1674 LotteryDraw ::= SEQUENCE OF INTEGER 

1675 ''' 

1676 componentType = Integer() 

1677 

1678 lotteryDraw = LotteryDraw() 

1679 lotteryDraw.extend([123, 456, 789]) 

1680 """ 

1681 def __init__(self, *args, **kwargs): 

1682 # support positional params for backward compatibility 

1683 if args: 

1684 for key, value in zip(('componentType', 'tagSet', 

1685 'subtypeSpec'), args): 

1686 if key in kwargs: 

1687 raise error.PyAsn1Error('Conflicting positional and keyword params!') 

1688 kwargs['componentType'] = value 

1689 

1690 self._componentValues = noValue 

1691 

1692 base.ConstructedAsn1Type.__init__(self, **kwargs) 

1693 

1694 # Python list protocol 

1695 

1696 def __getitem__(self, idx): 

1697 try: 

1698 return self.getComponentByPosition(idx) 

1699 

1700 except error.PyAsn1Error as exc: 

1701 raise IndexError(exc) 

1702 

1703 def __setitem__(self, idx, value): 

1704 try: 

1705 self.setComponentByPosition(idx, value) 

1706 

1707 except error.PyAsn1Error as exc: 

1708 raise IndexError(exc) 

1709 

1710 def append(self, value): 

1711 if self._componentValues is noValue: 

1712 pos = 0 

1713 

1714 else: 

1715 pos = len(self._componentValues) 

1716 

1717 self[pos] = value 

1718 

1719 def count(self, value): 

1720 return list(self._componentValues.values()).count(value) 

1721 

1722 def extend(self, values): 

1723 for value in values: 

1724 self.append(value) 

1725 

1726 if self._componentValues is noValue: 

1727 self._componentValues = {} 

1728 

1729 def index(self, value, start=0, stop=None): 

1730 if stop is None: 

1731 stop = len(self) 

1732 

1733 indices, values = zip(*self._componentValues.items()) 

1734 

1735 # TODO: remove when Py2.5 support is gone 

1736 values = list(values) 

1737 

1738 try: 

1739 return indices[values.index(value, start, stop)] 

1740 

1741 except error.PyAsn1Error as exc: 

1742 raise ValueError(exc) 

1743 

1744 def reverse(self): 

1745 self._componentValues.reverse() 

1746 

1747 def sort(self, key=None, reverse=False): 

1748 self._componentValues = dict( 

1749 enumerate(sorted(self._componentValues.values(), 

1750 key=key, reverse=reverse))) 

1751 

1752 def __len__(self): 

1753 if self._componentValues is noValue or not self._componentValues: 

1754 return 0 

1755 

1756 return max(self._componentValues) + 1 

1757 

1758 def __iter__(self): 

1759 for idx in range(0, len(self)): 

1760 yield self.getComponentByPosition(idx) 

1761 

1762 def _cloneComponentValues(self, myClone, cloneValueFlag): 

1763 for idx, componentValue in self._componentValues.items(): 

1764 if componentValue is not noValue: 

1765 if isinstance(componentValue, base.ConstructedAsn1Type): 

1766 myClone.setComponentByPosition( 

1767 idx, componentValue.clone(cloneValueFlag=cloneValueFlag) 

1768 ) 

1769 else: 

1770 myClone.setComponentByPosition(idx, componentValue.clone()) 

1771 

1772 def getComponentByPosition(self, idx, default=noValue, instantiate=True): 

1773 """Return |ASN.1| type component value by position. 

1774 

1775 Equivalent to Python sequence subscription operation (e.g. `[]`). 

1776 

1777 Parameters 

1778 ---------- 

1779 idx : :class:`int` 

1780 Component index (zero-based). Must either refer to an existing 

1781 component or to N+1 component (if *componentType* is set). In the latter 

1782 case a new component type gets instantiated and appended to the |ASN.1| 

1783 sequence. 

1784 

1785 Keyword Args 

1786 ------------ 

1787 default: :class:`object` 

1788 If set and requested component is a schema object, return the `default` 

1789 object instead of the requested component. 

1790 

1791 instantiate: :class:`bool` 

1792 If :obj:`True` (default), inner component will be automatically instantiated. 

1793 If :obj:`False` either existing component or the :class:`NoValue` object will be 

1794 returned. 

1795 

1796 Returns 

1797 ------- 

1798 : :py:class:`~pyasn1.type.base.PyAsn1Item` 

1799 Instantiate |ASN.1| component type or return existing component value 

1800 

1801 Examples 

1802 -------- 

1803 

1804 .. code-block:: python 

1805 

1806 # can also be SetOf 

1807 class MySequenceOf(SequenceOf): 

1808 componentType = OctetString() 

1809 

1810 s = MySequenceOf() 

1811 

1812 # returns component #0 with `.isValue` property False 

1813 s.getComponentByPosition(0) 

1814 

1815 # returns None 

1816 s.getComponentByPosition(0, default=None) 

1817 

1818 s.clear() 

1819 

1820 # returns noValue 

1821 s.getComponentByPosition(0, instantiate=False) 

1822 

1823 # sets component #0 to OctetString() ASN.1 schema 

1824 # object and returns it 

1825 s.getComponentByPosition(0, instantiate=True) 

1826 

1827 # sets component #0 to ASN.1 value object 

1828 s.setComponentByPosition(0, 'ABCD') 

1829 

1830 # returns OctetString('ABCD') value object 

1831 s.getComponentByPosition(0, instantiate=False) 

1832 

1833 s.clear() 

1834 

1835 # returns noValue 

1836 s.getComponentByPosition(0, instantiate=False) 

1837 """ 

1838 if isinstance(idx, slice): 

1839 indices = tuple(range(len(self))) 

1840 return [self.getComponentByPosition(subidx, default, instantiate) 

1841 for subidx in indices[idx]] 

1842 

1843 if idx < 0: 

1844 idx = len(self) + idx 

1845 if idx < 0: 

1846 raise error.PyAsn1Error( 

1847 'SequenceOf/SetOf index is out of range') 

1848 

1849 try: 

1850 componentValue = self._componentValues[idx] 

1851 

1852 except (KeyError, error.PyAsn1Error): 

1853 if not instantiate: 

1854 return default 

1855 

1856 self.setComponentByPosition(idx) 

1857 

1858 componentValue = self._componentValues[idx] 

1859 

1860 if default is noValue or componentValue.isValue: 

1861 return componentValue 

1862 else: 

1863 return default 

1864 

1865 def setComponentByPosition(self, idx, value=noValue, 

1866 verifyConstraints=True, 

1867 matchTags=True, 

1868 matchConstraints=True): 

1869 """Assign |ASN.1| type component by position. 

1870 

1871 Equivalent to Python sequence item assignment operation (e.g. `[]`) 

1872 or list.append() (when idx == len(self)). 

1873 

1874 Parameters 

1875 ---------- 

1876 idx: :class:`int` 

1877 Component index (zero-based). Must either refer to existing 

1878 component or to N+1 component. In the latter case a new component 

1879 type gets instantiated (if *componentType* is set, or given ASN.1 

1880 object is taken otherwise) and appended to the |ASN.1| sequence. 

1881 

1882 Keyword Args 

1883 ------------ 

1884 value: :class:`object` or :py:class:`~pyasn1.type.base.PyAsn1Item` derivative 

1885 A Python value to initialize |ASN.1| component with (if *componentType* is set) 

1886 or ASN.1 value object to assign to |ASN.1| component. 

1887 If `value` is not given, schema object will be set as a component. 

1888 

1889 verifyConstraints: :class:`bool` 

1890 If :obj:`False`, skip constraints validation 

1891 

1892 matchTags: :class:`bool` 

1893 If :obj:`False`, skip component tags matching 

1894 

1895 matchConstraints: :class:`bool` 

1896 If :obj:`False`, skip component constraints matching 

1897 

1898 Returns 

1899 ------- 

1900 self 

1901 

1902 Raises 

1903 ------ 

1904 ~pyasn1.error.ValueConstraintError, ~pyasn1.error.PyAsn1Error 

1905 On constraint violation or bad initializer 

1906 IndexError 

1907 When idx > len(self) 

1908 """ 

1909 if isinstance(idx, slice): 

1910 indices = tuple(range(len(self))) 

1911 startIdx = indices and indices[idx][0] or 0 

1912 for subIdx, subValue in enumerate(value): 

1913 self.setComponentByPosition( 

1914 startIdx + subIdx, subValue, verifyConstraints, 

1915 matchTags, matchConstraints) 

1916 return self 

1917 

1918 if idx < 0: 

1919 idx = len(self) + idx 

1920 if idx < 0: 

1921 raise error.PyAsn1Error( 

1922 'SequenceOf/SetOf index is out of range') 

1923 

1924 componentType = self.componentType 

1925 

1926 if self._componentValues is noValue: 

1927 componentValues = {} 

1928 

1929 else: 

1930 componentValues = self._componentValues 

1931 

1932 currentValue = componentValues.get(idx, noValue) 

1933 

1934 if value is noValue: 

1935 if componentType is not None: 

1936 value = componentType.clone() 

1937 

1938 elif currentValue is noValue: 

1939 raise error.PyAsn1Error('Component type not defined') 

1940 

1941 elif not isinstance(value, base.Asn1Item): 

1942 if (componentType is not None and 

1943 isinstance(componentType, base.SimpleAsn1Type)): 

1944 value = componentType.clone(value=value) 

1945 

1946 elif (currentValue is not noValue and 

1947 isinstance(currentValue, base.SimpleAsn1Type)): 

1948 value = currentValue.clone(value=value) 

1949 

1950 else: 

1951 raise error.PyAsn1Error( 

1952 'Non-ASN.1 value %r and undefined component' 

1953 ' type at %r' % (value, self)) 

1954 

1955 elif componentType is not None and (matchTags or matchConstraints): 

1956 subtypeChecker = ( 

1957 self.strictConstraints and 

1958 componentType.isSameTypeWith or 

1959 componentType.isSuperTypeOf) 

1960 

1961 if not subtypeChecker(value, verifyConstraints and matchTags, 

1962 verifyConstraints and matchConstraints): 

1963 # TODO: we should wrap componentType with UnnamedType to carry 

1964 # additional properties associated with componentType 

1965 if componentType.typeId != Any.typeId: 

1966 raise error.PyAsn1Error( 

1967 'Component value is tag-incompatible: %r vs ' 

1968 '%r' % (value, componentType)) 

1969 

1970 componentValues[idx] = value 

1971 

1972 self._componentValues = componentValues 

1973 

1974 return self 

1975 

1976 @property 

1977 def componentTagMap(self): 

1978 if self.componentType is not None: 

1979 return self.componentType.tagMap 

1980 

1981 @property 

1982 def components(self): 

1983 return [self._componentValues[idx] 

1984 for idx in sorted(self._componentValues)] 

1985 

1986 def clear(self): 

1987 """Remove all components and become an empty |ASN.1| value object. 

1988 

1989 Has the same effect on |ASN.1| object as it does on :class:`list` 

1990 built-in. 

1991 """ 

1992 self._componentValues = {} 

1993 return self 

1994 

1995 def reset(self): 

1996 """Remove all components and become a |ASN.1| schema object. 

1997 

1998 See :meth:`isValue` property for more information on the 

1999 distinction between value and schema objects. 

2000 """ 

2001 self._componentValues = noValue 

2002 return self 

2003 

2004 def prettyPrint(self, scope=0): 

2005 scope += 1 

2006 representation = self.__class__.__name__ + ':\n' 

2007 

2008 if not self.isValue: 

2009 return representation 

2010 

2011 for idx, componentValue in enumerate(self): 

2012 representation += ' ' * scope 

2013 if (componentValue is noValue and 

2014 self.componentType is not None): 

2015 representation += '<empty>' 

2016 else: 

2017 representation += componentValue.prettyPrint(scope) 

2018 

2019 return representation 

2020 

2021 def prettyPrintType(self, scope=0): 

2022 scope += 1 

2023 representation = '%s -> %s {\n' % (self.tagSet, self.__class__.__name__) 

2024 if self.componentType is not None: 

2025 representation += ' ' * scope 

2026 representation += self.componentType.prettyPrintType(scope) 

2027 return representation + '\n' + ' ' * (scope - 1) + '}' 

2028 

2029 

2030 @property 

2031 def isValue(self): 

2032 """Indicate that |ASN.1| object represents ASN.1 value. 

2033 

2034 If *isValue* is :obj:`False` then this object represents just ASN.1 schema. 

2035 

2036 If *isValue* is :obj:`True` then, in addition to its ASN.1 schema features, 

2037 this object can also be used like a Python built-in object 

2038 (e.g. :class:`int`, :class:`str`, :class:`dict` etc.). 

2039 

2040 Returns 

2041 ------- 

2042 : :class:`bool` 

2043 :obj:`False` if object represents just ASN.1 schema. 

2044 :obj:`True` if object represents ASN.1 schema and can be used as a normal value. 

2045 

2046 Note 

2047 ---- 

2048 There is an important distinction between PyASN1 schema and value objects. 

2049 The PyASN1 schema objects can only participate in ASN.1 schema-related 

2050 operations (e.g. defining or testing the structure of the data). Most 

2051 obvious uses of ASN.1 schema is to guide serialisation codecs whilst 

2052 encoding/decoding serialised ASN.1 contents. 

2053 

2054 The PyASN1 value objects can **additionally** participate in many operations 

2055 involving regular Python objects (e.g. arithmetic, comprehension etc). 

2056 """ 

2057 if self._componentValues is noValue: 

2058 return False 

2059 

2060 if len(self._componentValues) != len(self): 

2061 return False 

2062 

2063 for componentValue in self._componentValues.values(): 

2064 if componentValue is noValue or not componentValue.isValue: 

2065 return False 

2066 

2067 return True 

2068 

2069 @property 

2070 def isInconsistent(self): 

2071 """Run necessary checks to ensure |ASN.1| object consistency. 

2072 

2073 Default action is to verify |ASN.1| object against constraints imposed 

2074 by `subtypeSpec`. 

2075 

2076 Raises 

2077 ------ 

2078 :py:class:`~pyasn1.error.PyAsn1tError` on any inconsistencies found 

2079 """ 

2080 if self.componentType is noValue or not self.subtypeSpec: 

2081 return False 

2082 

2083 if self._componentValues is noValue: 

2084 return True 

2085 

2086 mapping = {} 

2087 

2088 for idx, value in self._componentValues.items(): 

2089 # Absent fields are not in the mapping 

2090 if value is noValue: 

2091 continue 

2092 

2093 mapping[idx] = value 

2094 

2095 try: 

2096 # Represent SequenceOf/SetOf as a bare dict to constraints chain 

2097 self.subtypeSpec(mapping) 

2098 

2099 except error.PyAsn1Error as exc: 

2100 return exc 

2101 

2102 return False 

2103 

2104class SequenceOf(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, 0x10) 

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 SetOf(SequenceOfAndSetOfBase): 

2128 __doc__ = SequenceOfAndSetOfBase.__doc__ 

2129 

2130 #: Set (on class, not on instance) or return a 

2131 #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s) 

2132 #: associated with |ASN.1| type. 

2133 tagSet = tag.initTagSet( 

2134 tag.Tag(tag.tagClassUniversal, tag.tagFormatConstructed, 0x11) 

2135 ) 

2136 

2137 #: Default :py:class:`~pyasn1.type.base.PyAsn1Item` derivative 

2138 #: object representing ASN.1 type allowed within |ASN.1| type 

2139 componentType = None 

2140 

2141 #: Set (on class, not on instance) or return a 

2142 #: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection` object 

2143 #: imposing constraints on |ASN.1| type initialization values. 

2144 subtypeSpec = constraint.ConstraintsIntersection() 

2145 

2146 # Disambiguation ASN.1 types identification 

2147 typeId = SequenceOfAndSetOfBase.getTypeId() 

2148 

2149 

2150class SequenceAndSetBase(base.ConstructedAsn1Type): 

2151 """Create |ASN.1| schema or value object. 

2152 

2153 |ASN.1| class is based on :class:`~pyasn1.type.base.ConstructedAsn1Type`, 

2154 its objects are mutable and duck-type Python :class:`dict` objects. 

2155 

2156 Keyword Args 

2157 ------------ 

2158 componentType: :py:class:`~pyasn1.type.namedtype.NamedType` 

2159 Object holding named ASN.1 types allowed within this collection 

2160 

2161 tagSet: :py:class:`~pyasn1.type.tag.TagSet` 

2162 Object representing non-default ASN.1 tag(s) 

2163 

2164 subtypeSpec: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection` 

2165 Object representing non-default ASN.1 subtype constraint(s). Constraints 

2166 verification for |ASN.1| type can only occur on explicit 

2167 `.isInconsistent` call. 

2168 

2169 Examples 

2170 -------- 

2171 

2172 .. code-block:: python 

2173 

2174 class Description(Sequence): # Set is similar 

2175 ''' 

2176 ASN.1 specification: 

2177 

2178 Description ::= SEQUENCE { 

2179 surname IA5String, 

2180 first-name IA5String OPTIONAL, 

2181 age INTEGER DEFAULT 40 

2182 } 

2183 ''' 

2184 componentType = NamedTypes( 

2185 NamedType('surname', IA5String()), 

2186 OptionalNamedType('first-name', IA5String()), 

2187 DefaultedNamedType('age', Integer(40)) 

2188 ) 

2189 

2190 descr = Description() 

2191 descr['surname'] = 'Smith' 

2192 descr['first-name'] = 'John' 

2193 """ 

2194 #: Default :py:class:`~pyasn1.type.namedtype.NamedTypes` 

2195 #: object representing named ASN.1 types allowed within |ASN.1| type 

2196 componentType = namedtype.NamedTypes() 

2197 

2198 

2199 class DynamicNames(object): 

2200 """Fields names/positions mapping for component-less objects""" 

2201 def __init__(self): 

2202 self._keyToIdxMap = {} 

2203 self._idxToKeyMap = {} 

2204 

2205 def __len__(self): 

2206 return len(self._keyToIdxMap) 

2207 

2208 def __contains__(self, item): 

2209 return item in self._keyToIdxMap or item in self._idxToKeyMap 

2210 

2211 def __iter__(self): 

2212 return (self._idxToKeyMap[idx] for idx in range(len(self._idxToKeyMap))) 

2213 

2214 def __getitem__(self, item): 

2215 try: 

2216 return self._keyToIdxMap[item] 

2217 

2218 except KeyError: 

2219 return self._idxToKeyMap[item] 

2220 

2221 def getNameByPosition(self, idx): 

2222 try: 

2223 return self._idxToKeyMap[idx] 

2224 

2225 except KeyError: 

2226 raise error.PyAsn1Error('Type position out of range') 

2227 

2228 def getPositionByName(self, name): 

2229 try: 

2230 return self._keyToIdxMap[name] 

2231 

2232 except KeyError: 

2233 raise error.PyAsn1Error('Name %s not found' % (name,)) 

2234 

2235 def addField(self, idx): 

2236 self._keyToIdxMap['field-%d' % idx] = idx 

2237 self._idxToKeyMap[idx] = 'field-%d' % idx 

2238 

2239 

2240 def __init__(self, **kwargs): 

2241 base.ConstructedAsn1Type.__init__(self, **kwargs) 

2242 self._componentTypeLen = len(self.componentType) 

2243 if self._componentTypeLen: 

2244 self._componentValues = [] 

2245 else: 

2246 self._componentValues = noValue 

2247 self._dynamicNames = self._componentTypeLen or self.DynamicNames() 

2248 

2249 def __getitem__(self, idx): 

2250 if isinstance(idx, str): 

2251 try: 

2252 return self.getComponentByName(idx) 

2253 

2254 except error.PyAsn1Error as exc: 

2255 # duck-typing dict 

2256 raise KeyError(exc) 

2257 

2258 else: 

2259 try: 

2260 return self.getComponentByPosition(idx) 

2261 

2262 except error.PyAsn1Error as exc: 

2263 # duck-typing list 

2264 raise IndexError(exc) 

2265 

2266 def __setitem__(self, idx, value): 

2267 if isinstance(idx, str): 

2268 try: 

2269 self.setComponentByName(idx, value) 

2270 

2271 except error.PyAsn1Error as exc: 

2272 # duck-typing dict 

2273 raise KeyError(exc) 

2274 

2275 else: 

2276 try: 

2277 self.setComponentByPosition(idx, value) 

2278 

2279 except error.PyAsn1Error as exc: 

2280 # duck-typing list 

2281 raise IndexError(exc) 

2282 

2283 def __contains__(self, key): 

2284 if self._componentTypeLen: 

2285 return key in self.componentType 

2286 else: 

2287 return key in self._dynamicNames 

2288 

2289 def __len__(self): 

2290 return len(self._componentValues) 

2291 

2292 def __iter__(self): 

2293 return iter(self.componentType or self._dynamicNames) 

2294 

2295 # Python dict protocol 

2296 

2297 def values(self): 

2298 for idx in range(self._componentTypeLen or len(self._dynamicNames)): 

2299 yield self[idx] 

2300 

2301 def keys(self): 

2302 return iter(self) 

2303 

2304 def items(self): 

2305 for idx in range(self._componentTypeLen or len(self._dynamicNames)): 

2306 if self._componentTypeLen: 

2307 yield self.componentType[idx].name, self[idx] 

2308 else: 

2309 yield self._dynamicNames[idx], self[idx] 

2310 

2311 def update(self, *iterValue, **mappingValue): 

2312 for k, v in iterValue: 

2313 self[k] = v 

2314 for k in mappingValue: 

2315 self[k] = mappingValue[k] 

2316 

2317 def clear(self): 

2318 """Remove all components and become an empty |ASN.1| value object. 

2319 

2320 Has the same effect on |ASN.1| object as it does on :class:`dict` 

2321 built-in. 

2322 """ 

2323 self._componentValues = [] 

2324 self._dynamicNames = self.DynamicNames() 

2325 return self 

2326 

2327 def reset(self): 

2328 """Remove all components and become a |ASN.1| schema object. 

2329 

2330 See :meth:`isValue` property for more information on the 

2331 distinction between value and schema objects. 

2332 """ 

2333 self._componentValues = noValue 

2334 self._dynamicNames = self.DynamicNames() 

2335 return self 

2336 

2337 @property 

2338 def components(self): 

2339 return self._componentValues 

2340 

2341 def _cloneComponentValues(self, myClone, cloneValueFlag): 

2342 if self._componentValues is noValue: 

2343 return 

2344 

2345 for idx, componentValue in enumerate(self._componentValues): 

2346 if componentValue is not noValue: 

2347 if isinstance(componentValue, base.ConstructedAsn1Type): 

2348 myClone.setComponentByPosition( 

2349 idx, componentValue.clone(cloneValueFlag=cloneValueFlag) 

2350 ) 

2351 else: 

2352 myClone.setComponentByPosition(idx, componentValue.clone()) 

2353 

2354 def getComponentByName(self, name, default=noValue, instantiate=True): 

2355 """Returns |ASN.1| type component by name. 

2356 

2357 Equivalent to Python :class:`dict` subscription operation (e.g. `[]`). 

2358 

2359 Parameters 

2360 ---------- 

2361 name: :class:`str` 

2362 |ASN.1| type component name 

2363 

2364 Keyword Args 

2365 ------------ 

2366 default: :class:`object` 

2367 If set and requested component is a schema object, return the `default` 

2368 object instead of the requested component. 

2369 

2370 instantiate: :class:`bool` 

2371 If :obj:`True` (default), inner component will be automatically 

2372 instantiated. 

2373 If :obj:`False` either existing component or the :class:`NoValue` 

2374 object will be returned. 

2375 

2376 Returns 

2377 ------- 

2378 : :py:class:`~pyasn1.type.base.PyAsn1Item` 

2379 Instantiate |ASN.1| component type or return existing 

2380 component value 

2381 """ 

2382 if self._componentTypeLen: 

2383 idx = self.componentType.getPositionByName(name) 

2384 else: 

2385 try: 

2386 idx = self._dynamicNames.getPositionByName(name) 

2387 

2388 except KeyError: 

2389 raise error.PyAsn1Error('Name %s not found' % (name,)) 

2390 

2391 return self.getComponentByPosition(idx, default=default, instantiate=instantiate) 

2392 

2393 def setComponentByName(self, name, value=noValue, 

2394 verifyConstraints=True, 

2395 matchTags=True, 

2396 matchConstraints=True): 

2397 """Assign |ASN.1| type component by name. 

2398 

2399 Equivalent to Python :class:`dict` item assignment operation (e.g. `[]`). 

2400 

2401 Parameters 

2402 ---------- 

2403 name: :class:`str` 

2404 |ASN.1| type component name 

2405 

2406 Keyword Args 

2407 ------------ 

2408 value: :class:`object` or :py:class:`~pyasn1.type.base.PyAsn1Item` derivative 

2409 A Python value to initialize |ASN.1| component with (if *componentType* is set) 

2410 or ASN.1 value object to assign to |ASN.1| component. 

2411 If `value` is not given, schema object will be set as a component. 

2412 

2413 verifyConstraints: :class:`bool` 

2414 If :obj:`False`, skip constraints validation 

2415 

2416 matchTags: :class:`bool` 

2417 If :obj:`False`, skip component tags matching 

2418 

2419 matchConstraints: :class:`bool` 

2420 If :obj:`False`, skip component constraints matching 

2421 

2422 Returns 

2423 ------- 

2424 self 

2425 """ 

2426 if self._componentTypeLen: 

2427 idx = self.componentType.getPositionByName(name) 

2428 else: 

2429 try: 

2430 idx = self._dynamicNames.getPositionByName(name) 

2431 

2432 except KeyError: 

2433 raise error.PyAsn1Error('Name %s not found' % (name,)) 

2434 

2435 return self.setComponentByPosition( 

2436 idx, value, verifyConstraints, matchTags, matchConstraints 

2437 ) 

2438 

2439 def getComponentByPosition(self, idx, default=noValue, instantiate=True): 

2440 """Returns |ASN.1| type component by index. 

2441 

2442 Equivalent to Python sequence subscription operation (e.g. `[]`). 

2443 

2444 Parameters 

2445 ---------- 

2446 idx: :class:`int` 

2447 Component index (zero-based). Must either refer to an existing 

2448 component or (if *componentType* is set) new ASN.1 schema object gets 

2449 instantiated. 

2450 

2451 Keyword Args 

2452 ------------ 

2453 default: :class:`object` 

2454 If set and requested component is a schema object, return the `default` 

2455 object instead of the requested component. 

2456 

2457 instantiate: :class:`bool` 

2458 If :obj:`True` (default), inner component will be automatically 

2459 instantiated. 

2460 If :obj:`False` either existing component or the :class:`NoValue` 

2461 object will be returned. 

2462 

2463 Returns 

2464 ------- 

2465 : :py:class:`~pyasn1.type.base.PyAsn1Item` 

2466 a PyASN1 object 

2467 

2468 Examples 

2469 -------- 

2470 

2471 .. code-block:: python 

2472 

2473 # can also be Set 

2474 class MySequence(Sequence): 

2475 componentType = NamedTypes( 

2476 NamedType('id', OctetString()) 

2477 ) 

2478 

2479 s = MySequence() 

2480 

2481 # returns component #0 with `.isValue` property False 

2482 s.getComponentByPosition(0) 

2483 

2484 # returns None 

2485 s.getComponentByPosition(0, default=None) 

2486 

2487 s.clear() 

2488 

2489 # returns noValue 

2490 s.getComponentByPosition(0, instantiate=False) 

2491 

2492 # sets component #0 to OctetString() ASN.1 schema 

2493 # object and returns it 

2494 s.getComponentByPosition(0, instantiate=True) 

2495 

2496 # sets component #0 to ASN.1 value object 

2497 s.setComponentByPosition(0, 'ABCD') 

2498 

2499 # returns OctetString('ABCD') value object 

2500 s.getComponentByPosition(0, instantiate=False) 

2501 

2502 s.clear() 

2503 

2504 # returns noValue 

2505 s.getComponentByPosition(0, instantiate=False) 

2506 """ 

2507 try: 

2508 if self._componentValues is noValue: 

2509 componentValue = noValue 

2510 

2511 else: 

2512 componentValue = self._componentValues[idx] 

2513 

2514 except IndexError: 

2515 componentValue = noValue 

2516 

2517 if not instantiate: 

2518 if componentValue is noValue or not componentValue.isValue: 

2519 return default 

2520 else: 

2521 return componentValue 

2522 

2523 if componentValue is noValue: 

2524 self.setComponentByPosition(idx) 

2525 

2526 componentValue = self._componentValues[idx] 

2527 

2528 if default is noValue or componentValue.isValue: 

2529 return componentValue 

2530 else: 

2531 return default 

2532 

2533 def setComponentByPosition(self, idx, value=noValue, 

2534 verifyConstraints=True, 

2535 matchTags=True, 

2536 matchConstraints=True): 

2537 """Assign |ASN.1| type component by position. 

2538 

2539 Equivalent to Python sequence item assignment operation (e.g. `[]`). 

2540 

2541 Parameters 

2542 ---------- 

2543 idx : :class:`int` 

2544 Component index (zero-based). Must either refer to existing 

2545 component (if *componentType* is set) or to N+1 component 

2546 otherwise. In the latter case a new component of given ASN.1 

2547 type gets instantiated and appended to |ASN.1| sequence. 

2548 

2549 Keyword Args 

2550 ------------ 

2551 value: :class:`object` or :py:class:`~pyasn1.type.base.PyAsn1Item` derivative 

2552 A Python value to initialize |ASN.1| component with (if *componentType* is set) 

2553 or ASN.1 value object to assign to |ASN.1| component. 

2554 If `value` is not given, schema object will be set as a component. 

2555 

2556 verifyConstraints : :class:`bool` 

2557 If :obj:`False`, skip constraints validation 

2558 

2559 matchTags: :class:`bool` 

2560 If :obj:`False`, skip component tags matching 

2561 

2562 matchConstraints: :class:`bool` 

2563 If :obj:`False`, skip component constraints matching 

2564 

2565 Returns 

2566 ------- 

2567 self 

2568 """ 

2569 componentType = self.componentType 

2570 componentTypeLen = self._componentTypeLen 

2571 

2572 if self._componentValues is noValue: 

2573 componentValues = [] 

2574 

2575 else: 

2576 componentValues = self._componentValues 

2577 

2578 try: 

2579 currentValue = componentValues[idx] 

2580 

2581 except IndexError: 

2582 currentValue = noValue 

2583 if componentTypeLen: 

2584 if componentTypeLen < idx: 

2585 raise error.PyAsn1Error('component index out of range') 

2586 

2587 componentValues = [noValue] * componentTypeLen 

2588 

2589 if value is noValue: 

2590 if componentTypeLen: 

2591 value = componentType.getTypeByPosition(idx) 

2592 if isinstance(value, base.ConstructedAsn1Type): 

2593 value = value.clone(cloneValueFlag=componentType[idx].isDefaulted) 

2594 

2595 elif currentValue is noValue: 

2596 raise error.PyAsn1Error('Component type not defined') 

2597 

2598 elif not isinstance(value, base.Asn1Item): 

2599 if componentTypeLen: 

2600 subComponentType = componentType.getTypeByPosition(idx) 

2601 if isinstance(subComponentType, base.SimpleAsn1Type): 

2602 value = subComponentType.clone(value=value) 

2603 

2604 else: 

2605 raise error.PyAsn1Error('%s can cast only scalar values' % componentType.__class__.__name__) 

2606 

2607 elif currentValue is not noValue and isinstance(currentValue, base.SimpleAsn1Type): 

2608 value = currentValue.clone(value=value) 

2609 

2610 else: 

2611 raise error.PyAsn1Error('%s undefined component type' % componentType.__class__.__name__) 

2612 

2613 elif ((verifyConstraints or matchTags or matchConstraints) and 

2614 componentTypeLen): 

2615 subComponentType = componentType.getTypeByPosition(idx) 

2616 if subComponentType is not noValue: 

2617 subtypeChecker = (self.strictConstraints and 

2618 subComponentType.isSameTypeWith or 

2619 subComponentType.isSuperTypeOf) 

2620 

2621 if not subtypeChecker(value, verifyConstraints and matchTags, 

2622 verifyConstraints and matchConstraints): 

2623 if not componentType[idx].openType: 

2624 raise error.PyAsn1Error('Component value is tag-incompatible: %r vs %r' % (value, componentType)) 

2625 

2626 if componentTypeLen or idx in self._dynamicNames: 

2627 componentValues[idx] = value 

2628 

2629 elif len(componentValues) == idx: 

2630 componentValues.append(value) 

2631 self._dynamicNames.addField(idx) 

2632 

2633 else: 

2634 raise error.PyAsn1Error('Component index out of range') 

2635 

2636 self._componentValues = componentValues 

2637 

2638 return self 

2639 

2640 @property 

2641 def isValue(self): 

2642 """Indicate that |ASN.1| object represents ASN.1 value. 

2643 

2644 If *isValue* is :obj:`False` then this object represents just ASN.1 schema. 

2645 

2646 If *isValue* is :obj:`True` then, in addition to its ASN.1 schema features, 

2647 this object can also be used like a Python built-in object (e.g. 

2648 :class:`int`, :class:`str`, :class:`dict` etc.). 

2649 

2650 Returns 

2651 ------- 

2652 : :class:`bool` 

2653 :obj:`False` if object represents just ASN.1 schema. 

2654 :obj:`True` if object represents ASN.1 schema and can be used as a 

2655 normal value. 

2656 

2657 Note 

2658 ---- 

2659 There is an important distinction between PyASN1 schema and value objects. 

2660 The PyASN1 schema objects can only participate in ASN.1 schema-related 

2661 operations (e.g. defining or testing the structure of the data). Most 

2662 obvious uses of ASN.1 schema is to guide serialisation codecs whilst 

2663 encoding/decoding serialised ASN.1 contents. 

2664 

2665 The PyASN1 value objects can **additionally** participate in many operations 

2666 involving regular Python objects (e.g. arithmetic, comprehension etc). 

2667 

2668 It is sufficient for |ASN.1| objects to have all non-optional and non-defaulted 

2669 components being value objects to be considered as a value objects as a whole. 

2670 In other words, even having one or more optional components not turned into 

2671 value objects, |ASN.1| object is still considered as a value object. Defaulted 

2672 components are normally value objects by default. 

2673 """ 

2674 if self._componentValues is noValue: 

2675 return False 

2676 

2677 componentType = self.componentType 

2678 

2679 if componentType: 

2680 for idx, subComponentType in enumerate(componentType.namedTypes): 

2681 if subComponentType.isDefaulted or subComponentType.isOptional: 

2682 continue 

2683 

2684 if not self._componentValues: 

2685 return False 

2686 

2687 componentValue = self._componentValues[idx] 

2688 if componentValue is noValue or not componentValue.isValue: 

2689 return False 

2690 

2691 else: 

2692 for componentValue in self._componentValues: 

2693 if componentValue is noValue or not componentValue.isValue: 

2694 return False 

2695 

2696 return True 

2697 

2698 @property 

2699 def isInconsistent(self): 

2700 """Run necessary checks to ensure |ASN.1| object consistency. 

2701 

2702 Default action is to verify |ASN.1| object against constraints imposed 

2703 by `subtypeSpec`. 

2704 

2705 Raises 

2706 ------ 

2707 :py:class:`~pyasn1.error.PyAsn1tError` on any inconsistencies found 

2708 """ 

2709 if self.componentType is noValue or not self.subtypeSpec: 

2710 return False 

2711 

2712 if self._componentValues is noValue: 

2713 return True 

2714 

2715 mapping = {} 

2716 

2717 for idx, value in enumerate(self._componentValues): 

2718 # Absent fields are not in the mapping 

2719 if value is noValue: 

2720 continue 

2721 

2722 name = self.componentType.getNameByPosition(idx) 

2723 

2724 mapping[name] = value 

2725 

2726 try: 

2727 # Represent Sequence/Set as a bare dict to constraints chain 

2728 self.subtypeSpec(mapping) 

2729 

2730 except error.PyAsn1Error as exc: 

2731 return exc 

2732 

2733 return False 

2734 

2735 def prettyPrint(self, scope=0): 

2736 """Return an object representation string. 

2737 

2738 Returns 

2739 ------- 

2740 : :class:`str` 

2741 Human-friendly object representation. 

2742 """ 

2743 scope += 1 

2744 representation = self.__class__.__name__ + ':\n' 

2745 for idx, componentValue in enumerate(self._componentValues): 

2746 if componentValue is not noValue and componentValue.isValue: 

2747 representation += ' ' * scope 

2748 if self.componentType: 

2749 representation += self.componentType.getNameByPosition(idx) 

2750 else: 

2751 representation += self._dynamicNames.getNameByPosition(idx) 

2752 representation = '%s=%s\n' % ( 

2753 representation, componentValue.prettyPrint(scope) 

2754 ) 

2755 return representation 

2756 

2757 def prettyPrintType(self, scope=0): 

2758 scope += 1 

2759 representation = '%s -> %s {\n' % (self.tagSet, self.__class__.__name__) 

2760 for idx, componentType in enumerate(self.componentType.values() or self._componentValues): 

2761 representation += ' ' * scope 

2762 if self.componentType: 

2763 representation += '"%s"' % self.componentType.getNameByPosition(idx) 

2764 else: 

2765 representation += '"%s"' % self._dynamicNames.getNameByPosition(idx) 

2766 representation = '%s = %s\n' % ( 

2767 representation, componentType.prettyPrintType(scope) 

2768 ) 

2769 return representation + '\n' + ' ' * (scope - 1) + '}' 

2770 

2771 # backward compatibility 

2772 

2773 def setDefaultComponents(self): 

2774 return self 

2775 

2776 def getComponentType(self): 

2777 if self._componentTypeLen: 

2778 return self.componentType 

2779 

2780 def getNameByPosition(self, idx): 

2781 if self._componentTypeLen: 

2782 return self.componentType[idx].name 

2783 

2784class Sequence(SequenceAndSetBase): 

2785 __doc__ = SequenceAndSetBase.__doc__ 

2786 

2787 #: Set (on class, not on instance) or return a 

2788 #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s) 

2789 #: associated with |ASN.1| type. 

2790 tagSet = tag.initTagSet( 

2791 tag.Tag(tag.tagClassUniversal, tag.tagFormatConstructed, 0x10) 

2792 ) 

2793 

2794 #: Set (on class, not on instance) or return a 

2795 #: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection` object 

2796 #: imposing constraints on |ASN.1| type initialization values. 

2797 subtypeSpec = constraint.ConstraintsIntersection() 

2798 

2799 #: Default collection of ASN.1 types of component (e.g. :py:class:`~pyasn1.type.namedtype.NamedType`) 

2800 #: object imposing size constraint on |ASN.1| objects 

2801 componentType = namedtype.NamedTypes() 

2802 

2803 # Disambiguation ASN.1 types identification 

2804 typeId = SequenceAndSetBase.getTypeId() 

2805 

2806 # backward compatibility 

2807 

2808 def getComponentTagMapNearPosition(self, idx): 

2809 if self.componentType: 

2810 return self.componentType.getTagMapNearPosition(idx) 

2811 

2812 def getComponentPositionNearType(self, tagSet, idx): 

2813 if self.componentType: 

2814 return self.componentType.getPositionNearType(tagSet, idx) 

2815 else: 

2816 return idx 

2817 

2818 

2819class Set(SequenceAndSetBase): 

2820 __doc__ = SequenceAndSetBase.__doc__ 

2821 

2822 #: Set (on class, not on instance) or return a 

2823 #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s) 

2824 #: associated with |ASN.1| type. 

2825 tagSet = tag.initTagSet( 

2826 tag.Tag(tag.tagClassUniversal, tag.tagFormatConstructed, 0x11) 

2827 ) 

2828 

2829 #: Default collection of ASN.1 types of component (e.g. :py:class:`~pyasn1.type.namedtype.NamedType`) 

2830 #: object representing ASN.1 type allowed within |ASN.1| type 

2831 componentType = namedtype.NamedTypes() 

2832 

2833 #: Set (on class, not on instance) or return a 

2834 #: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection` object 

2835 #: imposing constraints on |ASN.1| type initialization values. 

2836 subtypeSpec = constraint.ConstraintsIntersection() 

2837 

2838 # Disambiguation ASN.1 types identification 

2839 typeId = SequenceAndSetBase.getTypeId() 

2840 

2841 def getComponent(self, innerFlag=False): 

2842 return self 

2843 

2844 def getComponentByType(self, tagSet, default=noValue, 

2845 instantiate=True, innerFlag=False): 

2846 """Returns |ASN.1| type component by ASN.1 tag. 

2847 

2848 Parameters 

2849 ---------- 

2850 tagSet : :py:class:`~pyasn1.type.tag.TagSet` 

2851 Object representing ASN.1 tags to identify one of 

2852 |ASN.1| object component 

2853 

2854 Keyword Args 

2855 ------------ 

2856 default: :class:`object` 

2857 If set and requested component is a schema object, return the `default` 

2858 object instead of the requested component. 

2859 

2860 instantiate: :class:`bool` 

2861 If :obj:`True` (default), inner component will be automatically 

2862 instantiated. 

2863 If :obj:`False` either existing component or the :class:`noValue` 

2864 object will be returned. 

2865 

2866 Returns 

2867 ------- 

2868 : :py:class:`~pyasn1.type.base.PyAsn1Item` 

2869 a pyasn1 object 

2870 """ 

2871 componentValue = self.getComponentByPosition( 

2872 self.componentType.getPositionByType(tagSet), 

2873 default=default, instantiate=instantiate 

2874 ) 

2875 if innerFlag and isinstance(componentValue, Set): 

2876 # get inner component by inner tagSet 

2877 return componentValue.getComponent(innerFlag=True) 

2878 else: 

2879 # get outer component by inner tagSet 

2880 return componentValue 

2881 

2882 def setComponentByType(self, tagSet, value=noValue, 

2883 verifyConstraints=True, 

2884 matchTags=True, 

2885 matchConstraints=True, 

2886 innerFlag=False): 

2887 """Assign |ASN.1| type component by ASN.1 tag. 

2888 

2889 Parameters 

2890 ---------- 

2891 tagSet : :py:class:`~pyasn1.type.tag.TagSet` 

2892 Object representing ASN.1 tags to identify one of 

2893 |ASN.1| object component 

2894 

2895 Keyword Args 

2896 ------------ 

2897 value: :class:`object` or :py:class:`~pyasn1.type.base.PyAsn1Item` derivative 

2898 A Python value to initialize |ASN.1| component with (if *componentType* is set) 

2899 or ASN.1 value object to assign to |ASN.1| component. 

2900 If `value` is not given, schema object will be set as a component. 

2901 

2902 verifyConstraints : :class:`bool` 

2903 If :obj:`False`, skip constraints validation 

2904 

2905 matchTags: :class:`bool` 

2906 If :obj:`False`, skip component tags matching 

2907 

2908 matchConstraints: :class:`bool` 

2909 If :obj:`False`, skip component constraints matching 

2910 

2911 innerFlag: :class:`bool` 

2912 If :obj:`True`, search for matching *tagSet* recursively. 

2913 

2914 Returns 

2915 ------- 

2916 self 

2917 """ 

2918 idx = self.componentType.getPositionByType(tagSet) 

2919 

2920 if innerFlag: # set inner component by inner tagSet 

2921 componentType = self.componentType.getTypeByPosition(idx) 

2922 

2923 if componentType.tagSet: 

2924 return self.setComponentByPosition( 

2925 idx, value, verifyConstraints, matchTags, matchConstraints 

2926 ) 

2927 else: 

2928 componentType = self.getComponentByPosition(idx) 

2929 return componentType.setComponentByType( 

2930 tagSet, value, verifyConstraints, matchTags, matchConstraints, innerFlag=innerFlag 

2931 ) 

2932 else: # set outer component by inner tagSet 

2933 return self.setComponentByPosition( 

2934 idx, value, verifyConstraints, matchTags, matchConstraints 

2935 ) 

2936 

2937 @property 

2938 def componentTagMap(self): 

2939 if self.componentType: 

2940 return self.componentType.tagMapUnique 

2941 

2942 

2943class Choice(Set): 

2944 """Create |ASN.1| schema or value object. 

2945 

2946 |ASN.1| class is based on :class:`~pyasn1.type.base.ConstructedAsn1Type`, 

2947 its objects are mutable and duck-type Python :class:`list` objects. 

2948 

2949 Keyword Args 

2950 ------------ 

2951 componentType: :py:class:`~pyasn1.type.namedtype.NamedType` 

2952 Object holding named ASN.1 types allowed within this collection 

2953 

2954 tagSet: :py:class:`~pyasn1.type.tag.TagSet` 

2955 Object representing non-default ASN.1 tag(s) 

2956 

2957 subtypeSpec: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection` 

2958 Object representing non-default ASN.1 subtype constraint(s). Constraints 

2959 verification for |ASN.1| type can only occur on explicit 

2960 `.isInconsistent` call. 

2961 

2962 Examples 

2963 -------- 

2964 

2965 .. code-block:: python 

2966 

2967 class Afters(Choice): 

2968 ''' 

2969 ASN.1 specification: 

2970 

2971 Afters ::= CHOICE { 

2972 cheese [0] IA5String, 

2973 dessert [1] IA5String 

2974 } 

2975 ''' 

2976 componentType = NamedTypes( 

2977 NamedType('cheese', IA5String().subtype( 

2978 implicitTag=Tag(tagClassContext, tagFormatSimple, 0) 

2979 ), 

2980 NamedType('dessert', IA5String().subtype( 

2981 implicitTag=Tag(tagClassContext, tagFormatSimple, 1) 

2982 ) 

2983 ) 

2984 

2985 afters = Afters() 

2986 afters['cheese'] = 'Mascarpone' 

2987 """ 

2988 #: Set (on class, not on instance) or return a 

2989 #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s) 

2990 #: associated with |ASN.1| type. 

2991 tagSet = tag.TagSet() # untagged 

2992 

2993 #: Default collection of ASN.1 types of component (e.g. :py:class:`~pyasn1.type.namedtype.NamedType`) 

2994 #: object representing ASN.1 type allowed within |ASN.1| type 

2995 componentType = namedtype.NamedTypes() 

2996 

2997 #: Set (on class, not on instance) or return a 

2998 #: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection` object 

2999 #: imposing constraints on |ASN.1| type initialization values. 

3000 subtypeSpec = constraint.ConstraintsIntersection( 

3001 constraint.ValueSizeConstraint(1, 1) 

3002 ) 

3003 

3004 # Disambiguation ASN.1 types identification 

3005 typeId = Set.getTypeId() 

3006 

3007 _currentIdx = None 

3008 

3009 def __eq__(self, other): 

3010 if self._componentValues: 

3011 return self._componentValues[self._currentIdx] == other 

3012 return NotImplemented 

3013 

3014 def __ne__(self, other): 

3015 if self._componentValues: 

3016 return self._componentValues[self._currentIdx] != other 

3017 return NotImplemented 

3018 

3019 def __lt__(self, other): 

3020 if self._componentValues: 

3021 return self._componentValues[self._currentIdx] < other 

3022 return NotImplemented 

3023 

3024 def __le__(self, other): 

3025 if self._componentValues: 

3026 return self._componentValues[self._currentIdx] <= other 

3027 return NotImplemented 

3028 

3029 def __gt__(self, other): 

3030 if self._componentValues: 

3031 return self._componentValues[self._currentIdx] > other 

3032 return NotImplemented 

3033 

3034 def __ge__(self, other): 

3035 if self._componentValues: 

3036 return self._componentValues[self._currentIdx] >= other 

3037 return NotImplemented 

3038 

3039 def __bool__(self): 

3040 return bool(self._componentValues) 

3041 

3042 def __len__(self): 

3043 return self._currentIdx is not None and 1 or 0 

3044 

3045 def __contains__(self, key): 

3046 if self._currentIdx is None: 

3047 return False 

3048 return key == self.componentType[self._currentIdx].getName() 

3049 

3050 def __iter__(self): 

3051 if self._currentIdx is None: 

3052 raise StopIteration 

3053 yield self.componentType[self._currentIdx].getName() 

3054 

3055 # Python dict protocol 

3056 

3057 def values(self): 

3058 if self._currentIdx is not None: 

3059 yield self._componentValues[self._currentIdx] 

3060 

3061 def keys(self): 

3062 if self._currentIdx is not None: 

3063 yield self.componentType[self._currentIdx].getName() 

3064 

3065 def items(self): 

3066 if self._currentIdx is not None: 

3067 yield self.componentType[self._currentIdx].getName(), self[self._currentIdx] 

3068 

3069 def checkConsistency(self): 

3070 if self._currentIdx is None: 

3071 raise error.PyAsn1Error('Component not chosen') 

3072 

3073 def _cloneComponentValues(self, myClone, cloneValueFlag): 

3074 try: 

3075 component = self.getComponent() 

3076 except error.PyAsn1Error: 

3077 pass 

3078 else: 

3079 if isinstance(component, Choice): 

3080 tagSet = component.effectiveTagSet 

3081 else: 

3082 tagSet = component.tagSet 

3083 if isinstance(component, base.ConstructedAsn1Type): 

3084 myClone.setComponentByType( 

3085 tagSet, component.clone(cloneValueFlag=cloneValueFlag) 

3086 ) 

3087 else: 

3088 myClone.setComponentByType(tagSet, component.clone()) 

3089 

3090 def getComponentByPosition(self, idx, default=noValue, instantiate=True): 

3091 __doc__ = Set.__doc__ 

3092 

3093 if self._currentIdx is None or self._currentIdx != idx: 

3094 return Set.getComponentByPosition(self, idx, default=default, 

3095 instantiate=instantiate) 

3096 

3097 return self._componentValues[idx] 

3098 

3099 def setComponentByPosition(self, idx, value=noValue, 

3100 verifyConstraints=True, 

3101 matchTags=True, 

3102 matchConstraints=True): 

3103 """Assign |ASN.1| type component by position. 

3104 

3105 Equivalent to Python sequence item assignment operation (e.g. `[]`). 

3106 

3107 Parameters 

3108 ---------- 

3109 idx: :class:`int` 

3110 Component index (zero-based). Must either refer to existing 

3111 component or to N+1 component. In the latter case a new component 

3112 type gets instantiated (if *componentType* is set, or given ASN.1 

3113 object is taken otherwise) and appended to the |ASN.1| sequence. 

3114 

3115 Keyword Args 

3116 ------------ 

3117 value: :class:`object` or :py:class:`~pyasn1.type.base.PyAsn1Item` derivative 

3118 A Python value to initialize |ASN.1| component with (if *componentType* is set) 

3119 or ASN.1 value object to assign to |ASN.1| component. Once a new value is 

3120 set to *idx* component, previous value is dropped. 

3121 If `value` is not given, schema object will be set as a component. 

3122 

3123 verifyConstraints : :class:`bool` 

3124 If :obj:`False`, skip constraints validation 

3125 

3126 matchTags: :class:`bool` 

3127 If :obj:`False`, skip component tags matching 

3128 

3129 matchConstraints: :class:`bool` 

3130 If :obj:`False`, skip component constraints matching 

3131 

3132 Returns 

3133 ------- 

3134 self 

3135 """ 

3136 oldIdx = self._currentIdx 

3137 Set.setComponentByPosition(self, idx, value, verifyConstraints, matchTags, matchConstraints) 

3138 self._currentIdx = idx 

3139 if oldIdx is not None and oldIdx != idx: 

3140 self._componentValues[oldIdx] = noValue 

3141 return self 

3142 

3143 @property 

3144 def effectiveTagSet(self): 

3145 """Return a :class:`~pyasn1.type.tag.TagSet` object of the currently initialized component or self (if |ASN.1| is tagged).""" 

3146 if self.tagSet: 

3147 return self.tagSet 

3148 else: 

3149 component = self.getComponent() 

3150 return component.effectiveTagSet 

3151 

3152 @property 

3153 def tagMap(self): 

3154 """"Return a :class:`~pyasn1.type.tagmap.TagMap` object mapping 

3155 ASN.1 tags to ASN.1 objects contained within callee. 

3156 """ 

3157 if self.tagSet: 

3158 return Set.tagMap.fget(self) 

3159 else: 

3160 return self.componentType.tagMapUnique 

3161 

3162 def getComponent(self, innerFlag=False): 

3163 """Return currently assigned component of the |ASN.1| object. 

3164 

3165 Returns 

3166 ------- 

3167 : :py:class:`~pyasn1.type.base.PyAsn1Item` 

3168 a PyASN1 object 

3169 """ 

3170 if self._currentIdx is None: 

3171 raise error.PyAsn1Error('Component not chosen') 

3172 else: 

3173 c = self._componentValues[self._currentIdx] 

3174 if innerFlag and isinstance(c, Choice): 

3175 return c.getComponent(innerFlag) 

3176 else: 

3177 return c 

3178 

3179 def getName(self, innerFlag=False): 

3180 """Return the name of currently assigned component of the |ASN.1| object. 

3181 

3182 Returns 

3183 ------- 

3184 : :py:class:`str` 

3185 |ASN.1| component name 

3186 """ 

3187 if self._currentIdx is None: 

3188 raise error.PyAsn1Error('Component not chosen') 

3189 else: 

3190 if innerFlag: 

3191 c = self._componentValues[self._currentIdx] 

3192 if isinstance(c, Choice): 

3193 return c.getName(innerFlag) 

3194 return self.componentType.getNameByPosition(self._currentIdx) 

3195 

3196 @property 

3197 def isValue(self): 

3198 """Indicate that |ASN.1| object represents ASN.1 value. 

3199 

3200 If *isValue* is :obj:`False` then this object represents just ASN.1 schema. 

3201 

3202 If *isValue* is :obj:`True` then, in addition to its ASN.1 schema features, 

3203 this object can also be used like a Python built-in object (e.g. 

3204 :class:`int`, :class:`str`, :class:`dict` etc.). 

3205 

3206 Returns 

3207 ------- 

3208 : :class:`bool` 

3209 :obj:`False` if object represents just ASN.1 schema. 

3210 :obj:`True` if object represents ASN.1 schema and can be used as a normal 

3211 value. 

3212 

3213 Note 

3214 ---- 

3215 There is an important distinction between PyASN1 schema and value objects. 

3216 The PyASN1 schema objects can only participate in ASN.1 schema-related 

3217 operations (e.g. defining or testing the structure of the data). Most 

3218 obvious uses of ASN.1 schema is to guide serialisation codecs whilst 

3219 encoding/decoding serialised ASN.1 contents. 

3220 

3221 The PyASN1 value objects can **additionally** participate in many operations 

3222 involving regular Python objects (e.g. arithmetic, comprehension etc). 

3223 """ 

3224 if self._currentIdx is None: 

3225 return False 

3226 

3227 componentValue = self._componentValues[self._currentIdx] 

3228 

3229 return componentValue is not noValue and componentValue.isValue 

3230 

3231 def clear(self): 

3232 self._currentIdx = None 

3233 return Set.clear(self) 

3234 

3235 # compatibility stubs 

3236 

3237 def getMinTagSet(self): 

3238 return self.minTagSet 

3239 

3240 

3241class Any(OctetString): 

3242 """Create |ASN.1| schema or value object. 

3243 

3244 |ASN.1| class is based on :class:`~pyasn1.type.base.SimpleAsn1Type`, 

3245 its objects are immutable and duck-type :class:`bytes`. 

3246 When used in Unicode context, |ASN.1| type assumes 

3247 "|encoding|" serialisation. 

3248 

3249 Keyword Args 

3250 ------------ 

3251 value: :class:`unicode`, :class:`str`, :class:`bytes` or |ASN.1| object 

3252 :class:`bytes`, alternatively :class:`str` 

3253 representing character string to be serialised into octets (note 

3254 `encoding` parameter) or |ASN.1| object. 

3255 If `value` is not given, schema object will be created. 

3256 

3257 tagSet: :py:class:`~pyasn1.type.tag.TagSet` 

3258 Object representing non-default ASN.1 tag(s) 

3259 

3260 subtypeSpec: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection` 

3261 Object representing non-default ASN.1 subtype constraint(s). Constraints 

3262 verification for |ASN.1| type occurs automatically on object 

3263 instantiation. 

3264 

3265 encoding: :py:class:`str` 

3266 Unicode codec ID to encode/decode 

3267 :class:`str` the payload when |ASN.1| object is used 

3268 in text string context. 

3269 

3270 binValue: :py:class:`str` 

3271 Binary string initializer to use instead of the *value*. 

3272 Example: '10110011'. 

3273 

3274 hexValue: :py:class:`str` 

3275 Hexadecimal string initializer to use instead of the *value*. 

3276 Example: 'DEADBEEF'. 

3277 

3278 Raises 

3279 ------ 

3280 ~pyasn1.error.ValueConstraintError, ~pyasn1.error.PyAsn1Error 

3281 On constraint violation or bad initializer. 

3282 

3283 Examples 

3284 -------- 

3285 .. code-block:: python 

3286 

3287 class Error(Sequence): 

3288 ''' 

3289 ASN.1 specification: 

3290 

3291 Error ::= SEQUENCE { 

3292 code INTEGER, 

3293 parameter ANY DEFINED BY code -- Either INTEGER or REAL 

3294 } 

3295 ''' 

3296 componentType=NamedTypes( 

3297 NamedType('code', Integer()), 

3298 NamedType('parameter', Any(), 

3299 openType=OpenType('code', {1: Integer(), 

3300 2: Real()})) 

3301 ) 

3302 

3303 error = Error() 

3304 error['code'] = 1 

3305 error['parameter'] = Integer(1234) 

3306 """ 

3307 #: Set (on class, not on instance) or return a 

3308 #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s) 

3309 #: associated with |ASN.1| type. 

3310 tagSet = tag.TagSet() # untagged 

3311 

3312 #: Set (on class, not on instance) or return a 

3313 #: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection` object 

3314 #: imposing constraints on |ASN.1| type initialization values. 

3315 subtypeSpec = constraint.ConstraintsIntersection() 

3316 

3317 # Disambiguation ASN.1 types identification 

3318 typeId = OctetString.getTypeId() 

3319 

3320 @property 

3321 def tagMap(self): 

3322 """"Return a :class:`~pyasn1.type.tagmap.TagMap` object mapping 

3323 ASN.1 tags to ASN.1 objects contained within callee. 

3324 """ 

3325 try: 

3326 return self._tagMap 

3327 

3328 except AttributeError: 

3329 self._tagMap = tagmap.TagMap( 

3330 {self.tagSet: self}, 

3331 {eoo.endOfOctets.tagSet: eoo.endOfOctets}, 

3332 self 

3333 ) 

3334 

3335 return self._tagMap 

3336 

3337# XXX 

3338# coercion rules?