贡献 Python 代码#

Bokeh 代码库结合了使用 Python 和 TypeScript 编写的代码。本章概述了在处理 Bokeh 的 Python 代码时需要了解的最重要事项。

代码风格#

Bokeh 的 Python 代码通常遵循 PEP8 标准。一些值得注意的例外包括

Bokeh 为每个 Pull Request 使用代码质量测试的组合。Python 代码的相关测试包括 Ruffisort。使用以下命令在本地运行这些代码库测试

pytest tests/codebase

要了解有关在您的系统上运行这些测试的更多信息,请参阅 运行代码库测试

测试#

所有添加或更新代码的 Pull Request 都应包含新的或更新的测试。有关测试(包括特定于 Python 的测试)的更多信息,请参阅 运行测试编写测试

源代码组织#

Bokeh 仓库包含 Bokeh 的 Python 代码以及 BokehJS 的 JavaScript 代码。以下是包含 Python 代码的最相关的文件夹

src/bokeh/

Bokeh 库本身的 Python 代码位于 src/bokeh 文件夹中。

构成 Bokeh 可视化的一切内容(例如 工具glyphswidgetsColumnDataSources)都基于 Bokeh 模型。所有模型的 Python 代码都位于 src/bokeh/models 中。有关模型的更多信息,请参阅下面的 模型和属性

此文件夹中的其他子目录包括

有关此目录及其子目录结构的更多信息,请参阅参考指南

examples/

examples 文件夹包含 Bokeh 大部分功能的示例。其中一些示例用于 Bokeh 的 画廊

tests/

tests 文件夹包含 Bokeh 的测试套件。有关测试的更多信息,请参阅 运行测试编写测试

typings/

src/typings 文件夹包含 Bokeh 类型提示的 存根文件

模型和属性#

所有 Bokeh 可视化的中心构建块是基于 Bokeh 的 模型 的对象。这些模型是 绘图 元素的表示,例如 坐标轴glyphswidgets

在 Python 端,Bokeh 将每个绘图元素对象的属性序列化为 JSON 数据。在浏览器端,BokehJS 反序列化此 JSON 数据并基于此信息创建 JavaScript 对象。BokehJS 然后使用这些 JavaScript 对象来渲染可视化。

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.

每当您在 Python 中更新或添加模型时,您还需要 更新 BokehJS 的相应 TypeScript 代码

所有 Bokeh 的 Python 模型都位于 src/bokeh/models 及其子文件夹中。它们都是 Model 的子类

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

模型包含属性,这些属性是在 bokeh.core.properties 中定义的类属性。例如

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

在此示例中,ModelWithIntProps 模型表示具有两个整数值 prop1prop2 的对象。

Bokeh 使用各种属性类型

  • 原始类型,例如 ByteIntFloatComplexString

  • 将其他属性作为参数的类似容器的属性,例如 List (List(Int)) 或 Dict (Dict(String, Double))

  • 专用类型,例如 Instance (Instance(Plot))、Enum (Enum("foo", "bar", "baz")) 或 Either (Either(Int, String))

这些属性类型有几个用途

  • 类型检查 不同的模型

  • 确保模型在 Python 和 JavaScript 之间保持兼容

  • 自动为参考指南生成一些基本文档

更真实的模型的示例可能如下所示

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))

有关更多详细信息,请参阅 bokeh.core.properties

警告

Any 类是所有其他类型的超类型,并将接受任何类型的值。由于这规避了所有类型验证,请确保谨慎使用它,如果可以的话尽量不要使用。

类型标注#

Bokeh 使用两个系统来检查 Python 代码的类型

  • 对于上面描述的模型系统,Bokeh 使用其自身的属性系统。有关更多信息,请参阅模型和属性

  • 对于任何不使用模型的代码,Bokeh 使用 PEP 484 风格的提示。如果需要,请使用 Python 标准 typingtyping_extensions 模块。

Bokeh 的 CI 使用 mypy 来检查类型。要在本地类型检查您的代码,请运行 mypy bokeh

注意

如果您想将类型信息与 mypy 以外的工具一起使用(例如,使用 typing.get_type_hints 提取信息),您很可能需要使用 Python 3.10 或更高版本。这是因为 Bokeh 的某些类型提示使用 PEP 604 中定义的联合类型的 X | Y 语法。