8
8
9
9
method_call_ctx_factory = None
10
10
11
+ def handle_pandas_extention_call (method , method_signature , obj , args , kwargs ):
12
+ """
13
+ This function is called when the user calls the registered method on pandas dataframe object.
14
+ pandas extention mechanism passes args and kwargs of original method call as it was applied to obj
15
+
16
+ Implementation uses global var *method_call_ctx_factory"
17
+
18
+ a) case when *method_call_ctx_factory* is None
19
+ In this case the implementation calls the registered method with unmodified args and kwargs and returns underlying method result.
20
+
21
+ b) case when *method_call_ctx_factory* is not None
22
+ In this case *method_call_ctx_factory* expected to refer to the function to create the context object. The context object will be used
23
+ to process inputs and outputs of *method* call. It is also possible that the context object method *handle_start_method_call*
24
+ will modify original args and kwargs before *method* call.
25
+
26
+ method_call_ctx_factory function signature: (method_name: str, args: list, kwargs: dict) -> ctx object
27
+
28
+ ctx object should implement *with* context __enter__/__exit__ as well as methods:
29
+ - handle_start_method_call(method_name: str, method_signature: inspect.Signature, args: list, kwargs: dict) -> (list, dict)
30
+ - handle_end_method(obj) -> None
31
+
32
+ Parameters
33
+ ----------
34
+ method :
35
+ method object as registered by decorator register_dataframe_method (or register_series_method)
36
+ method_signature :
37
+ signature of method as returned by inspect.signature
38
+ obj :
39
+ pandas object - Dataframe or Series
40
+ *args : list
41
+ The arguments to pass to the registered method.
42
+ **kwargs : dict
43
+ The keyword arguments to pass to the registered method.
44
+
45
+ Returns
46
+ -------
47
+ object :
48
+ The result of calling of the method.
49
+ """
50
+
51
+ global method_call_ctx_factory
52
+
53
+ method_call_ctx = (
54
+ method_call_ctx_factory (method .__name__ , args , kwargs )
55
+ if method_call_ctx_factory
56
+ else nullcontext ()
57
+ )
58
+
59
+ with method_call_ctx :
60
+ if not isinstance (method_call_ctx , nullcontext ):
61
+ all_args = tuple ([obj ] + list (args ))
62
+ (
63
+ new_args ,
64
+ new_kwargs ,
65
+ ) = method_call_ctx .handle_start_method_call (
66
+ method .__name__ , method_signature , all_args , kwargs
67
+ )
68
+ args = new_args [1 :]
69
+ kwargs = new_kwargs
70
+
71
+ ret = method (obj , * args , ** kwargs )
72
+
73
+ if not isinstance (method_call_ctx , nullcontext ):
74
+ method_call_ctx .handle_end_method_call (ret )
75
+
76
+ return ret
11
77
12
78
def register_dataframe_method (method ):
13
79
"""Register a function as a method attached to the Pandas DataFrame.
@@ -32,30 +98,7 @@ def __init__(self, pandas_obj):
32
98
33
99
@wraps (method )
34
100
def __call__ (self , * args , ** kwargs ):
35
- global method_call_ctx_factory
36
- method_call_ctx = (
37
- method_call_ctx_factory (method .__name__ , args , kwargs )
38
- if method_call_ctx_factory
39
- else nullcontext ()
40
- )
41
- with method_call_ctx :
42
- if not isinstance (method_call_ctx , nullcontext ):
43
- all_args = tuple ([self ._obj ] + list (args ))
44
- (
45
- new_args ,
46
- new_kwargs ,
47
- ) = method_call_ctx .handle_start_method_call (
48
- method .__name__ , method_signature , all_args , kwargs
49
- )
50
- args = new_args [1 :]
51
- kwargs = new_kwargs
52
-
53
- ret = method (self ._obj , * args , ** kwargs )
54
-
55
- if not isinstance (method_call_ctx , nullcontext ):
56
- method_call_ctx .handle_end_method_call (ret )
57
-
58
- return ret
101
+ return handle_pandas_extention_call (method , method_signature , self ._obj , args , kwargs )
59
102
60
103
register_dataframe_accessor (method .__name__ )(AccessorMethod )
61
104
@@ -78,30 +121,7 @@ def __init__(self, pandas_obj):
78
121
79
122
@wraps (method )
80
123
def __call__ (self , * args , ** kwargs ):
81
- global method_call_ctx_factory
82
- method_call_ctx = (
83
- method_call_ctx_factory (method .__name__ , args , kwargs )
84
- if method_call_ctx_factory
85
- else nullcontext ()
86
- )
87
- with method_call_ctx :
88
- if not isinstance (method_call_ctx , nullcontext ):
89
- all_args = tuple ([self ._obj ] + list (args ))
90
- (
91
- new_args ,
92
- new_kwargs ,
93
- ) = method_call_ctx .handle_start_method_call (
94
- method .__name__ , method_signature , all_args , kwargs
95
- )
96
- args = new_args [1 :]
97
- kwargs = new_kwargs
98
-
99
- ret = method (self ._obj , * args , ** kwargs )
100
-
101
- if not isinstance (method_call_ctx , nullcontext ):
102
- method_call_ctx .handle_end_method_call (ret )
103
-
104
- return ret
124
+ return handle_pandas_extention_call (method , method_signature , self ._obj , args , kwargs )
105
125
106
126
register_series_accessor (method .__name__ )(AccessorMethod )
107
127
0 commit comments