[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH v2 01/38] [DO-NOT-MERGE] qapi: add debugging tools
From: |
John Snow |
Subject: |
[PATCH v2 01/38] [DO-NOT-MERGE] qapi: add debugging tools |
Date: |
Tue, 22 Sep 2020 17:00:24 -0400 |
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))
+
+
+def record_locals(show: bool = False, dict_names: bool = False) -> None:
+ caller = caller_frame()
+ name = caller.f_code.co_name
+ for key, value in caller.f_locals.items():
+ record_type(f"{name}.{key}", value, dict_names=dict_names)
+ if show:
+ show_types()
--
2.26.2
- [PATCH v2 00/38] qapi: static typing conversion, pt1, John Snow, 2020/09/22
- [PATCH v2 01/38] [DO-NOT-MERGE] qapi: add debugging tools,
John Snow <=
- [PATCH v2 02/38] qapi-gen: Separate arg-parsing from generation, John Snow, 2020/09/22
- Re: [PATCH v2 02/38] qapi-gen: Separate arg-parsing from generation, Eduardo Habkost, 2020/09/22
- Re: [PATCH v2 02/38] qapi-gen: Separate arg-parsing from generation, Cleber Rosa, 2020/09/22
- Re: [PATCH v2 02/38] qapi-gen: Separate arg-parsing from generation, Markus Armbruster, 2020/09/25
- Re: [PATCH v2 02/38] qapi-gen: Separate arg-parsing from generation, John Snow, 2020/09/25
- Re: [PATCH v2 02/38] qapi-gen: Separate arg-parsing from generation, Markus Armbruster, 2020/09/28