#-----------------------------------------------------------------------------# Copyright (c) Anaconda, Inc., and Bokeh Contributors.# All rights reserved.## The full license is in the file LICENSE.txt, distributed with this software.#-----------------------------------------------------------------------------""" Provide the numeric properties."""#-----------------------------------------------------------------------------# Boilerplate#-----------------------------------------------------------------------------from__future__importannotationsimportlogging# isort:skiplog=logging.getLogger(__name__)#-----------------------------------------------------------------------------# Imports#-----------------------------------------------------------------------------# Standard library importsfromtypingimportAny,TypeVar# Bokeh importsfrom.basesimport(Init,Property,SingleParameterizedProperty,TypeOrInst,)from.primitiveimportFloat,Intfrom.singletonsimportIntrinsic,Undefined#-----------------------------------------------------------------------------# Globals and constants#-----------------------------------------------------------------------------__all__=('Angle','Byte','Interval','NonNegative','Percent','Positive','Size',)T=TypeVar("T",bound=int|float)#-----------------------------------------------------------------------------# General API#-----------------------------------------------------------------------------
[docs]classNonNegative(SingleParameterizedProperty[T]):""" A property accepting a value of some other type while having undefined default. """def__init__(self,type_param:TypeOrInst[Property[T]],*,default:Init[T]=Intrinsic,help:str|None=None)->None:super().__init__(type_param,default=default,help=help)defvalidate(self,value:Any,detail:bool=True)->None:super().validate(value,detail)ifnot(0<=value):raiseValueError(f"expected a non-negative number, got {value!r}")
[docs]classPositive(SingleParameterizedProperty[T]):""" A property accepting a value of some other type while having undefined default. """def__init__(self,type_param:TypeOrInst[Property[T]],*,default:Init[T]=Intrinsic,help:str|None=None)->None:super().__init__(type_param,default=default,help=help)defvalidate(self,value:Any,detail:bool=True)->None:super().validate(value,detail)ifnot(0<value):raiseValueError(f"expected a positive number, got {value!r}")
[docs]classInterval(SingleParameterizedProperty[T]):""" Accept numeric values that are contained within a given interval. Args: interval_type (numeric property): numeric types for the range, e.g. ``Int``, ``Float`` start (number) : A minimum allowable value for the range. Values less than ``start`` will result in validation errors. end (number) : A maximum allowable value for the range. Values greater than ``end`` will result in validation errors. Example: .. code-block:: python >>> class RangeModel(HasProps): ... prop = Range(Float, 10, 20) ... >>> m = RangeModel() >>> m.prop = 10 >>> m.prop = 20 >>> m.prop = 15 >>> m.prop = 2 # ValueError !! >>> m.prop = 22 # ValueError !! >>> m.prop = "foo" # ValueError !! """def__init__(self,type_param:TypeOrInst[Property[T]],start:T,end:T,*,default:Init[T]=Undefined,help:str|None=None)->None:super().__init__(type_param,default=default,help=help)self.type_param.validate(start)self.type_param.validate(end)self.start=startself.end=enddef__str__(self)->str:class_name=self.__class__.__name__returnf"{class_name}({self.type_param}, {self.start!r}, {self.end!r})"defvalidate(self,value:Any,detail:bool=True)->None:super().validate(value,detail)ifnot(self.type_param.is_valid(value)andvalue>=self.startandvalue<=self.end):msg=""ifnotdetailelsef"expected a value of type {self.type_param} in range [{self.start}, {self.end}], got {value!r}"raiseValueError(msg)
[docs]classSize(Float):""" Accept non-negative numeric values. Args: default (float, optional) : A default value for attributes created from this property to have. help (str or None, optional) : A documentation string for this property. It will be automatically used by the :ref:`bokeh.sphinxext.bokeh_prop` extension when generating Spinx documentation. (default: None) Example: .. code-block:: python >>> class SizeModel(HasProps): ... prop = Size() ... >>> m = SizeModel() >>> m.prop = 0 >>> m.prop = 10e6 >>> m.prop = -10 # ValueError !! >>> m.prop = "foo" # ValueError !! """defvalidate(self,value:Any,detail:bool=True)->None:super().validate(value,detail)ifvalue<0:msg=""ifnotdetailelsef"expected a non-negative number, got {value!r}"raiseValueError(msg)
[docs]classPercent(Float):""" Accept floating point percentage values. ``Percent`` can be useful and semantically meaningful for specifying things like alpha values and extents. Args: default (float, optional) : A default value for attributes created from this property to have. help (str or None, optional) : A documentation string for this property. It will be automatically used by the :ref:`bokeh.sphinxext.bokeh_prop` extension when generating Spinx documentation. (default: None) Example: .. code-block:: python >>> class PercentModel(HasProps): ... prop = Percent() ... >>> m = PercentModel() >>> m.prop = 0.0 >>> m.prop = 0.2 >>> m.prop = 1.0 >>> m.prop = -2 # ValueError !! >>> m.prop = 5 # ValueError !! """defvalidate(self,value:Any,detail:bool=True)->None:super().validate(value,detail)if0.0<=value<=1.0:returnmsg=""ifnotdetailelsef"expected a value in range [0, 1], got {value!r}"raiseValueError(msg)
[docs]classAngle(Float):""" Accept floating point angle values. ``Angle`` is equivalent to :class:`~bokeh.core.properties.Float` but is provided for cases when it is more semantically meaningful. Args: default (float, optional) : A default value for attributes created from this property to have. help (str or None, optional) : A documentation string for this property. It will be automatically used by the :ref:`bokeh.sphinxext.bokeh_prop` extension when generating Spinx documentation. (default: None) """
#-----------------------------------------------------------------------------# Dev API#-----------------------------------------------------------------------------#-----------------------------------------------------------------------------# Private API#-----------------------------------------------------------------------------#-----------------------------------------------------------------------------# Code#-----------------------------------------------------------------------------