提交 bf42b0a7 编写于 作者: M Mars Liu

fixed nid prefix

上级 978ce20a
......@@ -117,46 +117,6 @@ log 'hello';
这是一个最基本的习题结构,它包含标题、答案、选项,注意这几个一级和二级标题必须填写正确,解释器会读取这几个标题。而选项的标题会被直接忽略掉,在最终生成的习题中不包含选项的三级标题,所以这个标题可以用来标注一些编辑信息,例如“此选项没有关闭文件连接”,“类型错误”等等。
### 增强信息
为了编写习题和生成 notebook 的需要,markdown 解释器支持两种模板能力,具体到 oceanbase ,现在还没有对应的 notebook 支持,所以这部分内容仅供参考,未来如果支持了 oceanbase notebook,就按照下文规范。
````markdown
## aop
### before
```sql
create table test(id integer primary key, content varchar(256));
```
### after
```java
drop table test;
```
````
那么在创建notebook的时候,before 会插入到源代码前一个单元,after 则会插入到源代码后。aop 章节可以只包含 before 或 after 中的某一个,也可以两个都有。
另一些情况下,我们可能需要把各个选项中重复的代码提取出来,建立一个模板,此时可以在答案之前建立一个名为 template 的二级标题,例如:
````markdwon
## template
```sql
begin
$code
end;
```
````
注意这里的代码中,有一个 `$code` 占位符,它在管道程序处理过程中,会替换成答案和个选项内容中的代码。
在后续的数据处理流程中,markdown 会被编译为 prepared 类型的习题。
## 技能树合成
......
{
"keywords": [],
"node_id": "c-a4c730f9873b4d1c985048c5e63990cf",
"node_id": "ob-84787e0a055640d2af669b7ff61bd08a",
"title": "安装OBD"
}
\ No newline at end of file
{
"keywords": [],
"node_id": "c-e175537376e64d88840ca4d9d1e81610",
"node_id": "ob-3c6f0c81923943bab108563f409738c1",
"title": "使用OBD部署"
}
\ No newline at end of file
{
"keywords": [],
"node_id": "c-15525a96d7f24538a3d449ae623efd48",
"node_id": "ob-853a46feb30842b5bafea317687e04df",
"title": "问题排查"
}
\ No newline at end of file
{
"keywords": [],
"node_id": "c-9c2a5df2e2c34cf3a1103cd2e2a3267b",
"node_id": "ob-9ebb7b7c868d41b489286a631c86f918",
"title": "使用OBD"
}
\ No newline at end of file
{
"keywords": [],
"node_id": "c-79d5327189b34b5a90fa74ad32b27305",
"node_id": "ob-a70706dc6bd340fc960132aad2c87707",
"title": "快速入门"
}
\ No newline at end of file
{
"keywords": [],
"node_id": "c-cae5477828d14b448afb6660947859d0",
"node_id": "ob-013bdab5013c4ce4913233f87592f844",
"title": "数据库操作"
}
\ No newline at end of file
{
"keywords": [],
"node_id": "c-e675cce191c3420aa85b7c6b96580635",
"node_id": "ob-d9a4ab293b494b1e8b5dcc4bc6e28685",
"title": "表操作"
}
\ No newline at end of file
{
"keywords": [],
"node_id": "c-c50584a0656e495bb7e800a8b6ceaf77",
"node_id": "ob-22610873050f4f219af2dd3516442690",
"title": "索引操作"
}
\ No newline at end of file
{
"keywords": [],
"node_id": "c-999212d4ca42491ca47f34b936399fcf",
"node_id": "ob-0f74a0152cc54bac9fe0f4875c7b22d3",
"title": "插入数据"
}
\ No newline at end of file
{
"keywords": [],
"node_id": "c-70958f7d51b54425b958cefc6ac45269",
"node_id": "ob-24f2d9140dae40cba5714ad8b91cc233",
"title": "删除数据"
}
\ No newline at end of file
{
"keywords": [],
"node_id": "c-be0d2dee8d904f6cb886a7056d9e46f8",
"node_id": "ob-d4735b0199e041cea568eaf5da3d5bfd",
"title": "更新数据"
}
\ No newline at end of file
{
"keywords": [],
"node_id": "c-a7151df5705f4579bf5f63413385242e",
"node_id": "ob-c9288cdb530e4af789dfc76150e922d8",
"title": "查询数据",
"export": ["hello.json"]
"export": [
"hello.json"
]
}
\ No newline at end of file
{
"type": "code_options",
"author": "刘鑫",
"source": "hello.md"
"source": "hello.md",
"exercise_id": "89b7c140d8734edcbab44cb16f0e836d"
}
\ No newline at end of file
{
"keywords": [],
"node_id": "c-3a77f96aec6e43d7ac98d4d300c02cf5",
"node_id": "ob-511b322d90f9484d9a25108a6ad63aa0",
"title": "提交事务"
}
\ No newline at end of file
{
"keywords": [],
"node_id": "c-f35dcc63713745a6876ab5d4ff328dfe",
"node_id": "ob-ab9965aed5794e7d84cfad5d10ec5599",
"title": "回滚事务"
}
\ No newline at end of file
{
"keywords": [],
"node_id": "c-5021529f00ca4b9daa02569d4cddbb24",
"node_id": "ob-ec5c1a3d85db4ac4b51891002c9585db",
"title": "基本操作"
}
\ No newline at end of file
{
"keywords": [],
"node_id": "c-f599bcb975bd48f89e54e072a988bfb7",
"node_id": "ob-68ab7889257b44979a53385573f73505",
"title": "整体架构"
}
\ No newline at end of file
{
"keywords": [],
"node_id": "c-0dc6506e5e594e30990147b7265bbaa1",
"node_id": "ob-ec3fe81c7bab4cd79c54d6b74e1c1113",
"title": "数据分布"
}
\ No newline at end of file
{
"keywords": [],
"node_id": "c-b9d8c4a7d8a14f398f73c521107017db",
"node_id": "ob-3b0443341ac0408b9488952de107adff",
"title": "数据模型"
}
\ No newline at end of file
{
"keywords": [],
"node_id": "c-43e78261e6bb42fe92e5a5c238bf826a",
"node_id": "ob-47ce8e30a33f479594bf6d2ff0da1bfa",
"title": "高可用"
}
\ No newline at end of file
{
"keywords": [],
"node_id": "c-c2c32929d7c0478d8f93884568b5c13d",
"node_id": "ob-1ec046c02a77404eb53ff06b91573a40",
"title": "事务管理"
}
\ No newline at end of file
{
"keywords": [],
"node_id": "c-5a0baf4394b84466aca8c703366843cc",
"node_id": "ob-b50c55d09413418d90bb648ea9e98c43",
"title": "存储架构"
}
\ No newline at end of file
{
"keywords": [],
"node_id": "c-b3ea14fb38134f089c8583d1fd427cf6",
"node_id": "ob-d86684074ed34222b7fb7896de920dc4",
"title": "SQL引擎"
}
\ No newline at end of file
{
"keywords": [],
"node_id": "c-517b0507b9994e7aab49c3af40479af4",
"node_id": "ob-f31680ba954b4a358f9506f3195c84ee",
"title": "备份与恢复"
}
\ No newline at end of file
{
"keywords": [],
"node_id": "c-cb9ef6b2ddcc4a76a8031f32c4e10ad0",
"node_id": "ob-013816a853dc48469ac7b9cff78de825",
"title": "整体概览"
}
\ No newline at end of file
{
"keywords": [],
"node_id": "c-9304eceab88a41fca82a970dbafc92d8",
"node_id": "ob-f09fe5be766942d787941675c5c0a9bb",
"title": "OceanBase初阶"
}
\ No newline at end of file
{
"keywords": [],
"node_id": "c-a917487b75574a68bb956d210da1170f",
"node_id": "ob-1df64a4e78e94dbdb51b3a233114360a",
"title": "数据库基础组件"
}
\ No newline at end of file
{
"keywords": [],
"node_id": "c-226ffd9c22e9419b912ba9a9ee965307",
"node_id": "ob-1bd2eb6cbd8d439881cd2737cf2996d0",
"title": "数据库管理工具"
}
\ No newline at end of file
{
"keywords": [],
"node_id": "c-d5165a59206347949d45b8f95b7400f2",
"node_id": "ob-a343d533aeea43f08458c09eb810a6a0",
"title": "数据库基础管理"
}
\ No newline at end of file
{
"keywords": [],
"node_id": "c-88118ffc8e1741c6aa44dd1be3606e03",
"node_id": "ob-8e9f8e33ac984fe89b3b9187d3742093",
"title": "数据库对象管理"
}
\ No newline at end of file
{
"keywords": [],
"node_id": "c-52d13d48fb1b4ac4a2ed73cf1f3afd09",
"node_id": "ob-341cfdd78a2a4fb0abe587342bd9b4fa",
"title": "数据库分布和链路管理"
}
\ No newline at end of file
{
"keywords": [],
"node_id": "c-539923037c6a46b5b1ad94f6059a01fd",
"node_id": "ob-9d7b7e878a364a82a3b4362ed78c7803",
"title": "事务管理"
}
\ No newline at end of file
{
"keywords": [],
"node_id": "c-3d5e9c3efc2447cfabf92042ec2f1e8b",
"node_id": "ob-1f1088a4c2214c50a7e2a36cfa8a75a8",
"title": "用户权限管理"
}
\ No newline at end of file
{
"keywords": [],
"node_id": "c-6b15f53d05dc48ae8ba5459334e14533",
"node_id": "ob-7ed2708b1407433794ab475437749b6e",
"title": "数据高可用"
}
\ No newline at end of file
{
"keywords": [],
"node_id": "c-1aa1f8af64dc43fca95163e01ced58b1",
"node_id": "ob-799a2e57c16c48cb9db7756365234b26",
"title": "管理员指南"
}
\ No newline at end of file
{
"keywords": [],
"node_id": "c-18974cc7c0b7434fa77fc3d5e7e6eeba",
"node_id": "ob-a16e1992943c444ab01d885294fb5474",
"title": "事务保存点"
}
\ No newline at end of file
{
"keywords": [],
"node_id": "c-f167b583bd154a468f7748da99330693",
"node_id": "ob-f91c9ce7233e4c83a2cb476963b4682c",
"title": "事务超时"
}
\ No newline at end of file
{
"keywords": [],
"node_id": "c-c13e52bd07294f7ea94a025436658e18",
"node_id": "ob-6cf0404835ee406c914db0a311dab7db",
"title": "创建和管理表"
}
\ No newline at end of file
{
"keywords": [],
"node_id": "c-b1093113f6a349a096f9259fce155d11",
"node_id": "ob-3ba77eca63574cd3a1ded9b4e22053fb",
"title": "创建和管理分区表"
}
\ No newline at end of file
{
"keywords": [],
"node_id": "c-6624753925a54634aa9f995024130db5",
"node_id": "ob-f859f7e05996436aae79d84abb787d77",
"title": "创建和管理表组"
}
\ No newline at end of file
{
"keywords": [],
"node_id": "c-242155c0caf846b1b0862c969da53f21",
"node_id": "ob-e1173a9545f94652bc68383ac3540c3a",
"title": "创建和管理视图"
}
\ No newline at end of file
{
"keywords": [],
"node_id": "c-cdc5f596c1d64103a3c139e470a0df1b",
"node_id": "ob-b759630e2e1344b68c5f358f06751b21",
"title": "迁移和同步"
}
\ No newline at end of file
{
"keywords": [],
"node_id": "c-43de7039f5b64679b681eb361c0aaee7",
"node_id": "ob-005963893ef748439ec3f0eee2a62213",
"title": "数据库集群"
}
\ No newline at end of file
{
"keywords": [],
"node_id": "c-8ef5ac8069114f5f87f50a856cdde5eb",
"node_id": "ob-4836c61e243a42b787aec151f427b0d9",
"title": "OceanBase租户"
}
\ No newline at end of file
{
"keywords": [],
"node_id": "c-f7ca41020acd4ba7a1bfa7c7fe1db5e2",
"node_id": "ob-dcb605252ba849c2b5d096fef3795166",
"title": "MySQL租户"
}
\ No newline at end of file
{
"keywords": [],
"node_id": "c-e605cdbd6dd14f5a9cb86038397613c1",
"node_id": "ob-e60b13f766254d8992e0e89e3b7bc195",
"title": "MySQL客户端"
}
\ No newline at end of file
{
"keywords": [],
"node_id": "c-fc2b0b1d033047b3827889e112d8e9c4",
"node_id": "ob-7a36da0b55c84453bf1d631151b6ecd7",
"title": "OceanBase客户端"
}
\ No newline at end of file
{
"keywords": [],
"node_id": "c-21f2d54deae642e2b98a5f678ccdff9d",
"node_id": "ob-99c7949b37754d6dbaad025b89ffe92e",
"title": "结构化查询语言"
}
\ No newline at end of file
{
"keywords": [],
"node_id": "c-cb4507b2ad80426597c38f904d7630f1",
"node_id": "ob-22ed99032fd94d1fa14d88f1b43fb87a",
"title": "Java连接驱动"
}
\ No newline at end of file
{
"keywords": [],
"node_id": "c-89c1e279cee04b109e40a05eea4ee800",
"node_id": "ob-e6459b45729b4257bb0ee6aad88b9a9c",
"title": "实例数据库"
}
\ No newline at end of file
{
"keywords": [],
"node_id": "c-92dff9fcbf0240aba97d1ff9af97ba99",
"node_id": "ob-ab747f1d6b0b4d14af766b3dcb193786",
"title": "开发者指南"
}
\ No newline at end of file
{
"keywords": [],
"node_id": "c-c716d8ca9e63427fb8165472b61d90ad",
"node_id": "ob-fca45361db8c421cbae40e3ea3ea30a3",
"title": "表查询"
}
\ No newline at end of file
{
"keywords": [],
"node_id": "c-15c6b14ca7624e528c1a4ca5df8c1980",
"node_id": "ob-efdc5f052bd6480cb59ef82791a3fbfb",
"title": "INSERT"
}
\ No newline at end of file
{
"keywords": [],
"node_id": "c-213bc6f5a4ec449fa3d4efced8403bd6",
"node_id": "ob-ebc8f0b58f7c4dcfa8ebb3d7f3dd8221",
"title": "UPDATE"
}
\ No newline at end of file
{
"keywords": [],
"node_id": "c-c1c3b2a58aa04d97b6f06481239b2487",
"node_id": "ob-2790316c37e744439ed7a595e43e9925",
"title": "DELETE"
}
\ No newline at end of file
{
"keywords": [],
"node_id": "c-ffdef42f321b4e9da804e50d24033d35",
"node_id": "ob-cbc6c19dabf84f7382198ff29d47aff0",
"title": "REPLACE"
}
\ No newline at end of file
{
"keywords": [],
"node_id": "c-5be80fbafdab400cb2581495c19b8c46",
"node_id": "ob-04e7b55f5e2240b78e03dc2cc24bbf4c",
"title": "提交事务"
}
\ No newline at end of file
{
"keywords": [],
"node_id": "c-183a734c8d064b1695f1c3ff296df02a",
"node_id": "ob-9b049efa61f748228242736e2601c615",
"title": "回滚事务"
}
\ No newline at end of file
{
"keywords": [],
"node_id": "c-e4d079949fa6404a9ab2ab30f7c5edc6",
"node_id": "ob-7c6aa61f496c4a76955e15bd77b8c8b1",
"title": "OceanBase中阶"
}
\ No newline at end of file
{
"keywords": [],
"node_id": "c-72e40f4c5b704d8ebbc55333a92bcd10",
"node_id": "ob-764fbe37c4104a159a788179177db3bf",
"title": "ob-admin"
}
\ No newline at end of file
{
"keywords": [],
"node_id": "c-f850d34c90be4ad6b4440a1ccb9ec252",
"node_id": "ob-957437fd9b7845f5b44bbdc8975dd637",
"title": "ob-agent"
}
\ No newline at end of file
{
"keywords": [],
"node_id": "c-c3953f56cc4d4cbdbfaebe899163c399",
"node_id": "ob-fcc597f83b724d4fac026263688103e9",
"title": "liboblog"
}
\ No newline at end of file
{
"keywords": [],
"node_id": "c-acfdf149d041465cbb137b9ee1113a68",
"node_id": "ob-2e91481029474f9bb8e11743e8c87a50",
"title": "oblogproxy"
}
\ No newline at end of file
{
"keywords": [],
"node_id": "c-4ffc00c8e57a49958fe0a21c406b2e8a",
"node_id": "ob-e3067da3f27247388d8db68dedea91c2",
"title": "oblogmsg"
}
\ No newline at end of file
{
"keywords": [],
"node_id": "c-fda3afb7b20542b4b0581f640f862863",
"node_id": "ob-623af001479940068ca008d7dc4d8048",
"title": "生态工具"
}
\ No newline at end of file
{
"keywords": [],
"node_id": "c-bcddfe107fa94f2db475cf3ba8b6cf6c",
"node_id": "ob-7ef4eb15586d4065a72b4fa397e7a5fb",
"title": "通用系统参数配置"
}
\ No newline at end of file
{
"keywords": [],
"node_id": "c-3dd02f73d75443829f8d110943321243",
"node_id": "ob-58e375cf2f1a48cb921b773eb34efdab",
"title": "默认生产参数配置"
}
\ No newline at end of file
{
"keywords": [],
"node_id": "c-850a30b6277547dfa1d34bfa4ca0d557",
"node_id": "ob-2591af1e55a14c948906706cc7a2cb7b",
"title": "最小资源参数配置"
}
\ No newline at end of file
{
"keywords": [],
"node_id": "c-a6c41eab49bf494cad102016646a29e0",
"node_id": "ob-fe0c9f76d5534776b1bdc706be88751e",
"title": "最佳性能参数配置"
}
\ No newline at end of file
{
"keywords": [],
"node_id": "c-f61d0f9a558c468dafb9027b2e42a9b1",
"node_id": "ob-fb64af120b5c4403bfb9dce995028b51",
"title": "最佳实践"
}
\ No newline at end of file
{
"keywords": [],
"node_id": "c-5065d39c76f847429b8e39af10b226f8",
"node_id": "ob-51a45bee595a4d3e8e855ad97bafbdfd",
"title": "子查询"
}
\ No newline at end of file
{
"keywords": [],
"node_id": "c-03c93d710d484e928753c100b08a3b5c",
"node_id": "ob-3c76979a5d4541a28db2667f67054a4d",
"title": "连接查询"
}
\ No newline at end of file
{
"keywords": [],
"node_id": "c-efc83dcbe5cb4e64828391fef26b6869",
"node_id": "ob-83b90cfb4ae740e09620f8498178fa1a",
"title": "数据分析"
}
\ No newline at end of file
{
"keywords": [],
"node_id": "c-cf0df1911b794d7abb27edca7465c608",
"node_id": "ob-732b80bf22b34dd9bc138b53939e14a8",
"title": "SQL请求执行顺序"
}
\ No newline at end of file
{
"keywords": [],
"node_id": "c-eee60b66d39147a6ae393334b3ca26b1",
"node_id": "ob-312b3dff536e4efb9ee9d38eec838365",
"title": "函数"
}
\ No newline at end of file
{
"keywords": [],
"node_id": "c-5dbadfb2e60b49e9b6fe796ff0813733",
"node_id": "ob-ada3b8f79a044c7fa9a830cd773c045a",
"title": "SQL执行计划"
}
\ No newline at end of file
{
"keywords": [],
"node_id": "c-1d075127ad8b44aba2086be1d5ecd97a",
"node_id": "ob-7b2c300920524e47bc7b05e25d6e096e",
"title": "分布式执行计划"
}
\ No newline at end of file
{
"keywords": [],
"node_id": "c-9bff77915066428eb36907fa8cae457e",
"node_id": "ob-fbaf5f48374f41cd8333839151ac932f",
"title": "优化"
}
\ No newline at end of file
{
"keywords": [],
"node_id": "c-2fda0435c133420dbc4c048ab571405f",
"node_id": "ob-09fb30cc8c814755824c1f3c35787048",
"title": "编程和查询"
}
\ No newline at end of file
{
"keywords": [],
"node_id": "c-59a8c215a192470388e31341ad679c47",
"node_id": "ob-4d56098f05734c609fd3c605ad37ba72",
"title": "OceanBase高阶"
}
\ No newline at end of file
{
"tree_name": "OceanBase",
"tree_name": "oceanbase",
"keywords": [],
"node_id": "569d5e11c4fc5de7844053d9a733c5e8",
"title": "C"
"node_id": "ob-6254ae328788405087e6831a171a0128",
"title": "OceanBase"
}
\ No newline at end of file
{
"OceanBase": {
"node_id": "569d5e11c4fc5de7844053d9a733c5e8",
"oceanbase": {
"node_id": "ob-6254ae328788405087e6831a171a0128",
"keywords": [],
"children": [
{
"OceanBase初阶": {
"node_id": "c-9304eceab88a41fca82a970dbafc92d8",
"node_id": "ob-f09fe5be766942d787941675c5c0a9bb",
"keywords": [],
"children": [
{
"快速入门": {
"node_id": "c-79d5327189b34b5a90fa74ad32b27305",
"node_id": "ob-a70706dc6bd340fc960132aad2c87707",
"keywords": [],
"children": [
{
"安装OBD": {
"node_id": "c-a4c730f9873b4d1c985048c5e63990cf",
"node_id": "ob-84787e0a055640d2af669b7ff61bd08a",
"keywords": [],
"children": []
}
},
{
"使用OBD部署": {
"node_id": "c-e175537376e64d88840ca4d9d1e81610",
"node_id": "ob-3c6f0c81923943bab108563f409738c1",
"keywords": [],
"children": []
}
},
{
"问题排查": {
"node_id": "c-15525a96d7f24538a3d449ae623efd48",
"node_id": "ob-853a46feb30842b5bafea317687e04df",
"keywords": [],
"children": []
}
},
{
"使用OBD": {
"node_id": "c-9c2a5df2e2c34cf3a1103cd2e2a3267b",
"node_id": "ob-9ebb7b7c868d41b489286a631c86f918",
"keywords": [],
"children": []
}
......@@ -46,68 +46,68 @@
},
{
"基本操作": {
"node_id": "c-5021529f00ca4b9daa02569d4cddbb24",
"node_id": "ob-ec5c1a3d85db4ac4b51891002c9585db",
"keywords": [],
"children": [
{
"数据库操作": {
"node_id": "c-cae5477828d14b448afb6660947859d0",
"node_id": "ob-013bdab5013c4ce4913233f87592f844",
"keywords": [],
"children": []
}
},
{
"表操作": {
"node_id": "c-e675cce191c3420aa85b7c6b96580635",
"node_id": "ob-d9a4ab293b494b1e8b5dcc4bc6e28685",
"keywords": [],
"children": []
}
},
{
"索引操作": {
"node_id": "c-c50584a0656e495bb7e800a8b6ceaf77",
"node_id": "ob-22610873050f4f219af2dd3516442690",
"keywords": [],
"children": []
}
},
{
"插入数据": {
"node_id": "c-999212d4ca42491ca47f34b936399fcf",
"node_id": "ob-0f74a0152cc54bac9fe0f4875c7b22d3",
"keywords": [],
"children": []
}
},
{
"删除数据": {
"node_id": "c-70958f7d51b54425b958cefc6ac45269",
"node_id": "ob-24f2d9140dae40cba5714ad8b91cc233",
"keywords": [],
"children": []
}
},
{
"更新数据": {
"node_id": "c-be0d2dee8d904f6cb886a7056d9e46f8",
"node_id": "ob-d4735b0199e041cea568eaf5da3d5bfd",
"keywords": [],
"children": []
}
},
{
"查询数据": {
"node_id": "c-a7151df5705f4579bf5f63413385242e",
"node_id": "ob-c9288cdb530e4af789dfc76150e922d8",
"keywords": [],
"children": []
}
},
{
"提交事务": {
"node_id": "c-3a77f96aec6e43d7ac98d4d300c02cf5",
"node_id": "ob-511b322d90f9484d9a25108a6ad63aa0",
"keywords": [],
"children": []
}
},
{
"回滚事务": {
"node_id": "c-f35dcc63713745a6876ab5d4ff328dfe",
"node_id": "ob-ab9965aed5794e7d84cfad5d10ec5599",
"keywords": [],
"children": []
}
......@@ -117,61 +117,61 @@
},
{
"整体概览": {
"node_id": "c-cb9ef6b2ddcc4a76a8031f32c4e10ad0",
"node_id": "ob-013816a853dc48469ac7b9cff78de825",
"keywords": [],
"children": [
{
"整体架构": {
"node_id": "c-f599bcb975bd48f89e54e072a988bfb7",
"node_id": "ob-68ab7889257b44979a53385573f73505",
"keywords": [],
"children": []
}
},
{
"数据分布": {
"node_id": "c-0dc6506e5e594e30990147b7265bbaa1",
"node_id": "ob-ec3fe81c7bab4cd79c54d6b74e1c1113",
"keywords": [],
"children": []
}
},
{
"数据模型": {
"node_id": "c-b9d8c4a7d8a14f398f73c521107017db",
"node_id": "ob-3b0443341ac0408b9488952de107adff",
"keywords": [],
"children": []
}
},
{
"高可用": {
"node_id": "c-43e78261e6bb42fe92e5a5c238bf826a",
"node_id": "ob-47ce8e30a33f479594bf6d2ff0da1bfa",
"keywords": [],
"children": []
}
},
{
"事务管理": {
"node_id": "c-c2c32929d7c0478d8f93884568b5c13d",
"node_id": "ob-1ec046c02a77404eb53ff06b91573a40",
"keywords": [],
"children": []
}
},
{
"存储架构": {
"node_id": "c-5a0baf4394b84466aca8c703366843cc",
"node_id": "ob-b50c55d09413418d90bb648ea9e98c43",
"keywords": [],
"children": []
}
},
{
"SQL引擎": {
"node_id": "c-b3ea14fb38134f089c8583d1fd427cf6",
"node_id": "ob-d86684074ed34222b7fb7896de920dc4",
"keywords": [],
"children": []
}
},
{
"备份与恢复": {
"node_id": "c-517b0507b9994e7aab49c3af40479af4",
"node_id": "ob-f31680ba954b4a358f9506f3195c84ee",
"keywords": [],
"children": []
}
......@@ -184,66 +184,66 @@
},
{
"OceanBase中阶": {
"node_id": "c-e4d079949fa6404a9ab2ab30f7c5edc6",
"node_id": "ob-7c6aa61f496c4a76955e15bd77b8c8b1",
"keywords": [],
"children": [
{
"管理员指南": {
"node_id": "c-1aa1f8af64dc43fca95163e01ced58b1",
"node_id": "ob-799a2e57c16c48cb9db7756365234b26",
"keywords": [],
"children": [
{
"数据库基础组件": {
"node_id": "c-a917487b75574a68bb956d210da1170f",
"node_id": "ob-1df64a4e78e94dbdb51b3a233114360a",
"keywords": [],
"children": []
}
},
{
"数据库管理工具": {
"node_id": "c-226ffd9c22e9419b912ba9a9ee965307",
"node_id": "ob-1bd2eb6cbd8d439881cd2737cf2996d0",
"keywords": [],
"children": []
}
},
{
"数据库基础管理": {
"node_id": "c-d5165a59206347949d45b8f95b7400f2",
"node_id": "ob-a343d533aeea43f08458c09eb810a6a0",
"keywords": [],
"children": []
}
},
{
"数据库对象管理": {
"node_id": "c-88118ffc8e1741c6aa44dd1be3606e03",
"node_id": "ob-8e9f8e33ac984fe89b3b9187d3742093",
"keywords": [],
"children": []
}
},
{
"数据库分布和链路管理": {
"node_id": "c-52d13d48fb1b4ac4a2ed73cf1f3afd09",
"node_id": "ob-341cfdd78a2a4fb0abe587342bd9b4fa",
"keywords": [],
"children": []
}
},
{
"事务管理": {
"node_id": "c-539923037c6a46b5b1ad94f6059a01fd",
"node_id": "ob-9d7b7e878a364a82a3b4362ed78c7803",
"keywords": [],
"children": []
}
},
{
"用户权限管理": {
"node_id": "c-3d5e9c3efc2447cfabf92042ec2f1e8b",
"node_id": "ob-1f1088a4c2214c50a7e2a36cfa8a75a8",
"keywords": [],
"children": []
}
},
{
"数据高可用": {
"node_id": "c-6b15f53d05dc48ae8ba5459334e14533",
"node_id": "ob-7ed2708b1407433794ab475437749b6e",
"keywords": [],
"children": []
}
......@@ -253,110 +253,110 @@
},
{
"事务保存点": {
"node_id": "c-18974cc7c0b7434fa77fc3d5e7e6eeba",
"node_id": "ob-a16e1992943c444ab01d885294fb5474",
"keywords": [],
"children": []
}
},
{
"事务超时": {
"node_id": "c-f167b583bd154a468f7748da99330693",
"node_id": "ob-f91c9ce7233e4c83a2cb476963b4682c",
"keywords": [],
"children": []
}
},
{
"创建和管理表": {
"node_id": "c-c13e52bd07294f7ea94a025436658e18",
"node_id": "ob-6cf0404835ee406c914db0a311dab7db",
"keywords": [],
"children": []
}
},
{
"创建和管理分区表": {
"node_id": "c-b1093113f6a349a096f9259fce155d11",
"node_id": "ob-3ba77eca63574cd3a1ded9b4e22053fb",
"keywords": [],
"children": []
}
},
{
"创建和管理表组": {
"node_id": "c-6624753925a54634aa9f995024130db5",
"node_id": "ob-f859f7e05996436aae79d84abb787d77",
"keywords": [],
"children": []
}
},
{
"创建和管理视图": {
"node_id": "c-242155c0caf846b1b0862c969da53f21",
"node_id": "ob-e1173a9545f94652bc68383ac3540c3a",
"keywords": [],
"children": []
}
},
{
"迁移和同步": {
"node_id": "c-cdc5f596c1d64103a3c139e470a0df1b",
"node_id": "ob-b759630e2e1344b68c5f358f06751b21",
"keywords": [],
"children": []
}
},
{
"开发者指南": {
"node_id": "c-92dff9fcbf0240aba97d1ff9af97ba99",
"node_id": "ob-ab747f1d6b0b4d14af766b3dcb193786",
"keywords": [],
"children": [
{
"数据库集群": {
"node_id": "c-43de7039f5b64679b681eb361c0aaee7",
"node_id": "ob-005963893ef748439ec3f0eee2a62213",
"keywords": [],
"children": []
}
},
{
"OceanBase租户": {
"node_id": "c-8ef5ac8069114f5f87f50a856cdde5eb",
"node_id": "ob-4836c61e243a42b787aec151f427b0d9",
"keywords": [],
"children": []
}
},
{
"MySQL租户": {
"node_id": "c-f7ca41020acd4ba7a1bfa7c7fe1db5e2",
"node_id": "ob-dcb605252ba849c2b5d096fef3795166",
"keywords": [],
"children": []
}
},
{
"MySQL客户端": {
"node_id": "c-e605cdbd6dd14f5a9cb86038397613c1",
"node_id": "ob-e60b13f766254d8992e0e89e3b7bc195",
"keywords": [],
"children": []
}
},
{
"OceanBase客户端": {
"node_id": "c-fc2b0b1d033047b3827889e112d8e9c4",
"node_id": "ob-7a36da0b55c84453bf1d631151b6ecd7",
"keywords": [],
"children": []
}
},
{
"结构化查询语言": {
"node_id": "c-21f2d54deae642e2b98a5f678ccdff9d",
"node_id": "ob-99c7949b37754d6dbaad025b89ffe92e",
"keywords": [],
"children": []
}
},
{
"Java连接驱动": {
"node_id": "c-cb4507b2ad80426597c38f904d7630f1",
"node_id": "ob-22ed99032fd94d1fa14d88f1b43fb87a",
"keywords": [],
"children": []
}
},
{
"实例数据库": {
"node_id": "c-89c1e279cee04b109e40a05eea4ee800",
"node_id": "ob-e6459b45729b4257bb0ee6aad88b9a9c",
"keywords": [],
"children": []
}
......@@ -366,49 +366,49 @@
},
{
"表查询": {
"node_id": "c-c716d8ca9e63427fb8165472b61d90ad",
"node_id": "ob-fca45361db8c421cbae40e3ea3ea30a3",
"keywords": [],
"children": []
}
},
{
"INSERT": {
"node_id": "c-15c6b14ca7624e528c1a4ca5df8c1980",
"node_id": "ob-efdc5f052bd6480cb59ef82791a3fbfb",
"keywords": [],
"children": []
}
},
{
"UPDATE": {
"node_id": "c-213bc6f5a4ec449fa3d4efced8403bd6",
"node_id": "ob-ebc8f0b58f7c4dcfa8ebb3d7f3dd8221",
"keywords": [],
"children": []
}
},
{
"DELETE": {
"node_id": "c-c1c3b2a58aa04d97b6f06481239b2487",
"node_id": "ob-2790316c37e744439ed7a595e43e9925",
"keywords": [],
"children": []
}
},
{
"REPLACE": {
"node_id": "c-ffdef42f321b4e9da804e50d24033d35",
"node_id": "ob-cbc6c19dabf84f7382198ff29d47aff0",
"keywords": [],
"children": []
}
},
{
"提交事务": {
"node_id": "c-5be80fbafdab400cb2581495c19b8c46",
"node_id": "ob-04e7b55f5e2240b78e03dc2cc24bbf4c",
"keywords": [],
"children": []
}
},
{
"回滚事务": {
"node_id": "c-183a734c8d064b1695f1c3ff296df02a",
"node_id": "ob-9b049efa61f748228242736e2601c615",
"keywords": [],
"children": []
}
......@@ -418,45 +418,45 @@
},
{
"OceanBase高阶": {
"node_id": "c-59a8c215a192470388e31341ad679c47",
"node_id": "ob-4d56098f05734c609fd3c605ad37ba72",
"keywords": [],
"children": [
{
"生态工具": {
"node_id": "c-fda3afb7b20542b4b0581f640f862863",
"node_id": "ob-623af001479940068ca008d7dc4d8048",
"keywords": [],
"children": [
{
"ob-admin": {
"node_id": "c-72e40f4c5b704d8ebbc55333a92bcd10",
"node_id": "ob-764fbe37c4104a159a788179177db3bf",
"keywords": [],
"children": []
}
},
{
"ob-agent": {
"node_id": "c-f850d34c90be4ad6b4440a1ccb9ec252",
"node_id": "ob-957437fd9b7845f5b44bbdc8975dd637",
"keywords": [],
"children": []
}
},
{
"liboblog": {
"node_id": "c-c3953f56cc4d4cbdbfaebe899163c399",
"node_id": "ob-fcc597f83b724d4fac026263688103e9",
"keywords": [],
"children": []
}
},
{
"oblogproxy": {
"node_id": "c-acfdf149d041465cbb137b9ee1113a68",
"node_id": "ob-2e91481029474f9bb8e11743e8c87a50",
"keywords": [],
"children": []
}
},
{
"oblogmsg": {
"node_id": "c-4ffc00c8e57a49958fe0a21c406b2e8a",
"node_id": "ob-e3067da3f27247388d8db68dedea91c2",
"keywords": [],
"children": []
}
......@@ -466,33 +466,33 @@
},
{
"最佳实践": {
"node_id": "c-f61d0f9a558c468dafb9027b2e42a9b1",
"node_id": "ob-fb64af120b5c4403bfb9dce995028b51",
"keywords": [],
"children": [
{
"通用系统参数配置": {
"node_id": "c-bcddfe107fa94f2db475cf3ba8b6cf6c",
"node_id": "ob-7ef4eb15586d4065a72b4fa397e7a5fb",
"keywords": [],
"children": []
}
},
{
"默认生产参数配置": {
"node_id": "c-3dd02f73d75443829f8d110943321243",
"node_id": "ob-58e375cf2f1a48cb921b773eb34efdab",
"keywords": [],
"children": []
}
},
{
"最小资源参数配置": {
"node_id": "c-850a30b6277547dfa1d34bfa4ca0d557",
"node_id": "ob-2591af1e55a14c948906706cc7a2cb7b",
"keywords": [],
"children": []
}
},
{
"最佳性能参数配置": {
"node_id": "c-a6c41eab49bf494cad102016646a29e0",
"node_id": "ob-fe0c9f76d5534776b1bdc706be88751e",
"keywords": [],
"children": []
}
......@@ -502,61 +502,61 @@
},
{
"编程和查询": {
"node_id": "c-2fda0435c133420dbc4c048ab571405f",
"node_id": "ob-09fb30cc8c814755824c1f3c35787048",
"keywords": [],
"children": [
{
"子查询": {
"node_id": "c-5065d39c76f847429b8e39af10b226f8",
"node_id": "ob-51a45bee595a4d3e8e855ad97bafbdfd",
"keywords": [],
"children": []
}
},
{
"连接查询": {
"node_id": "c-03c93d710d484e928753c100b08a3b5c",
"node_id": "ob-3c76979a5d4541a28db2667f67054a4d",
"keywords": [],
"children": []
}
},
{
"数据分析": {
"node_id": "c-efc83dcbe5cb4e64828391fef26b6869",
"node_id": "ob-83b90cfb4ae740e09620f8498178fa1a",
"keywords": [],
"children": []
}
},
{
"SQL请求执行顺序": {
"node_id": "c-cf0df1911b794d7abb27edca7465c608",
"node_id": "ob-732b80bf22b34dd9bc138b53939e14a8",
"keywords": [],
"children": []
}
},
{
"函数": {
"node_id": "c-eee60b66d39147a6ae393334b3ca26b1",
"node_id": "ob-312b3dff536e4efb9ee9d38eec838365",
"keywords": [],
"children": []
}
},
{
"SQL执行计划": {
"node_id": "c-5dbadfb2e60b49e9b6fe796ff0813733",
"node_id": "ob-ada3b8f79a044c7fa9a830cd773c045a",
"keywords": [],
"children": []
}
},
{
"分布式执行计划": {
"node_id": "c-1d075127ad8b44aba2086be1d5ecd97a",
"node_id": "ob-7b2c300920524e47bc7b05e25d6e096e",
"keywords": [],
"children": []
}
},
{
"优化": {
"node_id": "c-9bff77915066428eb36907fa8cae457e",
"node_id": "ob-fbaf5f48374f41cd8333839151ac932f",
"keywords": [],
"children": []
}
......
from src.tree import gen_tree
if __name__ == '__main__':
gen_tree('data')
# -*- coding: UTF-8 -*-
import importlib
def dispatch(config, options, actions, targets):
''' 分发命令行 action '''
action_len = len(actions)
if action_len < 2:
return
index = 1
next = targets
action = actions[index]
print(f"[命令路由中..]: {actions[0]}")
while action_len >= index:
if type(next) == type({}):
if index == action_len:
if next.get('run') != None:
print(f"[命令路由执行]:", '->'.join(actions))
next['run']()
break
action = actions[index]
if next.get(action) != None:
print(f"[命令路由中..]: {action}")
next = next[action]
index += 1
else:
print("[命令路由错误]: 未找到支持的命令行路由:", '->'.join(actions))
index += 1
else:
print(f"[命令路由执行]:", '->'.join(actions))
next()
index += 1
break
def dispatch_runner(config, options, actions, targets):
''' 分发命令行 action '''
action_len = len(actions)
if action_len < 2:
return
def load_and_run(target):
modules = target.split('.')
class_pos = len(modules)-2
path_pos = len(modules)-1
if class_pos >= 0 and modules[class_pos][0].isupper():
constructor = modules[class_pos]
runner = modules[path_pos]
module_path = '.'.join(modules[:class_pos])
importlib.import_module(module_path).__getattribute__(
constructor)(config, options).__getattribute__(runner)()
else:
runner = modules[path_pos]
module_path = '.'.join(modules[:path_pos])
importlib.import_module(module_path).__getattribute__(
runner)(config, options)
index = 1
next = targets
while action_len >= index:
if type(next) == type({}):
if index == action_len:
if next.get('run') != None:
load_and_run(next['run'])
break
action = actions[index]
if next.get(action) != None:
next = next[action]
index += 1
else:
load_and_run(next)
index += 1
break
# -*- coding: UTF-8 -*-
import os
import logging
import platform
from logging.handlers import RotatingFileHandler
def is_osx():
p = platform.platform()
return p.find('macOS') >= 0 or p.find('Darwin') >= 0
def get_root_log_dir(config, options):
action = 'default'
if options.action:
action = options.action
if is_osx():
return '/tmp/csdn/ai/{}'.format(action)
else:
is_dev = (options.cluster is None) or (options.cluster == 'dev')
if is_dev:
return '../log/csdn/ai/{}'.format(action)
else:
return '/var/csdn/csdn/ai/{}'.format(action)
class TruncatedFileHandler(RotatingFileHandler):
'''
日志文件按固定大小自动分割
'''
def __init__(self, filename, mode='a', maxBytes=0, encoding=None, delay=0):
super(TruncatedFileHandler, self).__init__(
filename, mode, maxBytes, 0, encoding, delay)
def doRollover(self):
"""Truncate the file"""
if self.stream:
self.stream.close()
dfn = self.baseFilename + ".1"
if os.path.exists(dfn):
os.remove(dfn)
os.rename(self.baseFilename, dfn)
os.remove(dfn)
self.mode = 'w'
self.stream = self._open()
def init_log(config, options):
# 创建日志目录
root_log_dir = get_root_log_dir(config, options)
os.makedirs(root_log_dir, exist_ok=True)
print('root_log_dir:', root_log_dir)
# 文件日志控制器
log_filename = root_log_dir+'/app.log'
file_handler = TruncatedFileHandler(log_filename, "w", 10*1024)
# 控制台日志控制器
console_handler = logging.StreamHandler()
# 日志配置
logging.basicConfig(
# 日志格式
format="[%(levelname)s][%(asctime)s][%(filename)s:%(lineno)d at %(funcName)s]: %(message)s",
# 日期格式
datefmt='%Y-%m-%d %H:%M:%S',
# 日志级别
level=logging.INFO,
# 输出目标,日志文件+控制台
handlers=[
file_handler,
console_handler
]
)
# -*- coding: UTF-8 -*-
import os
import json
from lib.apollo import ApolloClient
def load_apollo_config(options):
'''
阿波罗配置加载
===
* 如果是 `pro` 环境,则使用线上配置
* 否则,使用内网配置
'''
config_url = None
if options.cluster == 'pro':
config_url = 'http://pro.config.csdn.net:8080'
elif options.cluster == 'fat':
config_url = 'http://fat.config.csdn.net:8080'
elif options.cluster == 'uat':
config_url = 'http://uat.config.csdn.net:8080'
else:
config_url = 'http://dev.config.csdn.net:8080'
client = ApolloClient(
app_id="949",
cluster="default",
config_url=config_url,
start_hot_update=False
)
config = client.get_value("csdn-ai", namespace="application")
return json.loads(config)
def load_config(options, args):
'''
配置加载
===
* 如果本地 config/config 目录下存在配置,则使用本地配置文件
* 如果本地 config/config 目录下不存在配置,
* 默认使用 阿波罗配置中心 cluster=dev 配置
* 如果指定 --cluster,则使用指定 cluster 的阿波罗配置中心的配置
'''
profile_path = "config/config/{}.json".format(options.profile)
config = None
if options.cluster:
config = load_apollo_config(options)
else:
if os.path.exists(profile_path):
with open(profile_path, "r") as f:
config = json.loads(f.read())
else:
# try:
# options.cluster = 'dev'
# config = load_apollo_config(options)
# except:
config = {}
return config
# -*- coding: UTF-8 -*-
from common.logger import init_log
from config.config import load_config
from options import parse_options, show_help
from tree import gen_tree
from os import walk
import os.path
def test(config, options, actions):
import test as test
test.dispatch(config, options, actions)
def readall(path):
with open(path) as f:
return f.read()
def write(path, data):
with open(path, "w") as f:
f.write(data)
def makeup():
for dir, sub_dirs, files in walk("../data"):
for fname in files:
_, ext = os.path.splitext(fname)
if ext == ".md":
full_path = os.path.join(dir, fname)
content = readall(full_path)
lines = content.split("\n")
new_lines = []
flag = False
in_block = False
for line in lines:
new_line = line
if line.startswith("```"):
if in_block:
in_block = False
else:
in_block = True
if line[3:] != "":
continue
else:
new_line = line + 'c'
flag = True
new_lines.append(new_line)
if flag:
content = "\n".join(new_lines)
write(full_path, content)
def tree(config, options, actions):
import test as test
gen_tree("../data")
def run(options):
# 操作入口
if options.action is not None:
actions = options.action.split('.')
if len(actions) == 0:
return
print('@init config...')
config = load_config(options, args)
print('')
print('@init log...')
init_log(config, options)
print('')
print('@dispatch action:{}...'.format(options.action))
root_action = actions[0]
next = actions[1:]
dispatch = {
'test': lambda: test(config, options, next),
'tree': lambda: tree(config, options, next),
'makeup': lambda: makeup()
}
dispatch[root_action]()
else:
show_help()
if __name__ == "__main__":
[options, args] = parse_options()
run(options)
from optparse import OptionParser
def parse_common_options(parser):
'''
## 公共选项
* -t 或者 --tag_id : 某个操作限制到指定tag_id的数据范围
* --reset: 重置选项
* --tag_name: 标签名字
* --model: 模型名字
* --log: 日志级别
* --train: 训练
* --port: 端口
* --show_config: 显示配置
* --count: 指定数量
* --query: 自定义查询
'''
parser.add_option(
"-t", "--tag_id",
dest="tag_id",
help="tag_id",
metavar="TAG_ID"
)
parser.add_option(
"--reset",
dest="reset",
help="reset",
action="store_true",
metavar="RESET"
)
parser.add_option(
"--tag_name",
dest="tag_name",
help="tag_name",
metavar="TAG_NAME"
)
parser.add_option(
"--model",
dest="model",
help="model",
metavar="MODEL"
)
parser.add_option(
"--log",
dest="log",
help="log",
metavar="LOG"
)
parser.add_option(
"--train",
dest="train",
help="train",
action="store_true",
metavar="TRAIN"
)
parser.add_option(
"--port",
dest="port",
help="port",
metavar="PORT"
)
parser.add_option(
"--server",
dest="server",
help="server",
metavar="SERVER"
)
parser.add_option(
"--show_config",
dest="show_config",
help="show_config",
metavar="SHOW_CONFIG"
)
parser.add_option(
"--count",
dest="count",
help="count",
metavar="COUNT"
)
parser.add_option(
"--query",
dest="query",
help="query",
metavar="QUERY"
)
def parse_profile_options(parser):
'''
## 环境配置选项
* -p 或 --profile 指定配置环境,可选的有 `dev`, `fat`, `pre`, `pro`
* 如果本地 config/config 目录下存在配置,则使用本地配置文件
* 如果本地 config/config 目录下不存在配置,
* 默认使用 阿波罗配置中心 cluster=dev 配置
* 如果指定 --cluster,则使用指定 cluster 的阿波罗配置中心的配置
'''
parser.add_option(
"-p", "--profile",
dest="profile",
help="profile",
default='pro',
metavar="PROFILE"
)
parser.add_option(
"--cluster",
dest="cluster",
help="cluster",
metavar="REMOTE"
)
def parse_action_options(parser):
'''
## 操作选项
* -a 或 --action 指定了操作目标,多级目标用点号分割,例如:
* -a dataset.build.tag.all
* -a server.ask
* -a test.code
* 参考[README](./README.md)
'''
parser.add_option(
"-a", "--action",
dest="action",
help="action",
metavar="ACTION"
)
def parse_test_options(parser):
'''
## 测试选项
执行 -a test.xx 测试时默认执行冒烟测试,下面的选项改变行为
* --label 指定执行测试并生成待标注数据
* --count 指定标注上限
'''
parser.add_option(
"--label",
dest="label",
help="label",
action="store_true",
metavar="LABEL"
)
def parse_db_options(parser):
'''
## 数据库 migrate 选项
* --message 传入一个消息变量,db.migrate action 接收此参数
* --revision 传入版本参数,db.upgrade, db.downgrade, db.stamp, db.show, db.edit 接受此参数
'''
parser.add_option(
"--message",
dest="message",
help="message",
metavar="MESSAGE"
)
parser.add_option(
"--revision",
dest="revision",
help="revision",
metavar="REVISION"
)
def parse_options():
parser = OptionParser()
parse_common_options(parser)
parse_profile_options(parser)
parse_action_options(parser)
parse_test_options(parser)
parse_db_options(parser)
(options, args) = parser.parse_args()
return [options, args]
def show_help():
'''
命令行选项说明:
==
'''
help = '\n'.join([
show_help.__doc__,
parse_common_options.__doc__,
parse_profile_options.__doc__,
parse_action_options.__doc__
])
print(help)
......@@ -21,7 +21,7 @@ def dump_json(p, j, exist_ok=False, override=False):
print(f"{p} already exist")
sys.exit(0)
with open(p, 'w') as f:
with open(p, 'w+') as f:
f.write(json.dumps(j, indent=2, ensure_ascii=False))
......@@ -56,7 +56,7 @@ def gen_tree(data_path):
def gen_node_id():
# return ''.join(str(uuid.uuid5(uuid.NAMESPACE_URL, 'skill_tree')).split('-'))
return "c-" + uuid.uuid4().hex
return "ob-" + uuid.uuid4().hex
def list_dir(p):
v = os.listdir(p)
......@@ -117,7 +117,7 @@ def gen_tree(data_path):
cfg_path = os.path.join(data_path, 'config.json')
cfg = load_json(cfg_path)
if ensure_node_id(cfg):
dump_json(cfg_path, cfg)
dump_json(cfg_path, cfg, exist_ok=True, override=True)
if ensure_title(cfg, cfg_path):
cfg["title"] = "C"
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册