10
10
from _appmap import wrapt
11
11
12
12
from .env import Env
13
- from .utils import FnType
13
+ from .utils import FnType , Scope
14
14
15
15
logger = Env .current .getLogger (__name__ )
16
16
17
17
18
- Filterable = namedtuple ("Filterable" , "fqname obj" )
18
+ Filterable = namedtuple ("Filterable" , "scope fqname obj" )
19
19
20
20
21
21
class FilterableMod (Filterable ):
22
22
__slots__ = ()
23
23
24
24
def __new__ (cls , mod ):
25
25
fqname = mod .__name__
26
- return super (FilterableMod , cls ).__new__ (cls , fqname , mod )
27
-
28
- def classify_fn (self , _ ):
29
- return FnType .MODULE
26
+ return super (FilterableMod , cls ).__new__ (cls , Scope .MODULE , fqname , mod )
30
27
31
28
32
29
class FilterableCls (Filterable ):
33
30
__slots__ = ()
34
31
35
32
def __new__ (cls , clazz ):
36
33
fqname = "%s.%s" % (clazz .__module__ , clazz .__qualname__ )
37
- return super (FilterableCls , cls ).__new__ (cls , fqname , clazz )
38
-
39
- def classify_fn (self , static_fn ):
40
- return FnType .classify (static_fn )
34
+ return super (FilterableCls , cls ).__new__ (cls , Scope .CLASS , fqname , clazz )
41
35
42
36
43
37
class FilterableFn (
44
38
namedtuple (
45
39
"FilterableFn" ,
46
- Filterable ._fields
47
- + (
48
- "scope" ,
49
- "static_fn" ,
50
- ),
40
+ Filterable ._fields + ("static_fn" ,),
51
41
)
52
42
):
53
43
__slots__ = ()
54
44
55
45
def __new__ (cls , scope , fn , static_fn ):
56
46
fqname = "%s.%s" % (scope .fqname , fn .__name__ )
57
- self = super (FilterableFn , cls ).__new__ (cls , fqname , fn , scope , static_fn )
47
+ self = super (FilterableFn , cls ).__new__ (cls , scope . scope , fqname , fn , static_fn )
58
48
return self
59
49
60
50
@property
61
51
def fntype (self ):
62
- return self .scope .classify_fn (self .static_fn )
52
+ if self .scope == Scope .MODULE :
53
+ return FnType .MODULE
54
+ else :
55
+ return FnType .classify (self .static_fn )
63
56
64
57
65
58
class Filter (ABC ): # pylint: disable=too-few-public-methods
@@ -161,6 +154,17 @@ def initialize(cls):
161
154
def use_filter (cls , filter_class ):
162
155
cls .filter_stack .append (filter_class )
163
156
157
+ @classmethod
158
+ def instrument_function (cls , fn_name , filterableFn : FilterableFn , selected_functions = None ):
159
+ # Only instrument the function if it was specifically called out for the package
160
+ # (e.g. because it should be labeled), or it's included by the filters
161
+ matched = cls .filter_chain .filter (filterableFn )
162
+ selected = selected_functions and fn_name in selected_functions
163
+ if selected or matched :
164
+ return cls .filter_chain .wrap (filterableFn )
165
+
166
+ return filterableFn .obj
167
+
164
168
@classmethod
165
169
def do_import (cls , * args , ** kwargs ):
166
170
mod = args [0 ]
@@ -177,15 +181,10 @@ def instrument_functions(filterable, selected_functions=None):
177
181
logger .trace (" functions %s" , functions )
178
182
179
183
for fn_name , static_fn , fn in functions :
180
- # Only instrument the function if it was specifically called out for the package
181
- # (e.g. because it should be labeled), or it's included by the filters
182
184
filterableFn = FilterableFn (filterable , fn , static_fn )
183
- matched = cls .filter_chain .filter (filterableFn )
184
- selected = selected_functions and fn_name in selected_functions
185
- if selected or matched :
186
- new_fn = cls .filter_chain .wrap (filterableFn )
187
- if fn != new_fn :
188
- wrapt .wrap_function_wrapper (filterable .obj , fn_name , new_fn )
185
+ new_fn = cls .instrument_function (fn_name , filterableFn , selected_functions )
186
+ if new_fn != fn :
187
+ wrapt .wrap_function_wrapper (filterable .obj , fn_name , new_fn )
189
188
190
189
# Import Config here, to avoid circular top-level imports.
191
190
from .configuration import Config # pylint: disable=import-outside-toplevel
0 commit comments