Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/pyparsing/results.py: 41%

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

316 statements  

1# results.py 

2 

3from __future__ import annotations 

4 

5import collections 

6from collections.abc import ( 

7 MutableMapping, 

8 Mapping, 

9 MutableSequence, 

10 Iterator, 

11 Iterable, 

12) 

13import pprint 

14from typing import Any 

15 

16from .util import replaced_by_pep8 

17 

18 

19str_type: tuple[type, ...] = (str, bytes) 

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

21 

22 

23class _ParseResultsWithOffset: 

24 tup: tuple[ParseResults, int] 

25 __slots__ = ["tup"] 

26 

27 def __init__(self, p1: ParseResults, p2: int) -> None: 

28 self.tup: tuple[ParseResults, int] = (p1, p2) 

29 

30 def __getitem__(self, i): 

31 return self.tup[i] 

32 

33 def __getstate__(self): 

34 return self.tup 

35 

36 def __setstate__(self, *args): 

37 self.tup = args[0] 

38 

39 

40class ParseResults: 

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

42 the parsed data: 

43 

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

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

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

47 

48 Example: 

49 

50 .. testcode:: 

51 

52 integer = Word(nums) 

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

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

55 + integer.set_results_name("day")) 

56 # equivalent form: 

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

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

59 # + integer("day")) 

60 

61 # parse_string returns a ParseResults object 

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

63 

64 def test(s, fn=repr): 

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

66 

67 test("list(result)") 

68 test("result[0]") 

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

70 test("result.day") 

71 test("'month' in result") 

72 test("'minutes' in result") 

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

74 

75 prints: 

76 

77 .. testoutput:: 

78 

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

80 result[0] -> '1999' 

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

82 result.day -> '31' 

83 'month' in result -> True 

84 'minutes' in result -> False 

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

86 - day: '31' 

87 - month: '12' 

88 - year: '1999' 

89 

90 """ 

91 

92 _null_values: tuple[Any, ...] = (None, [], ()) 

93 

94 _name: str 

95 _parent: ParseResults 

96 _all_names: set[str] 

97 _modal: bool 

98 _toklist: list[Any] 

99 _tokdict: dict[str, Any] 

100 

101 __slots__ = ( 

102 "_name", 

103 "_parent", 

104 "_all_names", 

105 "_modal", 

106 "_toklist", 

107 "_tokdict", 

108 ) 

109 

110 class List(list): 

111 """ 

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

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

114 

115 .. testcode:: 

116 

117 import pyparsing as pp 

118 ppc = pp.common 

119 

120 LBRACK, RBRACK, LPAR, RPAR = pp.Suppress.using_each("[]()") 

121 element = pp.Forward() 

122 item = ppc.integer 

123 item_list = pp.DelimitedList(element) 

124 element_list = LBRACK + item_list + RBRACK | LPAR + item_list + RPAR 

125 element <<= item | element_list 

126 

127 # add parse action to convert from ParseResults 

128 # to actual Python collection types 

129 @element_list.add_parse_action 

130 def as_python_list(t): 

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

132 

133 element.run_tests(''' 

134 100 

135 [2,3,4] 

136 [[2, 1],3,4] 

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

138 (2,3,4) 

139 ([2, 3], 4) 

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

141 ) 

142 

143 prints: 

144 

145 .. testoutput:: 

146 :options: +NORMALIZE_WHITESPACE 

147 

148 

149 100 

150 (100, <class 'int'>) 

151 

152 [2,3,4] 

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

154 

155 [[2, 1],3,4] 

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

157 

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

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

160 

161 (2,3,4) 

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

163 

164 ([2, 3], 4) 

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

166 

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

168 """ 

169 

170 def __new__(cls, contained=None): 

171 if contained is None: 

172 contained = [] 

173 

174 if not isinstance(contained, list): 

175 raise TypeError( 

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

177 ) 

178 

179 return list.__new__(cls) 

180 

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

182 if isinstance(toklist, ParseResults): 

183 return toklist 

184 self = object.__new__(cls) 

185 self._name = None 

186 self._parent = None 

187 self._all_names = set() 

188 

189 if toklist is None: 

190 self._toklist = [] 

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

192 self._toklist = ( 

193 [toklist[:]] 

194 if isinstance(toklist, ParseResults.List) 

195 else list(toklist) 

196 ) 

197 else: 

198 self._toklist = [toklist] 

199 self._tokdict = dict() 

200 return self 

201 

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

203 # constructor as small and fast as possible 

204 def __init__( 

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

206 ) -> None: 

207 self._tokdict: dict[str, _ParseResultsWithOffset] 

208 self._modal = modal 

209 

210 if name is None or name == "": 

211 return 

212 

213 if isinstance(name, int): 

214 name = str(name) 

215 

216 if not modal: 

217 self._all_names = {name} 

218 

219 self._name = name 

220 

221 if toklist in self._null_values: 

222 return 

223 

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

225 toklist = [toklist] 

226 

227 if asList: 

228 if isinstance(toklist, ParseResults): 

229 self[name] = _ParseResultsWithOffset(ParseResults(toklist._toklist), 0) 

230 else: 

231 self[name] = _ParseResultsWithOffset(ParseResults(toklist[0]), 0) 

232 self[name]._name = name 

233 return 

234 

235 try: 

236 self[name] = toklist[0] 

237 except (KeyError, TypeError, IndexError): 

238 if toklist is not self: 

239 self[name] = toklist 

240 else: 

241 self._name = name 

242 

243 def __getitem__(self, i): 

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

245 return self._toklist[i] 

246 

247 if i not in self._all_names: 

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

249 

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

251 

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

253 if isinstance(v, _ParseResultsWithOffset): 

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

255 sub = v[0] 

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

257 self._toklist[k] = v 

258 sub = v 

259 else: 

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

261 _ParseResultsWithOffset(v, 0) 

262 ] 

263 sub = v 

264 if isinstance(sub, ParseResults): 

265 sub._parent = self 

266 

267 def __delitem__(self, i): 

268 if not isinstance(i, (int, slice)): 

269 del self._tokdict[i] 

270 return 

271 

272 mylen = len(self._toklist) 

273 del self._toklist[i] 

274 

275 # convert int to slice 

276 if isinstance(i, int): 

277 if i < 0: 

278 i += mylen 

279 i = slice(i, i + 1) 

280 # get removed indices 

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

282 removed.reverse() 

283 # fixup indices in token dictionary 

284 for occurrences in self._tokdict.values(): 

285 for j in removed: 

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

287 occurrences[k] = _ParseResultsWithOffset( 

288 value, position - (position > j) 

289 ) 

290 

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

292 return k in self._tokdict 

293 

294 def __len__(self) -> int: 

295 return len(self._toklist) 

296 

297 def __bool__(self) -> bool: 

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

299 

300 def __iter__(self) -> Iterator: 

301 return iter(self._toklist) 

302 

303 def __reversed__(self) -> Iterator: 

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

305 

306 def keys(self): 

307 return iter(self._tokdict) 

308 

309 def values(self): 

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

311 

312 def items(self): 

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

314 

315 def haskeys(self) -> bool: 

316 """ 

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

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

319 return not not self._tokdict 

320 

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

322 """ 

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

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

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

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

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

328 semantics and pop the corresponding value from any defined results 

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

330 ``dict.pop()``. 

331 

332 Example: 

333 

334 .. doctest:: 

335 

336 >>> numlist = Word(nums)[...] 

337 >>> print(numlist.parse_string("0 123 321")) 

338 ['0', '123', '321'] 

339 

340 >>> def remove_first(tokens): 

341 ... tokens.pop(0) 

342 ... 

343 >>> numlist.add_parse_action(remove_first) 

344 [W:(0-9)]... 

345 >>> print(numlist.parse_string("0 123 321")) 

346 ['123', '321'] 

347 

348 >>> label = Word(alphas) 

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

350 >>> print(patt.parse_string("AAB 123 321").dump()) 

351 ['AAB', '123', '321'] 

352 - LABEL: 'AAB' 

353 

354 >>> # Use pop() in a parse action to remove named result 

355 >>> # (note that corresponding value is not 

356 >>> # removed from list form of results) 

357 >>> def remove_LABEL(tokens): 

358 ... tokens.pop("LABEL") 

359 ... return tokens 

360 ... 

361 >>> patt.add_parse_action(remove_LABEL) 

362 {W:(A-Za-z) {W:(0-9)}...} 

363 >>> print(patt.parse_string("AAB 123 321").dump()) 

364 ['AAB', '123', '321'] 

365 

366 """ 

367 if not args: 

368 args = [-1] 

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

370 if k == "default": 

371 args = (args[0], v) 

372 else: 

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

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

375 index = args[0] 

376 ret = self[index] 

377 del self[index] 

378 return ret 

379 else: 

380 defaultvalue = args[1] 

381 return defaultvalue 

382 

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

384 """ 

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

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

387 ``default_value`` is specified. 

388 

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

390 

391 Example: 

392 

393 .. doctest:: 

394 

395 >>> integer = Word(nums) 

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

397 

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

399 >>> result.get("year") 

400 '1999' 

401 >>> result.get("hour", "not specified") 

402 'not specified' 

403 >>> result.get("hour") 

404 

405 """ 

406 if key in self: 

407 return self[key] 

408 else: 

409 return default_value 

410 

411 def insert(self, index, ins_string): 

412 """ 

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

414 

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

416 

417 Example: 

418 

419 .. doctest:: 

420 

421 >>> numlist = Word(nums)[...] 

422 >>> print(numlist.parse_string("0 123 321")) 

423 ['0', '123', '321'] 

424 

425 >>> # use a parse action to insert the parse location 

426 >>> # in the front of the parsed results 

427 >>> def insert_locn(locn, tokens): 

428 ... tokens.insert(0, locn) 

429 ... 

430 >>> numlist.add_parse_action(insert_locn) 

431 [W:(0-9)]... 

432 >>> print(numlist.parse_string("0 123 321")) 

433 [0, '0', '123', '321'] 

434 

435 """ 

436 self._toklist.insert(index, ins_string) 

437 # fixup indices in token dictionary 

438 for occurrences in self._tokdict.values(): 

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

440 occurrences[k] = _ParseResultsWithOffset( 

441 value, position + (position > index) 

442 ) 

443 

444 def append(self, item): 

445 """ 

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

447 

448 Example: 

449 

450 .. doctest:: 

451 

452 >>> numlist = Word(nums)[...] 

453 >>> print(numlist.parse_string("0 123 321")) 

454 ['0', '123', '321'] 

455 

456 >>> # use a parse action to compute the sum of the parsed integers, 

457 >>> # and add it to the end 

458 >>> def append_sum(tokens): 

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

460 ... 

461 >>> numlist.add_parse_action(append_sum) 

462 [W:(0-9)]... 

463 >>> print(numlist.parse_string("0 123 321")) 

464 ['0', '123', '321', 444] 

465 """ 

466 self._toklist.append(item) 

467 

468 def extend(self, itemseq): 

469 """ 

470 Add sequence of elements to end of :class:`ParseResults` list of elements. 

471 

472 Example: 

473 

474 .. testcode:: 

475 

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

477 

478 # use a parse action to append the reverse of the matched strings, 

479 # to make a palindrome 

480 def make_palindrome(tokens): 

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

482 return ''.join(tokens) 

483 

484 patt.add_parse_action(make_palindrome) 

485 print(patt.parse_string("lskdj sdlkjf lksd")) 

486 

487 prints: 

488 

489 .. testoutput:: 

490 

491 ['lskdjsdlkjflksddsklfjkldsjdksl'] 

492 """ 

493 if isinstance(itemseq, ParseResults): 

494 self.__iadd__(itemseq) 

495 else: 

496 self._toklist.extend(itemseq) 

497 

498 def clear(self): 

499 """ 

500 Clear all elements and results names. 

501 """ 

502 del self._toklist[:] 

503 self._tokdict.clear() 

504 

505 def __getattr__(self, name): 

506 try: 

507 return self[name] 

508 except KeyError: 

509 if name.startswith("__"): 

510 raise AttributeError(name) 

511 return "" 

512 

513 def __add__(self, other: ParseResults) -> ParseResults: 

514 ret = self.copy() 

515 ret += other 

516 return ret 

517 

518 def __iadd__(self, other: ParseResults) -> ParseResults: 

519 if not other: 

520 return self 

521 

522 if other._tokdict: 

523 offset = len(self._toklist) 

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

525 otheritems = other._tokdict.items() 

526 otherdictitems = [ 

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

528 for k, vlist in otheritems 

529 for v in vlist 

530 ] 

531 for k, v in otherdictitems: 

532 self[k] = v 

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

534 v[0]._parent = self 

535 

536 self._toklist += other._toklist 

537 self._all_names |= other._all_names 

538 return self 

539 

540 def __radd__(self, other) -> ParseResults: 

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

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

543 return self.copy() 

544 else: 

545 # this may raise a TypeError - so be it 

546 return other + self 

547 

548 def __repr__(self) -> str: 

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

550 

551 def __str__(self) -> str: 

552 return ( 

553 "[" 

554 + ", ".join( 

555 [ 

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

557 for i in self._toklist 

558 ] 

559 ) 

560 + "]" 

561 ) 

562 

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

564 out = [] 

565 for item in self._toklist: 

566 if out and sep: 

567 out.append(sep) 

568 if isinstance(item, ParseResults): 

569 out += item._asStringList() 

570 else: 

571 out.append(str(item)) 

572 return out 

573 

574 def as_list(self, *, flatten: bool = False) -> list: 

575 """ 

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

577 If ``flatten`` is True, all the nesting levels in the returned list are collapsed. 

578 

579 Example: 

580 

581 .. doctest:: 

582 

583 >>> patt = Word(alphas)[1, ...] 

584 >>> result = patt.parse_string("sldkj lsdkj sldkj") 

585 >>> # even though the result prints in string-like form, 

586 >>> # it is actually a pyparsing ParseResults 

587 >>> type(result) 

588 <class 'pyparsing.results.ParseResults'> 

589 >>> print(result) 

590 ['sldkj', 'lsdkj', 'sldkj'] 

591 

592 .. doctest:: 

593 

594 >>> # Use as_list() to create an actual list 

595 >>> result_list = result.as_list() 

596 >>> type(result_list) 

597 <class 'list'> 

598 >>> print(result_list) 

599 ['sldkj', 'lsdkj', 'sldkj'] 

600  

601 .. versionchanged:: 3.2.0 

602 New ``flatten`` argument. 

603 """ 

604 

605 def flattened(pr): 

606 to_visit = collections.deque([*self]) 

607 while to_visit: 

608 to_do = to_visit.popleft() 

609 if isinstance(to_do, ParseResults): 

610 to_visit.extendleft(to_do[::-1]) 

611 else: 

612 yield to_do 

613 

614 if flatten: 

615 return [*flattened(self)] 

616 else: 

617 return [ 

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

619 for res in self._toklist 

620 ] 

621 

622 def as_dict(self) -> dict: 

623 """ 

624 Returns the named parse results as a nested dictionary. 

625 

626 Example: 

627 

628 .. doctest:: 

629 

630 >>> integer = pp.Word(pp.nums) 

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

632 

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

634 >>> type(result) 

635 <class 'pyparsing.results.ParseResults'> 

636 >>> result 

637 ParseResults(['1999', '/', '12', '/', '31'], {'year': '1999', 'month': '12', 'day': '31'}) 

638 

639 >>> result_dict = result.as_dict() 

640 >>> type(result_dict) 

641 <class 'dict'> 

642 >>> result_dict 

643 {'year': '1999', 'month': '12', 'day': '31'} 

644 

645 >>> # even though a ParseResults supports dict-like access, 

646 >>> # sometime you just need to have a dict 

647 >>> import json 

648 >>> print(json.dumps(result)) 

649 Traceback (most recent call last): 

650 TypeError: Object of type ParseResults is not JSON serializable 

651 >>> print(json.dumps(result.as_dict())) 

652 {"year": "1999", "month": "12", "day": "31"} 

653 """ 

654 

655 def to_item(obj): 

656 if isinstance(obj, ParseResults): 

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

658 else: 

659 return obj 

660 

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

662 

663 def copy(self) -> ParseResults: 

664 """ 

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

666 :class:`ParseResults` items contained within the source are 

667 shared with the copy. Use :meth:`ParseResults.deepcopy` to 

668 create a copy with its own separate content values. 

669 """ 

670 ret = ParseResults(self._toklist) 

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

672 ret._parent = self._parent 

673 ret._all_names |= self._all_names 

674 ret._name = self._name 

675 return ret 

676 

677 def deepcopy(self) -> ParseResults: 

678 """ 

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

680 

681 .. versionadded:: 3.1.0 

682 """ 

683 ret = self.copy() 

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

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

686 if isinstance(obj, ParseResults): 

687 ret._toklist[i] = obj.deepcopy() 

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

689 pass 

690 elif isinstance(obj, MutableMapping): 

691 ret._toklist[i] = dest = type(obj)() 

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

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

694 elif isinstance(obj, Iterable): 

695 ret._toklist[i] = type(obj)( 

696 v.deepcopy() if isinstance(v, ParseResults) else v for v in obj # type: ignore[call-arg] 

697 ) 

698 return ret 

699 

700 def get_name(self) -> str | None: 

701 r""" 

702 Returns the results name for this token expression. 

703 

704 Useful when several different expressions might match 

705 at a particular location. 

706 

707 Example: 

708 

709 .. testcode:: 

710 

711 integer = Word(nums) 

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

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

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

715 | Group(ssn_expr)("ssn") 

716 | Group(integer)("age")) 

717 user_info = user_data[1, ...] 

718 

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

720 for item in result: 

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

722 

723 prints: 

724 

725 .. testoutput:: 

726 

727 age : 22 

728 ssn : 111-22-3333 

729 house_number : 221B 

730 

731 """ 

732 if self._name: 

733 return self._name 

734 elif self._parent: 

735 par: ParseResults = self._parent 

736 parent_tokdict_items = par._tokdict.items() 

737 return next( 

738 ( 

739 k 

740 for k, vlist in parent_tokdict_items 

741 for v, loc in vlist 

742 if v is self 

743 ), 

744 None, 

745 ) 

746 elif ( 

747 len(self) == 1 

748 and len(self._tokdict) == 1 

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

750 ): 

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

752 else: 

753 return None 

754 

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

756 """ 

757 Diagnostic method for listing out the contents of 

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

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

760 

761 Example: 

762 

763 .. testcode:: 

764 

765 integer = Word(nums) 

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

767 

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

769 print(result.dump()) 

770 

771 prints: 

772 

773 .. testoutput:: 

774 

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

776 - day: '31' 

777 - month: '12' 

778 - year: '1999' 

779 """ 

780 out = [] 

781 NL = "\n" 

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

783 

784 if not full: 

785 return "".join(out) 

786 

787 if self.haskeys(): 

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

789 for k, v in items: 

790 if out: 

791 out.append(NL) 

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

793 if not isinstance(v, ParseResults): 

794 out.append(repr(v)) 

795 continue 

796 

797 if not v: 

798 out.append(str(v)) 

799 continue 

800 

801 out.append( 

802 v.dump( 

803 indent=indent, 

804 full=full, 

805 include_list=include_list, 

806 _depth=_depth + 1, 

807 ) 

808 ) 

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

810 return "".join(out) 

811 

812 v = self 

813 incr = " " 

814 nl = "\n" 

815 for i, vv in enumerate(v): 

816 if isinstance(vv, ParseResults): 

817 vv_dump = vv.dump( 

818 indent=indent, 

819 full=full, 

820 include_list=include_list, 

821 _depth=_depth + 1, 

822 ) 

823 out.append( 

824 f"{nl}{indent}{incr * _depth}[{i}]:{nl}{indent}{incr * (_depth + 1)}{vv_dump}" 

825 ) 

826 else: 

827 out.append( 

828 f"{nl}{indent}{incr * _depth}[{i}]:{nl}{indent}{incr * (_depth + 1)}{vv}" 

829 ) 

830 

831 return "".join(out) 

832 

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

834 """ 

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

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

837 Accepts additional positional or keyword args as defined for 

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

839 

840 Example: 

841 

842 .. testcode:: 

843 

844 ident = Word(alphas, alphanums) 

845 num = Word(nums) 

846 func = Forward() 

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

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

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

850 result.pprint(width=40) 

851 

852 prints: 

853 

854 .. testoutput:: 

855 

856 ['fna', 

857 ['a', 

858 'b', 

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

860 '100']] 

861 """ 

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

863 

864 # add support for pickle protocol 

865 def __getstate__(self): 

866 return ( 

867 self._toklist, 

868 ( 

869 self._tokdict.copy(), 

870 None, 

871 self._all_names, 

872 self._name, 

873 ), 

874 ) 

875 

876 def __setstate__(self, state): 

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

878 self._all_names = set(inAccumNames) 

879 self._parent = None 

880 

881 def __getnewargs__(self): 

882 return self._toklist, self._name 

883 

884 def __dir__(self): 

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

886 

887 @classmethod 

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

889 """ 

890 Helper classmethod to construct a :class:`ParseResults` from a ``dict``, preserving the 

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

892 given, a nested :class:`ParseResults` will be returned. 

893 """ 

894 

895 def is_iterable(obj): 

896 try: 

897 iter(obj) 

898 except Exception: 

899 return False 

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

901 else: 

902 return not isinstance(obj, str_type) 

903 

904 ret = cls([]) 

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

906 if isinstance(v, Mapping): 

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

908 else: 

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

910 if name is not None: 

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

912 return ret 

913 

914 asList = as_list 

915 """ 

916 .. deprecated:: 3.0.0 

917 use :meth:`as_list` 

918 """ 

919 asDict = as_dict 

920 """ 

921 .. deprecated:: 3.0.0 

922 use :meth:`as_dict` 

923 """ 

924 getName = get_name 

925 """ 

926 .. deprecated:: 3.0.0 

927 use :meth:`get_name` 

928 """ 

929 

930 

931MutableMapping.register(ParseResults) 

932MutableSequence.register(ParseResults)