rattail.batch.handlers

Data Batch Handlers

rattail.batch.handlers.get_batch_handler(config, batch_key, default=None, error=True)[source]
class rattail.batch.handlers.BatchHandler(config, **kwargs)[source]

Base class and partial default implementation for batch handlers. It is expected that all batch handlers will ultimately inherit from this base class, therefore it defines the implementation “interface” loosely speaking. Custom batch handlers are welcome to supplement or override this as needed, and in fact must do so for certain aspects.

pseudo_remove_rows

Flag indicating that when a row is “removed” it is merely marked as such, but is not deleted outright. This flag is on by default; if a handler sets it to false then rows will be deleted outright instead.

We’ll try to list the various attributes and methods below, in an order which somewhat follows the life cycle of a batch.

batch_key

The “batch type key” for the handler, e.g. 'labels'. This is not meant to uniquely identify the handler itself, but rather the type of batch which it handles. Therefore multiple handlers may be defined which share the same batch_key - although in practice usually each app will need only one handler per batch type.

If the handler doesn’t define this, it will be obtained from the batch_key attribute of the batch_model_class attribute.

batch_model_class

Reference to the data model class of the batch type for which this handler is responsible, e.g. LabelBatch. Each handler must define this (or inherit from one that does).

consume_batch_id(session, as_str=False)[source]

Consumes a new batch ID from the generator, and returns it.

Parameters:
  • session – Current session for Rattail DB.

  • as_str – Flag indicating whether the return value should be a string, as opposed to the default of integer.

Returns:

Batch ID as integer, or zero-padded string of 8 chars.

make_batch(session, progress=None, **kwargs)[source]

Make and return a new batch instance.

This is the method which callers should use. It invokes make_basic_batch() to actually create the new batch instance, and then init_batch() to perform any extra initialization for it. Note that the batch returned will not yet be fully populated.

make_basic_batch(session, user=None, progress=None, **kwargs)[source]

Make a new “basic” batch, with no customization beyond what is provided by kwargs, which are passed directly to the batch class constructor.

Note that the new batch instance will be added to the provided session, which will also be flushed.

Callers should use make_batch() instead of this method.

init_batch(batch, progress=None, **kwargs)[source]

Perform extra initialization for the given batch, in whatever way might make sense. Default of course is to do nothing here; handlers are free to override as needed.

Note that initial population of a batch should not happen here; see populate() for a place to define that logic.

populate_batches

Simple flag to indicate whether any/all batches will require initial population from a relevant data source. Note that this flag should be set to True if any batches may need population (its default value is False). Whether or not a given batch actually needs to be populated, is ultimately determined by the should_populate() method.

Default value is False which means no batches will be populated.

Set this to True and do not override should_populate() if you need all batches to be populated.

Set this to True and do override should_populate() if you need more fine-grained control, e.g. by inspecting the given batch.

should_populate(batch)[source]

Must return a boolean indicating whether the given batch should be populated from an initial data source, i.e. at time of batch creation. Override this method if you need to inspect the batch in order to determine whether the populate step is needed. Default behavior is to simply return the value of populate_batches.

populate_with_versioning

This flag indicates whether it’s okay for data versioning to be enabled during initial batch population.

If set to True (the default), then versioning is allowed and therefore the caller need take no special precautions when populating the batch.

If set to False then versioning is not allowed; if versioning is not enabled for the current process, the caller may populate the batch with no special precautions. However if versioning is enabled, the caller must launch a separate process with versioning disabled, in order to populate the batch.

setup_populate(batch, progress=None)[source]

Perform any setup (caching etc.) necessary for populating a batch.

do_populate(batch, user, progress=None)[source]

Perform initial population for the batch, i.e. fill it with data rows. Where the handler obtains the data to do this, will vary greatly.

Note that callers should use this method, but custom batch handlers should not override this method. Conversely, custom handlers should override the populate() method, but callers should not use that one directly.

populate(batch, progress=None)[source]

Populate the batch with initial data rows. It is assumed that the data source to be used will be known by inspecting various properties of the batch itself.

Note that callers should not use this method, but custom batch handlers should override this method. Conversely, custom handlers should not override the do_populate() method, but callers should use that one directly.

make_row(**kwargs)[source]

Make a new row for the batch. Note however 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.

add_row(batch, row)[source]

Add the given row to the given batch. This assumes it is a new row which does not yet belong to any batch. This logic performs the following steps:

The row is officially added to the batch, and is immediately “refreshed” via refresh_row().

The row is then examined to see if it has been marked as “removed” by the refresh. If it was not removed then the batch’s cached rowcount is incremented, and the after_add_row() hook is invoked.

after_add_row(batch, row)[source]

Event hook, called immediately after the given row has been “properly” added to the batch. This is a good place to update totals for the batch, to account for the new row, etc.

teardown_populate(batch, progress=None)[source]

Perform any teardown (cleanup etc.) necessary after populating a batch.

repopulate_when_refresh

Flag to indicate that when a batch is refreshed, the first step of that should be to delete all data rows for, and then re-populate the batch. The flag is False by default, in which case the batch is not repopulated, i.e. the refresh will work with existing batch rows.

refreshable(batch)[source]

This method should return a boolean indicating whether or not the handler supports a “refresh” operation for the batch, given its current condition. The default assumes a refresh is allowed unless the batch has already been executed.

refresh_with_versioning

This flag indicates whether it’s okay for data versioning to be enabled during batch refresh.

If set to True (the default), then versioning is allowed and therefore the caller need take no special precautions when populating the batch.

If set to False then versioning is not allowed; if versioning is not enabled for the current process, the caller may populate the batch with no special precautions. However if versioning is enabled, the caller must launch a separate process with versioning disabled, in order to refresh the batch.

setup_refresh(batch, progress=None)[source]

Perform any setup (caching etc.) necessary for refreshing a batch.

do_refresh(batch, user, progress=None)[source]

Perform a full data refresh for the batch, i.e. update any data which may have become stale, etc.

Note that callers should use this method, but custom batch handlers should not override this method. Conversely, custom handlers should override the refresh() method, but callers should not use that one directly.

refresh(batch, progress=None)[source]

Perform a full data refresh for the batch. What exactly this means will depend on the type of batch, and specific handler logic.

Generally speaking this refresh is meant to use queries etc. to obtain “fresh” data for the batch (header) and all its rows. In most cases certain data is expected to be “core” to the batch and/or rows, and such data will be left intact, with all other data values being re-calculated and/or reset etc.

Note that callers should not use this method, but custom batch handlers should override this method. Conversely, custom handlers should not override the do_refresh() method, but callers should use that one directly.

refresh_many(batches, user=None, progress=None)[source]

Refresh a set of batches, with given progress. Default behavior is to simply refresh each batch in succession. Any batches which are already executed are skipped.

Handlers may have to override this method if “grouping” or other special behavior is needed.

refresh_row(row)[source]

This method will be passed a row object which has already been properly added to a batch, and which has basic required fields already populated. This method is then responsible for further populating all applicable fields for the row, based on current data within the appropriate system(s).

Note that in some cases this method may be called multiple times for the same row, e.g. once when first creating the batch and then later when a user explicitly refreshes the batch. The method logic must account for this possibility.

locate_product_for_entry(session, entry, **kwargs)[source]

Convenience method which invokes rattail.products.ProductsHandler.locate_product_for_entry().

refresh_batch_status(batch)[source]

Update the batch status, as needed. This method does nothing by default, but may be overridden if the overall batch status needs to be updated according to the status of its rows. This method may be invoked whenever rows are added, removed, updated etc.

teardown_refresh(batch, progress=None)[source]

Perform any teardown (cleanup etc.) necessary after refreshing a batch.

do_remove_row(row)[source]

Remove the given row from its batch, and update the batch accordingly. Uses the following logic:

If the row’s removed flag is already set, does nothing and returns immediately.

Otherwise, it invokes remove_row() and then decrements the batch rowcount attribute.

Note that callers should use this method, but custom batch handlers should not override this method. Conversely, custom handlers should override the remove_row() method, but callers should not use that one directly.

remove_row(row)[source]

Remove the given row from its batch, and update the batch accordingly. How exactly the row is “removed” is up to this method. Default is to set the row’s removed flag, then invoke the refresh_batch_status() method.

Note that callers should not use this method, but custom batch handlers should override this method. Conversely, custom handlers should not override the do_remove_row() method, but callers should use that one directly.

get_effective_rows(batch)[source]

Should return the set of rows from the given batch which are considered “effective” - i.e. when the batch is executed, these rows should be processed whereas the remainder should not.

Parameters:

batch – A VendorCatalogBatch instance.

Returns:

List of VendorCatalogBatchRow instances.

executable(batch)[source]

This method should return a boolean indicating whether or not execution should be allowed for the batch, given its current condition.

While you may override this method, you are encouraged to override why_not_execute() instead. Default logic for this method is as follows:

If the batch is None then the caller simply wants to know if “any” batch may be executed, so we return True.

If the batch has already been executed then we return False.

If the why_not_execute() method returns a value, then we assume execution is not allowed and return False.

Finally we will return True if none of the above rules matched.

why_not_execute(batch, user=None, **kwargs)[source]

This method should inspect the given batch and, if there is a reason that execution should not be allowed for it, the method should return a text string indicating that reason. It should return None if no such reason could be identified, and execution should be allowed.

Note that it is assumed the batch has not already been executed, since execution is globally prevented for such batches. In other words you needn’t check for that as a possible reason not to execute.

auto_executable(batch)[source]

Must return a boolean indicating whether the given bath is eligible for “automatic” execution, i.e. immediately after batch is created.

execute_with_versioning

This flag indicates whether it’s okay for data versioning to be enabled during batch execution.

If set to True (the default), then versioning is allowed and therefore the caller need take no special precautions when populating the batch.

If set to False then versioning is not allowed; if versioning is not enabled for the current process, the caller may populate the batch with no special precautions. However if versioning is enabled, the caller must launch a separate process with versioning disabled, in order to execute the batch.

do_execute(batch, user, progress=None, **kwargs)[source]

Perform final execution for the batch. What that means for any given batch, will vary greatly.

Note that callers should use this method, but custom batch handlers should not override this method. Conversely, custom handlers should override the execute() method, but callers should not use that one directly.

execute(batch, progress=None, **kwargs)[source]

Execute the given batch, according to the given kwargs. This is really where the magic happens, although each handler must define that magic, since the default logic does nothing at all.

Note that callers should not use this method, but custom batch handlers should override this method. Conversely, custom handlers should not override the do_execute() method, but callers should use that one directly.

execute_many(batches, progress=None, **kwargs)[source]

Execute a set of batches, with given progress and kwargs. Default behavior is to simply execute each batch in succession. Any batches which are already executed are skipped.

Handlers may have to override this method if “grouping” or other special behavior is needed.

setup_clone(oldbatch, progress=None)[source]

Perform any setup (caching etc.) necessary for cloning batch. Note that the oldbatch arg is the “old” batch, i.e. the one from which a clone is to be created.

clone(oldbatch, created_by, progress=None, **kwargs)[source]

Clone the given batch as a new batch, and return the new batch.

teardown_clone(newbatch, progress=None)[source]

Perform any teardown (cleanup etc.) necessary after cloning a batch. Note that the newbatch arg is the “new” batch, i.e. the one which was just created by cloning the old batch.

delete(batch, delete_all_data=True, progress=None, **kwargs)[source]

Delete all data for the batch, including any related (e.g. row) records, as well as files on disk etc. This method should not delete the batch itself however.

Note that callers should not use this method, but custom batch handlers should override this method. Conversely, custom handlers should not override the do_delete() method, but callers should use that one directly.

Parameters:

delete_all_data – Flag indicating whether all data should be deleted. You should probably set this to False if in dry-run mode, since deleting all data often implies deleting files from disk, which is not transactional and therefore can’t be rolled back.

purge_batches(session, before=None, before_days=90, dry_run=False, delete_all_data=None, progress=None, **kwargs)[source]

Purge all batches which were executed prior to a given date.

Parameters:
  • before – If provided, must be a timezone-aware datetime object. If not provided, it will be calculated from the current date, using before_days.

  • before_days – Number of days before the current date, to be used as the cutoff date if before is not specified.

  • dry_run – Flag indicating that this is a “dry run” and all logic involved should be (made) aware of that fact.

  • delete_all_data – Flag indicating whether all data should be deleted for each batch being purged. This flag is passed along to delete(); see that for more info. NOTE: This flag should probably be deprecated, but so far has not been…but dry_run should be preferred for readability etc.

Returns:

Integer indicating the number of batches purged.