sopel.tools.jobs#

Sopel’s Job Scheduler: internal tool for job management.

Important

As of Sopel 5.3, this is an internal tool used by Sopel to manage internal jobs and should not be used by plugin authors. Its usage and documentation is for Sopel core development and advanced developers. It is subject to rapid changes between versions without much (or any) warning.

class sopel.tools.jobs.Job(intervals, plugin=None, label=None, handler=None, threaded=True, doc=None)#

Holds information about when a function should be called next.

Parameters:
  • intervals (iterable) – set of intervals; each is a number of seconds between calls to handler

  • plugin (str) – optional plugin name to which the job belongs

  • label (str) – optional label (name) for the job

  • handler (function) – function to be called when the job is ready to execute

  • doc (str) – optional documentation for the job

Job is a simple structure that holds information about when a function should be called next. They are best used with a Scheduler that will manage job execution when they are ready.

The function to execute is the handler, which must be a callable with this signature:

def handler(manager):
    # perform action periodically
    # return is optional

The manager parameter can be any kind of object; usually it’s an instance of sopel.bot.Sopel.

When a job is ready, you can execute it by calling its execute() method (providing the appropriate manager argument):

if job.is_ready_to_run(time.time()):
    job.execute(manager)  # marked as running
    # "next times" have been updated; the job is not running

In that case, execute takes care of the running state of the job.

Alternatively, you can use a with statement to perform action before and/or after executing the job; in that case, the with statement takes precedence, and the execute() method won’t interfere:

with job:
    # the job is now running, you can perform pre-execute action
    job.execute()  # execute the job's action, no state modification
    # the job is still marked as "running"
    # you can perform post-execute action

# outside of the with statement, the job is not running anymore

See also

The sopel.plugins.jobs.Scheduler class is specifically designed for plugins’ jobs, expecting an instance of sopel.bot.Sopel as a manager, and should be used to manipulate plugin jobs.

In all other case, the sopel.tools.jobs.Scheduler class is a generic job scheduler.

execute(manager)#

Execute the job’s handler and return its result.

Parameters:

manager (object) – used as argument to the job’s handler

Returns:

the return value from the handler’s execution

This method executes the job’s handler. It doesn’t change its running state, as this must be done by the caller:

with job:  # mark as running
    # before execution
    job.execute(manager)
    # after execution
classmethod from_callable(settings, handler)#

Instantiate a Job from the bot’s settings and a handler.

Parameters:
get_doc()#

Get the job’s documentation.

Return type:

str

A job’s documentation is a short text that can be displayed to a user.

get_job_label()#

Get the job’s label.

Return type:

str

A job can have a label, which can identify the job by string, the same way rules can be. This label can be used to manipulate or display the job’s information in a more human-readable way. Note that the label has no effect on the job’s execution.

get_plugin_name()#

Get the job’s plugin name.

Return type:

str

The job’s plugin name will be used in various places to select, register, unregister, and manipulate the job based on its plugin, which is referenced by its name.

intervals#

Set of intervals at which to execute the job.

is_ready_to_run(at_time)#

Check if this job is (or will be) ready to run at the given time.

Parameters:

at_time (int) – Timestamp to check, in seconds

Returns:

True if the job is (or will be) ready to run, False otherwise

Return type:

bool

is_running#

Running flag: it tells if the job is running or not.

This flag is set and cleared automatically by the execute() method. It is also set and cleared when the job is used with the with statement:

with job:
    # you do something before executing the job
    # this ensures that the job is marked as "running"

Note

When set manually or with the with statement, the execute() method won’t clear this attribute itself.

is_threaded()#

Tell if the job’s execution should be in a thread.

Returns:

True if the execution should be in a thread, False otherwise

Return type:

bool

classmethod kwargs_from_callable(handler)#

Generate the keyword arguments to create a new instance.

Parameters:

handler (function) – callable used to generate keyword arguments

Returns:

a map of keyword arguments

Return type:

dict

This classmethod takes the handler’s attributes to generate a map of keyword arguments for the class. This can be used by the from_callable() classmethod to instantiate a new rule object.

The expected attributes are the ones set by decorators from the sopel.plugin module.

next(current_time)#

Update next_times, assuming it executed at current_time.

Parameters:

current_time (int) – timestamp of the current time

Returns:

a modified job object

next_times#

Tracking of when to execute the job next time.

class sopel.tools.jobs.Scheduler(manager)#

Generic Job Scheduler.

Parameters:

manager (object) – manager passed to jobs as argument

Scheduler is a thread that keeps track of Jobs and periodically checks which ones are ready to execute. When ready, their execute() method is called, either in a separate thread or in the scheduler’s thread (it depends on the job’s is_threaded() method).

It can be started as any other thread:

# on bot's startup
scheduler = jobs.Scheduler(bot)
scheduler.start()  # run the thread forever

Then it runs forever until the stop() method is called, usually when the bot shuts down.

Note

Thread safety is ensured with threading’s Lock and Event when:

These actions can be performed while the scheduler is running.

Important

This is an internal tool used by Sopel to manage internal jobs and should not be used by plugin authors. Its usage and documentation is for Sopel core development and advanced developers. It is subject to rapid changes between versions without much (or any) warning.

clear_jobs()#

Clear current Job queue and start fresh.

This method is thread safe. However, it won’t cancel or stop any currently running jobs.

manager#

Job manager, used as argument for jobs.

register(job)#

Register a Job to the current job queue.

Parameters:

job (sopel.tools.jobs.Job) – job to register

This method is thread safe.

remove_callable_job(callable)#

Remove callable from the job queue.

Parameters:

callable (function) – the callable to remove

This method is thread safe. However, it won’t cancel or stop any currently running jobs.

run()#

Run forever until stop() is called.

This method waits at most a second between each iteration. At each step it retrieves the jobs that are ready for execution, and executes them. See the Job.execute() method for more information.

Internally, it loops forever until its stopping event is set.

Note

This should not be called directly, as it will be done by the threading.Thread.start() method.

stop()#

Ask the job scheduler to stop.

The scheduler thread will stop its loop over jobs to process, but it won’t join the thread, or clear its queue—this has to be done separately by the calling thread:

scheduler.stop()  # ask the scheduler to stop
scheduler.join()  # wait for the scheduler to actually stop

Note that this won’t cancel or stop any currently running jobs.

stopping#

Stopping flag. See stop().