Skip to content

Decorators

save_code(obj)

A decorator function which save the code of the class/function in a file (to be kept along with the training logs) File name will be according to the class/function name

usage:

@save_code MyClass(): ...

def foo():
    ...

@save_code
def do_something():
    ...

This example will generate two files named MyClass.py and do_something.py, that will be saved in the checkpoint directory and uploaded to remote storage (if defined). the text of the class and the function will also be added to the tensorboard (or any other tracking service)

Source code in src/super_gradients/common/decorators/code_save_decorator.py
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
def save_code(obj):
    """
    A decorator function which save the code of the class/function in a file (to be kept along with the training logs)
    File name will be according to the class/function name

    usage:

    @save_code
    MyClass():
        ...

        def foo():
            ...

        @save_code
        def do_something():
            ...

    This example will generate two files named MyClass.py and do_something.py, that will be saved in the checkpoint directory
    and uploaded to remote storage (if defined). the text of the class and the function will also be added to the tensorboard (or
    any other tracking service)
    """
    code = inspect.getsource(obj)
    name = obj.__name__
    saved_codes[name] = code
    return obj

save_file(obj)

A decorator function which save the code of the entire file (to be kept along with the training logs). one call to this decorator in the file is enough to save the entire file

usage:

@save_file MyClass(): ...

def foo():
    ...

def do_something():
    ...

This example will save the file containing this code in the checkpoint directory and uploaded to remote storage (if defined). the content of the file will also be added to the tensorboard (or any other tracking service)

Source code in src/super_gradients/common/decorators/code_save_decorator.py
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
def save_file(obj):
    """
    A decorator function which save the code of the entire file (to be kept along with the training logs).
    one call to this decorator in the file is enough to save the entire file


    usage:

    @save_file
    MyClass():
        ...

        def foo():
            ...

        def do_something():
            ...

    This example will save the file containing this code in the checkpoint directory and uploaded to remote storage (if defined).
    the content of the file will also be added to the tensorboard (or any other tracking service)

    """
    path = inspect.getsourcefile(obj)
    name = os.path.split(path)[-1]
    with open(path, "r") as f:
        code = f.read()
    saved_codes[name] = code
    return obj

deci_class_logger()

This decorator wraps every class method with deci_func_logger decorator. It works by checking if class method is callable and if so it will set a new decorated method as the same method name.

Source code in src/super_gradients/common/decorators/deci_logger.py
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
def deci_class_logger():
    """
    This decorator wraps every class method with deci_func_logger decorator.
    It works by checking if class method is callable and if so it will set a new decorated method as the same method name.
    """

    def wrapper(cls):
        # TODO: Not Working - Breaks the code, tests does not pass (s3 connector, platform...)
        # TODO: Fix problem with ExplicitParamValidation error (arguments not passed)
        # TODO: Run ALL test suite of deci2 (NOT circieCI test suite, but ALL the tests under tests folders)
        # TODO: Delete/Update all failing tests.

        # for attr in cls.__dict__:
        #     if callable(getattr(cls, attr)) and attr != '__init__':
        #         decorated_function = deci_func_logger(name=cls.__name__)(getattr(cls, attr))
        #         if type(cls.__dict__[attr]) is staticmethod:
        #             decorated_function = staticmethod(decorated_function)
        #         setattr(cls, attr, decorated_function)
        return cls

    return wrapper

deci_func_logger(_func=None, *, name='abstract_decorator')

This decorator is used to wrap our functions with logs. It will log every enter and exit of the functon with the equivalent parameters as extras. It will also log exceptions that raises in the function. It will also log the exception time of the function.

How it works:` First it will check if the decorator called with name keyword. If so it will return a new decorator that its logger is the name parameter. If not it will return a new decorator that its logger is the wrapped function name. Then the return decorator will return a new function that warps the original function with the new logs. For further understanding advise real-python "fancy decorators documentation"

Parameters:

Name Type Description Default
_func

used when called without name specify. dont pass it directly

None
name str

The name of the logger to save logs by.

'abstract_decorator'

Returns:

Type Description

a decorator that wraps function with logs logic.

Source code in src/super_gradients/common/decorators/deci_logger.py
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
def deci_func_logger(_func=None, *, name: str = "abstract_decorator"):
    """
    This decorator is used to wrap our functions with logs.
    It will log every enter and exit of the functon with the equivalent parameters as extras.
    It will also log exceptions that raises in the function.
    It will also log the exception time of the function.

    How it works:`
        First it will check if the decorator called with name keyword.
        If so it will return a new decorator that its logger is the name parameter.
        If not it will return a new decorator that its logger is the wrapped function name.
        Then the return decorator will return a new function that warps the original function with the new logs.
        For further understanding advise real-python "fancy decorators documentation"

    :param _func:    used when called without name specify. dont pass it directly
    :param name:     The name of the logger to save logs by.

    :return: a decorator that wraps function with logs logic.
    """
    # TODO: Not Working - Breaks the code, tests does not pass (s3 connector, platform...)
    # TODO: Fix problem with ExplicitParamValidation error (arguments not passed)
    # TODO: Run ALL test suite of deci2 (NOT circieCI test suite, but ALL the tests under tests folders)
    # TODO: Delete/Update all failing tests.

    # def deci_logger_decorator(fn):
    #
    # @functools.wraps(fn)
    # def wrapper_func(*args, **kwargs):
    #     try:
    #
    #         try:
    #             logger.debug(f"Start: {fn.__name__}", extra={"args": args, "kwargs": kwargs})
    #             time1 = time.perf_counter()
    #         except Exception:
    #             # failed to write log - continue.
    #             pass
    #
    #         result = fn(*args, **kwargs)
    #
    #         try:
    #             time2 = time.perf_counter()
    #             logger.debug(f"End: {fn.__name__}",
    #                          extra={'duration': (time2 - time1) * 1000.0, 'return_value': result})
    #         except Exception:
    #             # failed to write log - continue.
    #             pass
    #
    #         return result
    #
    #     except Exception as ex:
    #         # This exception was raised from inside the function call
    #         logger.error(f"Exception: {ex}", exc_info=ex)
    #         raise ex
    #
    # return wrapper_func

    # if _func is None:
    #     logger = get_logger(name)
    #     return deci_logger_decorator
    # else:
    #     logger = get_logger(_func.__name__)
    #     return deci_logger_decorator(_func)

    return _func

resolve_param(param_name, factory)

A decorator function which resolves a specific named parameter using a defined Factory usage: @resolve_param(my_param_name, MyFactory()) def foo(self, a, my_param_name, b, c) ...

this will use MyFactory to generate an object from the provided value of my_param_name
Source code in src/super_gradients/common/decorators/factory_decorator.py
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
def resolve_param(param_name: str, factory: AbstractFactory):
    """
    A decorator function which resolves a specific named parameter using a defined Factory
    usage:
        @resolve_param(my_param_name, MyFactory())
        def foo(self, a, my_param_name, b, c)
            ...

        this will use MyFactory to generate an object from the provided value of my_param_name
    """

    def inner(func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            if param_name in kwargs:
                # handle kwargs
                kwargs[param_name] = factory.get(kwargs[param_name])
            else:
                # handle args
                func_args = inspect.getfullargspec(func).args
                if param_name in func_args:
                    index = func_args.index(param_name)
                    if index < len(args):
                        new_value = factory.get(args[index])
                        args = _assign_tuple(args, index, new_value)
            return func(*args, **kwargs)

        return wrapper

    return inner

SingletonMeta

Bases: type

A Singleton meta class. A class that derives from this class will have only 1 instance of that type for the process.

Source code in src/super_gradients/common/decorators/singleton.py
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
class SingletonMeta(type):
    """
    A Singleton meta class.
    A class that derives from this class will have only 1 instance of that type for the process.
    """

    _instances = {}

    def __call__(cls, *args, **kwargs):
        if cls not in cls._instances:
            cls._instances[cls] = super(SingletonMeta, cls).__call__(*args, **kwargs)
        return cls._instances[cls]

singleton(cls)

A singleton decorator. Returns a wrapper objects. A call on that object returns a single instance object of decorated class. Use the wrapped attribute to access decorated class directly in unit tests

Source code in src/super_gradients/common/decorators/singleton.py
32
33
34
35
36
37
38
def singleton(cls):
    """
    A singleton decorator. Returns a wrapper objects. A call on that object
    returns a single instance object of decorated class. Use the __wrapped__
    attribute to access decorated class directly in unit tests
    """
    return _SingletonWrapper(cls)