创建一个新的插件以扩展 CLI#
虽然 JupyterLite 应用程序的大部分行为可以通过扩展进行配置或修改,但这可能无法满足所有需求。也可以通过_插件_来扩展底层的jupyter lite
CLI。
自定义_插件_可以对已构建的 lite 应用程序的_输出文件夹_执行任何操作,以及修改其他_插件_(包括构成核心 API 的插件)的行为。
一些用例
发布复杂的前端扩展
可预测地修补已构建应用程序中的文件
代码检查、测试、压缩或其他验证和优化技术
注意
选择_插件_是为了将这些组件与浏览器端的_插件_和前端的_扩展_区分开来,并且所有jupyter lite
核心行为都作为_插件_实现。
CLI 架构#
在深入构建插件之前,值得了解它们在 CLI 整体结构中的位置。
为了从多个源下载、解压和更新静态文件和配置,CLI 使用了多层。
组件 |
示例 |
作用 |
---|---|---|
应用 |
加载配置并解析 CLI 参数 |
|
管理器 |
加载插件,运行 |
|
插件 |
生成任务计划并实现操作 |
|
|
收集逻辑生命周期任务 |
|
|
任务的细粒度排序 |
|
|
具有任务和文件依赖关系的一组操作 |
|
Action |
|
实际移动和更新文件 |
插件的结构#
最简单的插件以以下签名初始化
class MyAddon:
__all__ = ["status"]
def status(self, manager):
yield dict(name="hello", actions=[lambda: print("world")])
__all__
成员列出了插件实现的_钩子_钩子也可以带有
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"],
)
App 级别的任务已经根据它们的钩子父级配置了doit.create_after
,这意味着任务可以_自信地_依赖其父级(由任何其他插件)已经存在的文件。
虽然不是_必需的_,但拥有准确的file_dep
和targets
有助于确保已构建的应用程序始终处于一致状态,_而无需_大量返工。
BaseAddon
#
一个便捷类,jupyterlite_core.addons.base.BaseAddon
可以扩展以提供许多有用的功能。它扩展了traitlets.LoggingConfigurable
,并将LiteManager
设为_插件_的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
)的_插件_可以告知父应用程序它公开了额外的 CLI _别名_和_标志_,用于执行以及使用--help
查询时。
提示
鼓励_插件_作者使用共同前缀对他们的别名和标志进行分组。
别名#
_别名_将 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)
# ...
警告
_插件_不得重载核心别名或先前加载的插件的别名。
标志#
_标志_将 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)
# ...
注意
_插件_可以增强现有标志的行为,但不得覆盖先前注册的配置值。帮助文本将附加换行符。
打包#
_插件_通过entry_points
进行广告,例如在pyproject.toml
中
[project.entry-points."jupyterlite.addon.v0"]
my-unique-addon = "my_module:MyAddon"
一般指南#
值得研究
BaseAddon
及其子类如何处理某些任务记住可重现性,尽可能多地缓存,并利用
file_deps
、targets
和uptodate
来保持构建速度