问题
我正在试图弄清楚如何动态包装我的一些结构功能,为了创建一个小的mcve片段:
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())
当我尝试通过执行fab -l
列出可用的结构任务时出现问题,输出将是:
(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
问题
知道如何正确指出wrapped_foo
是一项结构任务吗?
失败的原因
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))
...
答案 0 :(得分:0)
解决此问题的一种可能方法是使用functools.wraps,下面的用法示例:
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))
通过使用上面的代码,结构将能够正确枚举包装函数,即:
(py362_32) D:\sources\personal\python\framework\pyfab>fab -l
Available commands:
foo