Lets say I have a function:
def foo(arg1: int, arg2: Text):
print(arg1, arg2)
Given foo, how could I programmatically create a second function that has the same function signature but just passes? e.g.
def foo(arg1: int, arg2: Text):
pass
Context:
I have a worker library that looks like:
registry = {}
def foo(arg1: int, arg2: Sequence[Dict[Text, Any]]):
run_foo()
registry['foo'] = foo
while true:
message = json.loads(queue.get_message())
registry[message['name']](*message['args'])
and I have an API server library that looks something like this:
def enqueue(fn_name: str, fn_args: Any):
message = json.dumps({'name': fn_name, 'args': fn_args})
queue.send_message(message)
The API server and the worker binaries have a messenger queue between them, like RabbitMQ or SQS or whatever. But the API server can import the worker as a library, and thereby get all of the function signatures of the worker. I am running pytype, a static python type checker. I want to modify the enqueue function to do something like:
import workerlib
def enqueue(fn_name: str, fn_args: Any):
# This should 'simulate' a fn call to foo with the same sig,
# but without calling it because the function just passes now.
# The simulation would be caught by pytype, which would give me
# static type checking across the messenger queue boundary
foo = workerlib.registry[fn_name]
foo = make_fn_pass(foo)
foo(*fn_args)
message = json.dumps({'name': fn_name, 'args': fn_args})
queue.send_message(message)
Open to suggestions on how to do this other ways. The goal is to get the static type checker to understand what function is intended, even though the function itself is not being called directly.
EDIT One possible approach might be to do something like:
import types
def copy_func(f, name=None):
fn = types.FunctionType(f.__code__, f.__globals__, name or f.__name__,
f.__defaults__, f.__closure__)
# in case f was given attrs (note this dict is a shallow copy):
fn.__dict__.update(f.__dict__)
return fn
def foo(arg1, arg2):
print(arg1, arg2)
def dummy(*args, **kwargs):
pass
x = copy_func(foo)
x.__code__ = dummy.__code__
x(1, 2) # Succeed pytype, and does nothing at runtime.
x(1, 2, 3) # SHOULD fail pytype, does nothing at runtime.
foo(1, 2) # Works as normal.
The problem here is that pytype cannot track the function signature of foo through the copy_func function, so the call to x(1, 2, 3) doesn't trigger an error from pytype.