wuttjamaican.batch
¶
Batch Handlers
- class wuttjamaican.batch.BatchHandler(config)[source]¶
Base class and partial default implementation for batch handlers.
This handler class “works as-is” but does not actually do anything. Subclass must implement logic for various things as needed, e.g.:
- add_row(batch, row)[source]¶
Add the given row to the given batch.
This assumes a new row which does not yet belong to a batch, as returned by
make_row()
.It will add it to batch
rows
, callrefresh_row()
for it, and update therow_count
.
- property batch_type¶
Convenience property to return the batch type which the current handler is meant to process.
This is effectively an alias to
batch_type
.
- consume_batch_id(session, as_str=False)[source]¶
Fetch a new batch ID from the counter, and return it.
This may be called automatically from
make_batch()
.- Parameters:
session – Current db session.
as_str – Indicates the return value should be a string instead of integer.
- Returns:
Batch ID as integer, or zero-padded 8-char string.
- describe_execution(batch, user=None, **kwargs)[source]¶
This should return some text which briefly describes what will happen when the given batch is executed.
Note that Markdown is supported here, e.g.:
def describe_execution(self, batch, **kwargs): return """ This batch does some crazy things! **you cannot possibly fathom it** here are a few of them: - first - second - third """
Nothing is returned by default; subclass should define.
- Parameters:
batch – The batch in question; eligible for execution.
user – Reference to current user who might choose to execute the batch.
**kwargs – Execution kwargs for the batch; should be similar to those for
execute()
.
- Returns:
Markdown text describing batch execution.
- do_delete(batch, user, dry_run=False, progress=None, **kwargs)[source]¶
Delete the given batch entirely.
This will delete the batch proper, all data rows, and any files which may be associated with it.
- do_execute(batch, user, progress=None, **kwargs)[source]¶
Perform the execution steps for a batch.
This first calls
why_not_execute()
to make sure this is even allowed.If so, it calls
execute()
and then updatesexecuted
andexecuted_by
on the batch, to reflect current time+user.So, callers should use
do_execute()
, and subclass should overrideexecute()
.- Parameters:
batch – The batch to execute; instance of
BatchMixin
(among other classes).user –
User
who is executing the batch.progress – Optional progress indicator factory.
**kwargs – Additional kwargs as needed. These are passed as-is to
why_not_execute()
andexecute()
.
- do_populate(batch, progress=None)[source]¶
Populate the batch from initial data source(s).
This method is a convenience wrapper, which ultimately will call
populate()
for the implementation logic.Therefore callers should use this
do_populate()
method, but subclass should overridepopulate()
instead (if needed).See also
should_populate()
- you should check that before callingdo_populate()
.
- execute(batch, user=None, progress=None, **kwargs)[source]¶
Execute the given batch.
Callers should use
do_execute()
instead, which calls this method automatically.This does nothing by default; subclass must define logic.
- Parameters:
batch – A batch; instance of
BatchMixin
(among other classes).user –
User
who is executing the batch.progress – Optional progress indicator factory.
**kwargs – Additional kwargs which may affect the batch execution behavior. There are none by default, but some handlers may declare/use them.
- get_data_path(batch=None, filename=None, makedirs=False)[source]¶
Returns a path to batch data file(s).
This can be used to return any of the following, depending on how it’s called:
path to root data dir for handler’s
batch_type
path to data dir for specific batch
path to specific filename, for specific batch
For instance:
# nb. assuming batch_type = 'inventory' batch = handler.make_batch(session, created_by=user) handler.get_data_path() # => env/app/data/batch/inventory handler.get_data_path(batch) # => env/app/data/batch/inventory/03/7721fe56c811ef9223743af49773a4 handler.get_data_path(batch, 'counts.csv') # => env/app/data/batch/inventory/03/7721fe56c811ef9223743af49773a4/counts.csv
- Parameters:
batch – Optional batch instance. If specified, will return path for this batch in particular. Otherwise will return the “generic” path for handler’s batch type.
filename – Optional filename, in context of the batch. If set, the returned path will include this filename. Only relevant if
batch
is also specified.makedirs – Whether the folder(s) should be created, if not already present.
- Returns:
Path to root data dir for handler’s batch type.
- init_batch(batch, session=None, progress=None, **kwargs)[source]¶
Initialize a new batch.
This is called automatically from
make_batch()
.Default logic does nothing; subclass should override if needed.
Note
Population of the new batch should not happen here; see instead
populate()
.
- make_batch(session, progress=None, **kwargs)[source]¶
Make and return a new batch (
model_class
) instance.This will create the new batch, and auto-assign its
id
value (unless caller specifies it) by callingconsume_batch_id()
.It then will call
init_batch()
to perform any custom initialization needed.Therefore callers should use this
make_batch()
method, but subclass should overrideinit_batch()
instead (if needed).- Parameters:
session – Current db session.
progress – Optional progress indicator factory.
**kwargs – Additional kwargs to pass to the batch constructor.
- Returns:
New batch; instance of
model_class
.
- make_row(**kwargs)[source]¶
Make a new row for the batch. This will be an instance of
__row_class__
.Note that the row will not be added to the batch; that should be done with
add_row()
.- Returns:
A new row object, which does not yet belong to any batch.
- property model_class¶
Reference to the batch data model class which this batch handler is meant to work with.
This is expected to be a subclass of
BatchMixin
(among other classes).Subclass must define this; default is not implemented.
- populate(batch, progress=None)[source]¶
Populate the batch from initial data source(s).
It is assumed that the data source(s) to be used will be known by inspecting various properties of the batch itself.
Subclass should override this method to provide the implementation logic. It may populate some batches differently based on the batch attributes, or it may populate them all the same. Whatever is needed.
Callers should always use
do_populate()
instead of callingpopulate()
directly.
- refresh_row(row)[source]¶
Update the given batch row as needed, to reflect latest data.
This method is a bit of a catch-all in that it could be used to do any of the following (etc.):
fetch latest “live” data for comparison with batch input data
(re-)calculate row values based on latest data
set row status based on other row attributes
This method is called when the row is first added to the batch via
add_row()
- but may be called multiple times after that depending on the workflow.
- should_populate(batch)[source]¶
Must return true or false, indicating whether the given batch should be populated from initial data source(s).
So, true means fill the batch with data up front - by calling
do_populate()
- and false means the batch will start empty.Default logic here always return false; subclass should override if needed.
- why_not_execute(batch, user=None, **kwargs)[source]¶
Returns text indicating the reason (if any) that a given batch should not be executed.
By default the only reason a batch cannot be executed, is if it has already been executed. But in some cases it should be more restrictive; hence this method.
A “brief but descriptive” message should be returned, which may be displayed to the user e.g. so they understand why the execute feature is not allowed for the batch. (There is no need to check if batch is already executed since other logic handles that.)
If no text is returned, the assumption will be made that this batch is safe to execute.
- Parameters:
- Returns:
Text reason to prevent execution, or
None
.
The user interface should normally check this and if it returns anything, that should be shown and the user should be prevented from executing the batch.
However
do_execute()
will also call this method, and raise aRuntimeError
if text was returned. This is done out of safety, to avoid relying on the user interface.