def publish(config, source=None, template=None, destination=None, jinja_env=None, no_write=False):
if not isinstance(config, Config):<EOL><INDENT>raise PublishError(<EOL>"<STR_LIT>"<EOL>"<STR_LIT>".format(type(config).__name__))<EOL><DEDENT>if source is None and template is None:<EOL><INDENT>raise PublishError('<STR_LIT>')<EOL><DEDENT>variables = config.variables<EOL>if source:<EOL><INDENT>all_block, extracted_variables = linker.link(source)<EOL>variables.update(extracted_variables)<EOL>block_variables = {}<EOL>for rule in config.rules:<EOL><INDENT>if rule.applies(source, destination):<EOL><INDENT>if isinstance(rule, VariableRule):<EOL><INDENT>variables.update(rule.apply(str(all_block)))<EOL><DEDENT>else:<EOL><INDENT>all_block.apply_rule(rule)<EOL><DEDENT><DEDENT><DEDENT>block_variables.update(linker.get_block_dict(all_block))<EOL>variables['<STR_LIT>'] = block_variables   <EOL><DEDENT>if template:<EOL><INDENT>if not jinja_env:<EOL><INDENT>jinja_env = jinja2.Environment(loader=jinja2.FileSystemLoader(config.template_dirs))<EOL><DEDENT>jinja_template = jinja_env.get_template(template)<EOL>result = jinja_template.render(variables)<EOL>iterations = <NUM_LIT:0><EOL>while config.recursively_evaluate_jinja_expressionsand iterations < _MAX_JINJA_RECURSIVE_DEPTH + <NUM_LIT:1>and  _jinja_expression_re.search(result):<EOL><INDENT>if iterations == _MAX_JINJA_RECURSIVE_DEPTH:<EOL><INDENT>raise PublishError('<STR_LIT:\n>'.join([<EOL>'<STR_LIT>'<EOL>'<STR_LIT>',<EOL>result]))<EOL><DEDENT>jinja_env = jinja2.Environment(loader=jinja2.DictLoader({'<STR_LIT>': result}))<EOL>jinja_template = jinja_env.get_template('<STR_LIT>')<EOL>result = jinja_template.render(variables)<EOL>iterations += <NUM_LIT:1><EOL><DEDENT><DEDENT>else:<EOL><INDENT>result = variables['<STR_LIT>']['<STR_LIT:all>']<EOL><DEDENT>if not no_write and destination:<EOL><INDENT>destination_dir = os.path.dirname(destination)<EOL>if destination_dir != '<STR_LIT>' and not os.path.isdir(destination_dir):<EOL><INDENT>os.makedirs(destination_dir)<EOL><DEDENT>with open(destination, '<STR_LIT:w>') as f:<EOL><INDENT>f.write(result)<EOL><DEDENT><DEDENT>return result<EOL>
Given a config, performs an end-to-end publishing pipeline and returns the result:

        linking -> compiling -> templating -> writing

    NOTE: at most one of source and template can be None. If both are None, the publisher
    effectively has nothing to do; an exception is raised.

    PARAMETERS:
    config      -- Config; a context that includes variables, compiler options, and templater
                   information.
    source      -- str; path to a source file, relative to the current working directory. If None,
                   the publisher effectively becomes a templating engine.
    template    -- str; path to a Jinja template file. Templar treats the path as relative to the
                   list of template directories in config. If the template cannot be found relative
                   to those directories, Templar finally tries the path relative to the current
                   directory.

                   If template is None, the publisher effectively becomes a linker and compiler.
    destination -- str; path for the destination file.
    jinja_env   -- jinja2.Environment; if None, a Jinja2 Environment is created with a
                   FileSystemLoader that is configured with config.template_dirs. Otherwise, the
                   given Jinja2 Environment is used to retrieve and render the template.
    no_write    -- bool; if True, the result is not written to a file or printed. If False and
                   destination is provided, the result is written to the provided destination file.

    RETURNS:
    str; the result of the publishing pipeline.