Render a template from a python source file

    Returns::

        {'result': bool,
         'data': <Error data or rendered file path>}

def py(sfn, string=False, **kwargs):  # pylint: disable=C0103
    '''
    Render a template from a python source file

    Returns::

        {'result': bool,
         'data': <Error data or rendered file path>}
    '''
    if not os.path.isfile(sfn):
        return {}

    base_fname = os.path.basename(sfn)
    name = base_fname.split('.')[0]

    if USE_IMPORTLIB:
        # pylint: disable=no-member
        loader = importlib.machinery.SourceFileLoader(name, sfn)
        spec = importlib.util.spec_from_file_location(name, sfn, loader=loader)
        if spec is None:
            raise ImportError()
        mod = importlib.util.module_from_spec(spec)
        spec.loader.exec_module(mod)
        # pylint: enable=no-member
        sys.modules[name] = mod
    else:
        mod = imp.load_source(name, sfn)

    # File templates need these set as __var__
    if '__env__' not in kwargs and 'saltenv' in kwargs:
        setattr(mod, '__env__', kwargs['saltenv'])
        builtins = ['salt', 'grains', 'pillar', 'opts']
        for builtin in builtins:
            arg = '__{0}__'.format(builtin)
            setattr(mod, arg, kwargs[builtin])

    for kwarg in kwargs:
        setattr(mod, kwarg, kwargs[kwarg])

    try:
        data = mod.run()
        if string:
            return {'result': True,
                    'data': data}
        tgt = salt.utils.files.mkstemp()
        with salt.utils.files.fopen(tgt, 'w+') as target:
            target.write(salt.utils.stringutils.to_str(data))
        return {'result': True,
                'data': tgt}
    except Exception:
        trb = traceback.format_exc()
        return {'result': False,
                'data': trb}