Skip to content

Commit dbde2d4

Browse files
committed
chore: allow method_logger to directly decorate functions with params in parentheses
1 parent 913de1b commit dbde2d4

File tree

2 files changed

+60
-39
lines changed

2 files changed

+60
-39
lines changed

bigframes/core/log_adapter.py

Lines changed: 48 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -149,49 +149,58 @@ def wrap(cls):
149149
return wrap(decorated_cls)
150150

151151

152-
def method_logger(method, /, *, custom_base_name: Optional[str] = None):
152+
def method_logger(method = None, /, *, custom_base_name: Optional[str] = None):
153153
"""Decorator that adds logging functionality to a method."""
154154

155-
@functools.wraps(method)
156-
def wrapper(*args, **kwargs):
157-
api_method_name = getattr(method, LOG_OVERRIDE_NAME, method.__name__)
158-
if custom_base_name is None:
159-
qualname_parts = getattr(method, "__qualname__", method.__name__).split(".")
160-
class_name = qualname_parts[-2] if len(qualname_parts) > 1 else ""
161-
base_name = (
162-
class_name if class_name else "_".join(method.__module__.split(".")[1:])
163-
)
164-
else:
165-
base_name = custom_base_name
166-
167-
full_method_name = f"{base_name.lower()}-{api_method_name}"
168-
# Track directly called methods
169-
if len(_call_stack) == 0:
170-
add_api_method(full_method_name)
171-
172-
_call_stack.append(full_method_name)
173-
174-
try:
175-
return method(*args, **kwargs)
176-
except (NotImplementedError, TypeError) as e:
177-
# Log method parameters that are implemented in pandas but either missing (TypeError)
178-
# or not fully supported (NotImplementedError) in BigFrames.
179-
# Logging is currently supported only when we can access the bqclient through
180-
# _block.session.bqclient.
181-
if len(_call_stack) == 1:
182-
submit_pandas_labels(
183-
_get_bq_client(*args, **kwargs),
184-
base_name,
185-
api_method_name,
186-
args,
187-
kwargs,
188-
task=PANDAS_PARAM_TRACKING_TASK,
155+
def outer_wrapper(method):
156+
157+
@functools.wraps(method)
158+
def wrapper(*args, **kwargs):
159+
api_method_name = getattr(method, LOG_OVERRIDE_NAME, method.__name__)
160+
if custom_base_name is None:
161+
qualname_parts = getattr(method, "__qualname__", method.__name__).split(".")
162+
class_name = qualname_parts[-2] if len(qualname_parts) > 1 else ""
163+
base_name = (
164+
class_name if class_name else "_".join(method.__module__.split(".")[1:])
189165
)
190-
raise e
191-
finally:
192-
_call_stack.pop()
166+
else:
167+
base_name = custom_base_name
193168

194-
return wrapper
169+
full_method_name = f"{base_name.lower()}-{api_method_name}"
170+
# Track directly called methods
171+
if len(_call_stack) == 0:
172+
add_api_method(full_method_name)
173+
174+
_call_stack.append(full_method_name)
175+
176+
try:
177+
return method(*args, **kwargs)
178+
except (NotImplementedError, TypeError) as e:
179+
# Log method parameters that are implemented in pandas but either missing (TypeError)
180+
# or not fully supported (NotImplementedError) in BigFrames.
181+
# Logging is currently supported only when we can access the bqclient through
182+
# _block.session.bqclient.
183+
if len(_call_stack) == 1:
184+
submit_pandas_labels(
185+
_get_bq_client(*args, **kwargs),
186+
base_name,
187+
api_method_name,
188+
args,
189+
kwargs,
190+
task=PANDAS_PARAM_TRACKING_TASK,
191+
)
192+
raise e
193+
finally:
194+
_call_stack.pop()
195+
196+
return wrapper
197+
198+
if method is None:
199+
# Called with parentheses
200+
return outer_wrapper
201+
202+
# Called without parentheses
203+
return outer_wrapper(method)
195204

196205

197206
def property_logger(prop):

tests/unit/core/test_log_adapter.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,18 @@ def test_method_logging_with_custom_base_name(test_method_w_custom_base):
101101
assert "pandas-method1" in api_methods
102102

103103

104+
def test_method_logging_with_custom_base__logger_as_decorator():
105+
106+
@log_adapter.method_logger(custom_base_name="pandas")
107+
def my_method():
108+
pass
109+
110+
my_method()
111+
112+
api_methods = log_adapter.get_and_reset_api_methods()
113+
assert "pandas-my_method" in api_methods
114+
115+
104116
def test_property_logging(test_instance):
105117
test_instance.my_field
106118

0 commit comments

Comments
 (0)