Shoddy Decorators (or - Pain, Tears & Decorators)

Hi all,

So, here’s what’s happening. When you add the @anvil.server.callable decorator to a function, by default it registers a server function with the name (strictly, __name__) of the function you decorated. So…

@anvil.server.callable
def my_func():
  return 42

… registers a server function called “my_func”. Unfortunately this…


def my_decorator(f):
  def wrapper():
    return 2 * f()
  
  return wrapper

@anvil.server.callable
@my_decorator
def my_func():
  return 42

… registers a server function called “wrapper”, because that’s the name of the function passed to the callable decorator. And @anvil.server.callable must come first, otherwise we won’t call our custom decorator.

The solution here is to manually specify the name of the server function, like so:


def my_decorator(f):
  def wrapper():
    return 2 * f()
  
  return wrapper

@anvil.server.callable("my_func")     # Notice manual name registration
@my_decorator
def my_func():
  return 42

We have to do this, because @anvil.server.callable can no-longer work out what the function should be called.

So, to sum up:

  • Always use @anvil.server.callable as the first decorator to your functions
  • If using multiple decorators, explicitly pass the name you want to use to call the function as an argument to @anvil.server.callable.

Hope that helps!

6 Likes