upsies.jobs.base
Abstract base class for jobs
Functions
- upsies.jobs.base.raise_if_finished(method)[source]
Decorator for
JobBasemethods that raisesRuntimeErrorif the jobis_startedandis_finished
- upsies.jobs.base.raise_if_not_started(method)[source]
Decorator for
JobBasemethods that raisesRuntimeErrorif the job was not started
- upsies.jobs.base.raise_if_started(method)[source]
Decorator for
JobBasemethods that raisesRuntimeErrorif the jobis_started
- upsies.jobs.base.raise_if_terminated(method)[source]
Decorator for
JobBasemethods that raisesRuntimeErrorif the jobis_terminated
- upsies.jobs.base.unless_job_is_finished(method)[source]
Decorator for
JobBasemethods that blocks calls to the decorated method if the jobis_finishedIf a job gets terminated early, the
DaemonProcessis usually still running and can be reporting information back to the main process by calling a callback method. If the callback method callsadd_output(), for example, this raises aRuntimeErrorbecause adding output on a finished job is a bad idea.This should only happen in error cases, and ignoring callbacks should be fine because we are only interested in shutting everyting down in a somewhat controlled manner.
Classes
- class upsies.jobs.base.JobBase(*, home_directory=None, cache_directory=None, cache_id='', ignore_cache=False, no_output_is_ok=False, hidden=False, autostart=True, guaranteed=False, precondition=None, prejobs=(), callbacks={}, **kwargs)[source]
Bases:
ABCBase class for all jobs
- Parameters:
home_directory (str) – Directory that is used to store created files
cache_directory (str) – Directory that is used to cache output
ignore_cache (str) – Whether cached output and previously created files should not be re-used
no_output_is_ok (bool) – Whether the job can succeed without any
outputhidden –
Whether to hide the job’s output in the UI
This can be a
boolor callable that takes no arguments and returns abool.autostart (bool) – Whether this job is started automatically
guaranteed (bool) – Whether this job should run and finish even if other jobs fail
precondition – Callable that gets no arguments and returns whether this job is enabled or disabled
prejobs – Sequence of
prerequisite jobscallbacks – Mapping of
signalnames to callable or sequence of callables toregister()for that signal
Any additional keyword arguments are passed on to
initialize().If possible, arguments should be validated before creating a job instance. This means we can fail early before any sibling jobs have started doing expensive work (e.g. torrent creation) that has to be cancelled.
- abstract property name
Internal name (e.g. for the cache file name)
- abstract property label
User-facing name
- property home_directory
Directory that is used to store files (e.g. generated screenshots, torrent files, etc) or empty string
The directory is guaranteed to exist.
- property cache_directory
Path to existing directory that stores
cache_fileSubclasses may use this directory for storing custom cache files.
This directory is guaranteed to exist.
- property ignore_cache
Whether cached output and previously created files should not be re-used
Whether to hide this job’s output in the UI
This can also be set to a callable that takes no arguments and returns a
boolvalue.
- property autostart
Whether this job is started automatically by the UI
The UI must check this value before calling
start.If this value is falsy,
start()must be called manually.
- property is_guaranteed
Whether this job should run and finish even if other jobs fail
This means that calling
terminate()on a guaranteed job has no effect.
- property is_enabled
Whether this job is allowed to
start()A job is enabled if
preconditionreturns anything truthy and allprejobsare either finished or disabled.This property must be checked by the UI every time any job finishes and when the refresh_ui
signalis emitted. If this property is True, this job must bestartedand displayed (unless it ishidden).
- property signal
SignalinstanceThe following signals are added by the base class. Subclasses can add their own signals.
startedEmitted by
start()if job is not disabled. Unlikerunning, this signal is also emitted if output is read from cache andrun()is not called. Registered callbacks get the job instance as a positional argument.runningEmitted when a task for
run()was created bystart(). Unlikestarted, this signal is only called if no cached output is read. Registered callbacks get the job instance as a positional argument.finishedEmitted when a job
is_finished. A job is finished when all its tasks are done or cancelled or if cached output from a previous run is successfully read. Registered callbacks get the job instance as a positional argument.outputEmitted when
add_output()is called or when output is read from cache. Registered callbacks get the value passed toadd_output()as a positional argument.infoEmitted when
infois set. Registered callbacks get the newinfoas a positional argument.warningEmitted when
warn()is called. Registered callbacks get the value passed towarn()as a positional argument.errorEmitted when
error()is called. Registered callbacks get the value passed toerror()as a positional argument.promptEmitted when
add_prompt()is called. Registered callbacks get thePromptinstance passed toadd_prompt()as a positional argument. The user interface MUST subscribe to this signal and present dialogs to the user when it is emitted.refresh_uiEmitted when the user interface should update the focused widget, remove any finished jobs, start the next interactive job, etc. The UI usually only does this when a job finishes. This signal allows a job to force the refresh immediately. For example, emitting this signal may be necessary when a series of
promptsare added by the same job. Registered callbacks get no arguments.
- property siblings
Map job names to job instances for all instantiated jobs
- receive_all(job_name, signal, *, only_posargs=False)[source]
Iterate over signal emissions from another job
This is a convenience wrapper around
siblingsandreceive_all().These calls are mostly equivalent:
job.siblings['other_job'].receive_all('some_signal') job.receive_all('other_job, 'some_signal')
- Raises:
ValueError – if no job has the name job_name
- receive_one(job_name, signal, *, only_posargs=False)[source]
Return the first signal emission from another job
This is a convenience wrapper around
siblingsandreceive_one().Note
Because this will always only return the first emission, you probably shouldn’t use this to receive signals that are emitted multiple times.
These calls are equivalent:
job.siblings['other_job'].receive_one('some_signal') job.receive_one('other_job, 'some_signal')
- Raises:
ValueError – if no job has the name job_name
- async wait_for(job_name, signal)[source]
Wait for signal from job_name
This is a convenience wrapper around
siblingsandwait_for().Note
Because this will always only return the first emission, you probably shouldn’t use this to receive signals that are emitted multiple times.
These calls are equivalent:
job.siblings['other_job'].wait_for('some_signal') job.wait_for('other_job, 'some_signal')
- Raises:
ValueError – if no job has the name job_name
- property precondition
Callable that gets no arguments and returns whether this job should be
startedSee also
is_enabled.
- property prejobs
Sequence of prerequisite
jobsAll prejobs must be either
finishedordisabledbefore this job can start.See also
is_enabled.
- initialize()[source]
Called by
__init__()with additional keyword argumentsThis method should handle its arguments and return quickly.
- abstractmethod async run()[source]
Do the work
This method is called by
start(). Its coroutine is passed toadd_task().Any keyword arguments passed to
initialize()are available viakwargs.The job
is_finishedwhen alladded tasksare done or cancelled. (See alsofinalize()andfinalization().)This method may call
add_task()if more tasks are required.
- start()[source]
Load cached output if available, otherwise call
run()This method must be called by the UI if
autostartis True.Nothing is done if the job is already
started,finished,terminated. or notenabled,
- property is_started
Whether
start()was called while this jobis_enabledNote
This does not mean that
run()was called. A job is also considered to be started if output is read from cache.
- add_task(coro, callback=None)[source]
Run asynchronous coroutine in background task
The job
is_finishedwhen all added tasks are done or cancelled.Any exceptions from coro are raised by
wait_finished()or made available viaraised.- Parameters:
coro – Any awaitable object
callback –
Callable that is called with the return value or exception of coro
callback is not called if the task was cancelled.
- Returns:
asyncio.Taskinstance
- add_prompt(prompt)[source]
Create a dialog in the user interface
- Parameters:
prompt –
Promptobject that specifies the dialog and handles callbacks- Returns:
prompt so the
add_prompt()call can be conveniently awaited to get theresult
- async wait_started()[source]
Block until
start()is called successfullyThis is a convenience wrapper around
receive_one()that waits for the emission of thestartedsignal.See
signal.
- async wait_running()[source]
Block until
run()is calledThis is a convenience wrapper around
receive_one()that waits for the emission of therunningsignal.See
signal.
- async wait_finished()[source]
Block until all
added tasksare either done or cancelled and jobis_finishedBut first, wait for any
prejobsto finish and then check ifpreconditionreturns anything truthy. Thenwait_started()is called, so it is ok to call this method if the job was not started yet.If
finalization()was called,finalize()must be called before this method returns.Any exception raised by tasks are ignored here. It can be accessed via
raised.
- terminate(reason=None)[source]
Cancel all
added tasksDo nothing if job
is_finishedoris_terminated.- Parameters:
reason – Why this job is terminated (only used for debugging)
- property is_terminated
Whether
terminate()was called to end this job prematurely
- finalize()[source]
Unblock any calls awaiting
finalization()orwait_finished()
- async finalization()[source]
Block until
finalize()is calledThis is useful for interactive jobs that don’t have running tasks at all times. You can simply
await self.finalization()inrun()and callfinalize()later to finish the job.
- property is_finished
Whether all tasks are done
If
finalization()is awaited,finalize()must also be called.Before this job is started, None is returned.
- property exit_code
0 if job was successful,
> 0otherwise, None before jobis_finished
- add_output(output)[source]
Append output to
outputand emitoutputsignalNote
All output is converted to
str.
- property output
Immutable sequence of strings passed to
add_output()This value is supposed to be the effective product of running this job and should be usable by other jobs (e.g. URL(s) or path(s)).
- property info
Additional information (
str) that is only displayed to the user while the job is runningSetting this property emits the
infosignal.
- property warnings
Sequence of non-critical error messages the user can override or resolve
Unlike
errors, warnings do not imply failure.
- error(error)[source]
Append error to
errors, emiterrorsignal andterminate()this job
- property errors
Sequence of critical errors (strings or exceptions)
By default,
exit_codeis non-zero if any errors were reported.
- exception(exception)[source]
Make exception available as
raisedunless it is already setWarning
This method is mostly for internal use. Setting an exception means you want to throw a traceback at the user.
- Parameters:
exception (Exception) – Exception instance (nothing is done if this argument is falsy)
- property raised
Exception passed to
exception()
- property cache_file
File path in
cache_directoryto store cachedoutputinIf this property returns None, cache is not read or written.
- property cache_id
Any object that makes a job’s output unique
If this property returns None,
cache_fileis not read or written.If this property returns any other object, it is converted to a string and appended to
name. Multibyte characters and directory delimiters are replaced.By default, the cache_id argument from initialization is used, which is an empty string by default.