def render(input, saltenv='base', sls='', argline='', **kws):
    gen_start_state = False
    no_goal_state = False
    implicit_require = False

    def process_sls_data(data, context=None, extract=False):
        sls_dir = ospath.dirname(sls.replace('.', ospath.sep)) if '.' in sls else sls
        ctx = dict(sls_dir=sls_dir if sls_dir else '.')

        if context:
            ctx.update(context)

        tmplout = render_template(
                StringIO(data), saltenv, sls, context=ctx,
                argline=rt_argline.strip(), **kws
        )
        high = render_data(tmplout, saltenv, sls, argline=rd_argline.strip())
        return process_high_data(high, extract)

    def process_high_data(high, extract):
        # make a copy so that the original, un-preprocessed highstate data
        # structure can be used later for error checking if anything goes
        # wrong during the preprocessing.
        data = copy.deepcopy(high)
        try:
            rewrite_single_shorthand_state_decl(data)
            rewrite_sls_includes_excludes(data, sls, saltenv)

            if not extract and implicit_require:
                sid = has_names_decls(data)
                if sid:
                    raise SaltRenderError(
                        '\'names\' declaration(found in state id: {0}) is '
                        'not supported with implicitly ordered states! You '
                        'should generate the states in a template for-loop '
                        'instead.'.format(sid)
                    )
                add_implicit_requires(data)

            if gen_start_state:
                add_start_state(data, sls)

            if not extract and not no_goal_state:
                add_goal_state(data)

            rename_state_ids(data, sls)

            # We must extract no matter what so extending a stateconf sls file
            # works!
            extract_state_confs(data)
        except SaltRenderError:
            raise
        except Exception as err:
            log.exception(
                'Error found while pre-processing the salt file '
                '{0}:\n{1}'.format(sls, err)
            )
            from salt.state import State
            state = State(__opts__)
            errors = state.verify_high(high)
            if errors:
                raise SaltRenderError('\n'.join(errors))
            raise SaltRenderError('sls preprocessing/rendering failed!')
        return data
    # ----------------------
    renderers = kws['renderers']
    opts, args = getopt.getopt(argline.split(), 'Gosp')
    argline = ' '.join(args) if args else 'yaml . jinja'

    if ('-G', '') in opts:
        no_goal_state = True
    if ('-o', '') in opts:
        implicit_require = True
    if ('-s', '') in opts:
        gen_start_state = True

    if ('-p', '') in opts:
        data = process_high_data(input, extract=False)
    else:
        # Split on the first dot surrounded by spaces but not preceded by a
        # backslash. A backslash preceded dot will be replaced with just dot.
        args = [
            arg.strip().replace('\\.', '.')
            for arg in re.split(r'\s+(?<!\\)\.\s+', argline, 1)
        ]
        try:
            name, rd_argline = (args[0] + ' ').split(' ', 1)
            render_data = renderers[name]  # e.g., the yaml renderer
            if implicit_require:
                if name == 'yaml':
                    rd_argline = '-o ' + rd_argline
                else:
                    raise SaltRenderError(
                        'Implicit ordering is only supported if the yaml renderer '
                        'is used!'
                    )
            name, rt_argline = (args[1] + ' ').split(' ', 1)
            render_template = renderers[name]  # e.g., the mako renderer
        except __HOLE__ as err:
            raise SaltRenderError('Renderer: {0} is not available!'.format(err))
        except IndexError:
            raise INVALID_USAGE_ERROR

        if isinstance(input, six.string_types):
            with salt.utils.fopen(input, 'r') as ifile:
                sls_templ = ifile.read()
        else:  # assume file-like
            sls_templ = input.read()

        # first pass to extract the state configuration
        match = re.search(__opts__['stateconf_end_marker'], sls_templ)
        if match:
            process_sls_data(sls_templ[:match.start()], extract=True)

        # if some config has been extracted then remove the sls-name prefix
        # of the keys in the extracted stateconf.set context to make them easier
        # to use in the salt file.
        if STATE_CONF:
            tmplctx = STATE_CONF.copy()
            if tmplctx:
                prefix = sls + '::'
                for k in six.iterkeys(tmplctx):  # iterate over a copy of keys
                    if k.startswith(prefix):
                        tmplctx[k[len(prefix):]] = tmplctx[k]
                        del tmplctx[k]
        else:
            tmplctx = {}

        # do a second pass that provides the extracted conf as template context
        data = process_sls_data(sls_templ, tmplctx)

    if log.isEnabledFor(logging.DEBUG):
        import pprint  # FIXME: pprint OrderedDict
        log.debug('Rendered sls: {0}'.format(pprint.pformat(data)))
    return data
dataset/ETHPy150Open saltstack/salt/salt/renderers/stateconf.py/render