def _glyph_function(glyphclass, extra_docs=None):

    def func(self, *args, **kwargs):

        # pop off glyph *function* parameters that are not glyph class properties
        legend_name = kwargs.pop("legend", None)
        renderer_kws = _pop_renderer_args(kwargs)
        source = renderer_kws['data_source']

        # add the positional arguments as kwargs
        attributes = dict(zip(glyphclass._args, args))
        kwargs.update(attributes)

        # handle the main glyph, need to process literals
        glyph_ca = _pop_colors_and_alpha(glyphclass, kwargs)
        _process_sequence_literals(glyphclass, kwargs, source)
        _process_sequence_literals(glyphclass, glyph_ca, source)

        # handle the nonselection glyph, we always set one
        nsglyph_ca = _pop_colors_and_alpha(glyphclass, kwargs, prefix='nonselection_', default_alpha=0.1)

        # handle the selection glyph, if any properties were given
        if any(x.startswith('selection_') for x in kwargs):
            sglyph_ca = _pop_colors_and_alpha(glyphclass, kwargs, prefix='selection_')
        else:
            sglyph_ca = None

        # handle the hover glyph, if any properties were given
        if any(x.startswith('hover_') for x in kwargs):
            hglyph_ca = _pop_colors_and_alpha(glyphclass, kwargs, prefix='hover_')
        else:
            hglyph_ca = None

        glyph = _make_glyph(glyphclass, kwargs, glyph_ca)
        nsglyph = _make_glyph(glyphclass, kwargs, nsglyph_ca)
        hglyph = _make_glyph(glyphclass, kwargs, hglyph_ca)
        sglyph = _make_glyph(glyphclass, kwargs, sglyph_ca)

        glyph_renderer = GlyphRenderer(glyph=glyph,
                                       nonselection_glyph=nsglyph,
                                       selection_glyph=sglyph,
                                       hover_glyph=hglyph,
                                       **renderer_kws)

        if legend_name:
            _update_legend(self, legend_name, glyph_renderer)

        for tool in self.select(type=BoxSelectTool):
            # this awkward syntax is needed to go through Property.__set__ and
            # therefore trigger a change event. With improvements to Property
            # we might be able to use a more natural append() or +=
            tool.renderers = tool.renderers + [glyph_renderer]

        # awkward syntax for same reason mentioned above
        self.renderers = self.renderers + [glyph_renderer]
        return glyph_renderer

    func.__name__ = glyphclass.__view_model__

    arglines = []
    for arg in glyphclass._args:
        spec = getattr(glyphclass, arg)
        desc = " ".join(x.strip() for x in spec.__doc__.strip().split("\n\n")[0].split('\n'))
        arglines.append(_arg_template % (arg, spec.__class__.__name__, desc, spec.class_default(glyphclass)))

    kwlines = []
    kws = set(glyphclass._args) - glyphclass.properties()
    for kw in sorted(kws):
        if kw == "session": continue # TODO (bev) improve or remove
        spec = getattr(glyphclass, kw)
        if spec.__doc__:
            typ = spec.__class__.__name__
            desc = " ".join(x.strip() for x in spec.__doc__.strip().split("\n\n")[0].split('\n'))
        else:
            typ = str(spec)
            desc = ""
        kwlines.append(_arg_template % (kw, typ, desc, spec.class_default(glyphclass)))

    func.__doc__ = _doc_template  % (glyphclass.__name__, "\n".join(arglines), "\n".join(kwlines))

    if extra_docs:
        func.__doc__ += extra_docs
    return func
dataset/ETHPy150Open bokeh/bokeh/bokeh/plotting/helpers.py/_glyph_function/swapped operands of `-`