# Buggy code
def render_tmpl(
    tmplsrc, from_str=False, to_str=False, context=None, tmplpath=None, **kws
):
    if context is None:
        context = {}

    # Alias cmd.run to cmd.shell to make python_shell=True the default for
    # templated calls
    if "salt" in kws:
        kws["salt"] = AliasedLoader(kws["salt"])

    # We want explicit context to overwrite the **kws
    kws.update(context)
    context = kws
    assert "opts" in context
    assert "saltenv" in context

    if "sls" in context:
        slspath = context["sls"].replace(".", "/")
        if tmplpath is not None:
            context["tplpath"] = tmplpath
            if not tmplpath.lower().replace("\\", "/").endswith("/init.sls"):
                slspath = os.path.dirname(slspath)
            template = tmplpath.replace("\\", "/")
            i = template.rfind(slspath.replace(".", "/"))
            if i != -1:
                template = template[i:]
            tpldir = os.path.dirname(template).replace("\\", "/")
            tpldata = {
                "tplfile": template,
                "tpldir": "." if tpldir == "" else tpldir,
                "tpldot": tpldir.replace("/", "."),
            }
            context.update(tpldata)
        context["slsdotpath"] = slspath.replace("/", ".")
        context["slscolonpath"] = slspath.replace("/", ":")
        context["sls_path"] = slspath.replace("/", "_")
        context["slspath"] = slspath

    if isinstance(tmplsrc, six.string_types):
        if from_str:
            tmplstr = tmplsrc
        else:
            try:
                if tmplpath is not None:
                    tmplsrc = os.path.join(tmplpath, tmplsrc)
                with codecs.open(tmplsrc, "r", SLS_ENCODING) as _tmplsrc:
                    tmplstr = _tmplsrc.read()
            except (UnicodeDecodeError, ValueError, OSError, IOError) as exc:
                if salt.utils.files.is_binary(tmplsrc):
                    # Template is a bin file, return the raw file
                    return dict(result=True, data=tmplsrc)
                log.error(
                    "Exception occurred while reading file %s: %s",
                    tmplsrc,
                    exc,
                    exc_info_on_loglevel=logging.DEBUG,
                )
                six.reraise(*sys.exc_info())
    else:  # assume tmplsrc is file-like.
        tmplstr = tmplsrc.read()
        tmplsrc.close()
    try:
        output = render_str(tmplstr, context, tmplpath)
        if salt.utils.platform.is_windows():
            newline = False
            if salt.utils.stringutils.to_unicode(
                output, encoding=SLS_ENCODING
            ).endswith(("\n", os.linesep)):
                newline = True
            # Write out with Windows newlines
            output = os.linesep.join(output.splitlines())
            if newline:
                output += os.linesep

    except SaltRenderError as exc:
        log.exception("Rendering exception occurred")
        # return dict(result=False, data=six.text_type(exc))
        raise
    except Exception:
        return dict(result=False, data=traceback.format_exc())
    else:
        if to_str:  # then render as string
            return dict(result=True, data=output)
        with tempfile.NamedTemporaryFile(
            "wb", delete=False, prefix=salt.utils.files.TEMPFILE_PREFIX
        ) as outf:
            outf.write(salt.utils.stringutils.to_bytes(output, encoding=SLS_ENCODING))
            # Note: If nothing is replaced or added by the rendering
            #       function, then the contents of the output file will
            #       be exactly the same as the input.
        return dict(result=True, data=outf.name)


# Traceback (AttributeError)
test: [ERROR   ] An un-handled exception was caught by salt's global exception handler:
test: AttributeError: 'unicode' object has no attribute 'name'
test: Traceback (most recent call last):
test:   File "/bin/spm", line 12, in <module>
test:     salt_spm()
test:   File "/usr/lib/python2.7/site-packages/salt/scripts.py", line 527, in salt_spm
test:     spm.run()
test:   File "/usr/lib/python2.7/site-packages/salt/cli/spm.py", line 41, in run
test:     client.run(self.args)
test:   File "/usr/lib/python2.7/site-packages/salt/spm/__init__.py", line 125, in run
test:     self._install(args)
test:   File "/usr/lib/python2.7/site-packages/salt/spm/__init__.py", line 379, in _install
test:     self._install_indv_pkg(package, out_file)
test:   File "/usr/lib/python2.7/site-packages/salt/spm/__init__.py", line 532, in _install_indv_pkg
test:     self.files_conn)
test:   File "/usr/lib/python2.7/site-packages/salt/spm/__init__.py", line 161, in _pkgfiles_fun
test:     return self.pkgfiles['{0}.{1}'.format(self.files_prov, func)](*args, **kwargs)
test:   File "/usr/lib/python2.7/site-packages/salt/spm/pkgfiles/local.py", line 147, in install_file
test:     member.name = new_name.name.replace('{0}/'.format(package), '')
test: AttributeError: 'unicode' object has no attribute 'name'
test: Traceback (most recent call last):
test:   File "/bin/spm", line 12, in <module>
test:     salt_spm()
test:   File "/usr/lib/python2.7/site-packages/salt/scripts.py", line 527, in salt_spm
test:     spm.run()
test:   File "/usr/lib/python2.7/site-packages/salt/cli/spm.py", line 41, in run
test:     client.run(self.args)
test:   File "/usr/lib/python2.7/site-packages/salt/spm/__init__.py", line 125, in run
test:     self._install(args)
test:   File "/usr/lib/python2.7/site-packages/salt/spm/__init__.py", line 379, in _install
test:     self._install_indv_pkg(package, out_file)
test:   File "/usr/lib/python2.7/site-packages/salt/spm/__init__.py", line 532, in _install_indv_pkg
test:     self.files_conn)
test:   File "/usr/lib/python2.7/site-packages/salt/spm/__init__.py", line 161, in _pkgfiles_fun
test:     return self.pkgfiles['{0}.{1}'.format(self.files_prov, func)](*args, **kwargs)
test:   File "/usr/lib/python2.7/site-packages/salt/spm/pkgfiles/local.py", line 147, in install_file
test:     member.name = new_name.name.replace('{0}/'.format(package), '')
test: AttributeError: 'unicode' object has no attribute 'name'

# Fixed code
def render_tmpl(
    tmplsrc, from_str=False, to_str=False, context=None, tmplpath=None, **kws
):
    if context is None:
        context = {}

    # Alias cmd.run to cmd.shell to make python_shell=True the default for
    # templated calls
    if "salt" in kws:
        kws["salt"] = AliasedLoader(kws["salt"])

    # We want explicit context to overwrite the **kws
    kws.update(context)
    context = kws
    assert "opts" in context
    assert "saltenv" in context

    if "sls" in context:
        slspath = context["sls"].replace(".", "/")
        if tmplpath is not None:
            context["tplpath"] = tmplpath
            if not tmplpath.lower().replace("\\", "/").endswith("/init.sls"):
                slspath = os.path.dirname(slspath)
            template = tmplpath.replace("\\", "/")
            i = template.rfind(slspath.replace(".", "/"))
            if i != -1:
                template = template[i:]
            tpldir = os.path.dirname(template).replace("\\", "/")
            tpldata = {
                "tplfile": template,
                "tpldir": "." if tpldir == "" else tpldir,
                "tpldot": tpldir.replace("/", "."),
                "tplroot": tpldir.split("/")[0],
            }
            context.update(tpldata)
        context["slsdotpath"] = slspath.replace("/", ".")
        context["slscolonpath"] = slspath.replace("/", ":")
        context["sls_path"] = slspath.replace("/", "_")
        context["slspath"] = slspath

    if isinstance(tmplsrc, six.string_types):
        if from_str:
            tmplstr = tmplsrc
        else:
            try:
                if tmplpath is not None:
                    tmplsrc = os.path.join(tmplpath, tmplsrc)
                with codecs.open(tmplsrc, "r", SLS_ENCODING) as _tmplsrc:
                    tmplstr = _tmplsrc.read()
            except (UnicodeDecodeError, ValueError, OSError, IOError) as exc:
                if salt.utils.files.is_binary(tmplsrc):
                    # Template is a bin file, return the raw file
                    return dict(result=True, data=tmplsrc)
                log.error(
                    "Exception occurred while reading file %s: %s",
                    tmplsrc,
                    exc,
                    exc_info_on_loglevel=logging.DEBUG,
                )
                six.reraise(*sys.exc_info())
    else:  # assume tmplsrc is file-like.
        tmplstr = tmplsrc.read()
        tmplsrc.close()
    try:
        output = render_str(tmplstr, context, tmplpath)
        if salt.utils.platform.is_windows():
            newline = False
            if salt.utils.stringutils.to_unicode(
                output, encoding=SLS_ENCODING
            ).endswith(("\n", os.linesep)):
                newline = True
            # Write out with Windows newlines
            output = os.linesep.join(output.splitlines())
            if newline:
                output += os.linesep

    except SaltRenderError as exc:
        log.exception("Rendering exception occurred")
        # return dict(result=False, data=six.text_type(exc))
        raise
    except Exception:
        return dict(result=False, data=traceback.format_exc())
    else:
        if to_str:  # then render as string
            return dict(result=True, data=output)
        with tempfile.NamedTemporaryFile(
            "wb", delete=False, prefix=salt.utils.files.TEMPFILE_PREFIX
        ) as outf:
            outf.write(salt.utils.stringutils.to_bytes(output, encoding=SLS_ENCODING))
            # Note: If nothing is replaced or added by the rendering
            #       function, then the contents of the output file will
            #       be exactly the same as the input.
        return dict(result=True, data=outf.name)