Skip to content
This repository has been archived by the owner on Jul 3, 2023. It is now read-only.

Commit

Permalink
Refactors decorator counter methodology
Browse files Browse the repository at this point in the history
Now it's a decorator on the __call__ function.

That way we decouple the logic for telemetry needs -- without
it explicitly living within the NodeTransformLifecycle class.
I mean it's still coupled, it's just we can now change
that functionality more clearly.
  • Loading branch information
skrawcz committed Dec 27, 2022
1 parent 57e209b commit b0d4c4d
Showing 1 changed file with 22 additions and 9 deletions.
31 changes: 22 additions & 9 deletions hamilton/function_modifiers/base.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import abc
import collections
import functools
from typing import Any, Callable, Collection, Dict, List, Tuple

from hamilton import node
Expand All @@ -22,6 +23,26 @@ def sanitize_function_name(name: str) -> str:
COUNTER = collections.defaultdict(int)


def track_decorator_usage(call_fn: Callable) -> Callable:
"""Decorator to wrap the __call__ to count decorator usage.
:param call_fn: the `__call__` function.
:return: the wrapped call function.
"""

@functools.wraps(call_fn)
def replace__call__(self, fn):
global COUNTER
if self.__module__.startswith("hamilton.function_modifiers"):
# only capture counts for hamilton decorators
COUNTER[self.__class__.__name__] = COUNTER[self.__class__.__name__] + 1
else:
COUNTER["custom_decorator"] = COUNTER["custom_decorator"] + 1
return call_fn(self, fn)

return replace__call__


class NodeTransformLifecycle(abc.ABC):
"""Base class to represent the decorator lifecycle. Common among all node decorators."""

Expand Down Expand Up @@ -51,14 +72,7 @@ def validate(self, fn: Callable):
"""
pass

def count_decorator_usage(self):
global COUNTER
if self.__module__.startswith("hamilton.function_modifiers"):
# only capture counts for hamilton decorators
COUNTER[self.__class__.__name__] = COUNTER[self.__class__.__name__] + 1
else:
COUNTER["custom_decorator"] = COUNTER["custom_decorator"] + 1

@track_decorator_usage
def __call__(self, fn: Callable):
"""Calls the decorator by adding attributes using the get_lifecycle_name string.
These attributes are the pointer to the decorator object itself, and used later in resolve_nodes below.
Expand All @@ -67,7 +81,6 @@ def __call__(self, fn: Callable):
:return: The function again, with the desired properties.
"""
self.validate(fn)
self.count_decorator_usage()
lifecycle_name = self.__class__.get_lifecycle_name()
if hasattr(fn, self.get_lifecycle_name()):
if not self.allows_multiple():
Expand Down

0 comments on commit b0d4c4d

Please sign in to comment.