779 lines
27 KiB
Python
779 lines
27 KiB
Python
import importlib.util
|
|
import sys
|
|
import tempfile
|
|
import unittest
|
|
from pathlib import Path
|
|
|
|
|
|
SCRIPT = Path(__file__).parents[1] / "scripts" / "enrich_metadata.py"
|
|
|
|
|
|
def load_script():
|
|
spec = importlib.util.spec_from_file_location("tsl_enrich_metadata", SCRIPT)
|
|
module = importlib.util.module_from_spec(spec)
|
|
sys.modules[spec.name] = module
|
|
spec.loader.exec_module(module)
|
|
return module
|
|
|
|
|
|
class SourceCatalogTest(unittest.TestCase):
|
|
def setUp(self):
|
|
self.module = load_script()
|
|
self.temp_dir = tempfile.TemporaryDirectory()
|
|
self.docs = Path(self.temp_dir.name)
|
|
|
|
def tearDown(self):
|
|
self.temp_dir.cleanup()
|
|
|
|
def write_corpus(self, corpus, rows, descriptions):
|
|
root = self.docs / corpus
|
|
pages = root / "pages"
|
|
pages.mkdir(parents=True)
|
|
manifest = [
|
|
"id\ttitle\turl\tpath\tsource_bytes\tutf8_bytes\tsha256\tstatus"
|
|
]
|
|
for page_id, title in rows:
|
|
manifest.append(
|
|
f"{page_id}\t{title}\thttp://example/{page_id}\t"
|
|
f"pages/{page_id}.html\t1\t1\tsha\tok"
|
|
)
|
|
description = descriptions[page_id]
|
|
(pages / f"{page_id}.html").write_text(
|
|
"<div id='help_content'><h3>"
|
|
+ title
|
|
+ "</h3><div><div class='DescriteTitle'>简述</div></div>"
|
|
+ f"<div>{description}</div></div>",
|
|
encoding="utf-8",
|
|
)
|
|
(root / "manifest.tsv").write_text(
|
|
"\n".join(manifest) + "\n", encoding="utf-8"
|
|
)
|
|
|
|
def test_exact_matching_preserves_underscores_and_prefers_scope_corpus(self):
|
|
self.write_corpus(
|
|
"tsl_base",
|
|
[("1", "alpha_test")],
|
|
{"1": "基础解释器说明"},
|
|
)
|
|
self.write_corpus(
|
|
"net_function",
|
|
[("2", "alpha_test"), ("3", "alphaTest")],
|
|
{"2": "NET 说明", "3": "无下划线的另一个函数"},
|
|
)
|
|
catalog = self.module.SourceCatalog.from_docs_root(self.docs)
|
|
|
|
builtin = self.module.EntryContext(
|
|
name="alpha_test",
|
|
signature="alpha_test()",
|
|
kind="function",
|
|
scope="builtin",
|
|
page="builtin/demo.md",
|
|
summary="原说明",
|
|
)
|
|
dotnet = self.module.EntryContext(
|
|
name="alpha_test",
|
|
signature="alpha_test()",
|
|
kind="function",
|
|
scope="dotnet",
|
|
page="dotnet/demo.md",
|
|
summary="原说明",
|
|
)
|
|
|
|
self.assertEqual("tsl_base", catalog.match(builtin)[0].corpus)
|
|
self.assertEqual("net_function", catalog.match(dotnet)[0].corpus)
|
|
self.assertNotIn(
|
|
"alphaTest", {record.title for record in catalog.match(dotnet)}
|
|
)
|
|
|
|
def test_duplicate_titles_remain_visible_for_audit(self):
|
|
self.write_corpus(
|
|
"net_function",
|
|
[("1", "same_name"), ("2", "same_name")],
|
|
{"1": "说明一", "2": "说明二"},
|
|
)
|
|
catalog = self.module.SourceCatalog.from_docs_root(self.docs)
|
|
entry = self.module.EntryContext(
|
|
name="same_name",
|
|
signature="same_name()",
|
|
kind="function",
|
|
scope="dotnet",
|
|
page="dotnet/demo.md",
|
|
summary="原说明",
|
|
)
|
|
|
|
self.assertEqual(["1", "2"], [item.page_id for item in catalog.match(entry)])
|
|
|
|
|
|
class DescriptionQualityTest(unittest.TestCase):
|
|
def setUp(self):
|
|
self.module = load_script()
|
|
|
|
def entry(self, **overrides):
|
|
values = {
|
|
"name": "profitRatio",
|
|
"signature": "profitRatio(report_date)",
|
|
"kind": "function",
|
|
"scope": "dotnet",
|
|
"page": "dotnet/financial/profitability.md",
|
|
"summary": "总资产收益率(%)。",
|
|
}
|
|
values.update(overrides)
|
|
return self.module.EntryContext(**values)
|
|
|
|
def test_removes_only_terminal_sentence_punctuation(self):
|
|
entry = self.entry(summary="总资产收益率(%)。")
|
|
|
|
self.assertEqual(
|
|
"返回总资产收益率(%)",
|
|
self.module.improve_description(entry, []),
|
|
)
|
|
|
|
def test_preserves_formula_and_identifiers(self):
|
|
entry = self.entry(
|
|
summary="总资产报酬率(%)=利润总额/平均资产总额*100。"
|
|
)
|
|
|
|
self.assertEqual(
|
|
"计算总资产报酬率(%),公式为利润总额/平均资产总额*100",
|
|
self.module.improve_description(entry, []),
|
|
)
|
|
|
|
def test_rejects_source_process_prose(self):
|
|
entry = self.entry(summary="返回指定值")
|
|
source = self.module.SourceRecord(
|
|
corpus="net_function",
|
|
page_id="1",
|
|
title="profitRatio",
|
|
page=Path("1.html"),
|
|
description="Windows 已验证通过,Linux 返回 not found",
|
|
)
|
|
|
|
self.assertEqual(
|
|
"返回指定值", self.module.improve_description(entry, [source])
|
|
)
|
|
|
|
def test_current_environment_can_be_real_api_semantics(self):
|
|
self.assertEqual(
|
|
"获取当前环境时间系统参数",
|
|
self.module.safe_source_description("获取当前环境时间系统参数。"),
|
|
)
|
|
|
|
def test_property_access_is_stated_explicitly(self):
|
|
entry = self.entry(
|
|
name="Host",
|
|
signature="Host",
|
|
kind="property",
|
|
scope="builtin",
|
|
page="builtin/object/ftp.md",
|
|
summary="远程服务器地址。",
|
|
access="read/write",
|
|
owner="FTP",
|
|
)
|
|
|
|
self.assertEqual(
|
|
"获取或设置远程服务器地址",
|
|
self.module.improve_description(entry, []),
|
|
)
|
|
|
|
def test_boolean_property_description_is_idempotent(self):
|
|
entry = self.entry(
|
|
name="UseTLS",
|
|
signature="UseTLS",
|
|
kind="property",
|
|
scope="builtin",
|
|
page="builtin/object/imap.md",
|
|
summary="是否采用 SSL 连接",
|
|
access="read/write",
|
|
owner="IMAP",
|
|
)
|
|
|
|
first = self.module.improve_description(entry, [])
|
|
repeated = self.module.improve_description(
|
|
self.module.EntryContext(
|
|
**{**entry.__dict__, "summary": first}
|
|
),
|
|
[],
|
|
)
|
|
|
|
self.assertEqual("控制是否采用 SSL 连接", first)
|
|
self.assertEqual(first, repeated)
|
|
|
|
def test_low_confidence_sentence_is_kept_except_terminal_punctuation(self):
|
|
entry = self.entry(
|
|
name="opaqueApi",
|
|
page="dotnet.md",
|
|
summary="根据调用上下文处理结果,具体规则取决于输入。",
|
|
)
|
|
|
|
self.assertEqual(
|
|
"根据调用上下文处理结果,具体规则取决于输入",
|
|
self.module.improve_description(entry, []),
|
|
)
|
|
|
|
def test_short_description_is_not_replaced_by_ambiguous_source_text(self):
|
|
entry = self.entry(
|
|
name="clRed",
|
|
page="builtin/color.md",
|
|
summary="红色",
|
|
)
|
|
sources = [
|
|
self.module.SourceRecord(
|
|
corpus="net_function",
|
|
page_id="1",
|
|
title="clRed",
|
|
page=Path("1.html"),
|
|
description="定义",
|
|
)
|
|
]
|
|
|
|
self.assertEqual("红色", self.module.improve_description(entry, sources))
|
|
|
|
def test_existing_action_word_is_normalized_without_duplicate_verb(self):
|
|
getter = self.entry(
|
|
name="getCValue",
|
|
page="builtin/color.md",
|
|
summary="得到颜色的 CMYK 模式 C 值。",
|
|
)
|
|
writer = self.entry(
|
|
name="write",
|
|
page="builtin/cgi.md",
|
|
summary="输出字符串。",
|
|
)
|
|
|
|
self.assertEqual(
|
|
"获取颜色的 CMYK 模式 C 值",
|
|
self.module.improve_description(getter, []),
|
|
)
|
|
self.assertEqual("输出字符串", self.module.improve_description(writer, []))
|
|
|
|
def test_equation_inside_algorithm_sentence_is_not_rewritten_as_formula(self):
|
|
entry = self.entry(
|
|
name="se_Gauss",
|
|
page="builtin/optimization.md",
|
|
summary="用高斯消去法求解线性方程组 AX = B",
|
|
)
|
|
|
|
self.assertEqual(
|
|
"用高斯消去法求解线性方程组 AX = B",
|
|
self.module.improve_description(entry, []),
|
|
)
|
|
|
|
def test_builtin_class_gets_a_purpose_description(self):
|
|
entry = self.entry(
|
|
name="TStringList",
|
|
signature="TStringList",
|
|
kind="class",
|
|
scope="builtin",
|
|
page="builtin/object/tstringlist.md",
|
|
summary="TStringList 内置对象",
|
|
)
|
|
|
|
self.assertEqual(
|
|
"提供字符串集合存储、查找、排序和名称值管理能力的内置对象",
|
|
self.module.improve_description(entry, []),
|
|
)
|
|
|
|
def test_long_property_explanation_is_not_wrapped_in_access_boilerplate(self):
|
|
entry = self.entry(
|
|
name="CommaTextW",
|
|
signature="CommaTextW",
|
|
kind="property",
|
|
scope="builtin",
|
|
page="builtin/object/tstringlist.md",
|
|
summary=(
|
|
"功能同 CommaText,区别是在读取时返回宽字节字符串,"
|
|
"而 CommaText 返回多字节字符串"
|
|
),
|
|
access="read/write",
|
|
owner="TStringList",
|
|
)
|
|
|
|
self.assertEqual(
|
|
entry.summary, self.module.improve_description(entry, [])
|
|
)
|
|
|
|
def test_short_read_and_load_phrases_are_normalized(self):
|
|
read_entry = self.entry(
|
|
name="read",
|
|
page="builtin/object/tstream.md",
|
|
summary="读出内容",
|
|
)
|
|
load_entry = self.entry(
|
|
name="loadFromFile",
|
|
page="builtin/object/tstringlist.md",
|
|
summary="从指定的文件中装载内容",
|
|
)
|
|
|
|
self.assertEqual(
|
|
"读取内容", self.module.improve_description(read_entry, [])
|
|
)
|
|
self.assertEqual(
|
|
"从指定的文件中加载内容",
|
|
self.module.improve_description(load_entry, []),
|
|
)
|
|
|
|
def test_embedded_read_out_is_normalized_without_duplicate_prefix(self):
|
|
entry = self.entry(
|
|
name="readExcelSheets",
|
|
page="dotnet.md",
|
|
summary="从Excel文件中读出Sheets列表。",
|
|
)
|
|
|
|
self.assertEqual(
|
|
"从Excel文件中读取Sheets列表",
|
|
self.module.improve_description(entry, []),
|
|
)
|
|
|
|
def test_existing_decomposition_verb_is_not_prefixed(self):
|
|
entry = self.entry(
|
|
name="decodeGraphGroup",
|
|
page="builtin/graph.md",
|
|
summary="分解图形组合并写入输出参数",
|
|
)
|
|
|
|
self.assertEqual(
|
|
entry.summary, self.module.improve_description(entry, [])
|
|
)
|
|
|
|
def test_comparison_expression_is_not_rewritten_as_formula(self):
|
|
entry = self.entry(
|
|
name="stockStepAmount",
|
|
page="dotnet/financial/stock-capital-flow.md",
|
|
summary="分档区间 V1<=Value<V2 的成交金额",
|
|
)
|
|
|
|
self.assertEqual(
|
|
entry.summary, self.module.improve_description(entry, [])
|
|
)
|
|
|
|
def test_financial_action_sentence_is_not_prefixed_with_return(self):
|
|
for summary in (
|
|
"提取股票的财务比率,与系统证券相关",
|
|
"根据报告期获取财务指标",
|
|
"将日线数据转换为周线数据",
|
|
"统计指定报告期的基金数量",
|
|
"生成指定区间的分析结果",
|
|
):
|
|
with self.subTest(summary=summary):
|
|
entry = self.entry(
|
|
name="annualRatio",
|
|
page="dotnet/financial/financial-analysis.md",
|
|
summary=summary,
|
|
)
|
|
|
|
self.assertEqual(
|
|
entry.summary, self.module.improve_description(entry, [])
|
|
)
|
|
|
|
def test_financial_action_clauses_are_not_prefixed_with_return(self):
|
|
for summary in (
|
|
"用于生成投资组合结果名称",
|
|
"如果存在对应记录则返回证券代码",
|
|
"对矩阵进行正交处理",
|
|
"从净值表中获取基金列表",
|
|
"由交易价格倒推出隐含波动率",
|
|
"按照周期读取数据",
|
|
"与系统参数证券和日期相关",
|
|
):
|
|
with self.subTest(summary=summary):
|
|
entry = self.entry(
|
|
name="financialHelper",
|
|
page="dotnet/financial/financial-analysis.md",
|
|
summary=summary,
|
|
)
|
|
|
|
self.assertEqual(
|
|
entry.summary, self.module.improve_description(entry, [])
|
|
)
|
|
|
|
def test_financial_boolean_description_uses_judgment_wording(self):
|
|
entry = self.entry(
|
|
name="isBankBond",
|
|
page="dotnet/financial/bond-basic-info.md",
|
|
summary="是否银行间债券。如果是,返回1,否则返回0",
|
|
)
|
|
|
|
self.assertEqual(
|
|
"判断是否银行间债券。如果是,返回1,否则返回0",
|
|
self.module.improve_description(entry, []),
|
|
)
|
|
|
|
def test_function_boilerplate_is_removed_from_action_description(self):
|
|
entry = self.entry(
|
|
name="cb_ytm",
|
|
page="dotnet/financial/convertible-bond.md",
|
|
summary="该函数采用牛顿迭代法获取可转债的到期收益率",
|
|
)
|
|
|
|
self.assertEqual(
|
|
"采用牛顿迭代法获取可转债的到期收益率",
|
|
self.module.improve_description(entry, []),
|
|
)
|
|
|
|
def test_financial_numbered_explanation_is_not_prefixed_with_return(self):
|
|
entry = self.entry(
|
|
name="financialMode",
|
|
page="dotnet/financial/financial-analysis.md",
|
|
summary="1 表示合并报表,2 表示母公司报表",
|
|
)
|
|
|
|
self.assertEqual(
|
|
entry.summary, self.module.improve_description(entry, [])
|
|
)
|
|
|
|
def test_related_data_placeholder_is_made_explicit(self):
|
|
entry = self.entry(
|
|
name="cb_downPeriodConversionPeriod",
|
|
page="dotnet/financial/convertible-bond.md",
|
|
summary="CB_DownPeriodConversionPeriod 相关函数",
|
|
)
|
|
|
|
self.assertEqual(
|
|
"返回 CB_DownPeriodConversionPeriod 对应的数据",
|
|
self.module.improve_description(entry, []),
|
|
)
|
|
|
|
def test_reviewed_generic_descriptions_use_precise_purpose_text(self):
|
|
cases = (
|
|
(
|
|
"sf_Normal",
|
|
"统计分布相关函数。",
|
|
"计算正态分布函数值",
|
|
),
|
|
(
|
|
"readFile",
|
|
"文件访问函数相关函数。",
|
|
"读取本地文件中的数据",
|
|
),
|
|
(
|
|
"unicodeEsc2",
|
|
"多语言支持函数相关函数。",
|
|
"将字符串转换为 \\uxxxx 形式的 Unicode 编码串",
|
|
),
|
|
)
|
|
for name, summary, expected in cases:
|
|
with self.subTest(name=name):
|
|
entry = self.entry(name=name, page="dotnet.md", summary=summary)
|
|
self.assertEqual(
|
|
expected, self.module.improve_description(entry, [])
|
|
)
|
|
|
|
def test_reviewed_awkward_descriptions_are_rewritten_directly(self):
|
|
cases = (
|
|
(
|
|
"encodeGraph",
|
|
"返回根据指定的类型、名称、数据以及属性数组生成的图形。",
|
|
"根据指定的类型、名称、数据和属性数组生成图形并返回",
|
|
),
|
|
(
|
|
"dupeString",
|
|
"返回将指定的字符串AText重复ACount次后的字符串",
|
|
"将字符串 AText 重复 ACount 次并返回结果",
|
|
),
|
|
(
|
|
"stockpjcj",
|
|
"返回:区间平均成交,区间成交金额/区间成交量",
|
|
"返回区间平均成交价,计算公式为区间成交金额 / 区间成交量",
|
|
),
|
|
)
|
|
for name, summary, expected in cases:
|
|
with self.subTest(name=name):
|
|
entry = self.entry(
|
|
name=name, page="builtin/string.md", summary=summary
|
|
)
|
|
self.assertEqual(
|
|
expected, self.module.improve_description(entry, [])
|
|
)
|
|
|
|
|
|
class TagDerivationTest(unittest.TestCase):
|
|
def setUp(self):
|
|
self.module = load_script()
|
|
|
|
def test_array_deduplication_gets_controlled_chinese_and_english_aliases(self):
|
|
entry = self.module.EntryContext(
|
|
name="arrDropDuplicate",
|
|
signature="arrDropDuplicate(data)",
|
|
kind="function",
|
|
scope="builtin",
|
|
page="builtin/array.md",
|
|
summary="删除数组中的重复元素",
|
|
)
|
|
page = self.module.PageContext(
|
|
title="Builtin / 数组", path="builtin/array.md"
|
|
)
|
|
|
|
tags = self.module.derive_tags(entry, page)
|
|
|
|
self.assertTrue(
|
|
{"数组", "列表", "去重", "删除重复", "array", "deduplicate"}
|
|
<= set(tags)
|
|
)
|
|
self.assertLessEqual(len(tags), 12)
|
|
self.assertNotIn("函数", tags)
|
|
self.assertNotIn("builtin", tags)
|
|
|
|
def test_file_digest_gets_digest_and_hash_aliases(self):
|
|
entry = self.module.EntryContext(
|
|
name="getMsgDigest",
|
|
signature="getMsgDigest(s, mode)",
|
|
kind="function",
|
|
scope="builtin",
|
|
page="builtin/string.md",
|
|
summary="计算字符串摘要,支持 CRC32、MD5、SHA 和 SM3",
|
|
)
|
|
page = self.module.PageContext(
|
|
title="Builtin / 字符串", path="builtin/string.md"
|
|
)
|
|
|
|
tags = self.module.derive_tags(entry, page)
|
|
|
|
self.assertTrue(
|
|
{"字符串", "摘要", "哈希", "散列", "digest", "hash"}
|
|
<= set(tags)
|
|
)
|
|
|
|
def test_existing_tags_are_preserved_first_and_output_is_idempotent(self):
|
|
entry = self.module.EntryContext(
|
|
name="readFile",
|
|
signature="readFile(alias, file_name)",
|
|
kind="function",
|
|
scope="builtin",
|
|
page="builtin/file.md",
|
|
summary="读取文件内容",
|
|
tags=("自定义", "读取"),
|
|
)
|
|
page = self.module.PageContext(
|
|
title="Builtin / 文件", path="builtin/file.md"
|
|
)
|
|
|
|
first = self.module.derive_tags(entry, page)
|
|
second = self.module.derive_tags(
|
|
self.module.EntryContext(**{**entry.__dict__, "tags": tuple(first)}),
|
|
page,
|
|
)
|
|
|
|
self.assertEqual(["自定义", "读取"], first[:2])
|
|
self.assertEqual(first, second)
|
|
|
|
def test_substrings_do_not_create_digest_or_com_tags(self):
|
|
reshape = self.module.EntryContext(
|
|
name="reshape",
|
|
signature="reshape(data, shape)",
|
|
kind="function",
|
|
scope="builtin",
|
|
page="builtin/array.md",
|
|
summary="重构数组形状",
|
|
)
|
|
uncompress = self.module.EntryContext(
|
|
name="uniuncompress",
|
|
signature="uniuncompress(data, type)",
|
|
kind="function",
|
|
scope="builtin",
|
|
page="builtin/string.md",
|
|
summary="统一解压缩数据",
|
|
)
|
|
|
|
reshape_tags = self.module.derive_tags(
|
|
reshape,
|
|
self.module.PageContext("Builtin / 数组", reshape.page),
|
|
)
|
|
uncompress_tags = self.module.derive_tags(
|
|
uncompress,
|
|
self.module.PageContext("Builtin / 字符串", uncompress.page),
|
|
)
|
|
|
|
self.assertNotIn("摘要", reshape_tags)
|
|
self.assertNotIn("hash", reshape_tags)
|
|
self.assertNotIn("COM", uncompress_tags)
|
|
self.assertNotIn("OLE", uncompress_tags)
|
|
|
|
def test_runtime_and_character_names_do_not_create_time_or_graph_tags(self):
|
|
random_entry = self.module.EntryContext(
|
|
name="randomfrom",
|
|
signature="randomfrom(values)",
|
|
kind="function",
|
|
scope="builtin",
|
|
page="builtin/runtime.md",
|
|
summary="返回随机数组元素",
|
|
)
|
|
char_entry = self.module.EntryContext(
|
|
name="charToByteLen",
|
|
signature="charToByteLen(s, max_len)",
|
|
kind="function",
|
|
scope="builtin",
|
|
page="builtin/string.md",
|
|
summary="计算字符串占用的字节数",
|
|
)
|
|
|
|
random_tags = self.module.derive_tags(
|
|
random_entry,
|
|
self.module.PageContext("Builtin / 运行时", random_entry.page),
|
|
)
|
|
char_tags = self.module.derive_tags(
|
|
char_entry,
|
|
self.module.PageContext("Builtin / 字符串", char_entry.page),
|
|
)
|
|
|
|
self.assertNotIn("日期时间", random_tags)
|
|
self.assertNotIn("图形", char_tags)
|
|
|
|
def test_parameter_name_does_not_create_unrelated_time_domain(self):
|
|
entry = self.module.EntryContext(
|
|
name="futureValue",
|
|
signature=(
|
|
"futureValue(rate, n_periods, payment, present_value, payment_time)"
|
|
),
|
|
kind="function",
|
|
scope="builtin",
|
|
page="builtin/numeric.md",
|
|
summary="返回一项投资的未来值",
|
|
)
|
|
tags = self.module.derive_tags(
|
|
entry,
|
|
self.module.PageContext("Builtin / 数值计算", entry.page),
|
|
)
|
|
|
|
self.assertNotIn("日期时间", tags)
|
|
|
|
def test_hash_index_is_not_tagged_as_cryptographic_digest(self):
|
|
entry = self.module.EntryContext(
|
|
name="THashedStringList",
|
|
signature="THashedStringList",
|
|
kind="class",
|
|
scope="builtin",
|
|
page="builtin/object/thashedstringlist.md",
|
|
summary="使用哈希索引加速查找的字符串列表内置对象",
|
|
)
|
|
tags = self.module.derive_tags(
|
|
entry,
|
|
self.module.PageContext(
|
|
"Object / THashedStringList 字符串列表", entry.page
|
|
),
|
|
)
|
|
|
|
self.assertIn("哈希索引", tags)
|
|
self.assertIn("hash", tags)
|
|
self.assertNotIn("摘要", tags)
|
|
self.assertNotIn("digest", tags)
|
|
|
|
def test_business_statistics_verb_does_not_add_probability_domain(self):
|
|
entry = self.module.EntryContext(
|
|
name="fundCount",
|
|
signature="fundCount(report_date)",
|
|
kind="function",
|
|
scope="dotnet",
|
|
page="dotnet/financial/fund-holdings.md",
|
|
summary="统计指定报告期的基金数量",
|
|
)
|
|
tags = self.module.derive_tags(
|
|
entry,
|
|
self.module.PageContext("金融 / 基金 / 持仓", entry.page),
|
|
)
|
|
|
|
self.assertNotIn("概率", tags)
|
|
self.assertNotIn("statistics", tags)
|
|
self.assertNotIn("统计指定报告期的基金数量", tags)
|
|
self.assertNotIn("证券", tags)
|
|
|
|
def test_taxonomy_tags_remove_generic_suffixes(self):
|
|
entry = self.module.EntryContext(
|
|
name="weightedMedian",
|
|
signature="weightedMedian(data, weights)",
|
|
kind="function",
|
|
scope="dotnet",
|
|
page="dotnet/financial/weighted-statistics.md",
|
|
summary="计算加权中位数",
|
|
)
|
|
tags = self.module.derive_tags(
|
|
entry,
|
|
self.module.PageContext(
|
|
"基础算法常见加权统计量及其实现 / 时间相关函数",
|
|
entry.page,
|
|
),
|
|
)
|
|
|
|
self.assertIn("基础算法常见加权统计量", tags)
|
|
self.assertIn("时间", tags)
|
|
self.assertNotIn("基础算法常见加权统计量及其实现", tags)
|
|
self.assertNotIn("时间相关函数", tags)
|
|
|
|
def test_taxonomy_tags_drop_parenthetical_explanations_and_punctuation(self):
|
|
entry = self.module.EntryContext(
|
|
name="close",
|
|
signature="close()",
|
|
kind="function",
|
|
scope="dotnet",
|
|
page="dotnet/datawarehouse/after_market.md",
|
|
summary="收盘价,与系统参数股票、时间、周期和复权相关",
|
|
)
|
|
tags = self.module.derive_tags(
|
|
entry,
|
|
self.module.PageContext(
|
|
"数据仓库 / 盘后相关(在当日可用于盘中)", entry.page
|
|
),
|
|
)
|
|
|
|
self.assertIn("数据仓库", tags)
|
|
self.assertIn("盘后", tags)
|
|
self.assertNotIn("(", tags)
|
|
self.assertNotIn(")", tags)
|
|
self.assertNotIn("盘后相关在当日可用于盘中", tags)
|
|
self.assertNotIn("关闭", tags)
|
|
self.assertNotIn("close", tags)
|
|
|
|
def test_name_intent_does_not_override_an_explicit_action_clause(self):
|
|
entry = self.module.EntryContext(
|
|
name="openEndFundFilterByFundIndex",
|
|
signature="openEndFundFilterByFundIndex(fund_inds)",
|
|
kind="function",
|
|
scope="dotnet",
|
|
page="dotnet/financial/fund-pool.md",
|
|
summary="根据基金指数获取成分基金,并对基金进行筛选",
|
|
)
|
|
tags = self.module.derive_tags(
|
|
entry,
|
|
self.module.PageContext("金融 / 基金 / 基金池", entry.page),
|
|
)
|
|
|
|
self.assertNotIn("打开", tags)
|
|
self.assertNotIn("open", tags)
|
|
|
|
|
|
class MarkdownEnrichmentTest(unittest.TestCase):
|
|
def setUp(self):
|
|
self.module = load_script()
|
|
|
|
def test_inserts_tags_after_description_without_touching_code(self):
|
|
text = (
|
|
"# Builtin / 数组\n\n"
|
|
"## `arrDropDuplicate(data)`\n\n"
|
|
"声明:function\n\n"
|
|
"删除数组中的重复元素。\n\n"
|
|
"| 参数 | 类型 | 说明 |\n"
|
|
"| --- | --- | --- |\n"
|
|
"| `data` | array | 输入数组 |\n\n"
|
|
"返回:array\n\n"
|
|
"### 示例\n\n"
|
|
"```tsl\nreturn arrDropDuplicate(array(1, 1));\n```\n"
|
|
)
|
|
|
|
result, audit = self.module.enrich_markdown(
|
|
text, "builtin/array.md", self.module.SourceCatalog.empty()
|
|
)
|
|
repeated, repeated_audit = self.module.enrich_markdown(
|
|
result, "builtin/array.md", self.module.SourceCatalog.empty()
|
|
)
|
|
|
|
self.assertIn("删除数组中的重复元素\n\n<!-- tags:", result)
|
|
self.assertIn("return arrDropDuplicate(array(1, 1));", result)
|
|
self.assertEqual(result, repeated)
|
|
self.assertEqual(1, audit.changed_descriptions)
|
|
self.assertEqual(1, audit.changed_tags)
|
|
self.assertEqual(0, repeated_audit.changed_descriptions)
|
|
self.assertEqual(0, repeated_audit.changed_tags)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|