创建新的插件来扩展 CLI#
虽然 JupyterLite 应用程序的大部分行为可以通过 扩展 进行配置或修改,但这可能不足以满足所有需求。还可以通过插件来扩展底层的 jupyter lite
CLI。
自定义插件可以对构建的 lite 应用程序的输出文件夹进行任何操作,还可以修改其他插件的行为,包括构成核心 API 的插件。
一些用例
提供复杂的 前端扩展
可预测地修补构建的应用程序中的文件
代码风格检查、测试、压缩或其他验证和优化技术
注意
选择插件是为了将这些部分与 前端 的基于浏览器的插件和扩展区分开来,所有 jupyter lite
核心行为都是作为插件实现的。
CLI 架构#
在深入研究插件构建之前,值得了解它们在 CLI 的整体结构中的位置。
为了从多个来源下载、解压缩和更新静态文件和配置,CLI 使用了多个层。
组件 |
示例 |
角色 |
---|---|---|
应用 |
加载配置并解析 CLI 参数 |
|
管理器 |
加载 Addons,运行 |
|
Addon |
生成任务计划,并实现操作 |
|
|
收集逻辑生命周期任务 |
|
|
对任务进行细粒度排序 |
|
|
具有任务和文件依赖关系的操作集 |
|
操作 |
|
实际移动和更新文件 |
Addon 结构#
最简单的情况下,Addon 使用类似于以下签名的方式进行初始化
class MyAddon:
__all__ = ["status"]
def status(self, maanger):
yield dict(name="hello", actions=[lambda: print("world")])
__all__
成员列出了 Addon 实现的钩子钩子也可以以
pre_
和post_
阶段为前缀
钩子实现,如广告所示
值得注意的是
status
阶段不应该有任何副作用init
阶段主要保留用于“黄金母版”内容build
主要保留用于用户编写的內容
提示
请参阅此 JupyterLite 存储库中的现有示例,以了解其他钩子实现。
生成任务#
每个钩子实现都应该返回一个可迭代的 doit
任务,其最小形式为
def post_build(manager):
yield dict(
name="a:unique:name", # will have the Addon, and maybe a prefix, prepended
actions=[["things", "to", "do"]],
file_dep=["a-file", Path("another-file")],
targets=["an-output-file"],
)
应用程序级任务已经根据其 钩子父级 配置了 doit.create_after
,这意味着任务可以自信地依赖于其父级(由任何其他 addons)中已存在的文件。
虽然不是必需的,但拥有准确的 file_dep
和 targets
有助于确保构建的应用程序始终处于一致状态,无需大量返工。
BaseAddon
#
一个便利类,jupyterlite_core.addons.base.BaseAddon
可以扩展以提供许多有用的功能。它扩展了 traitlets.LoggingConfigurable
,并将 LiteManager
设为Addon的parent
,允许它通过 jupyter_lite_config.json
按名称配置
{
"LiteBuildConfig": {
"ignore_sys_prefix": true
},
"MyAddon": {
"enable_some_feature": true
}
}
… 或者通过命令行。
jupyter lite build --MyAddon.enable_some_feature=True
简短 CLI#
继承自 BaseAddon
(或以其他方式继承自 traitlets.Configurable
)的Addon可以告诉父应用程序它公开了额外的 CLI 别名和标志,用于执行和使用 --help
查询。
提示
Addons 作者鼓励使用通用前缀对别名和标志进行分组。
别名#
别名将 CLI 参数映射到单个特征。
from traitlets import Int
class MyFooAddon(BaseAddon):
__all__ = ["status"]
aliases = {
"how-many-foos": "MyFooAddon.foo",
}
foo = Int(0, help="The number of foos").tag(config=True)
# ...
警告
Addons 不能覆盖核心别名或先前加载的 addons 的别名。
标志#
标志将 CLI 参数映射到任何数量的 traitlets.Configurable
类上的任何数量的特征
from traitlets import Int, Bool
class MyFooBarAddon(BaseAddon):
__all__ = ["status"]
flags = {
"foo-bar": (
{"MyFooBarAddon": {"foo": 1, "bar": True}},
"Foo once, and bar",
)
}
foo = Int(0, help="The number of foos").tag(config=True)
bar = Bar(False, help="Whether to bar").tag(config=True)
# ...
注意
Addons 可以增强现有标志的行为,但不能覆盖先前注册的配置值。帮助文本将附加一个换行符。
打包#
扩展 通过 entry_points
进行广告,例如在 pyproject.toml
中。
[project.entry-points."jupyterlite.addon.v0"]
my-unique-addon = "my_module:MyAddon"
一般指南#
值得看看
BaseAddon
及其子类如何处理某些任务。牢记可重复性,自由地使用缓存,并利用
file_deps
、targets
和uptodate
来保持构建速度。