Contributing Python code

The Bokeh codebase combines code written in Python and TypeScript. This chapter provides an overview of the most important things to know when working on Bokeh’s Python code.

Code style

Bokeh’s Python code generally follows the PEP8 standard. Some notable exceptions include:

Bokeh uses a combination of code quality tests for each Pull Request. Relevant tests for Python code include Flake8 and isort. Use the following command to run those codebase tests locally:

pytest tests/codebase

To learn more about running those tests on your system, see Run codebase tests.

Tests

All Pull Requests that add or update code should include new or updated tests. See Running tests and Writing tests for more information on testing, including Python-specific tests.

Source code organization

The Bokeh repository contains Bokeh’s Python code as well as the JavaScript code of BokehJS. These are the most relevant folders containing Python code:

bokeh/

The Python code for the Bokeh library itself is located in the bokeh folder.

Everything that comprises a Bokeh visualization (such as tools, glyphs, widgets, or ColumnDataSources) is based on a Bokeh model. The Python code for all models is located in bokeh/models. See Models and properties below for more information on models.

Other subdirectories in this folder include:

See the reference guide for more information on the structure of this directory and its subdirectories.

examples/

The examples folder contains examples for most of Bokeh’s functionalities. Some of those examples are used in Bokeh’s gallery.

tests/

The tests folder contains Bokeh’s suite of tests. See Running tests and Writing tests for more information on testing.

typings/

The typings folder contains stub files for Bokeh’s type hints.

Models and properties

The central building blocks of all Bokeh visualizations are objects based on Bokeh’s models. These models are representations of plot elements, such as axes, glyphs, or widgets.

On the Python side, Bokeh serializes the attributes of each plot element object into JSON data. On the browser side, BokehJS deserializes this JSON data and creates JavaScript objects based on this information. BokehJS then uses these JavaScript objects to render the visualization.

Flowchart describing the flow of data from Python objects through JSON to the browser-side. There, the JSON data is converted into JavaScript objects which then get rendered as output. Output can be HTML Canvas, WebGL, or SVG.

Whenever you update or add models in Python, you need to also update the corresponding TypeScript code for BokehJS.

All of Bokeh’s Python models are located in bokeh/models and its subfolders. They all are subclasses of Model:

class SomeNewModel(Model):
    """ Some new model. """

Models contain properties, which are class attributes defined in bokeh.core.properties. For example:

class ModelWithIntProps(Model):
    prop1 = Int()
    prop2 = Int(10)

In this example, the ModelWithIntProps model represents objects that have two integer values, prop1 and prop2.

Bokeh uses a wide variety of property types:

  • Primitive types like Byte, Int, Float, Complex, or String

  • Container-like properties that take other properties as parameters, such as List (List(Int)) or Dict (Dict(String, Double))

  • Specialized types like Instance (Instance(Plot)), Enum (Enum("foo", "bar", "baz")), or Either (Either(Int, String))

These property types have several purposes:

  • type checking the different models

  • making sure that models remain compatible between Python and JavaScript

  • automatically generating some basic documentation for the reference guide

An example of a more realistic model might look like this:

class SomeModel(Model):
    prop1 = Int(127)
    prop2 = Either(Int, List(Int), Dict(String, List(Int)))
    prop3 = Enum("x", "y", "z")
    prop4 = Range(Float, 0.0, 1.0)
    prop5 = List(Instance(Range1d))

See bokeh.core.properties for more details.

Warning

The class Any is the super-type of all other types and will accept any type of value. Since this circumvents all type validation, make sure to use it sparingly, if at all.

Typing

Bokeh uses two systems for type checking Python code:

Bokeh’s CI uses mypy to check types. To type check your code locally, run mypy bokeh.

Note

In case you want to use type information with tools other than mypy (such as extracting information with typing.get_type_hints, for example), you will most likely need to use Python 3.10 or later. This is because some of Bokeh’s type hints use the X | Y syntax for union types as defined in PEP 604.