贡献#

如果你正在阅读这一部分,你可能对为JupyterLab做出贡献感兴趣。欢迎并感谢你对贡献的兴趣!

请查看贡献者文档,熟悉使用JupyterLab,并向社区介绍自己(在聊天和/或论坛上),并分享你对项目的哪个领域感兴趣。也请参阅Jupyter的社区指南

您可以通过以下方式帮助改进:

我们已经将一些问题标记为good first issuehelp wanted,我们认为这些都是小而独立的更改的好例子。我们鼓励那些对代码库不熟悉的人来实现和/或询问这些问题。你不需要请求许可来处理这样的问题,但如果你请求了并且在48小时内没有得到回复,请假设没有其他人正在处理它(即使之前有人自愿),并打开一个带有建议实现的拉取请求。如果你不确定实现,鼓励使用草稿拉取请求。

如果您认为在JupyterLab或任何Jupyter项目中发现了安全漏洞,请向security@ipython.org报告。如果您希望加密您的安全报告,您可以使用此PGP公钥

贡献的一般指南#

有关为Jupyter项目做出贡献的一般文档,请参阅 Project Jupyter Contributor DocumentationCode of Conduct

向后兼容性、版本和重大变更#

新版本的JupyterLab可能会破坏与扩展和其他Jupyter自定义的向后兼容性。尽可能将破坏性更改保持在最低限度。JupyterLab的开发和发布周期遵循语义版本控制,因此当需要进行破坏性更改时,它们通过版本编号方案进行传达。简而言之,这意味着对于JupyterLab版本X.Y.Z:

  • 主版本号(X)的变化表示有重大变更(不向后兼容)

  • 次要版本 (Y) 号的变化表示向后兼容的新功能添加

  • 补丁版本(Z)号的变化表示向后兼容的错误修复

对JupyterLab扩展和其他自定义的贡献应计划可能的破坏性更改。考虑在这些项目中向用户记录您的维护计划。在开发扩展时,您可能还希望考虑固定JupyterLab的主要版本(在您的包元数据中)。

我们会在后继版本首次发布后的一年内维护JupyterLab的主要版本。 详情请参阅版本生命周期。 JupyterLab v4于2023年5月15日发布,因此JupyterLab v3将维护至2024年5月15日。JupyterLab v1和v2已不再维护。 强烈建议所有JupyterLab v2和v3用户尽快升级。

语言、工具和流程#

所有源代码都是用 TypeScript编写的。请参阅风格指南

所有非Python源代码都使用prettier进行格式化,而Python源代码则使用ruff进行格式化。 当代码被修改并提交时,所有暂存的文件将 通过pre-commit git钩子自动格式化(借助 pre-commit的帮助)。使用像prettierruff这样的代码格式化工具的好处是,它可以在审查拉取请求时从讨论中移除代码风格的话题,从而 加快审查过程。

只要你的代码是有效的, 预提交钩子应该会处理它的外观。 pre-commit 及其相关的钩子会在你运行 pip install -e ".[dev,test]" 时自动安装。

要手动安装 pre-commit,请运行以下命令:

pip install pre-commit
pre-commit install

你可以随时手动调用预提交钩子:

pre-commit run

它应该会对你的代码进行任何自动格式化,并告诉你它无法自动修复的任何错误。你也可以在你的文本编辑器中安装ruff集成来自动格式化代码。

如果你在设置预提交钩子之前已经提交了文件,你可以使用pre-commit run --all-files来修复所有问题。之后你需要自己进行修复提交。

你也可以使用 prettier npm 脚本(例如 npm run prettieryarn prettierjlpm prettier)来格式化整个代码库。 我们建议为你的代码编辑器安装一个 prettier 扩展,并 配置它以通过键盘快捷键或 在保存时自动格式化你的代码。

提交拉取请求贡献#

通常,在打开拉取请求之前,应该先打开一个问题,描述一项提议的工作及其解决的问题。一个分类员将确保您的问题符合我们对“准备就绪”的定义,然后我们才能合并与之相关的任何拉取请求。

拉取请求必须针对开发分支(= main),即使其目的是解决稳定版本中的问题。一旦拉取请求在开发分支上合并,它将通过机器人操作(或如果机器人操作失败则手动)回迁到稳定分支。

注意

在PR描述中不要犹豫提及目标版本。 维护者将相应地设置里程碑。

问题管理#

开启一个问题可以让社区成员参与设计讨论,让其他人了解正在进行的工作,并为富有成效的社区互动奠定基础。当您开启一个新的错误或增强请求时,请提供问题模板中要求的所有信息,以便响应者能够及时处理您的错误。

一个拉取请求应该引用它正在解决的问题。一旦拉取请求被合并,与之相关的问题也将被关闭。如果围绕实现有额外的讨论,问题可能会被重新打开。一旦30天过去且没有额外的讨论,锁定机器人将锁定该问题。如果需要额外的讨论,或者拉取请求没有完全解决被锁定的问题,请打开一个新问题并引用被锁定的问题。

新问题需要进行分类。具有分类权限的开发人员(称为分类员)将执行以下操作:

  1. 阅读问题

  2. 搜索现有问题,并在必要时将其标记为重复

  3. 如果需要更多信息,请添加一条评论请求

  4. 如果问题已经准备好进行处理,将其分配到一个里程碑

  5. 为问题应用适当的标签(见下面的示例)

开发者可以在问题提交后立即开始处理。如果他们对你的问题有任何疑问,请与分类员合作,以便你的更改能够及时合并。

准备就绪的定义#

分类的主要目标之一是将问题处理到准备就绪的状态,以便有人可以开始工作。一旦分类者确认问题符合以下定义,他们将从中移除status:Needs Triage标签。我们不会合并仍需要分类的问题的拉取请求。

问题处理者还应确保问题具有描述其内容的适当标签,例如对于影响一个或多个包的问题,使用带有pkg:前缀的标签。

所有请求的信息,如适用,均已提供。 来自JupyterLab问题中的模板:

对于一个错误

  • 描述,最好包括屏幕截图

  • 重现步骤

  • 预期行为

  • 上下文,例如操作系统、浏览器、JupyterLab 版本以及输出或日志摘录

对于一个功能请求

  • 问题描述

  • 拟议解决方案的描述

  • 附加内容

问题应代表真实、相关、可行的工作。简而言之,如果一个有知识的人被分配到这个任务,他们应该能够在合理的努力和帮助下完成它,并且它有助于推进Jupyter项目的目标。

  • 问题应该是唯一的;分类是识别重复问题的最佳时机。

  • Bugs 代表了对 Jupyter 产品和服务使用的有效期望。

  • 对安全性、性能、可访问性和本地化的期望与使用Jupyter产品的社区中普遍接受的规范相匹配。

  • 该问题代表一个开发者可以承诺负责的工作,即使他们与其他开发者合作以获取反馈。过大的问题应拆分为多个问题,每个问题单独进行优先级排序,或拆分为team-compass问题以讨论更实质性的更改。

分类者使用的标签#

所有新的错误和改进请求都有status:Needs Triage标签。

定期地,Jupyter贡献者(问题审查员或审查员)会审查标记为status:Needs Triage的JupyterLab问题,从最旧的开始,并确定它们是否符合准备就绪的定义。

一旦问题被分类,如果问题已准备就绪,审阅者会移除status:Needs Triage标签;不需要额外的标签。如果提交的问题中没有足够的信息,分类审阅者会应用status:Needs Info标签,并保留status:Needs Triage。如果一个问题在status:Needs Info状态下停留超过14天且没有任何后续沟通,审阅者应应用status:Blocked标签。被阻止的问题在另外14天过去后如果没有收到解除阻止的回复,则应被关闭。

我们的期望是,每个新问题应在创建后的一周内进行检查。

分类者应将较简单/复杂度较低的问题标记为good first issue,以便于初学者贡献。一个好的第一个问题应具备:

  • 一个清晰、易于理解的描述,带有屏幕截图和期望,不需要对项目有太多熟悉

  • 链接,无论是在描述中还是在评论中,指向与问题相关的文档和源代码文件

  • 推荐的联络点,可以是GitHub用户名或其他论坛(如Discourse等),贡献者可以在这些地方获得帮助

除非问题具有时间敏感性,例如它是即将发布的版本的发布障碍,否则有经验的Jupyter贡献者应避免处理带有good first issue标签的近期问题。

使用标签标记问题#

没有JupyterLab仓库提交权限的用户可以使用@meeseeksdev机器人来标记问题。例如:要将标签foobar baz应用到某个问题上,可以在该问题上评论@meeseeksdev tag foo "bar baz"

在浏览器中贡献#

为JupyterLab代码库做出贡献也是可能的,无需设置本地环境,直接从Web浏览器进行:

  • GitHub的 codespace 可用(免费账户有 有限的月度资源)。

  • GitHub的 内置编辑器 适合贡献非常小的修复,

  • 更高级的 github.dev 编辑器可以通过在 JupyterLab GitHub 仓库中按下点 (.) 键来访问,

  • Gitpod 集成已启用,但未积极维护,

  • jupyterlab-playground, 允许在JupyterLab内部原型化JupyterLab扩展, 并且可以使用Binder在浏览器中无需安装即可运行。

使用Binder,您也可以在浏览器中测试当前的主分支和您的更改。我们建议您至少有8 GB的内存来进行此操作。要构建并启动最新JupyterLab主分支的实例,请在新标签页中打开此链接。构建大约需要7分钟完成。

要测试托管在GitHub上的你自己的分支,请在https://mybinder.org上输入它。 如果一切顺利,填写表单大约需要2分钟,构建应该再次需要大约7分钟。

设置本地开发环境#

注意

查看自动化开发环境部分,了解一些自动化设置本地开发环境的方法。

本节介绍如何设置本地开发环境。我们假设您使用GNU/Linux、macOS或Windows子系统用于Linux。如果使用Windows,我们建议安装Anaconda for windows,然后在所有安装步骤中使用Anaconda命令提示符。

安装 Node.js 和 jlpm#

从GitHub源代码构建JupyterLab需要Node.js。开发版本需要Node.js 20+版本,如dev_mode/package.json中的engines规范所定义。

如果你使用conda,你可以通过以下方式获取:

conda install -c conda-forge nodejs=20

如果您在 macOS 上使用 Homebrew

brew install node

你也可以使用Node.js网站上的安装程序。

要检查安装的Node.js版本:

node -v

使用自动化设置本地开发环境#

虽然通过遵循上述步骤可以学到很多,但它们可以自动化以节省时间。 使用自动化的主要优点是:减少环境启动和运行的时间,减少重新构建环境的时间,更好的标准化(“基线”,可复现的环境)。 本节展示了如何使用VS Code开发容器、Docker和Vagrant来实现这一点。

VS Code 设置#

要使用VS Code开发容器启动JupyterLab的本地开发环境,您需要:

  1. 安装 VS Code Dev Containers 扩展

  2. 分叉 JupyterLab repository

  3. 将你的fork克隆到本地:

git clone https://github.com/<your-github-username>/jupyterlab.git
  1. 使用 VS Code 打开本地克隆。

  2. 在容器中打开仓库。 VS Code 应该会弹出一个提示框让你这样做。如果没有弹出提示框,你可以点击左下角的图标 ><。然后选择 在容器中重新打开

注意

第一次会花费相当长的时间。

使用Docker进行设置#

在安装了docker的UNIX系统中启动JupyterLab开发容器:

  1. 分叉 JupyterLab repository

  2. 启动容器:

git clone https://github.com/<your-github-username>/jupyterlab.git
cd jupyterlab
bash docker/start.sh

上述命令将在Docker镜像不存在时构建它,然后启动容器并在监视模式下运行JupyterLab。端口8888被暴露,并且当前的JupyterLab仓库被挂载到容器中。然后,您可以使用您喜欢的IDE开始开发JupyterLab,JupyterLab将实时重建。

其他可用的命令:

bash docker/start.sh dev 4567 # Start JupyterLab dev container at port 4567
bash docker/start.sh stop  # Stop the running container
bash docker/start.sh clean  # Remove the docker image
bash docker/start.sh build  # Rebuild the docker image

# Log into the container's shell with the JupyterLab environment activated.
# It's useful to run the tests or install dependencies.
bash docker/start.sh shell

要向项目添加TypeScript依赖项,您需要登录到容器的shell,安装依赖项以更新package.json和yarn.lock文件,然后重新构建docker镜像。

bash docker/start.sh shell
# In the container shell
jlpm add ...
exit
# Back to host shell
bash docker/start.sh build

使用Vagrant进行设置#

一个实际的例子可以在那里找到,包括一个Vagrantfile,引导文件和额外的文档。

安装 JupyterLab#

分叉 JupyterLab repository

然后按照以下步骤操作:

git clone https://github.com/<your-github-username>/jupyterlab.git
cd jupyterlab
pip install -e ".[dev,test]"
jlpm install
jlpm run build  # Build the dev mode assets

# Build the core mode assets
jlpm run build:core

# Build the app dir assets
jupyter lab build

常见问题#

重要

在Windows上,对于Python 3.8或更高版本,需要在Windows 10或更高版本上通过激活“开发者模式”来激活符号链接。您的管理员可能不允许这样做。请参阅在Windows上激活开发者模式以获取说明。

  • 一些脚本将运行“python”。如果你的目标python被称为其他名称(例如“python3”),那么构建的某些部分将失败。你可能希望在conda环境中构建,或者创建一个别名。

  • jlpm 命令是 JupyterLab 提供的一个锁定版本的 yarn 包管理器。如果你已经安装了 yarn,你可以在开发时使用 yarn 命令,它会在仓库或构建的应用程序目录中使用 jupyterlab/yarn.js 中的本地版本 yarn

  • 如果您决定使用 jlpm 命令并遇到 jlpm: command not found 错误,请尝试将用户级别的 bin 目录添加到您的 PATH 环境变量中。您已经在之前的命令中安装了 jlpm 以及 JupyterLab,但由于 PATH 环境变量相关的问题, jlpm 可能无法访问。如果您使用的是 Unix 衍生系统(FreeBSD、GNU / Linux、OS X),您可以通过使用 export PATH="$HOME/.local/bin:$PATH" 命令来实现这一点。

  • 有时,可能需要使用命令 npm run clean:slate 来清理你的本地仓库。这将清理仓库,并重新安装和重建。

  • 如果 pip 给出 VersionConflict 错误,通常意味着已安装的 jupyterlab_server 版本已过时。运行 pip install --upgrade jupyterlab_server 以获取最新版本。

  • 要为单个conda/虚拟环境单独安装JupyterLab,您可以在上述扩展激活中添加--sys-prefix标志;这将把安装绑定到您环境的sys.prefix位置,而不会在您的用户范围内设置区域(对所有环境可见)中写入任何内容:

  • 你可以运行 jlpm run build:dev:prod 来构建更准确的源映射,这些源映射在调试时显示原始的 Typescript 代码。 然而,构建源文件需要更长的时间,因此默认情况下仅用于生产环境的构建。

对于想要编写文档的贡献者的安装说明,请参见 编写文档

运行 JupyterLab#

以开发模式启动 JupyterLab:

jupyter lab --dev-mode

开发模式确保您运行的是在开发安装的Python包中构建的JavaScript资源。请注意,在开发模式下运行时,扩展默认不会激活 - 请参阅扩展开发文档以了解更多信息。

在开发模式下运行时,页面顶部会出现一条红色条纹;这是为了表示正在运行未发布的版本。

如果你想更改TypeScript代码并即时重建 (每次重建后需要刷新页面):

jupyter lab --dev-mode --watch

构建并运行测试#

jlpm run build:testutils
jlpm test

您可以通过切换到相应的包文件夹来运行单个包的测试:

cd packages/notebook
jlpm run build:test
jlpm test --runInBand

注意

--runInBand 选项将在当前进程中串行运行所有测试。 我们建议使用它,因为一些测试正在启动一个不喜欢并行执行的 Jupyter 服务器。

我们使用jest进行所有测试,因此标准的jest工作流程适用。 测试可以在VSCode或Chrome中进行调试。在调试时,可以为特定测试添加it.only。每个包中的所有test* 脚本都接受jestcli选项

VSCode 调试#

要在VSCode中进行调试,请在VSCode中打开一个包文件夹。我们在每个包文件夹中提供了一个启动配置。在终端中运行jlpm test:debug:watch。在VSCode中,从“运行”侧边栏中选择“附加到Jest”以开始调试。有关更多详细信息,请参阅VSCode调试文档

Chrome 调试#

要在Chrome中调试,请在终端运行jlpm test:debug:watch。打开 Chrome并访问chrome://inspect/。选择远程设备并 开始调试。

测试工具#

testutils(这是一个名为@jupyterlab/testutils的公共npm包)中有一些辅助函数,这些函数被许多测试使用。

对于依赖@jupyterlab/services的测试(启动内核、与文件交互等),有两种选择。如果需要简单的交互,testutils暴露的Mock命名空间有许多模拟实现(参见testutils/src/mock.ts)。如果需要完整的服务器交互,请使用JupyterServer类。

我们有一个名为testEmission的辅助函数,用于帮助编写使用Lumino信号的测试,以及一个framePromise函数来获取requestAnimationFramePromise。我们有时需要在Promise内部设置一个哨兵值,然后检查哨兵是否被设置,如果我们需要一个不阻塞运行的承诺。

国际化#

可翻译字符串更新#

可翻译字符串的更新不能在补丁版本中进行。它们必须推迟到次要或主要版本。

性能测试#

JupyterLab 的基准测试是使用 Playwright 完成的。测量的操作包括:

  • 打开文件

  • 从文件切换到简单的文本文件

  • 切换回文件

  • 关闭文件

测试了两个文件:一个包含许多代码单元格的笔记本和另一个包含许多Markdown单元格的笔记本。

测试在CI上运行,通过比较PR分支开始时提交的结果和PR分支头在同一个CI作业上的结果,以确保使用相同的硬件。 基准测试作业在以下情况下触发:

  • 已批准的PR审查

  • 包含句子 please run benchmark 的PR审查

测试位于子文件夹 galata/test/benchmark 中。它们可以通过以下命令执行:

jlpm run test:benchmark

将在文件夹 benchmark-results 中生成一份特别报告,该报告将包含4个文件:

  • lab-benchmark.json: 测试的执行时间和一些元数据。

  • lab-benchmark.md: 一份Markdown格式的报告

  • lab-benchmark.png: 执行时间分布的对比

  • lab-benchmark.vl.json: 用于生成PNG文件的Vega-Lite描述。

参考,标记为expected,存储在lab-benchmark-expected.json中。可以使用Playwright的-u选项创建;即jlpm run test:benchmark -u

基准参数#

基准测试可以使用以下环境变量进行自定义:

  • BENCHMARK_NUMBER_SAMPLES: 计算执行时间分布的样本数量;默认值为20。

  • BENCHMARK_OUTPUTFILE: 基准测试结果输出文件;默认为 benchmark.json。它在 playwright-benchmark.config.js 中被覆盖。

  • BENCHMARK_REFERENCE: 数据的参考名称;默认情况下,当前数据为actual,参考数据为expected

可以在JupyterLab分支上手动进行更多测试,并在jupyterlab/benchmarks仓库的默认分支上每周运行。

视觉回归和用户界面测试#

作为JupyterLab CI工作流程的一部分,UI测试会进行视觉回归检查。 Galata 用于UI 测试。Galata 提供了 Playwright 助手,以编程方式控制和 检查JupyterLab UI。

UI测试在每次提交到JupyterLab项目的PR或直接提交时运行。代码更改有时会导致UI测试因各种原因失败。每次测试运行后,Galata会生成一个用户友好的测试结果报告,可用于检查失败的UI测试。结果报告显示失败原因、导致失败的调用堆栈以及视觉回归问题的详细信息。对于视觉回归错误,报告中提供了参考图像、测试捕获图像以及比较过程中生成的差异图像。您可以使用这些信息来调试失败的测试。Galata测试报告可以从GitHub Actions页面下载UI测试运行的测试工件。测试工件名为galata-report,解压后,您可以通过启动服务器来访问报告python -m http.server -d 。然后使用您的网络浏览器打开http://localhost:8000/

UI测试失败的主要原因有:

  1. 由代码更改引起的视觉回归:

    有时,项目源代码的修改会无意中引入UI更改。视觉回归测试的目的是检测这种UI更改。如果你的PR / 提交导致了视觉回归,那么调试并修复由此引起的回归。你可以在本地运行和调试UI测试以修复视觉回归。要调试你的测试,你可以运行PWDEBUG=1 jlpm playwright test 。一旦你有了修复方案,你可以将更改推送到你的GitHub分支,并使用GitHub Actions进行测试。

  2. 用户界面的预期更新:

    如果你的代码更改引入了用户界面的更新,导致现有的用户界面测试失败,那么你需要为失败的测试更新参考图像。为了做到这一点,你可以在你的PR上发布一个包含以下内容的评论:

    • please update galata snapshots: 一个机器人将推送一个新的提交到你的PR,更新galata测试快照。

    • please update documentation snapshots: 一个机器人将推送一个新的提交到你的PR,更新文档测试快照。

    • please update snapshots: 结合前两个评论的效果。

    机器人将用+1表情符号反应,表示运行已开始,并在完成后再次评论。

有关UI测试的更多信息,请阅读UI测试开发者文档Playwright文档

集成测试的最佳实践#

以下是一些编写集成测试时应遵循的良好实践:

  • 不要在同一个测试中比较多个截图;如果第一次比较失败,将需要多次运行CI工作流来修复所有测试。

为调试器前端做出贡献#

要更改调试器扩展,需要一个支持调试的内核。

查看用户文档以了解如何安装此类内核:调试器

然后刷新页面,调试器侧边栏应该会出现在右侧区域。

调试器适配器协议#

下图展示了JupyterLab扩展与内核之间发送的消息类型。

UML sequence diagram illustrating the interaction between a user, JupyterLab, and the kernel. From top to bottom, the timeline starts with opening the notebook and includes annotations where the debugger is started and stopped. Specific interactions and message types are discussed in the subsequent text.

在VS Code中检查调试消息#

在VS Code中检查调试消息有助于理解何时发出调试请求(例如由UI操作触发),并比较JupyterLab调试器与VS Code中的Python调试器的行为。

第一步是创建一个测试文件和一个调试配置 (launch.json):

An editor showing the menu for creating a debug configuration.
{
   "version": "0.2.0",
   "configurations": [
      {
         "name": "Python: Current File",
         "type": "python",
         "request": "launch",
         "program": "${file}",
         "console": "integratedTerminal",
         "env": { "DEBUGPY_LOG_DIR": "/path/to/logs/folder" }
      }
   ]
}

然后启动调试器:

A started debugging session in the editor. There are additional buttons in the upper right for navigating the session.

日志文件的内容如下所示:

...

D00000.032: IDE --> {
               "command": "initialize",
               "arguments": {
                  "clientID": "vscode",
                  "clientName": "Visual Studio Code",
                  "adapterID": "python",
                  "pathFormat": "path",
                  "linesStartAt1": true,
                  "columnsStartAt1": true,
                  "supportsVariableType": true,
                  "supportsVariablePaging": true,
                  "supportsRunInTerminalRequest": true,
                  "locale": "en-us"
               },
               "type": "request",
               "seq": 1
            }

...

使用:

  • IDE = VS Code

  • PYD = pydev 调试器

  • 消息遵循DAP

参考文献#

构建并运行独立示例#

要安装并构建examples目录中的示例:

jlpm run build:examples

要运行特定示例,请切换到示例目录(即 examples/filebrowser)并输入:

python main.py

在浏览器中调试#

所有构建JupyterLab的方法都会生成源映射。源映射应该可以在浏览器开发工具的源文件视图中找到,位于webpack://标题下。

在正常运行JupyterLab时,展开~标题以查看各个包的源映射。

--dev-mode模式下运行时,核心包位于packages/目录下,而第三方库则位于~目录下。注意:建议在调试时使用jupyter lab --watch --dev-mode

运行测试时,包将可在顶层使用(例如 application/src),并且当前可用的测试文件集位于 /src 下。注意:建议在调试测试选项时在测试文件夹中使用 jlpm run watch。更多信息请参见 above


高级架构#

JupyterLab 应用程序由两个主要部分组成:

  • 一个 npm 包

  • 一个 Jupyter 服务器扩展(Python 包)

每个部分都命名为jupyterlab开发者教程文档提供了额外的架构信息。

NPM 包#

该仓库包含许多使用 lerna 构建工具管理的 npm 包。npm 包的源文件位于 packages/ 子目录中。

从源代码构建NPM包#

git clone https://github.com/jupyterlab/jupyterlab.git
cd jupyterlab
pip install -e .
jlpm
jlpm run build:packages

重建

jlpm run clean
jlpm run build:packages

编写文档#

文档是用Markdown和reStructuredText编写的。特别是,我们在Read the Docs页面上的文档是用reStructuredText编写的。为了确保Read the Docs页面能够构建,您需要使用pip安装文档依赖项:

pip install -e ".[docs]"

要测试文档,请运行:

python -m pytest --check-links -k .md . || python -m pytest --check-links -k .md --lf .

Read the Docs 页面可以使用 make 来构建:

cd docs
make html

JupyterLab API 参考文档也包含在上一步中。 要访问文档,首先启动一个服务器来提供生成的文件:

make serve

然后在你的浏览器中访问 http://localhost:8000/

JupyterLab API 参考文档可以使用 jlpm 单独构建:

jlpm run docs

写作风格#

  • 以第二人称撰写文档,将读者称为“你”。不要使用第一人称复数“我们”。文档的作者并不坐在用户旁边,因此当事情没有按预期工作时,使用“我们”可能会导致挫败感。

  • 避免使用诸如“简单地”或“仅仅”这样的词语来轻视使用JupyterLab的行为。开发者认为简单或容易的任务对用户来说可能并非如此。

  • 使用主动语态书写。例如,“拖动笔记本单元格…”而不是“笔记本单元格可以被拖动…”。

  • 每个章节的开头应该以一个简短(1-2句话)的高级描述开始,描述主题、功能或组件。

  • 使用“启用”而不是“允许”来表示JupyterLab为用户提供的功能。使用“允许”意味着我们在给予他们许可,而“启用”则意味着赋予他们能力。

用户界面命名约定#

文档、文件和活动#

根据上下文,将文件称为文件或文档。

文档更以人为中心。如果人类的查看、解释或交互是体验的重要部分,使用术语“文档”。例如,笔记本和Markdown文件通常被称为文档,除非在文件系统的上下文中(例如,笔记本文件名)。

在较少以人为中心的上下文中使用术语文件。例如,参考与文件系统或文件名相关的文件。

活动 可以是一个打开的文档,或者是与文件无关的其他用户界面面板,例如终端、控制台或检查器。

笔记本单元格#

一个笔记本包含单元格,每个单元格都有输入和一个或多个输出。当用户运行一个单元格时,内核读取并执行输入并生成输出。然后笔记本显示单元格的输出。术语输出描述了运行一个单元格可能产生的多个结果之一。单元格输出描述了一个单元格的集体输出。使用所有单元格的输出来描述所有单元格的所有输出。

命令名称#

命令名称出现在菜单中、命令面板中以及工具栏按钮上(通常在悬停时显示名称)。

  • 保持命令名称简短、简洁且无歧义。

  • 在任何需要更多选项的命令名称后添加省略号(…)。这告诉用户在执行命令之前应该期待出现一个弹出窗口。

  • 命令应使用祈使句中的动词。不要使用冠词与名词。 例如,应写“清除单元格”,而不是“清除该单元格”或“正在清除单元格”。

元素名称#

  • 选项卡式用户界面的通用内容区域是一个面板。请使用其最具体的名称来引用面板,例如“文件浏览器”。标签栏包含标签,允许用户查看不同的面板。

  • 菜单栏包含有自己子菜单菜单项

  • 当名称明确时,将主工作区称为工作区。

  • 在描述用户界面中的元素时,优先使用通俗名称而非技术名称。例如,使用“文件浏览器”而不是“文件面板”。

大多数元素名称应使用小写。这些名称包括:

  • 标签

  • 面板

  • 菜单栏

  • 侧边栏

  • 文件

  • 文档

  • 活动

  • 标签栏

  • 主要工作区域

  • 文件浏览器

  • 命令面板

  • 单元格检查器

  • 代码控制台

使用一个或多个首字母大写来编写用户界面的以下部分,以反映它们在用户界面中的使用方式:

  • 活动栏

  • 文件菜单

  • 文件选项卡

  • 运行面板

  • 标签面板

  • 简单界面模式

请参阅JupyterLab 界面了解用户界面中元素的描述。

Jupyter 服务器扩展#

Jupyter服务器扩展源文件位于jupyterlab/子目录中。要使用此扩展,请确保已安装Jupyter Notebook服务器版本4.3或更高版本。

构建JupyterLab服务器扩展#

当你对 JupyterLab npm 包的源文件进行更改时,运行:

jlpm run build

构建更改,然后刷新浏览器以查看更改。

要在每次源文件更改后让系统构建,请运行:

jupyter lab --dev-mode --watch

构建工具#

有一系列构建工具用于维护仓库。要获取库的建议版本,请使用 jlpm run get:dependency foo。要在整个仓库中更新库的版本,请使用 jlpm run update:dependency foo ^latest。要删除不需要的依赖项,请使用 jlpm run remove:dependency foo

关键实用工具是 jlpm run integrity,它确保仓库中包的完整性。它将:

  • 确保核心包版本依赖在所有地方都匹配。

  • 确保导入的包与依赖项匹配。

  • 确保所有包版本一致。

  • 管理元包。

packages/metapackage 包用于一次性构建仓库中的所有 TypeScript,而不是进行 50 多个单独的构建。

完整性脚本还允许您通过在TypeScript文件中从包中导入来自动添加依赖项,然后从仓库根目录运行:jlpm run integrity

我们还有用于在packages/中创建和删除包的脚本,jlpm run create:packagejlpm run remove:package。在创建包时,如果它旨在包含在核心包中,请将jupyterlab: { coreDependency: true }元数据添加到package.json中。具有extensionmimeExtension元数据的包被视为核心依赖项,除非它们被明确标记为其他情况。

测试外部包的更改#

将包链接/取消链接到JupyterLab#

如果你想对JupyterLab的一个外部包进行更改(例如,Lumino)并在你的JupyterLab副本中测试它们,你可以使用link命令轻松完成:

  1. 进行更改,然后构建外部包

  2. 将JupyterLab链接到修改后的包

    • 导航到您的JupyterLab仓库的顶层,然后运行 jlpm link --all

3. 然后你可以(重新)构建JupyterLab(例如 jlpm run build),你的更改应该会被构建过程捕获。

要将JupyterLab恢复到其原始状态,您可以使用unlink命令:

  1. 取消链接 JupyterLab 和修改过的包

    • 导航到你的 JupyterLab 仓库的顶层,然后运行 jlpm unlink --all

  2. 在JupyterLab中重新安装外部包的原始版本

    • 运行 jlpm install --check-files

3. 然后你可以(重新)构建JupyterLab,一切应该会恢复到默认状态。

可能的链接陷阱#

如果您正在处理一个包含多个包的外部项目,您可能需要链接项目中的每个包的副本,包括那些您未做任何更改的包。如果不这样做,可能会导致与共享状态重复相关的问题。

具体来说,当使用Lumino时,你可能需要链接你的"@lumino/messaging"包(除了你实际修改的任何包)。这是由于messaging包提供的MessageLoop命名空间中可能包含的对象重复。

键盘快捷键#

按照以下方式排版键盘快捷键:

  • 等宽字体,各个键之间有空格: Shift Enter

  • 对于修饰键,使用描述键的平台独立词: Shift

  • 对于Accel键,请使用短语:Command/Ctrl

  • 不要使用特定平台的图标来表示修饰键,因为在Sphinx/RTD上以特定平台的方式显示它们很困难。

截图和动画#

我们的文档应包含说明和演示软件的截图和动画。以下是准备它们的一些指南:

  • 确保截图不包含受版权保护的材料(最好),或者许可证在我们的文档中是允许的并且明确声明。

  • 对于截图,您应该优先创建视觉测试。这允许动态更新它们。这些测试定义在galata/test/documentation文件夹中。

  • 如果拍摄png截图,请使用Firefox或Chrome开发者工具执行以下操作:

    • 将浏览器视口设置为1280x720像素

    • 将设备像素比设置为1:1(即非高DPI,非视网膜)

    • 使用浏览器开发者工具截取整个视口的截图。截图不应包含任何浏览器元素,如浏览器地址栏、浏览器标题栏等,也不应包含任何桌面背景。

  • 如果创建电影,请按照上述设置调整(1280x720 视口分辨率,非 hidpi),并使用您选择的屏幕捕捉工具仅捕捉浏览器视口。

  • 对于PNG文件,使用pngquant --speed 1 来减小它们的大小。 生成的文件名将会附加-fs8,所以请确保 重命名并使用生成的文件。将优化后的png文件提交到主仓库。每个png文件的大小不应超过几百KB。

  • 对于电影,将它们上传到 IPython/Jupyter YouTube 频道,并将它们添加到 jupyterlab-media 存储库中。要在文档中嵌入电影,请使用 www.youtube-nocookie.com 网站,该网站可以通过点击 YouTube 分享对话框中的“隐私增强”嵌入选项找到。在 URL 末尾添加以下参数 ?rel=0&showinfo=0。这将禁用视频标题和相关视频建议。

  • 截图或动画前应有一句话描述内容,例如“要打开文件,请在文件浏览器中双击其名称:”。

  • 我们有自定义的CSS,可以为截图和嵌入的YouTube视频添加阴影和适当的尺寸。请参阅文档中的示例,了解如何嵌入这些资源。

为了帮助我们组织截图和动画,请使用与它们所使用的源文件名称匹配的前缀来命名文件:

sourcefile.rst
sourcefile_filebrowser.png
sourcefile_editmenu.png

这将帮助我们随着文档内容的演变来跟踪图像。

注释#

  • 默认情况下,应用程序将从 JupyterLab 暂存目录加载(默认是 /share/jupyter/lab/build。如果您希望在 root>/jupyterlab/build 中运行核心应用程序,请运行 jupyter lab --core-mode。这是将要发布的核心应用程序。

  • 如果使用扩展,请参阅扩展文档

  • npm 模块与 Node/Babel/ES6/ES5 完全兼容。在使用非 TypeScript 语言时,只需省略类型声明即可。