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:
for consistency, use double quotation marks for strings (
"string"
)don’t write lines that are longer than 165 characters
write Google Python Style Guide docstrings (see Writing docstrings for more information)
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:
src/bokeh/
The Python code for the Bokeh library itself is located in the src/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 src/bokeh/models. See Models and properties below for more information on models.
Other subdirectories in this folder include:
src/bokeh/plotting contains Bokeh’s plotting interface
src/bokeh/colors contains code for handling colors
src/bokeh/embed contains code for embedding Bokeh content in web pages.
src/bokeh/io contains code for Bokeh’s IO functions, such as file export and notebook output
src/bokeh/palettes contains code for Bokeh’s palettes
src/bokeh/sphinxext contains code for custom Sphinx extension used in Bokeh’s documentation
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.
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 src/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:
Container-like properties that take other properties as parameters, such as
List
(List(Int)
) orDict
(Dict(String, Double)
)Specialized types like
Instance
(Instance(Plot)
),Enum
(Enum("foo", "bar", "baz")
), orEither
(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:
For the system of models described above, Bokeh uses its own system of properties. See Models and properties for more information.
For any code not using models, Bokeh uses PEP 484 style hints. Use the Python standard typing and typing_extensions modules if necessary.
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.