def test_List_wrap(): for y in (0, 1, 2.3, "foo", None, (), {}): r = List.wrap(y) assert r == y assert isinstance(r, type(y)) r = List.wrap([1,2,3]) assert r == [1,2,3] assert isinstance(r, bcpw.PropertyValueList) r2 = List.wrap(r) assert r is r2
class EmbedTestUtilModel(Model): a = Int(12) b = String("hello") c = List(Int, [1, 2, 3])
class MyText(HTMLBox): __implementation__ = 'mytext.ts' text = List(String) color = List(String) size = List(Int)
class SomeDataModel(DataModel): prop0 = Int() prop1 = Int(default=111) prop2 = List(Int, default=[1, 2, 3])
class MyPlot(Plot): __implementation__ = TypeScript(""" import {Plot, PlotView} from "models/plots/plot" import * as p from "core/properties" import "./custom.less" export class MyPlotView extends PlotView { model: MyPlot render(): void { super.render() this.el.classList.add("bk-my-plot") const angle = `${this.model.gradient_angle}deg` let offset = 0 const colors = [] const step = this.model.gradient_step for (const color of this.model.gradient_colors) { colors.push(`${color} ${offset}px`) offset += step colors.push(`${color} ${offset}px`) } this.el.style.backgroundImage = `repeating-linear-gradient(${angle}, ${colors.join(', ')})` } } export namespace MyPlot { export type Attrs = p.AttrsOf<Props> export type Props = Plot.Props & { gradient_angle: p.Property<number> gradient_step: p.Property<number> gradient_colors: p.Property<string[]> } } export interface MyPlot extends MyPlot.Attrs { width: number | null height: number | null } export class MyPlot extends Plot { properties: MyPlot.Props __view_type__: MyPlotView static { this.prototype.default_view = MyPlotView this.define<MyPlot.Props>(({Number, String, Array}) => ({ gradient_angle: [ Number, 0 ], gradient_step: [ Number, 20 ], gradient_colors: [ Array(String), ["white", "lightgray"] ], })) this.override<MyPlot.Props>({ background_fill_alpha: 0.0, border_fill_alpha: 0.0, }) } } """) gradient_angle = Float(default=0) gradient_step = Float(default=20) gradient_colors = List(Color, default=["white", "gray"]) background_fill_alpha = Override(default=0.0) border_fill_alpha = Override(default=0.0)
def test_wrap_list(self) -> None: prop = bcpn.Nullable(List(Int)) assert prop.wrap(None) is None wrapped = prop.wrap([10, 20]) assert isinstance(wrapped, PropertyValueList) assert prop.wrap(wrapped) is wrapped
def test_valid(self) -> None: prop = bcpn.NonNullable(List(Int)) assert prop.is_valid([]) assert prop.is_valid([1, 2, 3])
class CheckboxWithLegendGroup(CheckboxGroup): colors = List(String, help="List of legend colors") __implementation__ = ""
class Mixin(HasProps): mixin_num = Int(12) mixin_container = List(String) mixin_child = Instance(HasProps)
class Base(HasProps): num = Int(12) container = List(String) child = Instance(HasProps)
class HistogramGlyph(AggregateGlyph): """Depicts the distribution of values using rectangles created by binning. The histogram represents a distribution, so will likely include other options for displaying it, such as KDE and cumulative density. """ # input properties bin_width = Float() bin_count = Float( help="""Provide a manually specified number of bins to use.""") # derived models bins = Instance(Bins, help="""A stat used to calculate the bins. The bins stat includes attributes about each composite bin.""") bars = List(Instance(BarGlyph), help="""The histogram is comprised of many BarGlyphs that are derived from the values.""") def __init__(self, values, label=None, color=None, bin_count=None, **kwargs): if label is not None: kwargs['label'] = label kwargs['values'] = values kwargs['bin_count'] = bin_count if color is not None: kwargs['color'] = color # remove width, since this is handled automatically kwargs.pop('width', None) super(HistogramGlyph, self).__init__(**kwargs) self.setup() def _set_sources(self): # No need to set sources, since composite glyphs handle this pass def build_source(self): # No need to build source, since composite glyphs handle this return None def build_renderers(self): """Yield a bar glyph for each bin.""" self.bins = Bins(values=self.values, bin_count=self.bin_count) centers = [bin.center for bin in self.bins.bins] self.bin_width = centers[1] - centers[0] bars = [] for bin in self.bins.bins: bars.append( BarGlyph(label=self.label, x_label=bin.center, values=bin.values, color=self.color, fill_alpha=self.fill_alpha, agg=bin.stat, width=self.bin_width)) # provide access to bars as children for bounds properties self.bars = bars self.children = self.bars for comp_glyph in self.bars: for renderer in comp_glyph.renderers: yield renderer @property def y_min(self): return 0.0
class HorizonGlyph(AreaGlyph): num_folds = Int(default=3, help="""The count of times the data is overlapped.""") series = Int(default=0, help="""The id of the series as the order it will appear, starting from 0.""") series_count = Int() fold_height = Float(help="""The height of one fold.""") bins = List(Float, help="""The binedges calculated from the number of folds, and the maximum value of the entire source data.""") graph_ratio = Float( help="""Scales heights of each series based on number of folds and the number of total series being plotted. """) pos_color = Color("#006400", help="""The color used for positive values.""") neg_color = Color("#6495ed", help="""The color used for negative values.""") line_color = Color( help="""The color used for the area outline. This is by default set to the same color as the positive or negative color. """) flip_neg = Bool(default=True, help="""When True, the negative values will be plotted as their absolute value, then their individual axes is flipped. If False, then the negative values will still be taken as their absolute value, but the base of their shape will start from the same origin as the positive values. """) def __init__(self, bins=None, **kwargs): # fill alpha depends on how many folds will be layered kwargs['fill_alpha'] = 1.0 / kwargs['num_folds'] if bins is not None: kwargs['bins'] = bins # each series is shifted up to a synthetic y-axis kwargs['base'] = kwargs['series'] * max( bins) / kwargs['series_count'] kwargs['graph_ratio'] = float(kwargs['num_folds']) / float( kwargs['series_count']) super(HorizonGlyph, self).__init__(**kwargs) def build_source(self): data = {} # Build columns for the positive values pos_y = self.y.copy() pos_y[pos_y < 0] = 0 xs, ys = self._build_dims(self.x, pos_y) # list of positive colors and alphas colors = [self.pos_color] * len(ys) alphas = [(bin_idx * self.fill_alpha) for bin_idx in range(0, len(self.bins))] # If we have negative values at all, add the values for those as well if self.y.min() < 0: neg_y = self.y.copy() neg_y[neg_y > 0] = 0 neg_y = abs(neg_y) neg_xs, neg_ys = self._build_dims(self.x, neg_y, self.flip_neg) xs += neg_xs ys += neg_ys colors += ([self.neg_color] * len(neg_ys)) alphas += alphas # create clipped representation of each band data['x_values'] = xs data['y_values'] = ys data['fill_color'] = colors data['fill_alpha'] = colors data['line_color'] = colors return data def _build_dims(self, x, y, flip=False): """ Creates values needed to plot each fold of the horizon glyph. Bins the data based on the binning passed into the glyph, then copies and clips the values for each bin. Args: x (`pandas.Series`): array of x values y (`pandas.Series`): array of y values flip (bool): whether to flip values, used when handling negative values Returns: tuple(list(`numpy.ndarray`), list(`numpy.ndarray`)): returns a list of arrays for the x values and list of arrays for the y values. The data has been folded and transformed so the patches glyph presents the data in a way that looks like an area chart. """ # assign bins to each y value bin_idx = pd.cut(y, bins=self.bins, labels=False, include_lowest=True) xs, ys = [], [] for idx, bin in enumerate(self.bins[0:-1]): # subtract off values associated with lower bins, to get into this bin temp_vals = y.copy() - (idx * self.fold_height) # clip the values between the fold range and zero temp_vals[bin_idx > idx] = self.fold_height * self.graph_ratio temp_vals[bin_idx < idx] = 0 temp_vals[bin_idx == idx] = self.graph_ratio * temp_vals[bin_idx == idx] # if flipping, we must start the values from the top of each fold's range if flip: temp_vals = (self.fold_height * self.graph_ratio) - temp_vals base = self.base + (self.fold_height * self.graph_ratio) else: base = self.base # shift values up based on index of series temp_vals += self.base val_idx = temp_vals > 0 if pd.Series.any(val_idx): ys.append(temp_vals) xs.append(x) # transform clipped data so it always starts and ends at its base value if len(ys) > 0: xs, ys = map( list, zip(*[ generate_patch_base(x, y, base=base) for x, y in zip(xs, ys) ])) return xs, ys def build_renderers(self): # parse all series. We exclude the first attr as it's the x values # added for the index glyph = Patches(xs='x_values', ys='y_values', fill_alpha=self.fill_alpha, fill_color='fill_color', line_color='line_color') renderer = GlyphRenderer(data_source=self.source, glyph=glyph) yield renderer
class Parent(hp.HasProps): int1 = Int(default=10) ds1 = NumberSpec(default=field("x")) lst1 = List(String)
class EitherContainerDefault(hp.HasProps): foo = Either(List(Int), Int, default=[10])
class EitherSimpleDefault(hp.HasProps): foo = Either(List(Int), Int, default=10)
class Perspective(HTMLBox): aggregates = Either(Dict(String, Any), Null()) column_pivots = Either(List(String), Null()) columns = Either(List(String), Null) computed_columns = Either(List(String), Null()) editable = Nullable(Bool()) filters = Either(List(Any), Null()) plugin = String() plugin_config = Either(Dict(String, Any), Null) row_pivots = Either(List(String), Null()) selectable = Nullable(Bool()) schema = Dict(String, String) sort = Either(List(List(String)), Null()) source = Instance(ColumnDataSource) toggle_config = Bool(True) theme = String() # pylint: disable=line-too-long __javascript__ = [ "https://unpkg.com/@finos/[email protected]/dist/umd/perspective.js", "https://unpkg.com/@finos/[email protected]/dist/umd/perspective-viewer.js", "https://unpkg.com/@finos/[email protected]/dist/umd/perspective-viewer-datagrid.js", "https://unpkg.com/@finos/[email protected]/dist/umd/perspective-viewer-hypergrid.js", "https://unpkg.com/@finos/[email protected]/dist/umd/perspective-viewer-d3fc.js", ] __js_skip__ = { "perspective": __javascript__, } __js_require__ = { "paths": { "perspective": "https://unpkg.com/@finos/[email protected]/dist/umd/perspective", "perspective-viewer": "https://unpkg.com/@finos/[email protected]/dist/umd/perspective-viewer", "perspective-viewer-datagrid": "https://unpkg.com/@finos/[email protected]/dist/umd/perspective-viewer-datagrid", "perspective-viewer-hypergrid": "https://unpkg.com/@finos/[email protected]/dist/umd/perspective-viewer-hypergrid", "perspective-viewer-d3fc": "https://unpkg.com/@finos/[email protected]/dist/umd/perspective-viewer-d3fc", }, "exports": { "perspective": "Perspective", "perspective-viewer": "PerspectiveViewer", "perspective-viewer-datagrid": "PerspectiveViewerDatagrid", "perspective-viewer-hypergrid": "PerspectiveViewerHypergrid", "perspective-viewer-d3fc": "PerspectiveViewerD3fc", }, } __css__ = [ "https://unpkg.com/@finos/[email protected]/dist/umd/all-themes.css" ]
class Sub(Base, Mixin): sub_num = Int(12) sub_container = List(String) sub_child = Instance(HasProps)
class DataTabulator(HTMLBox): """A Bokeh Model that enables easy use of Tabulator tables See http://tabulator.info/ """ aggregators = Dict(String, String) buttons = Dict(String, String) configuration = Dict(String, Any) columns = List(Instance(TableColumn), help=""" The list of child column widgets. """) download = Bool(default=False) children = Dict(Int, Instance(LayoutDOM)) editable = Bool(default=True) expanded = List(Int) filename = String(default="table.csv") filters = List(Any) follow = Bool(True) frozen_rows = List(Int) groupby = List(String) hidden_columns = List(String) indexes = List(String) layout = Enum('fit_data', 'fit_data_fill', 'fit_data_stretch', 'fit_data_table', 'fit_columns', default="fit_data") source = Instance(ColumnDataSource) styles = Dict( String, Either( String, Dict(Int, Dict(Int, List(Either(String, Tuple(String, String))))))) pagination = Nullable(String) page = Nullable(Int) page_size = Int() max_page = Int() sorters = List(Dict(String, String)) select_mode = Any() selectable_rows = Nullable(List(Int)) theme = Enum(*TABULATOR_THEMES, default="simple") theme_url = String(default=THEME_URL) __css_raw__ = CSS_URLS @classproperty def __css__(cls): cls.__css_raw__ = [ url for url in cls.__css_raw__ if 'simple' in url or len(cls.__css_raw__) == 1 ] return bundled_files(cls, 'css') __javascript_raw__ = [JS_SRC, MOMENT_SRC] @classproperty def __javascript__(cls): return bundled_files(cls) @classproperty def __js_skip__(cls): return { 'Tabulator': cls.__javascript__[:1], 'moment': cls.__javascript__[1:] } __js_require__ = { 'paths': { 'tabulator': JS_SRC[:-3], 'moment': MOMENT_SRC[:-3] }, 'exports': { 'tabulator': 'Tabulator', 'moment': 'moment' } }
class Deep(Sub): deep_num = Int(12) deep_container = List(String) deep_child = Instance(HasProps)
def test_str(self) -> None: prop = bcpn.Nullable(List(Int)) assert str(prop) == "Nullable(List(Int))"
class FooUnrelated(HasProps): x = Int(12) y = String("hello") z = List(Int, [1, 2, 3])
class Foo(Model): foo = Int() bar = List(Int, default=[10]) baz = Int(default=20) quux = List(Int, default=[30])
class Foo(HasProps): x = Int(12) y = String("hello") z = List(Int, [1, 2, 3]) zz = Dict(String, Int) s = Nullable(String(None))
class HookListModel(Model): hooks = List(String)
class SomeModel(Model): a = Int(12) b = String("hello") c = List(Int, [1, 2, 3])
class CDSDerivedDataModel(ColumnDataSource, DataModel): prop0 = Int() prop1 = Int(default=111) prop2 = List(Int, default=[1, 2, 3]) data = Override(default={"default_column": [4, 5, 6]})
class V(self.pObjectClass): u1 = Instance(U) u2 = List(Instance(U)) u3 = Tuple(Int, Instance(U)) u4 = Dict(String, Instance(U)) u5 = Dict(String, List(Instance(U)))
class _TestModel2(HasProps): x = Int(12) y = String("hello") z = List(Int, [1, 2, 3]) zz = Dict(String, Int) s = String(None)
class HasListDefault(Model): value = List(String, default=["hello"])
class HasListProp(Model): foo = List(String) def __init__(self, **kwargs): super(HasListProp, self).__init__(**kwargs)
def test_List(self, detail): p = List(Float) with pytest.raises(ValueError) as e: p.validate("junk", detail) assert (str(e.value) == "") == (not detail)