Wrap file generation in a transaction, moving to output if finishes.

    The initial argument can be the world descriptive `data` dictionary, or
    a `config` dictionary. This is used to identify global settings for
    temporary directories to create transactional files in.

def file_transaction(*data_and_files):
    """Wrap file generation in a transaction, moving to output if finishes.

    The initial argument can be the world descriptive `data` dictionary, or
    a `config` dictionary. This is used to identify global settings for
    temporary directories to create transactional files in.
    """
    with _flatten_plus_safe(data_and_files) as (safe_names, orig_names):
        # remove any half-finished transactions
        map(utils.remove_safe, safe_names)
        # no need for try except block here,
        # because exceptions and tmp dir removal
        # are handled by tx_tmpdir contextmanager
        if len(safe_names) == 1:
            yield safe_names[0]
        else:
            yield tuple(safe_names)

        for safe, orig in zip(safe_names, orig_names):
            if os.path.exists(safe):
                _move_tmp_files(safe, orig)