Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/pyparsing/results.py: 49%
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, NamedTuple
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(NamedTuple):
25 result: ParseResults
26 offset: int
29class ParseResults:
30 """Structured parse results, to provide multiple means of access to
31 the parsed data:
33 - as a list (``len(results)``)
34 - by list index (``results[0], results[1]``, etc.)
35 - by attribute (``results.<results_name>`` - see :class:`ParserElement.set_results_name`)
37 Example:
39 .. testcode::
41 integer = Word(nums)
42 date_str = (integer.set_results_name("year") + '/'
43 + integer.set_results_name("month") + '/'
44 + integer.set_results_name("day"))
45 # equivalent form:
46 # date_str = (integer("year") + '/'
47 # + integer("month") + '/'
48 # + integer("day"))
50 # parse_string returns a ParseResults object
51 result = date_str.parse_string("1999/12/31")
53 def test(s, fn=repr):
54 print(f"{s} -> {fn(eval(s))}")
56 test("list(result)")
57 test("result[0]")
58 test("result['month']")
59 test("result.day")
60 test("'month' in result")
61 test("'minutes' in result")
62 test("result.dump()", str)
64 prints:
66 .. testoutput::
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'
79 """
81 _null_values: tuple[Any, ...] = (None, [], ())
83 _name: str
84 _parent: ParseResults
85 _all_names: set[str]
86 _modal: bool
87 _toklist: list[Any]
88 _tokdict: dict[str, Any]
90 __slots__ = (
91 "_name",
92 "_parent",
93 "_all_names",
94 "_modal",
95 "_toklist",
96 "_tokdict",
97 )
99 class List(list):
100 """
101 Simple wrapper class to distinguish parsed list results that should be preserved
102 as actual Python lists, instead of being converted to :class:`ParseResults`:
104 .. testcode::
106 import pyparsing as pp
107 ppc = pp.common
109 LBRACK, RBRACK, LPAR, RPAR = pp.Suppress.using_each("[]()")
110 element = pp.Forward()
111 item = ppc.integer
112 item_list = pp.DelimitedList(element)
113 element_list = LBRACK + item_list + RBRACK | LPAR + item_list + RPAR
114 element <<= item | element_list
116 # add parse action to convert from ParseResults
117 # to actual Python collection types
118 @element_list.add_parse_action
119 def as_python_list(t):
120 return pp.ParseResults.List(t.as_list())
122 element.run_tests('''
123 100
124 [2,3,4]
125 [[2, 1],3,4]
126 [(2, 1),3,4]
127 (2,3,4)
128 ([2, 3], 4)
129 ''', post_parse=lambda s, r: (r[0], type(r[0]))
130 )
132 prints:
134 .. testoutput::
135 :options: +NORMALIZE_WHITESPACE
138 100
139 (100, <class 'int'>)
141 [2,3,4]
142 ([2, 3, 4], <class 'list'>)
144 [[2, 1],3,4]
145 ([[2, 1], 3, 4], <class 'list'>)
147 [(2, 1),3,4]
148 ([[2, 1], 3, 4], <class 'list'>)
150 (2,3,4)
151 ([2, 3, 4], <class 'list'>)
153 ([2, 3], 4)
154 ([[2, 3], 4], <class 'list'>)
156 (Used internally by :class:`Group` when `aslist=True`.)
157 """
159 def __new__(cls, contained=None):
160 if contained is None:
161 contained = []
163 if not isinstance(contained, list):
164 raise TypeError(
165 f"{cls.__name__} may only be constructed with a list, not {type(contained).__name__}"
166 )
168 return list.__new__(cls)
170 def __new__(cls, toklist=None, name=None, **kwargs):
171 if isinstance(toklist, ParseResults):
172 return toklist
173 self = object.__new__(cls)
174 self._name = None
175 self._parent = None
176 self._all_names = set()
178 if toklist is None:
179 self._toklist = []
180 elif isinstance(toklist, (list, _generator_type)):
181 self._toklist = (
182 [toklist[:]]
183 if isinstance(toklist, ParseResults.List)
184 else list(toklist)
185 )
186 else:
187 self._toklist = [toklist]
188 self._tokdict = dict()
189 return self
191 # Performance tuning: we construct a *lot* of these, so keep this
192 # constructor as small and fast as possible
193 def __init__(
194 self,
195 toklist=None,
196 name=None,
197 aslist=True,
198 modal=True,
199 isinstance=isinstance,
200 **kwargs,
201 ) -> None:
202 asList = deprecate_argument(kwargs, "asList", True, new_name="aslist")
204 asList = asList and aslist
205 self._tokdict: dict[str, _ParseResultsWithOffset]
206 self._modal = modal
208 if name is None or name == "":
209 return
211 if isinstance(name, int):
212 name = str(name)
214 if not modal:
215 self._all_names = {name}
217 self._name = name
219 if toklist in self._null_values:
220 return
222 if isinstance(toklist, (str_type, type)):
223 toklist = [toklist]
225 if asList:
226 if isinstance(toklist, ParseResults):
227 self[name] = _ParseResultsWithOffset(ParseResults(toklist._toklist), 0)
228 else:
229 self[name] = _ParseResultsWithOffset(ParseResults(toklist[0]), 0)
230 self[name]._name = name
231 return
233 try:
234 self[name] = toklist[0]
235 except (KeyError, TypeError, IndexError):
236 if toklist is not self:
237 self[name] = toklist
238 else:
239 self._name = name
241 def __getitem__(self, i):
242 if isinstance(i, (int, slice)):
243 return self._toklist[i]
245 if i not in self._all_names:
246 return self._tokdict[i][-1].result
248 return ParseResults([v.result for v in self._tokdict[i]])
250 def __setitem__(self, k, v, isinstance=isinstance):
251 if isinstance(v, _ParseResultsWithOffset):
252 self._tokdict[k] = self._tokdict.get(k, list()) + [v]
253 sub = v.result
254 elif isinstance(k, (int, slice)):
255 self._toklist[k] = v
256 sub = v
257 else:
258 self._tokdict[k] = self._tokdict.get(k, []) + [
259 _ParseResultsWithOffset(v, 0)
260 ]
261 sub = v
262 if isinstance(sub, ParseResults):
263 sub._parent = self
265 def __delitem__(self, i):
266 if not isinstance(i, (int, slice)):
267 del self._tokdict[i]
268 return
270 # slight optimization if del results[:]
271 if i == NULL_SLICE:
272 self._toklist.clear()
273 return
275 mylen = len(self._toklist)
276 del self._toklist[i]
278 # convert int to slice
279 if isinstance(i, int):
280 if i < 0:
281 i += mylen
282 i = slice(i, i + 1)
283 # get removed indices
284 removed = list(range(*i.indices(mylen)))
285 removed.reverse()
286 # fixup indices in token dictionary
287 for occurrences in self._tokdict.values():
288 for j in removed:
289 for k, (value, position) in enumerate(occurrences):
290 if position > j:
291 occurrences[k] = _ParseResultsWithOffset(value, position - 1)
293 def __contains__(self, k) -> bool:
294 return k in self._tokdict
296 def __len__(self) -> int:
297 return len(self._toklist)
299 def __bool__(self) -> bool:
300 return not not (self._toklist or self._tokdict)
302 def __iter__(self) -> Iterator:
303 return iter(self._toklist)
305 def __reversed__(self) -> Iterator:
306 return iter(self._toklist[::-1])
308 def keys(self):
309 return iter(self._tokdict)
311 def values(self):
312 return (self[k] for k in self.keys())
314 def items(self):
315 return ((k, self[k]) for k in self.keys())
317 def haskeys(self) -> bool:
318 """
319 Since ``keys()`` returns an iterator, this method is helpful in bypassing
320 code that looks for the existence of any defined results names."""
321 return not not self._tokdict
323 def pop(self, *args, **kwargs):
324 """
325 Removes and returns item at specified index (default= ``last``).
326 Supports both ``list`` and ``dict`` semantics for ``pop()``. If
327 passed no argument or an integer argument, it will use ``list``
328 semantics and pop tokens from the list of parsed tokens. If passed
329 a non-integer argument (most likely a string), it will use ``dict``
330 semantics and pop the corresponding value from any defined results
331 names. A second default return value argument is supported, just as in
332 ``dict.pop()``.
334 Example:
336 .. doctest::
338 >>> numlist = Word(nums)[...]
339 >>> print(numlist.parse_string("0 123 321"))
340 ['0', '123', '321']
342 >>> def remove_first(tokens):
343 ... tokens.pop(0)
344 ...
345 >>> numlist.add_parse_action(remove_first)
346 [W:(0-9)]...
347 >>> print(numlist.parse_string("0 123 321"))
348 ['123', '321']
350 >>> label = Word(alphas)
351 >>> patt = label("LABEL") + Word(nums)[1, ...]
352 >>> print(patt.parse_string("AAB 123 321").dump())
353 ['AAB', '123', '321']
354 - LABEL: 'AAB'
356 >>> # Use pop() in a parse action to remove named result
357 >>> # (note that corresponding value is not
358 >>> # removed from list form of results)
359 >>> def remove_LABEL(tokens):
360 ... tokens.pop("LABEL")
361 ... return tokens
362 ...
363 >>> patt.add_parse_action(remove_LABEL)
364 {W:(A-Za-z) {W:(0-9)}...}
365 >>> print(patt.parse_string("AAB 123 321").dump())
366 ['AAB', '123', '321']
368 """
369 if not args:
370 args = [-1]
371 for k, v in kwargs.items():
372 if k == "default":
373 args = (args[0], v)
374 else:
375 raise TypeError(f"pop() got an unexpected keyword argument {k!r}")
376 if isinstance(args[0], int) or len(args) == 1 or args[0] in self:
377 index = args[0]
378 ret = self[index]
379 del self[index]
380 return ret
381 else:
382 defaultvalue = args[1]
383 return defaultvalue
385 def get(self, key, default_value=None):
386 """
387 Returns named result matching the given key, or if there is no
388 such name, then returns the given ``default_value`` or ``None`` if no
389 ``default_value`` is specified.
391 Similar to ``dict.get()``.
393 Example:
395 .. doctest::
397 >>> integer = Word(nums)
398 >>> date_str = integer("year") + '/' + integer("month") + '/' + integer("day")
400 >>> result = date_str.parse_string("1999/12/31")
401 >>> result.get("year")
402 '1999'
403 >>> result.get("hour", "not specified")
404 'not specified'
405 >>> result.get("hour")
407 """
408 if key in self:
409 return self[key]
410 else:
411 return default_value
413 def insert(self, index, ins_string):
414 """
415 Inserts new element at location index in the list of parsed tokens.
417 Similar to ``list.insert()``.
419 Example:
421 .. doctest::
423 >>> numlist = Word(nums)[...]
424 >>> print(numlist.parse_string("0 123 321"))
425 ['0', '123', '321']
427 >>> # use a parse action to insert the parse location
428 >>> # in the front of the parsed results
429 >>> def insert_locn(locn, tokens):
430 ... tokens.insert(0, locn)
431 ...
432 >>> numlist.add_parse_action(insert_locn)
433 [W:(0-9)]...
434 >>> print(numlist.parse_string("0 123 321"))
435 [0, '0', '123', '321']
437 """
438 self._toklist.insert(index, ins_string)
439 # fixup indices in token dictionary
440 for occurrences in self._tokdict.values():
441 for k, (value, position) in enumerate(occurrences):
442 if position > index:
443 occurrences[k] = _ParseResultsWithOffset(value, position + 1)
445 def append(self, item):
446 """
447 Add single element to end of ``ParseResults`` list of elements.
449 Example:
451 .. doctest::
453 >>> numlist = Word(nums)[...]
454 >>> print(numlist.parse_string("0 123 321"))
455 ['0', '123', '321']
457 >>> # use a parse action to compute the sum of the parsed integers,
458 >>> # and add it to the end
459 >>> def append_sum(tokens):
460 ... tokens.append(sum(map(int, tokens)))
461 ...
462 >>> numlist.add_parse_action(append_sum)
463 [W:(0-9)]...
464 >>> print(numlist.parse_string("0 123 321"))
465 ['0', '123', '321', 444]
466 """
467 self._toklist.append(item)
469 def extend(self, itemseq):
470 """
471 Add sequence of elements to end of :class:`ParseResults` list of elements.
473 Example:
475 .. testcode::
477 patt = Word(alphas)[1, ...]
479 # use a parse action to append the reverse of the matched strings,
480 # to make a palindrome
481 def make_palindrome(tokens):
482 tokens.extend(reversed([t[::-1] for t in tokens]))
483 return ''.join(tokens)
485 patt.add_parse_action(make_palindrome)
486 print(patt.parse_string("lskdj sdlkjf lksd"))
488 prints:
490 .. testoutput::
492 ['lskdjsdlkjflksddsklfjkldsjdksl']
493 """
494 if isinstance(itemseq, ParseResults):
495 self.__iadd__(itemseq)
496 else:
497 self._toklist.extend(itemseq)
499 def clear(self):
500 """
501 Clear all elements and results names.
502 """
503 del self._toklist[:]
504 self._tokdict.clear()
506 def __getattr__(self, name):
507 try:
508 return self[name]
509 except KeyError:
510 if name.startswith("__"):
511 raise AttributeError(name)
512 return ""
514 def __add__(self, other: ParseResults) -> ParseResults:
515 ret = self.copy()
516 ret += other
517 return ret
519 def __iadd__(self, other: ParseResults) -> ParseResults:
520 if not other:
521 return self
523 if other._tokdict:
524 offset = len(self._toklist)
525 # addoffset = lambda a: offset if a < 0 else a + offset
526 otheritems = other._tokdict.items()
527 otherdictitems = [
528 # (k, _ParseResultsWithOffset(v[0], addoffset(v[1])))
529 (
530 k,
531 _ParseResultsWithOffset(
532 v.result,
533 # addoffset(v[1])
534 (offset if v.offset < 0 else v.offset + offset),
535 ),
536 )
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.result, ParseResults):
543 v.result._parent = self
545 self._toklist += other._toklist
546 self._all_names |= other._all_names
547 return self
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
557 def __repr__(self) -> str:
558 return f"{type(self).__name__}({self._toklist!r}, {self.as_dict()})"
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 )
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
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.
588 Example:
590 .. doctest::
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']
601 .. doctest::
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']
610 .. versionchanged:: 3.2.0
611 New ``flatten`` argument.
612 """
614 if flatten:
615 return [*_flatten(self)]
616 else:
617 return [
618 res.as_list() if isinstance(res, ParseResults) else res
619 for res in self._toklist
620 ]
622 def as_dict(self) -> dict:
623 """
624 Returns the named parse results as a nested dictionary.
626 Example:
628 .. doctest::
630 >>> integer = pp.Word(pp.nums)
631 >>> date_str = integer("year") + '/' + integer("month") + '/' + integer("day")
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'})
639 >>> result_dict = result.as_dict()
640 >>> type(result_dict)
641 <class 'dict'>
642 >>> result_dict
643 {'year': '1999', 'month': '12', 'day': '31'}
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 """
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
661 return dict((k, to_item(v)) for k, v in self.items())
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 = object.__new__(ParseResults)
671 ret._toklist = self._toklist[:]
672 ret._tokdict = {**self._tokdict}
673 ret._parent = self._parent
674 ret._all_names = {*self._all_names}
675 ret._name = self._name
676 ret._modal = self._modal
677 return ret
679 def deepcopy(self) -> ParseResults:
680 """
681 Returns a new deep copy of a :class:`ParseResults` object.
683 .. versionadded:: 3.1.0
684 """
685 ret = self.copy()
686 # replace values with copies if they are of known mutable types
687 for i, obj in enumerate(self._toklist):
688 if isinstance(obj, ParseResults):
689 ret._toklist[i] = obj.deepcopy()
690 elif isinstance(obj, (str, bytes)):
691 pass
692 elif isinstance(obj, MutableMapping):
693 ret._toklist[i] = dest = type(obj)()
694 for k, v in obj.items():
695 dest[k] = v.deepcopy() if isinstance(v, ParseResults) else v
696 elif isinstance(obj, Iterable):
697 ret._toklist[i] = type(obj)(
698 v.deepcopy() if isinstance(v, ParseResults) else v for v in obj # type: ignore[call-arg]
699 )
700 return ret
702 def get_name(self) -> str | None:
703 r"""
704 Returns the results name for this token expression.
706 Useful when several different expressions might match
707 at a particular location.
709 Example:
711 .. testcode::
713 integer = Word(nums)
714 ssn_expr = Regex(r"\d\d\d-\d\d-\d\d\d\d")
715 house_number_expr = Suppress('#') + Word(nums, alphanums)
716 user_data = (Group(house_number_expr)("house_number")
717 | Group(ssn_expr)("ssn")
718 | Group(integer)("age"))
719 user_info = user_data[1, ...]
721 result = user_info.parse_string("22 111-22-3333 #221B")
722 for item in result:
723 print(item.get_name(), ':', item[0])
725 prints:
727 .. testoutput::
729 age : 22
730 ssn : 111-22-3333
731 house_number : 221B
733 """
734 if self._name:
735 return self._name
736 elif self._parent:
737 par: ParseResults = self._parent
738 parent_tokdict_items = par._tokdict.items()
739 return next(
740 (
741 k
742 for k, vlist in parent_tokdict_items
743 for v, loc in vlist
744 if v is self
745 ),
746 None,
747 )
748 elif len(self) == 1 and len(self._tokdict) == 1:
749 first_name, first_pr_offset = next(iter(self._tokdict.items()))
750 if first_pr_offset[0].offset <= 0:
751 return first_name
753 return None
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.
761 Example:
763 .. testcode::
765 integer = Word(nums)
766 date_str = integer("year") + '/' + integer("month") + '/' + integer("day")
768 result = date_str.parse_string('1999/12/31')
769 print(result.dump())
771 prints:
773 .. testoutput::
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 "")
784 if not full:
785 return "".join(out)
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
797 if not v:
798 out.append(str(v))
799 continue
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)
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 )
831 return "".join(out)
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>`_ .
840 Example:
842 .. testcode::
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)
852 prints:
854 .. testoutput::
856 ['fna',
857 ['a',
858 'b',
859 ['(', 'fnb', ['c', 'd', '200'], ')'],
860 '100']]
861 """
862 pprint.pprint(self.as_list(), *args, **kwargs)
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 )
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
881 def __getnewargs__(self):
882 return self._toklist, self._name
884 def __dir__(self):
885 return dir(type(self)) + list(self.keys())
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 ret = cls([])
895 for k, v in other.items():
896 if isinstance(v, Mapping):
897 ret += cls.from_dict(v, name=k)
898 else:
899 ret += cls([v], name=k, aslist=_is_iterable(v))
900 if name is not None:
901 ret = cls([ret], name=name)
902 return ret
904 asList = as_list
905 """
906 .. deprecated:: 3.0.0
907 use :meth:`as_list`
908 """
909 asDict = as_dict
910 """
911 .. deprecated:: 3.0.0
912 use :meth:`as_dict`
913 """
914 getName = get_name
915 """
916 .. deprecated:: 3.0.0
917 use :meth:`get_name`
918 """
921MutableMapping.register(ParseResults)
922MutableSequence.register(ParseResults)