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

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

318 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 deprecate_argument 

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, 

206 toklist=None, 

207 name=None, 

208 aslist=True, 

209 modal=True, 

210 isinstance=isinstance, 

211 **kwargs, 

212 ) -> None: 

213 asList = deprecate_argument(kwargs, "asList", True, new_name="aslist") 

214 

215 asList = asList and aslist 

216 self._tokdict: dict[str, _ParseResultsWithOffset] 

217 self._modal = modal 

218 

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

220 return 

221 

222 if isinstance(name, int): 

223 name = str(name) 

224 

225 if not modal: 

226 self._all_names = {name} 

227 

228 self._name = name 

229 

230 if toklist in self._null_values: 

231 return 

232 

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

234 toklist = [toklist] 

235 

236 if asList: 

237 if isinstance(toklist, ParseResults): 

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

239 else: 

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

241 self[name]._name = name 

242 return 

243 

244 try: 

245 self[name] = toklist[0] 

246 except (KeyError, TypeError, IndexError): 

247 if toklist is not self: 

248 self[name] = toklist 

249 else: 

250 self._name = name 

251 

252 def __getitem__(self, i): 

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

254 return self._toklist[i] 

255 

256 if i not in self._all_names: 

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

258 

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

260 

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

262 if isinstance(v, _ParseResultsWithOffset): 

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

264 sub = v[0] 

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

266 self._toklist[k] = v 

267 sub = v 

268 else: 

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

270 _ParseResultsWithOffset(v, 0) 

271 ] 

272 sub = v 

273 if isinstance(sub, ParseResults): 

274 sub._parent = self 

275 

276 def __delitem__(self, i): 

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

278 del self._tokdict[i] 

279 return 

280 

281 mylen = len(self._toklist) 

282 del self._toklist[i] 

283 

284 # convert int to slice 

285 if isinstance(i, int): 

286 if i < 0: 

287 i += mylen 

288 i = slice(i, i + 1) 

289 # get removed indices 

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

291 removed.reverse() 

292 # fixup indices in token dictionary 

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

294 for j in removed: 

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

296 occurrences[k] = _ParseResultsWithOffset( 

297 value, position - (position > j) 

298 ) 

299 

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

301 return k in self._tokdict 

302 

303 def __len__(self) -> int: 

304 return len(self._toklist) 

305 

306 def __bool__(self) -> bool: 

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

308 

309 def __iter__(self) -> Iterator: 

310 return iter(self._toklist) 

311 

312 def __reversed__(self) -> Iterator: 

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

314 

315 def keys(self): 

316 return iter(self._tokdict) 

317 

318 def values(self): 

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

320 

321 def items(self): 

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

323 

324 def haskeys(self) -> bool: 

325 """ 

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

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

328 return not not self._tokdict 

329 

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

331 """ 

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

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

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

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

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

337 semantics and pop the corresponding value from any defined results 

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

339 ``dict.pop()``. 

340 

341 Example: 

342 

343 .. doctest:: 

344 

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

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

347 ['0', '123', '321'] 

348 

349 >>> def remove_first(tokens): 

350 ... tokens.pop(0) 

351 ... 

352 >>> numlist.add_parse_action(remove_first) 

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

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

355 ['123', '321'] 

356 

357 >>> label = Word(alphas) 

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

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

360 ['AAB', '123', '321'] 

361 - LABEL: 'AAB' 

362 

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

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

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

366 >>> def remove_LABEL(tokens): 

367 ... tokens.pop("LABEL") 

368 ... return tokens 

369 ... 

370 >>> patt.add_parse_action(remove_LABEL) 

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

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

373 ['AAB', '123', '321'] 

374 

375 """ 

376 if not args: 

377 args = [-1] 

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

379 if k == "default": 

380 args = (args[0], v) 

381 else: 

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

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

384 index = args[0] 

385 ret = self[index] 

386 del self[index] 

387 return ret 

388 else: 

389 defaultvalue = args[1] 

390 return defaultvalue 

391 

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

393 """ 

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

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

396 ``default_value`` is specified. 

397 

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

399 

400 Example: 

401 

402 .. doctest:: 

403 

404 >>> integer = Word(nums) 

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

406 

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

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

409 '1999' 

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

411 'not specified' 

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

413 

414 """ 

415 if key in self: 

416 return self[key] 

417 else: 

418 return default_value 

419 

420 def insert(self, index, ins_string): 

421 """ 

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

423 

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

425 

426 Example: 

427 

428 .. doctest:: 

429 

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

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

432 ['0', '123', '321'] 

433 

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

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

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

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

438 ... 

439 >>> numlist.add_parse_action(insert_locn) 

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

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

442 [0, '0', '123', '321'] 

443 

444 """ 

445 self._toklist.insert(index, ins_string) 

446 # fixup indices in token dictionary 

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

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

449 occurrences[k] = _ParseResultsWithOffset( 

450 value, position + (position > index) 

451 ) 

452 

453 def append(self, item): 

454 """ 

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

456 

457 Example: 

458 

459 .. doctest:: 

460 

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

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

463 ['0', '123', '321'] 

464 

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

466 >>> # and add it to the end 

467 >>> def append_sum(tokens): 

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

469 ... 

470 >>> numlist.add_parse_action(append_sum) 

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

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

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

474 """ 

475 self._toklist.append(item) 

476 

477 def extend(self, itemseq): 

478 """ 

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

480 

481 Example: 

482 

483 .. testcode:: 

484 

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

486 

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

488 # to make a palindrome 

489 def make_palindrome(tokens): 

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

491 return ''.join(tokens) 

492 

493 patt.add_parse_action(make_palindrome) 

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

495 

496 prints: 

497 

498 .. testoutput:: 

499 

500 ['lskdjsdlkjflksddsklfjkldsjdksl'] 

501 """ 

502 if isinstance(itemseq, ParseResults): 

503 self.__iadd__(itemseq) 

504 else: 

505 self._toklist.extend(itemseq) 

506 

507 def clear(self): 

508 """ 

509 Clear all elements and results names. 

510 """ 

511 del self._toklist[:] 

512 self._tokdict.clear() 

513 

514 def __getattr__(self, name): 

515 try: 

516 return self[name] 

517 except KeyError: 

518 if name.startswith("__"): 

519 raise AttributeError(name) 

520 return "" 

521 

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

523 ret = self.copy() 

524 ret += other 

525 return ret 

526 

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

528 if not other: 

529 return self 

530 

531 if other._tokdict: 

532 offset = len(self._toklist) 

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

534 otheritems = other._tokdict.items() 

535 otherdictitems = [ 

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

537 for k, vlist in otheritems 

538 for v in vlist 

539 ] 

540 for k, v in otherdictitems: 

541 self[k] = v 

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

543 v[0]._parent = self 

544 

545 self._toklist += other._toklist 

546 self._all_names |= other._all_names 

547 return self 

548 

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

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

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

552 return self.copy() 

553 else: 

554 # this may raise a TypeError - so be it 

555 return other + self 

556 

557 def __repr__(self) -> str: 

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

559 

560 def __str__(self) -> str: 

561 return ( 

562 "[" 

563 + ", ".join( 

564 [ 

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

566 for i in self._toklist 

567 ] 

568 ) 

569 + "]" 

570 ) 

571 

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

573 out = [] 

574 for item in self._toklist: 

575 if out and sep: 

576 out.append(sep) 

577 if isinstance(item, ParseResults): 

578 out += item._asStringList() 

579 else: 

580 out.append(str(item)) 

581 return out 

582 

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

584 """ 

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

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

587 

588 Example: 

589 

590 .. doctest:: 

591 

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

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

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

595 >>> # it is actually a pyparsing ParseResults 

596 >>> type(result) 

597 <class 'pyparsing.results.ParseResults'> 

598 >>> print(result) 

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

600 

601 .. doctest:: 

602 

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

604 >>> result_list = result.as_list() 

605 >>> type(result_list) 

606 <class 'list'> 

607 >>> print(result_list) 

608 ['sldkj', 'lsdkj', 'sldkj'] 

609 

610 .. versionchanged:: 3.2.0 

611 New ``flatten`` argument. 

612 """ 

613 

614 def flattened(pr): 

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

616 while to_visit: 

617 to_do = to_visit.popleft() 

618 if isinstance(to_do, ParseResults): 

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

620 else: 

621 yield to_do 

622 

623 if flatten: 

624 return [*flattened(self)] 

625 else: 

626 return [ 

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

628 for res in self._toklist 

629 ] 

630 

631 def as_dict(self) -> dict: 

632 """ 

633 Returns the named parse results as a nested dictionary. 

634 

635 Example: 

636 

637 .. doctest:: 

638 

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

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

641 

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

643 >>> type(result) 

644 <class 'pyparsing.results.ParseResults'> 

645 >>> result 

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

647 

648 >>> result_dict = result.as_dict() 

649 >>> type(result_dict) 

650 <class 'dict'> 

651 >>> result_dict 

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

653 

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

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

656 >>> import json 

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

658 Traceback (most recent call last): 

659 TypeError: Object of type ParseResults is not JSON serializable 

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

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

662 """ 

663 

664 def to_item(obj): 

665 if isinstance(obj, ParseResults): 

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

667 else: 

668 return obj 

669 

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

671 

672 def copy(self) -> ParseResults: 

673 """ 

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

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

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

677 create a copy with its own separate content values. 

678 """ 

679 ret = ParseResults(self._toklist) 

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

681 ret._parent = self._parent 

682 ret._all_names |= self._all_names 

683 ret._name = self._name 

684 return ret 

685 

686 def deepcopy(self) -> ParseResults: 

687 """ 

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

689 

690 .. versionadded:: 3.1.0 

691 """ 

692 ret = self.copy() 

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

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

695 if isinstance(obj, ParseResults): 

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

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

698 pass 

699 elif isinstance(obj, MutableMapping): 

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

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

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

703 elif isinstance(obj, Iterable): 

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

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

706 ) 

707 return ret 

708 

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

710 r""" 

711 Returns the results name for this token expression. 

712 

713 Useful when several different expressions might match 

714 at a particular location. 

715 

716 Example: 

717 

718 .. testcode:: 

719 

720 integer = Word(nums) 

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

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

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

724 | Group(ssn_expr)("ssn") 

725 | Group(integer)("age")) 

726 user_info = user_data[1, ...] 

727 

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

729 for item in result: 

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

731 

732 prints: 

733 

734 .. testoutput:: 

735 

736 age : 22 

737 ssn : 111-22-3333 

738 house_number : 221B 

739 

740 """ 

741 if self._name: 

742 return self._name 

743 elif self._parent: 

744 par: ParseResults = self._parent 

745 parent_tokdict_items = par._tokdict.items() 

746 return next( 

747 ( 

748 k 

749 for k, vlist in parent_tokdict_items 

750 for v, loc in vlist 

751 if v is self 

752 ), 

753 None, 

754 ) 

755 elif ( 

756 len(self) == 1 

757 and len(self._tokdict) == 1 

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

759 ): 

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

761 else: 

762 return None 

763 

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

765 """ 

766 Diagnostic method for listing out the contents of 

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

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

769 

770 Example: 

771 

772 .. testcode:: 

773 

774 integer = Word(nums) 

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

776 

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

778 print(result.dump()) 

779 

780 prints: 

781 

782 .. testoutput:: 

783 

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

785 - day: '31' 

786 - month: '12' 

787 - year: '1999' 

788 """ 

789 out = [] 

790 NL = "\n" 

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

792 

793 if not full: 

794 return "".join(out) 

795 

796 if self.haskeys(): 

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

798 for k, v in items: 

799 if out: 

800 out.append(NL) 

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

802 if not isinstance(v, ParseResults): 

803 out.append(repr(v)) 

804 continue 

805 

806 if not v: 

807 out.append(str(v)) 

808 continue 

809 

810 out.append( 

811 v.dump( 

812 indent=indent, 

813 full=full, 

814 include_list=include_list, 

815 _depth=_depth + 1, 

816 ) 

817 ) 

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

819 return "".join(out) 

820 

821 v = self 

822 incr = " " 

823 nl = "\n" 

824 for i, vv in enumerate(v): 

825 if isinstance(vv, ParseResults): 

826 vv_dump = vv.dump( 

827 indent=indent, 

828 full=full, 

829 include_list=include_list, 

830 _depth=_depth + 1, 

831 ) 

832 out.append( 

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

834 ) 

835 else: 

836 out.append( 

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

838 ) 

839 

840 return "".join(out) 

841 

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

843 """ 

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

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

846 Accepts additional positional or keyword args as defined for 

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

848 

849 Example: 

850 

851 .. testcode:: 

852 

853 ident = Word(alphas, alphanums) 

854 num = Word(nums) 

855 func = Forward() 

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

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

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

859 result.pprint(width=40) 

860 

861 prints: 

862 

863 .. testoutput:: 

864 

865 ['fna', 

866 ['a', 

867 'b', 

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

869 '100']] 

870 """ 

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

872 

873 # add support for pickle protocol 

874 def __getstate__(self): 

875 return ( 

876 self._toklist, 

877 ( 

878 self._tokdict.copy(), 

879 None, 

880 self._all_names, 

881 self._name, 

882 ), 

883 ) 

884 

885 def __setstate__(self, state): 

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

887 self._all_names = set(inAccumNames) 

888 self._parent = None 

889 

890 def __getnewargs__(self): 

891 return self._toklist, self._name 

892 

893 def __dir__(self): 

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

895 

896 @classmethod 

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

898 """ 

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

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

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

902 """ 

903 

904 def is_iterable(obj): 

905 try: 

906 iter(obj) 

907 except Exception: 

908 return False 

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

910 else: 

911 return not isinstance(obj, str_type) 

912 

913 ret = cls([]) 

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

915 if isinstance(v, Mapping): 

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

917 else: 

918 ret += cls([v], name=k, aslist=is_iterable(v)) 

919 if name is not None: 

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

921 return ret 

922 

923 asList = as_list 

924 """ 

925 .. deprecated:: 3.0.0 

926 use :meth:`as_list` 

927 """ 

928 asDict = as_dict 

929 """ 

930 .. deprecated:: 3.0.0 

931 use :meth:`as_dict` 

932 """ 

933 getName = get_name 

934 """ 

935 .. deprecated:: 3.0.0 

936 use :meth:`get_name` 

937 """ 

938 

939 

940MutableMapping.register(ParseResults) 

941MutableSequence.register(ParseResults)