From aca703e1316442d34f60dff40a04e6a49bff285c Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Fri, 24 Jul 2020 20:06:53 +0200 Subject: [PATCH] Python: CG trace: Add support for flask --- .../recorded-call-graph-metrics/projects.json | 10 ++++++++ .../src/cg_trace/tracer.py | 24 ++++++++++++++----- 2 files changed, 28 insertions(+), 6 deletions(-) diff --git a/python/tools/recorded-call-graph-metrics/projects.json b/python/tools/recorded-call-graph-metrics/projects.json index e0754474034..c65c17cd1c2 100644 --- a/python/tools/recorded-call-graph-metrics/projects.json +++ b/python/tools/recorded-call-graph-metrics/projects.json @@ -14,5 +14,15 @@ "setup": [ "pip install nose" ] + }, + "flask": { + "repo": "https://github.com/pallets/flask.git", + "sha": "21c3df31de4bc2f838c945bd37d185210d9bab1a", + "module_command": "pytest -c /dev/null tests examples", + "setup": [ + "pip install -r requirements/tests.txt", + "pip install -q -e examples/tutorial[test]", + "pip install -q -e examples/javascript[test]" + ] } } diff --git a/python/tools/recorded-call-graph-metrics/src/cg_trace/tracer.py b/python/tools/recorded-call-graph-metrics/src/cg_trace/tracer.py index edd38cc8094..f5521865568 100644 --- a/python/tools/recorded-call-graph-metrics/src/cg_trace/tracer.py +++ b/python/tools/recorded-call-graph-metrics/src/cg_trace/tracer.py @@ -1,4 +1,5 @@ import dataclasses +import inspect import logging import os import sys @@ -104,6 +105,9 @@ _unknown_module_fixup_cache = dict() def _unkown_module_fixup(func): # TODO: Doesn't work for everything (for example: `OrderedDict.fromkeys`, `object.__new__`) + # TODO: Can make this logic easier by using `func.__self__`. For `f = dict().get`, `f.__self__.__class__ == dict` + # and `dict.__new__.__self__ = dict` + module = func.__module__ qualname = func.__qualname__ cls_name, method_name = qualname.split(".") @@ -114,12 +118,20 @@ def _unkown_module_fixup(func): matching_classes = list() for klass in object.__subclasses__(): - # type(dict.get) == METHOD_DESCRIPTOR_TYPE - # type(dict.__new__) == BUILTIN_FUNCTION_OR_METHOD - if klass.__qualname__ == cls_name and type( - getattr(klass, method_name, None) - ) in [BUILTIN_FUNCTION_OR_METHOD, METHOD_DESCRIPTOR_TYPE]: - matching_classes.append(klass) + + if inspect.isabstract(klass): + continue + + try: + # type(dict.get) == METHOD_DESCRIPTOR_TYPE + # type(dict.__new__) == BUILTIN_FUNCTION_OR_METHOD + if klass.__qualname__ == cls_name and type( + getattr(klass, method_name, None) + ) in [BUILTIN_FUNCTION_OR_METHOD, METHOD_DESCRIPTOR_TYPE]: + matching_classes.append(klass) + # For flask, observed to give `ValueError: Namespace class is abstract`, even with the isabstract above + except ValueError: + pass if len(matching_classes) == 1: klass = matching_classes[0]