提交 b7ce0d39 编写于 作者: L luxin

add keywords_must and keywords_forbid

上级 15539b61
......@@ -9,5 +9,7 @@
"export": [
"HelloWorld.json"
],
"title": "Hello World"
"title": "Hello World",
"keywords_must": [],
"keywords_forbid": []
}
\ No newline at end of file
......@@ -7,5 +7,7 @@
],
"export": [
"Intro.json"
]
],
"keywords_must": [],
"keywords_forbid": []
}
\ No newline at end of file
{
"node_id": "csharp-8f1055780aff4ed8bc5927bac6fb562b",
"keywords": [
".NET Standard",
".NET 实现"
".NET Standard",
".NET 实现"
],
"children": [],
"export": [
"Standard.json"
]
"Standard.json"
],
"keywords_must": [],
"keywords_forbid": []
}
\ No newline at end of file
{
"node_id": "csharp-7029a05888534973bfa9656762e0c187",
"keywords": [
".NET 共享库",
".NET 类库",
".NET 标准库"
".NET 共享库",
".NET 类库",
".NET 标准库"
],
"children": [],
"export": [
"Lib.json"
]
"Lib.json"
],
"keywords_must": [],
"keywords_forbid": []
}
\ No newline at end of file
{
"node_id": "csharp-65d2fd88ed1e44a6a646be4f3c302e50",
"keywords": [
".NET Standard 版本"
".NET Standard 版本"
],
"children": [],
"export": [
"StandardQuery.json"
]
"StandardQuery.json"
],
"keywords_must": [],
"keywords_forbid": []
}
\ No newline at end of file
{
"node_id": "csharp-e2aeed39b8d5434581176882e1838aa5",
"keywords": []
"keywords": [],
"keywords_must": [],
"keywords_forbid": []
}
\ No newline at end of file
{
"node_id": "csharp-8f63c0182bed428cb2c75bc1d10a6502",
"keywords": [
"C# HelloWorld"
"C# HelloWorld"
],
"children": [],
"export": [
"HelloWorld2.json"
]
"HelloWorld2.json"
],
"keywords_must": [],
"keywords_forbid": []
}
\ No newline at end of file
{
"node_id": "csharp-052799fae6c2498f9ef2966925377631",
"keywords": [
"C# 字符串",
"C# 变量",
"C# 整型",
"C# 基本类型"
"C# 字符串",
"C# 变量",
"C# 整型",
"C# 基本类型"
],
"children": [],
"export": [
"String.json",
"Variable.json"
]
"String.json",
"Variable.json"
],
"keywords_must": [],
"keywords_forbid": []
}
\ No newline at end of file
{
"node_id": "csharp-6213732b191f434fb809de14eadee919",
"keywords": [
"C# 字符串格式化"
"C# 字符串格式化"
],
"children": [],
"export": [
"Format.json",
"StringFormatting.json"
]
"Format.json",
"StringFormatting.json"
],
"keywords_must": [],
"keywords_forbid": []
}
\ No newline at end of file
{
"node_id": "csharp-8891612a2ed349b4a04dee606c44a292",
"keywords": [
"C# 数字运算符",
"C# 四则运算"
"C# 数字运算符",
"C# 四则运算"
],
"children": [],
"export": [
"Calc.json"
]
"Calc.json"
],
"keywords_must": [],
"keywords_forbid": []
}
\ No newline at end of file
{
"node_id": "csharp-ecdbead6dc0f4676b048a3d3d6a31741",
"keywords": [
".NET 基础类库"
".NET 基础类库"
],
"children": [],
"export": [
"Guess.json"
]
"Guess.json"
],
"keywords_must": [],
"keywords_forbid": []
}
\ No newline at end of file
{
"node_id": "csharp-d1ae8aa6b969476db5177062e3980a2f",
"keywords": [
"C# 分支判断"
"C# 分支判断"
],
"children": [],
"export": [
"Guard.json",
"Switch.json"
]
"Guard.json",
"Switch.json"
],
"keywords_must": [],
"keywords_forbid": []
}
\ No newline at end of file
{
"node_id": "csharp-e8990ea17ca34c49b4d0c69b3272bc10",
"keywords": [
"C# 数组",
"foreach",
"斐波那契数列"
"C# 数组",
"foreach",
"斐波那契数列"
],
"children": [],
"export": [
"Loop.json"
]
"Loop.json"
],
"keywords_must": [],
"keywords_forbid": []
}
\ No newline at end of file
{
"node_id": "csharp-302a68c721e44f489e00820b5898ec10",
"keywords": [
"C# 编码规范",
"C# 注释"
"C# 编码规范",
"C# 注释"
],
"children": [],
"export": [
"Comments.json"
]
"Comments.json"
],
"keywords_must": [],
"keywords_forbid": []
}
\ No newline at end of file
{
"node_id": "csharp-29be47be65ab45a1afa37ac2f2fdccc9",
"keywords": []
"keywords": [],
"keywords_must": [],
"keywords_forbid": []
}
\ No newline at end of file
......@@ -9,5 +9,7 @@
"扩展方法"
],
"children": [],
"export": []
"export": [],
"keywords_must": [],
"keywords_forbid": []
}
\ No newline at end of file
......@@ -7,5 +7,7 @@
"动态查找"
],
"children": [],
"export": []
"export": [],
"keywords_must": [],
"keywords_forbid": []
}
\ No newline at end of file
......@@ -8,5 +8,7 @@
"绑定运算符,:=:"
],
"children": [],
"export": []
"export": [],
"keywords_must": [],
"keywords_forbid": []
}
\ No newline at end of file
......@@ -14,5 +14,7 @@
"表达式方法体"
],
"children": [],
"export": []
"export": [],
"keywords_must": [],
"keywords_forbid": []
}
\ No newline at end of file
......@@ -20,5 +20,7 @@
"只读引用"
],
"children": [],
"export": []
"export": [],
"keywords_must": [],
"keywords_forbid": []
}
\ No newline at end of file
......@@ -9,5 +9,7 @@
"接口成员的默认实现"
],
"children": [],
"export": []
"export": [],
"keywords_must": [],
"keywords_forbid": []
}
\ No newline at end of file
......@@ -13,5 +13,7 @@
"非破坏性变化"
],
"children": [],
"export": []
"export": [],
"keywords_must": [],
"keywords_forbid": []
}
\ No newline at end of file
......@@ -17,5 +17,7 @@
"文件范围的 namespace"
],
"children": [],
"export": []
"export": [],
"keywords_must": [],
"keywords_forbid": []
}
\ No newline at end of file
{
"node_id": "csharp-a0968f78949448b7948a6a207b1d3262",
"keywords": []
"keywords": [],
"keywords_must": [],
"keywords_forbid": []
}
\ No newline at end of file
{
"node_id": "csharp-ce2781d4e5344ae7b5b82f34c5fcaed2",
"keywords": []
"keywords": [],
"keywords_must": [],
"keywords_forbid": []
}
\ No newline at end of file
{
"node_id": "csharp-202a0f83809340d2b38e8e0d4b00b48c",
"keywords": [
"Razor"
"Razor"
],
"children": [],
"export": []
"export": [],
"keywords_must": [],
"keywords_forbid": []
}
\ No newline at end of file
{
"node_id": "csharp-97413a9e08fb4b55a742b45b2d61e13a",
"keywords": [
".NET MVC"
".NET MVC"
],
"children": [],
"export": []
"export": [],
"keywords_must": [],
"keywords_forbid": []
}
\ No newline at end of file
{
"node_id": "csharp-b3c0aaca71c249fa8bc4052980637613",
"keywords": [
".NET Blazor"
".NET Blazor"
],
"children": [],
"export": []
"export": [],
"keywords_must": [],
"keywords_forbid": []
}
\ No newline at end of file
{
"node_id": "csharp-e1b867ff5a1344bd9a7e34201343711c",
"keywords": [
".NET Web API"
".NET Web API"
],
"children": [],
"export": []
"export": [],
"keywords_must": [],
"keywords_forbid": []
}
\ No newline at end of file
{
"node_id": "csharp-5ef3b2a32bc344c984bb195b42eae73c",
"keywords": [
".NET Minimal API"
".NET Minimal API"
],
"children": [],
"export": []
"export": [],
"keywords_must": [],
"keywords_forbid": []
}
\ No newline at end of file
{
"node_id": "csharp-f788d93e151e4f0ca4f1f2f809da584a",
"keywords": []
"keywords": [],
"keywords_must": [],
"keywords_forbid": []
}
\ No newline at end of file
{
"node_id": "csharp-6c14a94995674b10aff78bce72366612",
"keywords": [
"WinFrom开发"
"WinFrom开发"
],
"children": [],
"export": []
"export": [],
"keywords_must": [],
"keywords_forbid": []
}
\ No newline at end of file
{
"node_id": "csharp-ff82db75f96f42b89c75dfbf6fad534f",
"keywords": [
"WPF开发"
"WPF开发"
],
"children": [],
"export": []
"export": [],
"keywords_must": [],
"keywords_forbid": []
}
\ No newline at end of file
{
"node_id": "csharp-fd4985c683f64669b906a2cda0a4c070",
"keywords": [
"UWP开发"
"UWP开发"
],
"children": [],
"export": []
"export": [],
"keywords_must": [],
"keywords_forbid": []
}
\ No newline at end of file
{
"node_id": "csharp-7f969ccd70e048c99f8699b52cb1b744",
"keywords": []
"keywords": [],
"keywords_must": [],
"keywords_forbid": []
}
\ No newline at end of file
{
"node_id": "csharp-119e018d28074c5f99ff3288a70f5e95",
"keywords": []
"keywords": [],
"keywords_must": [],
"keywords_forbid": []
}
\ No newline at end of file
{
"node_id": "csharp-d779ab6fdf9d44f6ae18e0126665b9c0",
"keywords": []
"keywords": [],
"keywords_must": [],
"keywords_forbid": []
}
\ No newline at end of file
{
"node_id": "csharp-f00a308a6b5e4dfdbda247f8ab924bde",
"keywords": []
"keywords": [],
"keywords_must": [],
"keywords_forbid": []
}
\ No newline at end of file
{
"node_id": "csharp-4e9dd748b8b24a9180948c53d649cb86",
"keywords": []
"keywords": [],
"keywords_must": [],
"keywords_forbid": []
}
\ No newline at end of file
{
"node_id": "csharp-e931f114f5f44d53878989744c1f5e99",
"keywords": []
"keywords": [],
"keywords_must": [],
"keywords_forbid": []
}
\ No newline at end of file
{
"node_id": "csharp-96369fdba7914281b33829b2ad1272da",
"keywords": []
"keywords": [],
"keywords_must": [],
"keywords_forbid": []
}
\ No newline at end of file
{
"node_id": "csharp-f977fca66f044f05964ae467369a9e2a",
"keywords": []
"keywords": [],
"keywords_must": [],
"keywords_forbid": []
}
\ No newline at end of file
{
"node_id": "csharp-abf1bc85e96749d5a8c6a6a32f95d804",
"keywords": []
"keywords": [],
"keywords_must": [],
"keywords_forbid": []
}
\ No newline at end of file
{
"tree_name": "csharp",
"keywords": [],
"node_id": "csharp-f436d19758c84b0bb741e51f1f839c24"
"node_id": "csharp-f436d19758c84b0bb741e51f1f839c24",
"keywords_must": [],
"keywords_forbid": []
}
\ No newline at end of file
......@@ -21,7 +21,9 @@
"dotnet new",
"程序入口"
],
"children": []
"children": [],
"keywords_must": [],
"keywords_forbid": []
}
},
{
......@@ -32,7 +34,9 @@
".NET",
"跨平台"
],
"children": []
"children": [],
"keywords_must": [],
"keywords_forbid": []
}
},
{
......@@ -42,7 +46,9 @@
".NET Standard",
".NET 实现"
],
"children": []
"children": [],
"keywords_must": [],
"keywords_forbid": []
}
},
{
......@@ -53,7 +59,9 @@
".NET 类库",
".NET 标准库"
],
"children": []
"children": [],
"keywords_must": [],
"keywords_forbid": []
}
},
{
......@@ -62,10 +70,14 @@
"keywords": [
".NET Standard 版本"
],
"children": []
"children": [],
"keywords_must": [],
"keywords_forbid": []
}
}
]
],
"keywords_must": [],
"keywords_forbid": []
}
},
{
......@@ -79,7 +91,9 @@
"keywords": [
"C# HelloWorld"
],
"children": []
"children": [],
"keywords_must": [],
"keywords_forbid": []
}
},
{
......@@ -91,7 +105,9 @@
"C# 整型",
"C# 基本类型"
],
"children": []
"children": [],
"keywords_must": [],
"keywords_forbid": []
}
},
{
......@@ -100,7 +116,9 @@
"keywords": [
"C# 字符串格式化"
],
"children": []
"children": [],
"keywords_must": [],
"keywords_forbid": []
}
},
{
......@@ -110,7 +128,9 @@
"C# 数字运算符",
"C# 四则运算"
],
"children": []
"children": [],
"keywords_must": [],
"keywords_forbid": []
}
},
{
......@@ -119,7 +139,9 @@
"keywords": [
".NET 基础类库"
],
"children": []
"children": [],
"keywords_must": [],
"keywords_forbid": []
}
},
{
......@@ -128,7 +150,9 @@
"keywords": [
"C# 分支判断"
],
"children": []
"children": [],
"keywords_must": [],
"keywords_forbid": []
}
},
{
......@@ -139,7 +163,9 @@
"foreach",
"斐波那契数列"
],
"children": []
"children": [],
"keywords_must": [],
"keywords_forbid": []
}
},
{
......@@ -149,10 +175,14 @@
"C# 编码规范",
"C# 注释"
],
"children": []
"children": [],
"keywords_must": [],
"keywords_forbid": []
}
}
]
],
"keywords_must": [],
"keywords_forbid": []
}
},
{
......@@ -171,7 +201,9 @@
"对象与集合初始化器",
"扩展方法"
],
"children": []
"children": [],
"keywords_must": [],
"keywords_forbid": []
}
},
{
......@@ -183,7 +215,9 @@
"命名参数和可选参数",
"动态查找"
],
"children": []
"children": [],
"keywords_must": [],
"keywords_forbid": []
}
},
{
......@@ -196,7 +230,9 @@
"支持null类型运算",
"绑定运算符,:=:"
],
"children": []
"children": [],
"keywords_must": [],
"keywords_forbid": []
}
},
{
......@@ -215,7 +251,9 @@
"在集合初始化器中使用扩展的Add方法",
"表达式方法体"
],
"children": []
"children": [],
"keywords_must": [],
"keywords_forbid": []
}
},
{
......@@ -240,7 +278,9 @@
"占位符",
"只读引用"
],
"children": []
"children": [],
"keywords_must": [],
"keywords_forbid": []
}
},
{
......@@ -254,7 +294,9 @@
"Switch 表达式",
"接口成员的默认实现"
],
"children": []
"children": [],
"keywords_must": [],
"keywords_forbid": []
}
},
{
......@@ -272,7 +314,9 @@
"不可变性",
"非破坏性变化"
],
"children": []
"children": [],
"keywords_must": [],
"keywords_forbid": []
}
},
{
......@@ -294,13 +338,19 @@
"CallerArgumentExpression",
"文件范围的 namespace"
],
"children": []
"children": [],
"keywords_must": [],
"keywords_forbid": []
}
}
]
],
"keywords_must": [],
"keywords_forbid": []
}
}
]
],
"keywords_must": [],
"keywords_forbid": []
}
},
{
......@@ -319,7 +369,9 @@
"keywords": [
"Razor"
],
"children": []
"children": [],
"keywords_must": [],
"keywords_forbid": []
}
},
{
......@@ -328,7 +380,9 @@
"keywords": [
".NET MVC"
],
"children": []
"children": [],
"keywords_must": [],
"keywords_forbid": []
}
},
{
......@@ -337,7 +391,9 @@
"keywords": [
".NET Blazor"
],
"children": []
"children": [],
"keywords_must": [],
"keywords_forbid": []
}
},
{
......@@ -346,7 +402,9 @@
"keywords": [
".NET Web API"
],
"children": []
"children": [],
"keywords_must": [],
"keywords_forbid": []
}
},
{
......@@ -355,10 +413,14 @@
"keywords": [
".NET Minimal API"
],
"children": []
"children": [],
"keywords_must": [],
"keywords_forbid": []
}
}
]
],
"keywords_must": [],
"keywords_forbid": []
}
},
{
......@@ -372,7 +434,9 @@
"keywords": [
"WinFrom开发"
],
"children": []
"children": [],
"keywords_must": [],
"keywords_forbid": []
}
},
{
......@@ -381,7 +445,9 @@
"keywords": [
"WPF开发"
],
"children": []
"children": [],
"keywords_must": [],
"keywords_forbid": []
}
},
{
......@@ -390,41 +456,55 @@
"keywords": [
"UWP开发"
],
"children": []
"children": [],
"keywords_must": [],
"keywords_forbid": []
}
}
]
],
"keywords_must": [],
"keywords_forbid": []
}
},
{
"MAUI跨平台移动应用": {
"node_id": "csharp-119e018d28074c5f99ff3288a70f5e95",
"keywords": [],
"children": []
"children": [],
"keywords_must": [],
"keywords_forbid": []
}
},
{
"机器学习应用": {
"node_id": "csharp-d779ab6fdf9d44f6ae18e0126665b9c0",
"keywords": [],
"children": []
"children": [],
"keywords_must": [],
"keywords_forbid": []
}
},
{
"游戏应用": {
"node_id": "csharp-f00a308a6b5e4dfdbda247f8ab924bde",
"keywords": [],
"children": []
"children": [],
"keywords_must": [],
"keywords_forbid": []
}
},
{
"云原生应用": {
"node_id": "csharp-4e9dd748b8b24a9180948c53d649cb86",
"keywords": [],
"children": []
"children": [],
"keywords_must": [],
"keywords_forbid": []
}
}
]
],
"keywords_must": [],
"keywords_forbid": []
}
},
{
......@@ -436,19 +516,27 @@
" Dapr应用": {
"node_id": "csharp-96369fdba7914281b33829b2ad1272da",
"keywords": [],
"children": []
"children": [],
"keywords_must": [],
"keywords_forbid": []
}
},
{
"Web进阶应用": {
"node_id": "csharp-f977fca66f044f05964ae467369a9e2a",
"keywords": [],
"children": []
"children": [],
"keywords_must": [],
"keywords_forbid": []
}
}
]
],
"keywords_must": [],
"keywords_forbid": []
}
}
]
],
"keywords_must": [],
"keywords_forbid": []
}
}
\ No newline at end of file
......@@ -2,10 +2,10 @@ import json
import logging
import os
import re
import subprocess
import sys
import uuid
import re
import git
id_set = set()
logger = logging.getLogger(__name__)
......@@ -14,15 +14,31 @@ handler = logging.StreamHandler(sys.stdout)
formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')
handler.setFormatter(formatter)
logger.addHandler(handler)
repo = git.Repo(".")
def user_name():
return repo.config_reader().get_value("user", "name")
def search_author(author_dict, username):
for key in author_dict:
names = author_dict[key]
if username in names:
return key
return username
def user_name(md_file, author_dict):
ret = subprocess.Popen([
"git", "log", md_file
], stdout=subprocess.PIPE)
lines = list(map(lambda l: l.decode(), ret.stdout.readlines()))
author_lines = []
for line in lines:
if line.startswith('Author'):
author_lines.append(line.split(' ')[1])
author_nick_name = author_lines[-1]
return search_author(author_dict, author_nick_name)
def load_json(p):
with open(p, 'r') as f:
with open(p, 'r', encoding="utf-8") as f:
return json.loads(f.read())
......@@ -77,7 +93,18 @@ def check_export(base, cfg):
class TreeWalker:
def __init__(self, root, tree_name, title=None, log=None):
def __init__(
self, root,
tree_name,
title=None,
log=None,
authors=None,
enable_notebook=None,
ignore_keywords=False
):
self.ignore_keywords = ignore_keywords
self.authors = authors if authors else {}
self.enable_notebook = enable_notebook
self.name = tree_name
self.root = root
self.title = tree_name if title is None else title
......@@ -89,7 +116,9 @@ class TreeWalker:
root_node = {
"node_id": root["node_id"],
"keywords": root["keywords"],
"children": []
"children": [],
"keywords_must": root["keywords_must"],
"keywords_forbid": root["keywords_forbid"]
}
self.tree[root["tree_name"]] = root_node
self.load_levels(root_node)
......@@ -144,6 +173,8 @@ class TreeWalker:
"node_id": config["node_id"],
"keywords": config["keywords"],
"children": [],
"keywords_must": config["keywords_must"],
"keywords_forbid": config["keywords_forbid"]
}
}
......@@ -195,6 +226,8 @@ class TreeWalker:
"tree_name": self.name,
"keywords": [],
"node_id": self.gen_node_id(),
"keywords_must": [],
"keywords_forbid": []
}
dump_json(config_path, config, exist_ok=True, override=True)
else:
......@@ -224,7 +257,9 @@ class TreeWalker:
if not os.path.exists(config_path):
config = {
"node_id": self.gen_node_id(),
"keywords": []
"keywords": [],
"keywords_must": [],
"keywords_forbid": []
}
dump_json(config_path, config, exist_ok=True, override=True)
else:
......@@ -290,6 +325,8 @@ class TreeWalker:
"node_id": config["node_id"],
"keywords": config["keywords"],
"children": [],
"keywords_must": config["keywords_must"],
"keywords_forbid": config["keywords_forbid"]
}
}
return num, result
......@@ -301,7 +338,9 @@ class TreeWalker:
name: {
"node_id": config["node_id"],
"keywords": config["keywords"],
"children": config.get("children", [])
"children": config.get("children", []),
"keywords_must": config["keywords_must"],
"keywords_forbid": config["keywords_forbid"]
}
}
# if "children" in config:
......@@ -318,7 +357,8 @@ class TreeWalker:
continue
mfile = base + ".json"
meta_path = os.path.join(section_path, mfile)
self.ensure_exercises_meta(meta_path, source)
md_file = os.path.join(section_path, e)
self.ensure_exercises_meta(meta_path, source, md_file)
export = config.get("export", [])
if mfile not in export and self.name != "algorithm":
export.append(mfile)
......@@ -339,7 +379,7 @@ class TreeWalker:
else:
id_set.add(exercise["exercise_id"])
def ensure_exercises_meta(self, meta_path, source):
def ensure_exercises_meta(self, meta_path, source, md_file):
_, mfile = os.path.split(meta_path)
meta = None
if os.path.exists(meta_path):
......@@ -354,26 +394,31 @@ class TreeWalker:
if "source" not in meta:
meta["source"] = source
if "author" not in meta:
meta["author"] = user_name()
meta["author"] = user_name(md_file, self.authors)
if "type" not in meta:
meta["type"] = "code_options"
if meta is None:
meta = {
"type": "code_options",
"author": user_name(),
"source": source,
"notebook_enable": self.default_notebook(),
"exercise_id": uuid.uuid4().hex
}
if meta is None:
meta = {
"type": "code_options",
"author": user_name(md_file, self.authors),
"source": source,
"notebook_enable": self.default_notebook(),
"exercise_id": uuid.uuid4().hex
}
dump_json(meta_path, meta, True, True)
def default_notebook(self):
if self.enable_notebook is not None:
return self.enable_notebook
if self.name in ["python", "java", "c"]:
return True
else:
return False
def check_section_keywords(self, full_path):
if self.ignore_keywords:
return
config = self.ensure_section_config(full_path)
if not config.get("keywords", []):
self.logger.error(f"节点 [{full_path}] 的关键字为空,请修改配置文件写入关键字")
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册