0

I'm trying to use the following library (dbader/schedule) to schedule tasks and I'm trying to call some of the methods on the class dynamically from string values.

I have an object that comes back from a database that looks like the following:

{
  "scheduled_interval": "wednesday",
  "scheduled_time": "11:00",
  "tags": ["tag1"]
}

I am trying to achieve something like the following, but calling the functions programatically whereby the func call in bold is driven by the database value scheduled_interval:

schedule.every().wednesday.at("11:00").tags(["tag1"])

I tried using getattr as can be seen below, but i'm unsure as to how I can chain the calls in a way that doesn't include many nested getattr calls:

def add_to_schedule(task: Task):
    job = schedule.every()
    # Below should be equivalent to schedule.every().wednesday()
    job_1 = getattr(job, task.scheduled_interval)()
    job_2 = getattr(job_1, "at")
    # Below should be equivalent to schedule.every.wednesday().at("11:00")
    job_2(task.scheduled_time)
1
  • f = getattr(schedule.every, "wednesday") should get you the wednesday method of schedule.every. Commented Apr 18, 2021 at 13:00

1 Answer 1

1

You could extend operator.methodcaller by wrapping it with a function like this:

from operator import methodcaller


def chainmethodcaller(obj, calls): 
    for call in calls: 
        obj = methodcaller(*call)(obj)
    return obj

And use it like this

chainmethodcaller(
    schedule,
    [('every',), ('wednesday',), ('at', '11:00'), ('tags', ["tag1"])]
)

Feel free to add a few conditions if you don't want to pass iterables for methods without arguments.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.