Decorator to log function args in 'to.init_args'
from fastcore.test import *
from nbdev.showdoc import *
from fastcore.nb_imports import *

Note that this module may be removed in a future version. Use store_attr instead where possible.

log_args[source]

log_args(f=None, to_return=False, but=None, but_as=None)

Decorator to log function args in 'to.init_args'

class tst:
    @log_args
    def __init__(self, a, b, c=3, d=4):
        pass
test_eq(tst(1,2).init_args, {f'tst.__init__.{k}':v for k,v in dict(a=1,b=2,c=3,d=4).items()})

Use log_args to save function args in to.init_args. Optional args are:

  • to_return: applies to return value if True (for functions), otherwise to self (for class instances)
  • but: args that we do not want to save separated by ','
  • but_as: pull but arg from another log_args (which cannot have used to_return=True)

Notes:

  • @log_args needs to be placed below @patch and above @funcs_kwargs or @delegates
  • when wrapping a class, it will wrap its __init__ method
class tst:
    @log_args
    def __init__(self, a, b, c=3, d=4): pass
test_eq(tst(1,2).init_args, {f'tst.__init__.{k}':v for k,v in dict(a=1,b=2,c=3,d=4).items()})

@log_args
class tst:
    def __init__(self, a, b, c=3, d=4): pass
test_eq(tst(1,2).init_args, {f'tst.__init__.{k}':v for k,v in dict(a=1,b=2,c=3,d=4).items()})

@log_args(but='a,c')
class tst:
    def __init__(self, a, b, c=3, d=4): pass
test_eq(tst(1,2).init_args, {f'tst.__init__.{k}':v for k,v in dict(b=2,d=4).items()})

class tst: pass
@log_args(to_return=True)
def tst_f(a,b): return tst
test_eq(tst_f(1,2).init_args, {f'tst_f.{k}':v for k,v in dict(a=1,b=2).items()})

@log_args
@funcs_kwargs
class tst:
    _methods='a'.split()    
    def __init__(self, **kwargs): pass
test_eq(tst(a=noop).init_args['tst.__init__.a'], noop)
class tst_base:
    def __init__(self, a=None): pass

@log_args
@delegates(tst_base)
class tst:
    def __init__(self, **kwargs): pass
test_eq(tst(a=1).init_args['tst.__init__.a'], 1)

@log_args
class tst_parent:
    def __init__(self, a): pass
@log_args
class tst(tst_parent):
    def __init__(self, b): super().__init__(a=b)
test_eq(tst(1).init_args, {'tst_parent.__init__.a': 1, 'tst.__init__.b': 1})

class tst_ref:
    def __init__(self, a, b, c, d): pass

class tst:
    def __init__(self, a=1, b=2, c=3, d=4): pass
test_stdout(lambda: log_args(tst, but_as=tst_ref.__init__),
            "Did not find but_as with tst.__init__ in ['tst_ref.__init__']")
@log_args(but='a,b')
class tst_ref:
    def __init__(self, a, b, c, d): pass

@log_args(but_as=tst_ref.__init__)
class tst:
    def __init__(self, a=1, b=2, c=3, d=4):
        pass
test_eq(tst().init_args, {'tst.__init__.c': 3, 'tst.__init__.d': 4})

@log_args(but='a,b')
class tst_ref:
    def __init__(self, a, b, c, d): pass

@log_args(but='c', but_as=tst_ref.__init__)
class tst:
    def __init__(self, a=1, b=2, c=3, d=4): pass
test_eq(tst().init_args, {'tst.__init__.d': 4})