Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/pip/_vendor/pyparsing/results.py: 53%

290 statements  

« prev     ^ index     » next       coverage.py v7.4.3, created at 2024-02-26 06:33 +0000

1# results.py 

2from collections.abc import ( 

3 MutableMapping, 

4 Mapping, 

5 MutableSequence, 

6 Iterator, 

7 Sequence, 

8 Container, 

9) 

10import pprint 

11from typing import Tuple, Any, Dict, Set, List 

12 

13str_type: Tuple[type, ...] = (str, bytes) 

14_generator_type = type((_ for _ in ())) 

15 

16 

17class _ParseResultsWithOffset: 

18 tup: Tuple["ParseResults", int] 

19 __slots__ = ["tup"] 

20 

21 def __init__(self, p1: "ParseResults", p2: int): 

22 self.tup: Tuple[ParseResults, int] = (p1, p2) 

23 

24 def __getitem__(self, i): 

25 return self.tup[i] 

26 

27 def __getstate__(self): 

28 return self.tup 

29 

30 def __setstate__(self, *args): 

31 self.tup = args[0] 

32 

33 

34class ParseResults: 

35 """Structured parse results, to provide multiple means of access to 

36 the parsed data: 

37 

38 - as a list (``len(results)``) 

39 - by list index (``results[0], results[1]``, etc.) 

40 - by attribute (``results.<results_name>`` - see :class:`ParserElement.set_results_name`) 

41 

42 Example:: 

43 

44 integer = Word(nums) 

45 date_str = (integer.set_results_name("year") + '/' 

46 + integer.set_results_name("month") + '/' 

47 + integer.set_results_name("day")) 

48 # equivalent form: 

49 # date_str = (integer("year") + '/' 

50 # + integer("month") + '/' 

51 # + integer("day")) 

52 

53 # parse_string returns a ParseResults object 

54 result = date_str.parse_string("1999/12/31") 

55 

56 def test(s, fn=repr): 

57 print(f"{s} -> {fn(eval(s))}") 

58 test("list(result)") 

59 test("result[0]") 

60 test("result['month']") 

61 test("result.day") 

62 test("'month' in result") 

63 test("'minutes' in result") 

64 test("result.dump()", str) 

65 

66 prints:: 

67 

68 list(result) -> ['1999', '/', '12', '/', '31'] 

69 result[0] -> '1999' 

70 result['month'] -> '12' 

71 result.day -> '31' 

72 'month' in result -> True 

73 'minutes' in result -> False 

74 result.dump() -> ['1999', '/', '12', '/', '31'] 

75 - day: '31' 

76 - month: '12' 

77 - year: '1999' 

78 """ 

79 

80 _null_values: Tuple[Any, ...] = (None, [], ()) 

81 

82 _name: str 

83 _parent: "ParseResults" 

84 _all_names: Set[str] 

85 _modal: bool 

86 _toklist: List[Any] 

87 _tokdict: Dict[str, Any] 

88 

89 __slots__ = ( 

90 "_name", 

91 "_parent", 

92 "_all_names", 

93 "_modal", 

94 "_toklist", 

95 "_tokdict", 

96 ) 

97 

98 class List(list): 

99 """ 

100 Simple wrapper class to distinguish parsed list results that should be preserved 

101 as actual Python lists, instead of being converted to :class:`ParseResults`:: 

102 

103 LBRACK, RBRACK = map(pp.Suppress, "[]") 

104 element = pp.Forward() 

105 item = ppc.integer 

106 element_list = LBRACK + pp.DelimitedList(element) + RBRACK 

107 

108 # add parse actions to convert from ParseResults to actual Python collection types 

109 def as_python_list(t): 

110 return pp.ParseResults.List(t.as_list()) 

111 element_list.add_parse_action(as_python_list) 

112 

113 element <<= item | element_list 

114 

115 element.run_tests(''' 

116 100 

117 [2,3,4] 

118 [[2, 1],3,4] 

119 [(2, 1),3,4] 

120 (2,3,4) 

121 ''', post_parse=lambda s, r: (r[0], type(r[0]))) 

122 

123 prints:: 

124 

125 100 

126 (100, <class 'int'>) 

127 

128 [2,3,4] 

129 ([2, 3, 4], <class 'list'>) 

130 

131 [[2, 1],3,4] 

132 ([[2, 1], 3, 4], <class 'list'>) 

133 

134 (Used internally by :class:`Group` when `aslist=True`.) 

135 """ 

136 

137 def __new__(cls, contained=None): 

138 if contained is None: 

139 contained = [] 

140 

141 if not isinstance(contained, list): 

142 raise TypeError( 

143 f"{cls.__name__} may only be constructed with a list, not {type(contained).__name__}" 

144 ) 

145 

146 return list.__new__(cls) 

147 

148 def __new__(cls, toklist=None, name=None, **kwargs): 

149 if isinstance(toklist, ParseResults): 

150 return toklist 

151 self = object.__new__(cls) 

152 self._name = None 

153 self._parent = None 

154 self._all_names = set() 

155 

156 if toklist is None: 

157 self._toklist = [] 

158 elif isinstance(toklist, (list, _generator_type)): 

159 self._toklist = ( 

160 [toklist[:]] 

161 if isinstance(toklist, ParseResults.List) 

162 else list(toklist) 

163 ) 

164 else: 

165 self._toklist = [toklist] 

166 self._tokdict = dict() 

167 return self 

168 

169 # Performance tuning: we construct a *lot* of these, so keep this 

170 # constructor as small and fast as possible 

171 def __init__( 

172 self, toklist=None, name=None, asList=True, modal=True, isinstance=isinstance 

173 ): 

174 self._tokdict: Dict[str, _ParseResultsWithOffset] 

175 self._modal = modal 

176 if name is not None and name != "": 

177 if isinstance(name, int): 

178 name = str(name) 

179 if not modal: 

180 self._all_names = {name} 

181 self._name = name 

182 if toklist not in self._null_values: 

183 if isinstance(toklist, (str_type, type)): 

184 toklist = [toklist] 

185 if asList: 

186 if isinstance(toklist, ParseResults): 

187 self[name] = _ParseResultsWithOffset( 

188 ParseResults(toklist._toklist), 0 

189 ) 

190 else: 

191 self[name] = _ParseResultsWithOffset( 

192 ParseResults(toklist[0]), 0 

193 ) 

194 self[name]._name = name 

195 else: 

196 try: 

197 self[name] = toklist[0] 

198 except (KeyError, TypeError, IndexError): 

199 if toklist is not self: 

200 self[name] = toklist 

201 else: 

202 self._name = name 

203 

204 def __getitem__(self, i): 

205 if isinstance(i, (int, slice)): 

206 return self._toklist[i] 

207 else: 

208 if i not in self._all_names: 

209 return self._tokdict[i][-1][0] 

210 else: 

211 return ParseResults([v[0] for v in self._tokdict[i]]) 

212 

213 def __setitem__(self, k, v, isinstance=isinstance): 

214 if isinstance(v, _ParseResultsWithOffset): 

215 self._tokdict[k] = self._tokdict.get(k, list()) + [v] 

216 sub = v[0] 

217 elif isinstance(k, (int, slice)): 

218 self._toklist[k] = v 

219 sub = v 

220 else: 

221 self._tokdict[k] = self._tokdict.get(k, list()) + [ 

222 _ParseResultsWithOffset(v, 0) 

223 ] 

224 sub = v 

225 if isinstance(sub, ParseResults): 

226 sub._parent = self 

227 

228 def __delitem__(self, i): 

229 if isinstance(i, (int, slice)): 

230 mylen = len(self._toklist) 

231 del self._toklist[i] 

232 

233 # convert int to slice 

234 if isinstance(i, int): 

235 if i < 0: 

236 i += mylen 

237 i = slice(i, i + 1) 

238 # get removed indices 

239 removed = list(range(*i.indices(mylen))) 

240 removed.reverse() 

241 # fixup indices in token dictionary 

242 for name, occurrences in self._tokdict.items(): 

243 for j in removed: 

244 for k, (value, position) in enumerate(occurrences): 

245 occurrences[k] = _ParseResultsWithOffset( 

246 value, position - (position > j) 

247 ) 

248 else: 

249 del self._tokdict[i] 

250 

251 def __contains__(self, k) -> bool: 

252 return k in self._tokdict 

253 

254 def __len__(self) -> int: 

255 return len(self._toklist) 

256 

257 def __bool__(self) -> bool: 

258 return not not (self._toklist or self._tokdict) 

259 

260 def __iter__(self) -> Iterator: 

261 return iter(self._toklist) 

262 

263 def __reversed__(self) -> Iterator: 

264 return iter(self._toklist[::-1]) 

265 

266 def keys(self): 

267 return iter(self._tokdict) 

268 

269 def values(self): 

270 return (self[k] for k in self.keys()) 

271 

272 def items(self): 

273 return ((k, self[k]) for k in self.keys()) 

274 

275 def haskeys(self) -> bool: 

276 """ 

277 Since ``keys()`` returns an iterator, this method is helpful in bypassing 

278 code that looks for the existence of any defined results names.""" 

279 return not not self._tokdict 

280 

281 def pop(self, *args, **kwargs): 

282 """ 

283 Removes and returns item at specified index (default= ``last``). 

284 Supports both ``list`` and ``dict`` semantics for ``pop()``. If 

285 passed no argument or an integer argument, it will use ``list`` 

286 semantics and pop tokens from the list of parsed tokens. If passed 

287 a non-integer argument (most likely a string), it will use ``dict`` 

288 semantics and pop the corresponding value from any defined results 

289 names. A second default return value argument is supported, just as in 

290 ``dict.pop()``. 

291 

292 Example:: 

293 

294 numlist = Word(nums)[...] 

295 print(numlist.parse_string("0 123 321")) # -> ['0', '123', '321'] 

296 

297 def remove_first(tokens): 

298 tokens.pop(0) 

299 numlist.add_parse_action(remove_first) 

300 print(numlist.parse_string("0 123 321")) # -> ['123', '321'] 

301 

302 label = Word(alphas) 

303 patt = label("LABEL") + Word(nums)[1, ...] 

304 print(patt.parse_string("AAB 123 321").dump()) 

305 

306 # Use pop() in a parse action to remove named result (note that corresponding value is not 

307 # removed from list form of results) 

308 def remove_LABEL(tokens): 

309 tokens.pop("LABEL") 

310 return tokens 

311 patt.add_parse_action(remove_LABEL) 

312 print(patt.parse_string("AAB 123 321").dump()) 

313 

314 prints:: 

315 

316 ['AAB', '123', '321'] 

317 - LABEL: 'AAB' 

318 

319 ['AAB', '123', '321'] 

320 """ 

321 if not args: 

322 args = [-1] 

323 for k, v in kwargs.items(): 

324 if k == "default": 

325 args = (args[0], v) 

326 else: 

327 raise TypeError(f"pop() got an unexpected keyword argument {k!r}") 

328 if isinstance(args[0], int) or len(args) == 1 or args[0] in self: 

329 index = args[0] 

330 ret = self[index] 

331 del self[index] 

332 return ret 

333 else: 

334 defaultvalue = args[1] 

335 return defaultvalue 

336 

337 def get(self, key, default_value=None): 

338 """ 

339 Returns named result matching the given key, or if there is no 

340 such name, then returns the given ``default_value`` or ``None`` if no 

341 ``default_value`` is specified. 

342 

343 Similar to ``dict.get()``. 

344 

345 Example:: 

346 

347 integer = Word(nums) 

348 date_str = integer("year") + '/' + integer("month") + '/' + integer("day") 

349 

350 result = date_str.parse_string("1999/12/31") 

351 print(result.get("year")) # -> '1999' 

352 print(result.get("hour", "not specified")) # -> 'not specified' 

353 print(result.get("hour")) # -> None 

354 """ 

355 if key in self: 

356 return self[key] 

357 else: 

358 return default_value 

359 

360 def insert(self, index, ins_string): 

361 """ 

362 Inserts new element at location index in the list of parsed tokens. 

363 

364 Similar to ``list.insert()``. 

365 

366 Example:: 

367 

368 numlist = Word(nums)[...] 

369 print(numlist.parse_string("0 123 321")) # -> ['0', '123', '321'] 

370 

371 # use a parse action to insert the parse location in the front of the parsed results 

372 def insert_locn(locn, tokens): 

373 tokens.insert(0, locn) 

374 numlist.add_parse_action(insert_locn) 

375 print(numlist.parse_string("0 123 321")) # -> [0, '0', '123', '321'] 

376 """ 

377 self._toklist.insert(index, ins_string) 

378 # fixup indices in token dictionary 

379 for name, occurrences in self._tokdict.items(): 

380 for k, (value, position) in enumerate(occurrences): 

381 occurrences[k] = _ParseResultsWithOffset( 

382 value, position + (position > index) 

383 ) 

384 

385 def append(self, item): 

386 """ 

387 Add single element to end of ``ParseResults`` list of elements. 

388 

389 Example:: 

390 

391 numlist = Word(nums)[...] 

392 print(numlist.parse_string("0 123 321")) # -> ['0', '123', '321'] 

393 

394 # use a parse action to compute the sum of the parsed integers, and add it to the end 

395 def append_sum(tokens): 

396 tokens.append(sum(map(int, tokens))) 

397 numlist.add_parse_action(append_sum) 

398 print(numlist.parse_string("0 123 321")) # -> ['0', '123', '321', 444] 

399 """ 

400 self._toklist.append(item) 

401 

402 def extend(self, itemseq): 

403 """ 

404 Add sequence of elements to end of ``ParseResults`` list of elements. 

405 

406 Example:: 

407 

408 patt = Word(alphas)[1, ...] 

409 

410 # use a parse action to append the reverse of the matched strings, to make a palindrome 

411 def make_palindrome(tokens): 

412 tokens.extend(reversed([t[::-1] for t in tokens])) 

413 return ''.join(tokens) 

414 patt.add_parse_action(make_palindrome) 

415 print(patt.parse_string("lskdj sdlkjf lksd")) # -> 'lskdjsdlkjflksddsklfjkldsjdksl' 

416 """ 

417 if isinstance(itemseq, ParseResults): 

418 self.__iadd__(itemseq) 

419 else: 

420 self._toklist.extend(itemseq) 

421 

422 def clear(self): 

423 """ 

424 Clear all elements and results names. 

425 """ 

426 del self._toklist[:] 

427 self._tokdict.clear() 

428 

429 def __getattr__(self, name): 

430 try: 

431 return self[name] 

432 except KeyError: 

433 if name.startswith("__"): 

434 raise AttributeError(name) 

435 return "" 

436 

437 def __add__(self, other: "ParseResults") -> "ParseResults": 

438 ret = self.copy() 

439 ret += other 

440 return ret 

441 

442 def __iadd__(self, other: "ParseResults") -> "ParseResults": 

443 if not other: 

444 return self 

445 

446 if other._tokdict: 

447 offset = len(self._toklist) 

448 addoffset = lambda a: offset if a < 0 else a + offset 

449 otheritems = other._tokdict.items() 

450 otherdictitems = [ 

451 (k, _ParseResultsWithOffset(v[0], addoffset(v[1]))) 

452 for k, vlist in otheritems 

453 for v in vlist 

454 ] 

455 for k, v in otherdictitems: 

456 self[k] = v 

457 if isinstance(v[0], ParseResults): 

458 v[0]._parent = self 

459 

460 self._toklist += other._toklist 

461 self._all_names |= other._all_names 

462 return self 

463 

464 def __radd__(self, other) -> "ParseResults": 

465 if isinstance(other, int) and other == 0: 

466 # useful for merging many ParseResults using sum() builtin 

467 return self.copy() 

468 else: 

469 # this may raise a TypeError - so be it 

470 return other + self 

471 

472 def __repr__(self) -> str: 

473 return f"{type(self).__name__}({self._toklist!r}, {self.as_dict()})" 

474 

475 def __str__(self) -> str: 

476 return ( 

477 "[" 

478 + ", ".join( 

479 [ 

480 str(i) if isinstance(i, ParseResults) else repr(i) 

481 for i in self._toklist 

482 ] 

483 ) 

484 + "]" 

485 ) 

486 

487 def _asStringList(self, sep=""): 

488 out = [] 

489 for item in self._toklist: 

490 if out and sep: 

491 out.append(sep) 

492 if isinstance(item, ParseResults): 

493 out += item._asStringList() 

494 else: 

495 out.append(str(item)) 

496 return out 

497 

498 def as_list(self) -> list: 

499 """ 

500 Returns the parse results as a nested list of matching tokens, all converted to strings. 

501 

502 Example:: 

503 

504 patt = Word(alphas)[1, ...] 

505 result = patt.parse_string("sldkj lsdkj sldkj") 

506 # even though the result prints in string-like form, it is actually a pyparsing ParseResults 

507 print(type(result), result) # -> <class 'pyparsing.ParseResults'> ['sldkj', 'lsdkj', 'sldkj'] 

508 

509 # Use as_list() to create an actual list 

510 result_list = result.as_list() 

511 print(type(result_list), result_list) # -> <class 'list'> ['sldkj', 'lsdkj', 'sldkj'] 

512 """ 

513 return [ 

514 res.as_list() if isinstance(res, ParseResults) else res 

515 for res in self._toklist 

516 ] 

517 

518 def as_dict(self) -> dict: 

519 """ 

520 Returns the named parse results as a nested dictionary. 

521 

522 Example:: 

523 

524 integer = Word(nums) 

525 date_str = integer("year") + '/' + integer("month") + '/' + integer("day") 

526 

527 result = date_str.parse_string('12/31/1999') 

528 print(type(result), repr(result)) # -> <class 'pyparsing.ParseResults'> (['12', '/', '31', '/', '1999'], {'day': [('1999', 4)], 'year': [('12', 0)], 'month': [('31', 2)]}) 

529 

530 result_dict = result.as_dict() 

531 print(type(result_dict), repr(result_dict)) # -> <class 'dict'> {'day': '1999', 'year': '12', 'month': '31'} 

532 

533 # even though a ParseResults supports dict-like access, sometime you just need to have a dict 

534 import json 

535 print(json.dumps(result)) # -> Exception: TypeError: ... is not JSON serializable 

536 print(json.dumps(result.as_dict())) # -> {"month": "31", "day": "1999", "year": "12"} 

537 """ 

538 

539 def to_item(obj): 

540 if isinstance(obj, ParseResults): 

541 return obj.as_dict() if obj.haskeys() else [to_item(v) for v in obj] 

542 else: 

543 return obj 

544 

545 return dict((k, to_item(v)) for k, v in self.items()) 

546 

547 def copy(self) -> "ParseResults": 

548 """ 

549 Returns a new shallow copy of a :class:`ParseResults` object. `ParseResults` 

550 items contained within the source are shared with the copy. Use 

551 :class:`ParseResults.deepcopy()` to create a copy with its own separate 

552 content values. 

553 """ 

554 ret = ParseResults(self._toklist) 

555 ret._tokdict = self._tokdict.copy() 

556 ret._parent = self._parent 

557 ret._all_names |= self._all_names 

558 ret._name = self._name 

559 return ret 

560 

561 def deepcopy(self) -> "ParseResults": 

562 """ 

563 Returns a new deep copy of a :class:`ParseResults` object. 

564 """ 

565 ret = self.copy() 

566 # replace values with copies if they are of known mutable types 

567 for i, obj in enumerate(self._toklist): 

568 if isinstance(obj, ParseResults): 

569 self._toklist[i] = obj.deepcopy() 

570 elif isinstance(obj, (str, bytes)): 

571 pass 

572 elif isinstance(obj, MutableMapping): 

573 self._toklist[i] = dest = type(obj)() 

574 for k, v in obj.items(): 

575 dest[k] = v.deepcopy() if isinstance(v, ParseResults) else v 

576 elif isinstance(obj, Container): 

577 self._toklist[i] = type(obj)( 

578 v.deepcopy() if isinstance(v, ParseResults) else v for v in obj 

579 ) 

580 return ret 

581 

582 def get_name(self): 

583 r""" 

584 Returns the results name for this token expression. Useful when several 

585 different expressions might match at a particular location. 

586 

587 Example:: 

588 

589 integer = Word(nums) 

590 ssn_expr = Regex(r"\d\d\d-\d\d-\d\d\d\d") 

591 house_number_expr = Suppress('#') + Word(nums, alphanums) 

592 user_data = (Group(house_number_expr)("house_number") 

593 | Group(ssn_expr)("ssn") 

594 | Group(integer)("age")) 

595 user_info = user_data[1, ...] 

596 

597 result = user_info.parse_string("22 111-22-3333 #221B") 

598 for item in result: 

599 print(item.get_name(), ':', item[0]) 

600 

601 prints:: 

602 

603 age : 22 

604 ssn : 111-22-3333 

605 house_number : 221B 

606 """ 

607 if self._name: 

608 return self._name 

609 elif self._parent: 

610 par: "ParseResults" = self._parent 

611 parent_tokdict_items = par._tokdict.items() 

612 return next( 

613 ( 

614 k 

615 for k, vlist in parent_tokdict_items 

616 for v, loc in vlist 

617 if v is self 

618 ), 

619 None, 

620 ) 

621 elif ( 

622 len(self) == 1 

623 and len(self._tokdict) == 1 

624 and next(iter(self._tokdict.values()))[0][1] in (0, -1) 

625 ): 

626 return next(iter(self._tokdict.keys())) 

627 else: 

628 return None 

629 

630 def dump(self, indent="", full=True, include_list=True, _depth=0) -> str: 

631 """ 

632 Diagnostic method for listing out the contents of 

633 a :class:`ParseResults`. Accepts an optional ``indent`` argument so 

634 that this string can be embedded in a nested display of other data. 

635 

636 Example:: 

637 

638 integer = Word(nums) 

639 date_str = integer("year") + '/' + integer("month") + '/' + integer("day") 

640 

641 result = date_str.parse_string('1999/12/31') 

642 print(result.dump()) 

643 

644 prints:: 

645 

646 ['1999', '/', '12', '/', '31'] 

647 - day: '31' 

648 - month: '12' 

649 - year: '1999' 

650 """ 

651 out = [] 

652 NL = "\n" 

653 out.append(indent + str(self.as_list()) if include_list else "") 

654 

655 if full: 

656 if self.haskeys(): 

657 items = sorted((str(k), v) for k, v in self.items()) 

658 for k, v in items: 

659 if out: 

660 out.append(NL) 

661 out.append(f"{indent}{(' ' * _depth)}- {k}: ") 

662 if isinstance(v, ParseResults): 

663 if v: 

664 out.append( 

665 v.dump( 

666 indent=indent, 

667 full=full, 

668 include_list=include_list, 

669 _depth=_depth + 1, 

670 ) 

671 ) 

672 else: 

673 out.append(str(v)) 

674 else: 

675 out.append(repr(v)) 

676 if any(isinstance(vv, ParseResults) for vv in self): 

677 v = self 

678 for i, vv in enumerate(v): 

679 if isinstance(vv, ParseResults): 

680 out.append( 

681 "\n{}{}[{}]:\n{}{}{}".format( 

682 indent, 

683 (" " * (_depth)), 

684 i, 

685 indent, 

686 (" " * (_depth + 1)), 

687 vv.dump( 

688 indent=indent, 

689 full=full, 

690 include_list=include_list, 

691 _depth=_depth + 1, 

692 ), 

693 ) 

694 ) 

695 else: 

696 out.append( 

697 "\n%s%s[%d]:\n%s%s%s" 

698 % ( 

699 indent, 

700 (" " * (_depth)), 

701 i, 

702 indent, 

703 (" " * (_depth + 1)), 

704 str(vv), 

705 ) 

706 ) 

707 

708 return "".join(out) 

709 

710 def pprint(self, *args, **kwargs): 

711 """ 

712 Pretty-printer for parsed results as a list, using the 

713 `pprint <https://docs.python.org/3/library/pprint.html>`_ module. 

714 Accepts additional positional or keyword args as defined for 

715 `pprint.pprint <https://docs.python.org/3/library/pprint.html#pprint.pprint>`_ . 

716 

717 Example:: 

718 

719 ident = Word(alphas, alphanums) 

720 num = Word(nums) 

721 func = Forward() 

722 term = ident | num | Group('(' + func + ')') 

723 func <<= ident + Group(Optional(DelimitedList(term))) 

724 result = func.parse_string("fna a,b,(fnb c,d,200),100") 

725 result.pprint(width=40) 

726 

727 prints:: 

728 

729 ['fna', 

730 ['a', 

731 'b', 

732 ['(', 'fnb', ['c', 'd', '200'], ')'], 

733 '100']] 

734 """ 

735 pprint.pprint(self.as_list(), *args, **kwargs) 

736 

737 # add support for pickle protocol 

738 def __getstate__(self): 

739 return ( 

740 self._toklist, 

741 ( 

742 self._tokdict.copy(), 

743 None, 

744 self._all_names, 

745 self._name, 

746 ), 

747 ) 

748 

749 def __setstate__(self, state): 

750 self._toklist, (self._tokdict, par, inAccumNames, self._name) = state 

751 self._all_names = set(inAccumNames) 

752 self._parent = None 

753 

754 def __getnewargs__(self): 

755 return self._toklist, self._name 

756 

757 def __dir__(self): 

758 return dir(type(self)) + list(self.keys()) 

759 

760 @classmethod 

761 def from_dict(cls, other, name=None) -> "ParseResults": 

762 """ 

763 Helper classmethod to construct a ``ParseResults`` from a ``dict``, preserving the 

764 name-value relations as results names. If an optional ``name`` argument is 

765 given, a nested ``ParseResults`` will be returned. 

766 """ 

767 

768 def is_iterable(obj): 

769 try: 

770 iter(obj) 

771 except Exception: 

772 return False 

773 # str's are iterable, but in pyparsing, we don't want to iterate over them 

774 else: 

775 return not isinstance(obj, str_type) 

776 

777 ret = cls([]) 

778 for k, v in other.items(): 

779 if isinstance(v, Mapping): 

780 ret += cls.from_dict(v, name=k) 

781 else: 

782 ret += cls([v], name=k, asList=is_iterable(v)) 

783 if name is not None: 

784 ret = cls([ret], name=name) 

785 return ret 

786 

787 asList = as_list 

788 """Deprecated - use :class:`as_list`""" 

789 asDict = as_dict 

790 """Deprecated - use :class:`as_dict`""" 

791 getName = get_name 

792 """Deprecated - use :class:`get_name`""" 

793 

794 

795MutableMapping.register(ParseResults) 

796MutableSequence.register(ParseResults)