How to pass parameters to modify a decorator that takes a function with parameters

I have to create a decorator that has parameters, and uses those parameters to modify a function also with parameters. This is a general question of how to decorate any function with parameters with additional parameters, but for my specific case, I need it for Django RQ, to determine based on an environment variable whether to use an asynchronous queue that is activated through a decorator.

There is a function in Django RQ called django_rq.job that I use like this (it requires args and kwargs):

@django_rq.job('default', timeout=3600, result_ttl=86400)
def upload_missing_documents_s3(batches, projects, uuid_val):
   pass

# A simpler example:
@django_rq.job('default', timeout=3600, result_ttl=86400)
def sample(content):
    file = open("temp/sample.txt", "w+")
    file.write(content)
    file.close()

I need to essentially create a decorator that will take a boolean value and return either the modified function (with a job) or the unmodified function (no job). But I can’t seem to figure it out, because there are two sets of parameters. I tried something like this:

#My attempt, I don't think it works...
def conditional_django_job(function_name, *args, **kwargs):
    if settings.NO_QUEUE:
        return function_name
    else:
        return django_rq.job("default", None, *args, **kwargs)(function_name)

@conditional_django_job('default', timeout=3600, result_ttl=86400)
def sample(content):
    file = open("temp/sample.txt", "w+")
    file.write(content)
    file.close()

I also tried with an inner function, but I can’t seem to get it right. How do I implement a decorator with parameters that decorates a function?

I tried looking at this SO question but it didn’t seem to have an example where both the decorator and the function have parameters: How to make function decorators and chain them together?

Thank you!

Source: Python Questions

LEAVE A COMMENT