Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/pyparsing/results.py: 50%
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
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
1# results.py
3from __future__ import annotations
5import collections
6from collections.abc import (
7 MutableMapping,
8 Mapping,
9 MutableSequence,
10 Iterator,
11 Iterable,
12)
13import pprint
14from typing import Any
16from .util import deprecate_argument, _is_iterable, _flatten
19str_type: tuple[type, ...] = (str, bytes)
20_generator_type = type((_ for _ in ()))
21NULL_SLICE: slice = slice(None)
24class _ParseResultsWithOffset:
25 tup: tuple[ParseResults, int]
26 __slots__ = ["tup"]
28 def __init__(self, p1: ParseResults, p2: int) -> None:
29 self.tup: tuple[ParseResults, int] = (p1, p2)
31 def __getitem__(self, i):
32 return self.tup[i]
34 def __getstate__(self):
35 return self.tup
37 def __setstate__(self, *args):
38 self.tup = args[0]
41class ParseResults:
42 """Structured parse results, to provide multiple means of access to
43 the parsed data:
45 - as a list (``len(results)``)
46 - by list index (``results[0], results[1]``, etc.)
47 - by attribute (``results.<results_name>`` - see :class:`ParserElement.set_results_name`)
49 Example:
51 .. testcode::
53 integer = Word(nums)
54 date_str = (integer.set_results_name("year") + '/'
55 + integer.set_results_name("month") + '/'
56 + integer.set_results_name("day"))
57 # equivalent form:
58 # date_str = (integer("year") + '/'
59 # + integer("month") + '/'
60 # + integer("day"))
62 # parse_string returns a ParseResults object
63 result = date_str.parse_string("1999/12/31")
65 def test(s, fn=repr):
66 print(f"{s} -> {fn(eval(s))}")
68 test("list(result)")
69 test("result[0]")
70 test("result['month']")
71 test("result.day")
72 test("'month' in result")
73 test("'minutes' in result")
74 test("result.dump()", str)
76 prints:
78 .. testoutput::
80 list(result) -> ['1999', '/', '12', '/', '31']
81 result[0] -> '1999'
82 result['month'] -> '12'
83 result.day -> '31'
84 'month' in result -> True
85 'minutes' in result -> False
86 result.dump() -> ['1999', '/', '12', '/', '31']
87 - day: '31'
88 - month: '12'
89 - year: '1999'
91 """
93 _null_values: tuple[Any, ...] = (None, [], ())
95 _name: str
96 _parent: ParseResults
97 _all_names: set[str]
98 _modal: bool
99 _toklist: list[Any]
100 _tokdict: dict[str, Any]
102 __slots__ = (
103 "_name",
104 "_parent",
105 "_all_names",
106 "_modal",
107 "_toklist",
108 "_tokdict",
109 )
111 class List(list):
112 """
113 Simple wrapper class to distinguish parsed list results that should be preserved
114 as actual Python lists, instead of being converted to :class:`ParseResults`:
116 .. testcode::
118 import pyparsing as pp
119 ppc = pp.common
121 LBRACK, RBRACK, LPAR, RPAR = pp.Suppress.using_each("[]()")
122 element = pp.Forward()
123 item = ppc.integer
124 item_list = pp.DelimitedList(element)
125 element_list = LBRACK + item_list + RBRACK | LPAR + item_list + RPAR
126 element <<= item | element_list
128 # add parse action to convert from ParseResults
129 # to actual Python collection types
130 @element_list.add_parse_action
131 def as_python_list(t):
132 return pp.ParseResults.List(t.as_list())
134 element.run_tests('''
135 100
136 [2,3,4]
137 [[2, 1],3,4]
138 [(2, 1),3,4]
139 (2,3,4)
140 ([2, 3], 4)
141 ''', post_parse=lambda s, r: (r[0], type(r[0]))
142 )
144 prints:
146 .. testoutput::
147 :options: +NORMALIZE_WHITESPACE
150 100
151 (100, <class 'int'>)
153 [2,3,4]
154 ([2, 3, 4], <class 'list'>)
156 [[2, 1],3,4]
157 ([[2, 1], 3, 4], <class 'list'>)
159 [(2, 1),3,4]
160 ([[2, 1], 3, 4], <class 'list'>)
162 (2,3,4)
163 ([2, 3, 4], <class 'list'>)
165 ([2, 3], 4)
166 ([[2, 3], 4], <class 'list'>)
168 (Used internally by :class:`Group` when `aslist=True`.)
169 """
171 def __new__(cls, contained=None):
172 if contained is None:
173 contained = []
175 if not isinstance(contained, list):
176 raise TypeError(
177 f"{cls.__name__} may only be constructed with a list, not {type(contained).__name__}"
178 )
180 return list.__new__(cls)
182 def __new__(cls, toklist=None, name=None, **kwargs):
183 if isinstance(toklist, ParseResults):
184 return toklist
185 self = object.__new__(cls)
186 self._name = None
187 self._parent = None
188 self._all_names = set()
190 if toklist is None:
191 self._toklist = []
192 elif isinstance(toklist, (list, _generator_type)):
193 self._toklist = (
194 [toklist[:]]
195 if isinstance(toklist, ParseResults.List)
196 else list(toklist)
197 )
198 else:
199 self._toklist = [toklist]
200 self._tokdict = dict()
201 return self
203 # Performance tuning: we construct a *lot* of these, so keep this
204 # constructor as small and fast as possible
205 def __init__(
206 self,
207 toklist=None,
208 name=None,
209 aslist=True,
210 modal=True,
211 isinstance=isinstance,
212 **kwargs,
213 ) -> None:
214 asList = deprecate_argument(kwargs, "asList", True, new_name="aslist")
216 asList = asList and aslist
217 self._tokdict: dict[str, _ParseResultsWithOffset]
218 self._modal = modal
220 if name is None or name == "":
221 return
223 if isinstance(name, int):
224 name = str(name)
226 if not modal:
227 self._all_names = {name}
229 self._name = name
231 if toklist in self._null_values:
232 return
234 if isinstance(toklist, (str_type, type)):
235 toklist = [toklist]
237 if asList:
238 if isinstance(toklist, ParseResults):
239 self[name] = _ParseResultsWithOffset(ParseResults(toklist._toklist), 0)
240 else:
241 self[name] = _ParseResultsWithOffset(ParseResults(toklist[0]), 0)
242 self[name]._name = name
243 return
245 try:
246 self[name] = toklist[0]
247 except (KeyError, TypeError, IndexError):
248 if toklist is not self:
249 self[name] = toklist
250 else:
251 self._name = name
253 def __getitem__(self, i):
254 if isinstance(i, (int, slice)):
255 return self._toklist[i]
257 if i not in self._all_names:
258 return self._tokdict[i][-1][0]
260 return ParseResults([v[0] for v in self._tokdict[i]])
262 def __setitem__(self, k, v, isinstance=isinstance):
263 if isinstance(v, _ParseResultsWithOffset):
264 self._tokdict[k] = self._tokdict.get(k, list()) + [v]
265 sub = v[0]
266 elif isinstance(k, (int, slice)):
267 self._toklist[k] = v
268 sub = v
269 else:
270 self._tokdict[k] = self._tokdict.get(k, []) + [
271 _ParseResultsWithOffset(v, 0)
272 ]
273 sub = v
274 if isinstance(sub, ParseResults):
275 sub._parent = self
277 def __delitem__(self, i):
278 if not isinstance(i, (int, slice)):
279 del self._tokdict[i]
280 return
282 # slight optimization if del results[:]
283 if i == NULL_SLICE:
284 self._toklist.clear()
285 return
287 mylen = len(self._toklist)
288 del self._toklist[i]
290 # convert int to slice
291 if isinstance(i, int):
292 if i < 0:
293 i += mylen
294 i = slice(i, i + 1)
295 # get removed indices
296 removed = list(range(*i.indices(mylen)))
297 removed.reverse()
298 # fixup indices in token dictionary
299 for occurrences in self._tokdict.values():
300 for j in removed:
301 for k, (value, position) in enumerate(occurrences):
302 occurrences[k] = _ParseResultsWithOffset(
303 value, position - (position > j)
304 )
306 def __contains__(self, k) -> bool:
307 return k in self._tokdict
309 def __len__(self) -> int:
310 return len(self._toklist)
312 def __bool__(self) -> bool:
313 return not not (self._toklist or self._tokdict)
315 def __iter__(self) -> Iterator:
316 return iter(self._toklist)
318 def __reversed__(self) -> Iterator:
319 return iter(self._toklist[::-1])
321 def keys(self):
322 return iter(self._tokdict)
324 def values(self):
325 return (self[k] for k in self.keys())
327 def items(self):
328 return ((k, self[k]) for k in self.keys())
330 def haskeys(self) -> bool:
331 """
332 Since ``keys()`` returns an iterator, this method is helpful in bypassing
333 code that looks for the existence of any defined results names."""
334 return not not self._tokdict
336 def pop(self, *args, **kwargs):
337 """
338 Removes and returns item at specified index (default= ``last``).
339 Supports both ``list`` and ``dict`` semantics for ``pop()``. If
340 passed no argument or an integer argument, it will use ``list``
341 semantics and pop tokens from the list of parsed tokens. If passed
342 a non-integer argument (most likely a string), it will use ``dict``
343 semantics and pop the corresponding value from any defined results
344 names. A second default return value argument is supported, just as in
345 ``dict.pop()``.
347 Example:
349 .. doctest::
351 >>> numlist = Word(nums)[...]
352 >>> print(numlist.parse_string("0 123 321"))
353 ['0', '123', '321']
355 >>> def remove_first(tokens):
356 ... tokens.pop(0)
357 ...
358 >>> numlist.add_parse_action(remove_first)
359 [W:(0-9)]...
360 >>> print(numlist.parse_string("0 123 321"))
361 ['123', '321']
363 >>> label = Word(alphas)
364 >>> patt = label("LABEL") + Word(nums)[1, ...]
365 >>> print(patt.parse_string("AAB 123 321").dump())
366 ['AAB', '123', '321']
367 - LABEL: 'AAB'
369 >>> # Use pop() in a parse action to remove named result
370 >>> # (note that corresponding value is not
371 >>> # removed from list form of results)
372 >>> def remove_LABEL(tokens):
373 ... tokens.pop("LABEL")
374 ... return tokens
375 ...
376 >>> patt.add_parse_action(remove_LABEL)
377 {W:(A-Za-z) {W:(0-9)}...}
378 >>> print(patt.parse_string("AAB 123 321").dump())
379 ['AAB', '123', '321']
381 """
382 if not args:
383 args = [-1]
384 for k, v in kwargs.items():
385 if k == "default":
386 args = (args[0], v)
387 else:
388 raise TypeError(f"pop() got an unexpected keyword argument {k!r}")
389 if isinstance(args[0], int) or len(args) == 1 or args[0] in self:
390 index = args[0]
391 ret = self[index]
392 del self[index]
393 return ret
394 else:
395 defaultvalue = args[1]
396 return defaultvalue
398 def get(self, key, default_value=None):
399 """
400 Returns named result matching the given key, or if there is no
401 such name, then returns the given ``default_value`` or ``None`` if no
402 ``default_value`` is specified.
404 Similar to ``dict.get()``.
406 Example:
408 .. doctest::
410 >>> integer = Word(nums)
411 >>> date_str = integer("year") + '/' + integer("month") + '/' + integer("day")
413 >>> result = date_str.parse_string("1999/12/31")
414 >>> result.get("year")
415 '1999'
416 >>> result.get("hour", "not specified")
417 'not specified'
418 >>> result.get("hour")
420 """
421 if key in self:
422 return self[key]
423 else:
424 return default_value
426 def insert(self, index, ins_string):
427 """
428 Inserts new element at location index in the list of parsed tokens.
430 Similar to ``list.insert()``.
432 Example:
434 .. doctest::
436 >>> numlist = Word(nums)[...]
437 >>> print(numlist.parse_string("0 123 321"))
438 ['0', '123', '321']
440 >>> # use a parse action to insert the parse location
441 >>> # in the front of the parsed results
442 >>> def insert_locn(locn, tokens):
443 ... tokens.insert(0, locn)
444 ...
445 >>> numlist.add_parse_action(insert_locn)
446 [W:(0-9)]...
447 >>> print(numlist.parse_string("0 123 321"))
448 [0, '0', '123', '321']
450 """
451 self._toklist.insert(index, ins_string)
452 # fixup indices in token dictionary
453 for occurrences in self._tokdict.values():
454 for k, (value, position) in enumerate(occurrences):
455 occurrences[k] = _ParseResultsWithOffset(
456 value, position + (position > index)
457 )
459 def append(self, item):
460 """
461 Add single element to end of ``ParseResults`` list of elements.
463 Example:
465 .. doctest::
467 >>> numlist = Word(nums)[...]
468 >>> print(numlist.parse_string("0 123 321"))
469 ['0', '123', '321']
471 >>> # use a parse action to compute the sum of the parsed integers,
472 >>> # and add it to the end
473 >>> def append_sum(tokens):
474 ... tokens.append(sum(map(int, tokens)))
475 ...
476 >>> numlist.add_parse_action(append_sum)
477 [W:(0-9)]...
478 >>> print(numlist.parse_string("0 123 321"))
479 ['0', '123', '321', 444]
480 """
481 self._toklist.append(item)
483 def extend(self, itemseq):
484 """
485 Add sequence of elements to end of :class:`ParseResults` list of elements.
487 Example:
489 .. testcode::
491 patt = Word(alphas)[1, ...]
493 # use a parse action to append the reverse of the matched strings,
494 # to make a palindrome
495 def make_palindrome(tokens):
496 tokens.extend(reversed([t[::-1] for t in tokens]))
497 return ''.join(tokens)
499 patt.add_parse_action(make_palindrome)
500 print(patt.parse_string("lskdj sdlkjf lksd"))
502 prints:
504 .. testoutput::
506 ['lskdjsdlkjflksddsklfjkldsjdksl']
507 """
508 if isinstance(itemseq, ParseResults):
509 self.__iadd__(itemseq)
510 else:
511 self._toklist.extend(itemseq)
513 def clear(self):
514 """
515 Clear all elements and results names.
516 """
517 del self._toklist[:]
518 self._tokdict.clear()
520 def __getattr__(self, name):
521 try:
522 return self[name]
523 except KeyError:
524 if name.startswith("__"):
525 raise AttributeError(name)
526 return ""
528 def __add__(self, other: ParseResults) -> ParseResults:
529 ret = self.copy()
530 ret += other
531 return ret
533 def __iadd__(self, other: ParseResults) -> ParseResults:
534 if not other:
535 return self
537 if other._tokdict:
538 offset = len(self._toklist)
539 addoffset = lambda a: offset if a < 0 else a + offset
540 otheritems = other._tokdict.items()
541 otherdictitems = [
542 (k, _ParseResultsWithOffset(v[0], addoffset(v[1])))
543 for k, vlist in otheritems
544 for v in vlist
545 ]
546 for k, v in otherdictitems:
547 self[k] = v
548 if isinstance(v[0], ParseResults):
549 v[0]._parent = self
551 self._toklist += other._toklist
552 self._all_names |= other._all_names
553 return self
555 def __radd__(self, other) -> ParseResults:
556 if isinstance(other, int) and other == 0:
557 # useful for merging many ParseResults using sum() builtin
558 return self.copy()
559 else:
560 # this may raise a TypeError - so be it
561 return other + self
563 def __repr__(self) -> str:
564 return f"{type(self).__name__}({self._toklist!r}, {self.as_dict()})"
566 def __str__(self) -> str:
567 return (
568 "["
569 + ", ".join(
570 [
571 str(i) if isinstance(i, ParseResults) else repr(i)
572 for i in self._toklist
573 ]
574 )
575 + "]"
576 )
578 def _asStringList(self, sep=""):
579 out = []
580 for item in self._toklist:
581 if out and sep:
582 out.append(sep)
583 if isinstance(item, ParseResults):
584 out += item._asStringList()
585 else:
586 out.append(str(item))
587 return out
589 def as_list(self, *, flatten: bool = False) -> list:
590 """
591 Returns the parse results as a nested list of matching tokens, all converted to strings.
592 If ``flatten`` is True, all the nesting levels in the returned list are collapsed.
594 Example:
596 .. doctest::
598 >>> patt = Word(alphas)[1, ...]
599 >>> result = patt.parse_string("sldkj lsdkj sldkj")
600 >>> # even though the result prints in string-like form,
601 >>> # it is actually a pyparsing ParseResults
602 >>> type(result)
603 <class 'pyparsing.results.ParseResults'>
604 >>> print(result)
605 ['sldkj', 'lsdkj', 'sldkj']
607 .. doctest::
609 >>> # Use as_list() to create an actual list
610 >>> result_list = result.as_list()
611 >>> type(result_list)
612 <class 'list'>
613 >>> print(result_list)
614 ['sldkj', 'lsdkj', 'sldkj']
616 .. versionchanged:: 3.2.0
617 New ``flatten`` argument.
618 """
620 if flatten:
621 return [*_flatten(self)]
622 else:
623 return [
624 res.as_list() if isinstance(res, ParseResults) else res
625 for res in self._toklist
626 ]
628 def as_dict(self) -> dict:
629 """
630 Returns the named parse results as a nested dictionary.
632 Example:
634 .. doctest::
636 >>> integer = pp.Word(pp.nums)
637 >>> date_str = integer("year") + '/' + integer("month") + '/' + integer("day")
639 >>> result = date_str.parse_string('1999/12/31')
640 >>> type(result)
641 <class 'pyparsing.results.ParseResults'>
642 >>> result
643 ParseResults(['1999', '/', '12', '/', '31'], {'year': '1999', 'month': '12', 'day': '31'})
645 >>> result_dict = result.as_dict()
646 >>> type(result_dict)
647 <class 'dict'>
648 >>> result_dict
649 {'year': '1999', 'month': '12', 'day': '31'}
651 >>> # even though a ParseResults supports dict-like access,
652 >>> # sometime you just need to have a dict
653 >>> import json
654 >>> print(json.dumps(result))
655 Traceback (most recent call last):
656 TypeError: Object of type ParseResults is not JSON serializable
657 >>> print(json.dumps(result.as_dict()))
658 {"year": "1999", "month": "12", "day": "31"}
659 """
661 def to_item(obj):
662 if isinstance(obj, ParseResults):
663 return obj.as_dict() if obj.haskeys() else [to_item(v) for v in obj]
664 else:
665 return obj
667 return dict((k, to_item(v)) for k, v in self.items())
669 def copy(self) -> ParseResults:
670 """
671 Returns a new shallow copy of a :class:`ParseResults` object.
672 :class:`ParseResults` items contained within the source are
673 shared with the copy. Use :meth:`ParseResults.deepcopy` to
674 create a copy with its own separate content values.
675 """
676 ret = ParseResults(self._toklist)
677 ret._tokdict = self._tokdict.copy()
678 ret._parent = self._parent
679 ret._all_names |= self._all_names
680 ret._name = self._name
681 return ret
683 def deepcopy(self) -> ParseResults:
684 """
685 Returns a new deep copy of a :class:`ParseResults` object.
687 .. versionadded:: 3.1.0
688 """
689 ret = self.copy()
690 # replace values with copies if they are of known mutable types
691 for i, obj in enumerate(self._toklist):
692 if isinstance(obj, ParseResults):
693 ret._toklist[i] = obj.deepcopy()
694 elif isinstance(obj, (str, bytes)):
695 pass
696 elif isinstance(obj, MutableMapping):
697 ret._toklist[i] = dest = type(obj)()
698 for k, v in obj.items():
699 dest[k] = v.deepcopy() if isinstance(v, ParseResults) else v
700 elif isinstance(obj, Iterable):
701 ret._toklist[i] = type(obj)(
702 v.deepcopy() if isinstance(v, ParseResults) else v for v in obj # type: ignore[call-arg]
703 )
704 return ret
706 def get_name(self) -> str | None:
707 r"""
708 Returns the results name for this token expression.
710 Useful when several different expressions might match
711 at a particular location.
713 Example:
715 .. testcode::
717 integer = Word(nums)
718 ssn_expr = Regex(r"\d\d\d-\d\d-\d\d\d\d")
719 house_number_expr = Suppress('#') + Word(nums, alphanums)
720 user_data = (Group(house_number_expr)("house_number")
721 | Group(ssn_expr)("ssn")
722 | Group(integer)("age"))
723 user_info = user_data[1, ...]
725 result = user_info.parse_string("22 111-22-3333 #221B")
726 for item in result:
727 print(item.get_name(), ':', item[0])
729 prints:
731 .. testoutput::
733 age : 22
734 ssn : 111-22-3333
735 house_number : 221B
737 """
738 if self._name:
739 return self._name
740 elif self._parent:
741 par: ParseResults = self._parent
742 parent_tokdict_items = par._tokdict.items()
743 return next(
744 (
745 k
746 for k, vlist in parent_tokdict_items
747 for v, loc in vlist
748 if v is self
749 ),
750 None,
751 )
752 elif (
753 len(self) == 1
754 and len(self._tokdict) == 1
755 and next(iter(self._tokdict.values()))[0][1] in (0, -1)
756 ):
757 return next(iter(self._tokdict.keys()))
758 else:
759 return None
761 def dump(self, indent="", full=True, include_list=True, _depth=0) -> str:
762 """
763 Diagnostic method for listing out the contents of
764 a :class:`ParseResults`. Accepts an optional ``indent`` argument so
765 that this string can be embedded in a nested display of other data.
767 Example:
769 .. testcode::
771 integer = Word(nums)
772 date_str = integer("year") + '/' + integer("month") + '/' + integer("day")
774 result = date_str.parse_string('1999/12/31')
775 print(result.dump())
777 prints:
779 .. testoutput::
781 ['1999', '/', '12', '/', '31']
782 - day: '31'
783 - month: '12'
784 - year: '1999'
785 """
786 out = []
787 NL = "\n"
788 out.append(indent + str(self.as_list()) if include_list else "")
790 if not full:
791 return "".join(out)
793 if self.haskeys():
794 items = sorted((str(k), v) for k, v in self.items())
795 for k, v in items:
796 if out:
797 out.append(NL)
798 out.append(f"{indent}{(' ' * _depth)}- {k}: ")
799 if not isinstance(v, ParseResults):
800 out.append(repr(v))
801 continue
803 if not v:
804 out.append(str(v))
805 continue
807 out.append(
808 v.dump(
809 indent=indent,
810 full=full,
811 include_list=include_list,
812 _depth=_depth + 1,
813 )
814 )
815 if not any(isinstance(vv, ParseResults) for vv in self):
816 return "".join(out)
818 v = self
819 incr = " "
820 nl = "\n"
821 for i, vv in enumerate(v):
822 if isinstance(vv, ParseResults):
823 vv_dump = vv.dump(
824 indent=indent,
825 full=full,
826 include_list=include_list,
827 _depth=_depth + 1,
828 )
829 out.append(
830 f"{nl}{indent}{incr * _depth}[{i}]:{nl}{indent}{incr * (_depth + 1)}{vv_dump}"
831 )
832 else:
833 out.append(
834 f"{nl}{indent}{incr * _depth}[{i}]:{nl}{indent}{incr * (_depth + 1)}{vv}"
835 )
837 return "".join(out)
839 def pprint(self, *args, **kwargs):
840 """
841 Pretty-printer for parsed results as a list, using the
842 `pprint <https://docs.python.org/3/library/pprint.html>`_ module.
843 Accepts additional positional or keyword args as defined for
844 `pprint.pprint <https://docs.python.org/3/library/pprint.html#pprint.pprint>`_ .
846 Example:
848 .. testcode::
850 ident = Word(alphas, alphanums)
851 num = Word(nums)
852 func = Forward()
853 term = ident | num | Group('(' + func + ')')
854 func <<= ident + Group(Optional(DelimitedList(term)))
855 result = func.parse_string("fna a,b,(fnb c,d,200),100")
856 result.pprint(width=40)
858 prints:
860 .. testoutput::
862 ['fna',
863 ['a',
864 'b',
865 ['(', 'fnb', ['c', 'd', '200'], ')'],
866 '100']]
867 """
868 pprint.pprint(self.as_list(), *args, **kwargs)
870 # add support for pickle protocol
871 def __getstate__(self):
872 return (
873 self._toklist,
874 (
875 self._tokdict.copy(),
876 None,
877 self._all_names,
878 self._name,
879 ),
880 )
882 def __setstate__(self, state):
883 self._toklist, (self._tokdict, par, inAccumNames, self._name) = state
884 self._all_names = set(inAccumNames)
885 self._parent = None
887 def __getnewargs__(self):
888 return self._toklist, self._name
890 def __dir__(self):
891 return dir(type(self)) + list(self.keys())
893 @classmethod
894 def from_dict(cls, other, name=None) -> ParseResults:
895 """
896 Helper classmethod to construct a :class:`ParseResults` from a ``dict``, preserving the
897 name-value relations as results names. If an optional ``name`` argument is
898 given, a nested :class:`ParseResults` will be returned.
899 """
900 ret = cls([])
901 for k, v in other.items():
902 if isinstance(v, Mapping):
903 ret += cls.from_dict(v, name=k)
904 else:
905 ret += cls([v], name=k, aslist=_is_iterable(v))
906 if name is not None:
907 ret = cls([ret], name=name)
908 return ret
910 asList = as_list
911 """
912 .. deprecated:: 3.0.0
913 use :meth:`as_list`
914 """
915 asDict = as_dict
916 """
917 .. deprecated:: 3.0.0
918 use :meth:`as_dict`
919 """
920 getName = get_name
921 """
922 .. deprecated:: 3.0.0
923 use :meth:`get_name`
924 """
927MutableMapping.register(ParseResults)
928MutableSequence.register(ParseResults)