Skip to content

Commit e0f35a9

Browse files
committed
initial version
1 parent c60bfd4 commit e0f35a9

File tree

2 files changed

+81
-0
lines changed

2 files changed

+81
-0
lines changed

docs/tracing_ext-demo.py

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import pandas as pd
2+
import pandas_flavor as pf
3+
import time
4+
5+
@pf.register_dataframe_method
6+
def my_method(df: pd.DataFrame) -> pd.DataFrame:
7+
print("my_method called")
8+
return df.transpose()
9+
10+
@pf.register_dataframe_method
11+
def another_method(df: pd.DataFrame, new_col_d) -> pd.DataFrame:
12+
print("another_method called")
13+
for col, v in new_col_d.items():
14+
df[col] = v
15+
return df
16+
17+
class tracer:
18+
@staticmethod
19+
def create_tracer(*args):
20+
return tracer()
21+
22+
def __init__(self):
23+
self.method_name = None
24+
self.start_ts = None
25+
self.end_ts = None
26+
27+
def __enter__(self):
28+
return self
29+
30+
def handle_start_method_call(self,
31+
method_name,
32+
method_signature,
33+
method_args,
34+
method_kwagrs):
35+
self.method_name = method_name
36+
self.start_ts = time.time()
37+
return method_args, method_kwagrs
38+
39+
def handle_end_method_call(self, ret):
40+
self.end_ts = time.time()
41+
42+
def __exit__(self, exc_type, value, traceback):
43+
print(f"method {self.method_name} took {self.end_ts - self.start_ts} secs to execute")
44+
45+
46+
pf.register.method_call_ctx_factory = tracer.create_tracer
47+
s_df = pd.DataFrame([[i + j for i in range(10)] for j in range(10)])
48+
res_df = s_df.my_method().another_method({'new_col': 'new value'})
49+
print(res_df)

docs/tracing_ext.md

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# method_call_ctx_factory - tracing extention of pandas_flavor
2+
3+
`method_call_ctx_factory` global var defined in [pandas_flavor/register.py](https://github.com/pyjanitor-devs/pandas_flavor/blob/c60bfd43adbcc304b3455055af73ed9fc9ac10d1/pandas_flavor/register.py#L8) is used
4+
as an extention to allow registered method to be traced.
5+
6+
Default value of `method_call_ctx_factory` is None.
7+
8+
Starting version 0.5.0 `pandas_flavor` implements the way to pass registerd method name, signature and parameters to
9+
be handled by user-defined object when the call is made. To allow this the user of pandas_flavor must set
10+
`method_call_ctx_factory` to refer to function with signature `(method_name: str, method_args: list, method_kwargs: dict) -> tracing_ctx`.
11+
`tracing_ctx` should be class which implements methods with signatures as below:
12+
13+
```python
14+
class tracing_ctx:
15+
def __enter__(self) -> None: pass
16+
def __exit__(self, type, value, traceback): -> None: pass
17+
def handle_start_method_call(self, method_name: str,
18+
method_signature: inspect.Signature,
19+
method_args: list,
20+
method_kwargs: dict) -> (list, dict): pass
21+
def handle_end_method_call(self, method_ret: object) -> None: pass
22+
```
23+
24+
During method call `pandas_flavor` will create object of class `tracing_ctx` then will use that object to enter *with* code block.
25+
`handle_start_method_call` and `handle_end_method_call` will be called before and after actual method call. The input arguments
26+
and return object of actual method call will be passed to corresponding `tracing_ctx` method.
27+
28+
So `handle_start_method_call` and `handle_end_method_call` will have the chance to implement required tracing logic.
29+
Aslo, __exit__ method will be called if any exception would occur. This way it is possible to handle the situation of
30+
actual method ends by raising exception.
31+
32+
The example of tracer class implementation and factory function registration is given in [tracing_ext-demo.py...](...)

0 commit comments

Comments
 (0)