qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH v2 01/38] [DO-NOT-MERGE] qapi: add debugging tools


From: John Snow
Subject: Re: [PATCH v2 01/38] [DO-NOT-MERGE] qapi: add debugging tools
Date: Wed, 23 Sep 2020 12:48:47 -0400
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Thunderbird/68.11.0

On 9/22/20 7:43 PM, Cleber Rosa wrote:
On Tue, Sep 22, 2020 at 05:00:24PM -0400, John Snow wrote:
This adds some really childishly simple debugging tools. Maybe they're
interesting for someone else, too?

Signed-off-by: John Snow <jsnow@redhat.com>
---
  scripts/qapi/debug.py | 78 +++++++++++++++++++++++++++++++++++++++++++
  1 file changed, 78 insertions(+)
  create mode 100644 scripts/qapi/debug.py

diff --git a/scripts/qapi/debug.py b/scripts/qapi/debug.py
new file mode 100644
index 0000000000..bacf5ee180
--- /dev/null
+++ b/scripts/qapi/debug.py
@@ -0,0 +1,78 @@
+"""
+Small debugging facilities for mypy static analysis work.
+(C) 2020 John Snow, for Red Hat, Inc.
+"""
+
+import inspect
+import json
+from typing import Dict, List, Any
+from types import FrameType
+
+
+OBSERVED_TYPES: Dict[str, List[str]] = {}
+
+
+# You have no idea how long it took to find this return type...
+def caller_frame() -> FrameType:
+    """
+    Returns the stack frame of the caller's caller.
+    e.g. foo() -> caller() -> caller_frame() return's foo's stack frame.
+    """
+    stack = inspect.stack()
+    caller = stack[2].frame
+    if caller is None:
+        msg = "Python interpreter does not support stack frame inspection"
+        raise RuntimeError(msg)
+    return caller
+
+
+def _add_type_record(name: str, typestr: str) -> None:
+    seen = OBSERVED_TYPES.setdefault(name, [])
+    if typestr not in seen:
+        seen.append(typestr)
+
+
+def record_type(name: str, value: Any, dict_names: bool = False) -> None:
+    """
+    Record the type of a variable.
+
+    :param name: The name of the variable
+    :param value: The value of the variable
+    """
+    _add_type_record(name, str(type(value)))
+
+    try:
+        for key, subvalue in value.items():
+            subname = f"{name}.{key}" if dict_names else f"{name}.[dict_value]"
+            _add_type_record(subname, str(type(subvalue)))
+        return
+    except AttributeError:
+        # (Wasn't a dict or anything resembling one.)
+        pass
+
+    # str is iterable, but not in the way we want!
+    if isinstance(value, str):
+        return
+
+    try:
+        for elem in value:
+            _add_type_record(f"{name}.[list_elem]", str(type(elem)))
+    except TypeError:
+        # (Wasn't a list or anything else iterable.)
+        pass
+
+
+def show_types() -> None:
+    """
+    Print all of the currently known variable types to stdout.
+    """
+    print(json.dumps(OBSERVED_TYPES, indent=2))
+

Maybe the following will be cheaper (no json conversion):

    pprint.pprint(OBSERVED_TYPES, indent=2)

Other than that, I'd vote for including this if there's a bit more
documentation on how to use it, or an example script.  Maybe there
already is, and I did not get to it yet.

- Cleber.


Nope, this is just a dumb script I did to observe types in flight.

There are apparently bigger, beefier tools that I don't know how to use yet: https://github.com/dropbox/pyannotate

I just included my own little tool as a reference thing to be archived on list, I have no desire to spruce it up. I'd rather spend my time learning pyannotate.

--js




reply via email to

[Prev in Thread] Current Thread [Next in Thread]