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 <js...@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