'Create a CustomJSFilter instance from a Python function. The
fucntion is translated to JavaScript using PyScript.
The ``func`` function namespace will contain the variable ``source``
at render time. This will be the data source associated with the CDSView
that this filter is added to.'

@classmethod
def from_py_func(cls, func):

    if (not isinstance(func, FunctionType)):
        raise ValueError('CustomJSFilter.from_py_func    only    accepts    function    objects.')
    pyscript = import_required('flexx.pyscript', dedent('                                                                To    use    Python    functions    for    CustomJSFilter,    you    need    Flexx\n                                                                \'("conda    install    -c    bokeh    flexx"    or    "pip    install    flexx")'))
    argspec = inspect.getargspec(func)
    default_names = argspec.args
    default_values = (argspec.defaults or [])
    if ((len(default_names) - len(default_values)) != 0):
        raise ValueError('Function    may    only    contain    keyword    arguments.')
    if (default_values and (not any([isinstance(value, Model) for value in default_values]))):
        raise ValueError('Default    value    must    be    a    plot    object.')
    func_kwargs = dict(zip(default_names, default_values))
    code = (pyscript.py2js(func, 'filter') + ('return    filter(%s);\n' % ',    '.join(default_names)))
    return cls(code=code, args=func_kwargs)
