#-----------------------------------------------------------------------------
# Copyright (c) 2012 - 2021, Anaconda, Inc., and Bokeh Contributors.
# All rights reserved.
#
# The full license is in the file LICENSE.txt, distributed with this software.
#-----------------------------------------------------------------------------
''' Display a variety of visual shapes whose attributes can be associated
with data columns from ``ColumnDataSources``.
All these glyphs share a minimal common interface through their base class
``Glyph``:
.. autoclass:: Glyph
:members:
'''
#-----------------------------------------------------------------------------
# Boilerplate
#-----------------------------------------------------------------------------
from __future__ import annotations
import logging # isort:skip
log = logging.getLogger(__name__)
#-----------------------------------------------------------------------------
# Imports
#-----------------------------------------------------------------------------
# Standard library imports
from inspect import Parameter
# Bokeh imports
from ..core.has_props import abstract
from ..core.property._sphinx import type_link
from ..model import Model
#-----------------------------------------------------------------------------
# Globals and constants
#-----------------------------------------------------------------------------
__all__ = (
'ConnectedXYGlyph',
'Glyph',
'XYGlyph',
)
#-----------------------------------------------------------------------------
# General API
#-----------------------------------------------------------------------------
[docs]@abstract
class Glyph(Model):
''' Base class for all glyph models.
'''
# a canonical order for positional args that can be
# used for any functions derived from this class
_args = ()
_extra_kws = {}
[docs] @classmethod
def parameters(cls):
''' Generate Python ``Parameter`` values suitable for functions that are
derived from the glyph.
Returns:
list(Parameter)
'''
arg_params = []
no_more_defaults = False
for arg in reversed(cls._args):
descriptor = cls.lookup(arg)
default = descriptor.class_default(cls)
if default is None:
no_more_defaults = True
# simplify field(x) defaults to just present the column name
if isinstance(default, dict) and set(default) == {"field"}:
default = default["field"]
# make sure we don't hold on to references to actual Models
if isinstance(default, Model):
default = _ModelRepr(default)
param = Parameter(
name=arg,
kind=Parameter.POSITIONAL_OR_KEYWORD,
# For positional arg properties, default=None means no default.
default=Parameter.empty if no_more_defaults else default
)
if default:
del default
typ = type_link(descriptor.property)
arg_params.insert(0, (param, typ, descriptor.__doc__))
# these are not really useful, and should also really be private, just skip them
omissions = {'js_event_callbacks', 'js_property_callbacks', 'subscribed_events'}
kwarg_params = []
kws = set(cls.properties()) - set(cls._args) - omissions
for kw in kws:
descriptor = cls.lookup(kw)
default=descriptor.class_default(cls)
# simplify field(x) defaults to just present the column name
if isinstance(default, dict) and set(default) == {"field"}:
default = default["field"]
# make sure we don't hold on to references to actual Models
if isinstance(default, Model):
default = _ModelRepr(default)
param = Parameter(
name=kw,
kind=Parameter.KEYWORD_ONLY,
default=default
)
del default
typ = type_link(descriptor.property)
kwarg_params.append((param, typ, descriptor.__doc__))
for kw, (typ, doc) in cls._extra_kws.items():
param = Parameter(
name=kw,
kind=Parameter.KEYWORD_ONLY,
)
kwarg_params.append((param, typ, doc))
kwarg_params.sort(key=lambda x: x[0].name)
return arg_params + kwarg_params
@abstract
class XYGlyph(Glyph):
''' Base class of glyphs with `x` and `y` coordinate attributes.
'''
@abstract
class ConnectedXYGlyph(XYGlyph):
''' Base class of glyphs with `x` and `y` coordinate attributes and
a connected topology.
'''
@abstract
class LineGlyph(Glyph):
''' Glyphs with line properties
'''
@abstract
class FillGlyph(Glyph):
''' Glyphs with fill properties
'''
@abstract
class TextGlyph(Glyph):
''' Glyphs with text properties
'''
@abstract
class HatchGlyph(Glyph):
''' Glyphs with Hatch properties
'''
#-----------------------------------------------------------------------------
# Dev API
#-----------------------------------------------------------------------------
#-----------------------------------------------------------------------------
# Private API
#-----------------------------------------------------------------------------
class _ModelRepr:
''' This proxy is for storing reprs of Bokeh models that are property
defaults, so that holding references to those Models may be avoided.
'''
def __init__(self, model: Model) -> None:
self. _repr = repr(model)
def __repr__(self) -> str:
return self._repr
#-----------------------------------------------------------------------------
# Code
#-----------------------------------------------------------------------------