PROBLEM
I'm trying to figure out how to wrap dynamically some of my fabric functions, in order to do I've created a little mcve snippet:
mcve_lib.py:
from fabric.api import run
def foo():
run('hostname')
fabfile.py:
import sys
import mcve_lib
from fabric.api import settings, task, env, roles
env.roledefs = {
'servers': ['foo_server']
}
def register_function(name, module, wrapped_func):
@roles(['servers'])
@task()
def callback():
with settings():
getattr(module, wrapped_func)()
setattr(sys.modules[__name__], name, callback)
register_function("wrapped_foo", mcve_lib, "foo")
print(dir())
Problem comes when i try to list the available fabric tasks by doing fab -l
, the output will be this:
(py362_32) D:\sources\personal\python\framework\pyfab>fab -l
['__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'env', 'mcve_lib', 'register_function', 'roles', 'settings', 'sys', 'task', 'wrapped_foo']
Available commands:
callback
QUESTION
Any idea how to indicate properly that wrapped_foo
is a fabric task?
FAILED ATTEMPTS
Attempt1:
from fabric.tasks import WrappedCallableTask
...
def register_function(name, module, wrapped_func):
@roles(['servers'])
def callback():
with settings():
getattr(module, wrapped_func)()
setattr(sys.modules[__name__], name, WrappedCallableTask(callback))
...
One possible way to address this problem would be by using functools.wraps, usage example below:
import mcve_lib
import sys
from fabric.api import settings, task, env, roles
from functools import wraps
env.roledefs = {
'servers': ['foo_server']
}
def register_function(f):
@roles(['servers'])
@task
@wraps(f)
def callback():
with settings():
f()
return callback
module_funcs = [
('foo', mcve_lib.foo)
]
for dst_func, src_func in module_funcs:
setattr(sys.modules[__name__], dst_func, register_function(src_func))
By using the above code fabric will be able to enumerate properly the wrapped functions, ie:
(py362_32) D:\sources\personal\python\framework\pyfab>fab -l
Available commands:
foo