Skip to content

Commit d80ec75

Browse files
committed
common code placed into handle_pandas_extention_call, docstring added as requested
1 parent 02d1855 commit d80ec75

File tree

1 file changed

+68
-48
lines changed

1 file changed

+68
-48
lines changed

pandas_flavor/register.py

Lines changed: 68 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,72 @@
88

99
method_call_ctx_factory = None
1010

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
1177

1278
def register_dataframe_method(method):
1379
"""Register a function as a method attached to the Pandas DataFrame.
@@ -32,30 +98,7 @@ def __init__(self, pandas_obj):
3298

3399
@wraps(method)
34100
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)
59102

60103
register_dataframe_accessor(method.__name__)(AccessorMethod)
61104

@@ -78,30 +121,7 @@ def __init__(self, pandas_obj):
78121

79122
@wraps(method)
80123
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)
105125

106126
register_series_accessor(method.__name__)(AccessorMethod)
107127

0 commit comments

Comments
 (0)