autosnippet 3.0.0 → 3.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +230 -324
- package/bin/api-server.js +1 -1
- package/bin/cli.js +204 -244
- package/bin/mcp-server.js +5 -3
- package/config/knowledge-base.config.js +132 -132
- package/dashboard/dist/assets/{icons-CEfgGaZi.js → icons-Cdq22n2i.js} +95 -100
- package/dashboard/dist/assets/index-ClkyPkDX.js +133 -0
- package/dashboard/dist/assets/index-t4QrJwv1.css +1 -0
- package/dashboard/dist/index.html +3 -3
- package/lib/bootstrap.js +8 -8
- package/lib/cli/AiScanService.js +86 -40
- package/lib/cli/KnowledgeSyncService.js +113 -74
- package/lib/cli/SetupService.js +439 -277
- package/lib/cli/UpgradeService.js +63 -100
- package/lib/core/AstAnalyzer.js +276 -597
- package/lib/core/ast/ProjectGraph.js +101 -40
- package/lib/core/ast/ensure-grammars.js +232 -0
- package/lib/core/ast/index.js +115 -0
- package/lib/core/ast/lang-dart.js +661 -0
- package/lib/core/ast/lang-go.js +530 -0
- package/lib/core/ast/lang-java.js +435 -0
- package/lib/core/ast/lang-javascript.js +272 -0
- package/lib/core/ast/lang-kotlin.js +423 -0
- package/lib/core/ast/lang-objc.js +388 -0
- package/lib/core/ast/lang-python.js +371 -0
- package/lib/core/ast/lang-swift.js +337 -0
- package/lib/core/ast/lang-typescript.js +503 -0
- package/lib/core/capability/CapabilityProbe.js +18 -9
- package/lib/core/constitution/Constitution.js +2 -3
- package/lib/core/constitution/ConstitutionValidator.js +65 -24
- package/lib/core/discovery/DartDiscoverer.js +534 -0
- package/lib/core/discovery/DiscovererRegistry.js +83 -0
- package/lib/core/discovery/GenericDiscoverer.js +225 -0
- package/lib/core/discovery/GoDiscoverer.js +541 -0
- package/lib/core/discovery/JvmDiscoverer.js +506 -0
- package/lib/core/discovery/NodeDiscoverer.js +466 -0
- package/lib/core/discovery/ProjectDiscoverer.js +93 -0
- package/lib/core/discovery/PythonDiscoverer.js +338 -0
- package/lib/core/discovery/SpmDiscoverer.js +5 -0
- package/lib/core/discovery/index.js +53 -0
- package/lib/core/enhancement/EnhancementPack.js +71 -0
- package/lib/core/enhancement/EnhancementRegistry.js +47 -0
- package/lib/core/enhancement/android-enhancement.js +102 -0
- package/lib/core/enhancement/django-enhancement.js +70 -0
- package/lib/core/enhancement/fastapi-enhancement.js +63 -0
- package/lib/core/enhancement/go-grpc-enhancement.js +152 -0
- package/lib/core/enhancement/go-web-enhancement.js +201 -0
- package/lib/core/enhancement/index.js +65 -0
- package/lib/core/enhancement/node-server-enhancement.js +88 -0
- package/lib/core/enhancement/react-enhancement.js +86 -0
- package/lib/core/enhancement/spring-enhancement.js +112 -0
- package/lib/core/enhancement/vue-enhancement.js +96 -0
- package/lib/core/gateway/Gateway.js +8 -9
- package/lib/core/gateway/GatewayActionRegistry.js +1 -1
- package/lib/core/permission/PermissionManager.js +12 -8
- package/lib/domain/index.js +13 -9
- package/lib/domain/knowledge/KnowledgeEntry.js +111 -101
- package/lib/domain/knowledge/KnowledgeRepository.js +0 -1
- package/lib/domain/knowledge/Lifecycle.js +22 -22
- package/lib/domain/knowledge/index.js +9 -12
- package/lib/domain/knowledge/values/Constraints.js +31 -21
- package/lib/domain/knowledge/values/Content.js +21 -13
- package/lib/domain/knowledge/values/Quality.js +31 -18
- package/lib/domain/knowledge/values/Reasoning.js +20 -12
- package/lib/domain/knowledge/values/Relations.js +37 -25
- package/lib/domain/knowledge/values/Stats.js +18 -12
- package/lib/domain/knowledge/values/index.js +4 -3
- package/lib/domain/snippet/Snippet.js +35 -10
- package/lib/external/ai/AiFactory.js +48 -16
- package/lib/external/ai/AiProvider.js +184 -90
- package/lib/external/ai/providers/ClaudeProvider.js +25 -12
- package/lib/external/ai/providers/GoogleGeminiProvider.js +59 -30
- package/lib/external/ai/providers/MockProvider.js +9 -3
- package/lib/external/ai/providers/OpenAiProvider.js +51 -29
- package/lib/external/mcp/McpServer.js +66 -36
- package/lib/external/mcp/errorHandler.js +23 -11
- package/lib/external/mcp/handlers/LanguageExtensions.js +138 -53
- package/lib/external/mcp/handlers/TargetClassifier.js +52 -16
- package/lib/external/mcp/handlers/bootstrap/pipeline/BootstrapSnapshot.js +81 -20
- package/lib/external/mcp/handlers/bootstrap/pipeline/EpisodicMemory.js +71 -42
- package/lib/external/mcp/handlers/bootstrap/pipeline/IncrementalBootstrap.js +9 -17
- package/lib/external/mcp/handlers/bootstrap/pipeline/ToolResultCache.js +14 -9
- package/lib/external/mcp/handlers/bootstrap/pipeline/dimension-context.js +15 -7
- package/lib/external/mcp/handlers/bootstrap/pipeline/orchestrator.js +352 -153
- package/lib/external/mcp/handlers/bootstrap/pipeline/tier-scheduler.js +52 -12
- package/lib/external/mcp/handlers/bootstrap/skills.js +143 -39
- package/lib/external/mcp/handlers/bootstrap.js +691 -168
- package/lib/external/mcp/handlers/browse.js +66 -22
- package/lib/external/mcp/handlers/candidate.js +118 -35
- package/lib/external/mcp/handlers/consolidated.js +49 -17
- package/lib/external/mcp/handlers/guard.js +104 -39
- package/lib/external/mcp/handlers/knowledge.js +60 -36
- package/lib/external/mcp/handlers/search.js +43 -14
- package/lib/external/mcp/handlers/skill.js +120 -45
- package/lib/external/mcp/handlers/structure.js +240 -86
- package/lib/external/mcp/handlers/system.js +42 -12
- package/lib/external/mcp/handlers/wiki.js +58 -33
- package/lib/external/mcp/tools.js +306 -123
- package/lib/http/HttpServer.js +72 -47
- package/lib/http/middleware/RateLimiter.js +5 -3
- package/lib/http/middleware/errorHandler.js +6 -1
- package/lib/http/middleware/requestLogger.js +14 -3
- package/lib/http/middleware/roleResolver.js +30 -23
- package/lib/http/routes/ai.js +387 -265
- package/lib/http/routes/auth.js +81 -61
- package/lib/http/routes/candidates.js +430 -320
- package/lib/http/routes/commands.js +289 -189
- package/lib/http/routes/extract.js +158 -125
- package/lib/http/routes/guardRules.js +309 -217
- package/lib/http/routes/knowledge.js +213 -154
- package/lib/http/routes/modules.js +578 -0
- package/lib/http/routes/monitoring.js +6 -6
- package/lib/http/routes/recipes.js +104 -93
- package/lib/http/routes/search.js +361 -305
- package/lib/http/routes/skills.js +145 -98
- package/lib/http/routes/snippets.js +42 -30
- package/lib/http/routes/spm.js +3 -405
- package/lib/http/routes/violations.js +113 -93
- package/lib/http/routes/wiki.js +211 -170
- package/lib/http/utils/routeHelpers.js +3 -1
- package/lib/http/utils/sse-sessions.js +16 -6
- package/lib/http/utils/sse.js +15 -5
- package/lib/infrastructure/audit/AuditLogger.js +5 -2
- package/lib/infrastructure/audit/AuditStore.js +10 -7
- package/lib/infrastructure/cache/CacheService.js +3 -1
- package/lib/infrastructure/cache/GraphCache.js +8 -4
- package/lib/infrastructure/cache/UnifiedCacheAdapter.js +1 -1
- package/lib/infrastructure/config/ConfigLoader.js +9 -5
- package/lib/infrastructure/config/Defaults.js +30 -10
- package/lib/infrastructure/config/Paths.js +28 -8
- package/lib/infrastructure/config/TriggerSymbol.js +22 -10
- package/lib/infrastructure/database/DatabaseConnection.js +15 -10
- package/lib/infrastructure/database/migrations/001_initial_schema.js +0 -1
- package/lib/infrastructure/external/ClipboardManager.js +6 -2
- package/lib/infrastructure/external/NativeUi.js +50 -43
- package/lib/infrastructure/external/OpenBrowser.js +14 -17
- package/lib/infrastructure/external/XcodeAutomation.js +14 -258
- package/lib/infrastructure/logging/Logger.js +46 -30
- package/lib/infrastructure/monitoring/ErrorTracker.js +7 -5
- package/lib/infrastructure/monitoring/PerformanceMonitor.js +12 -4
- package/lib/infrastructure/paths/HeaderResolver.js +25 -9
- package/lib/infrastructure/paths/PathFinder.js +34 -12
- package/lib/infrastructure/plugin/PluginManager.js +26 -8
- package/lib/infrastructure/realtime/RealtimeService.js +2 -2
- package/lib/infrastructure/vector/Chunker.js +22 -7
- package/lib/infrastructure/vector/IndexingPipeline.js +46 -22
- package/lib/infrastructure/vector/JsonVectorAdapter.js +90 -53
- package/lib/infrastructure/vector/VectorStore.js +28 -10
- package/lib/injection/ServiceContainer.js +247 -93
- package/lib/platform/ios/index.js +63 -0
- package/lib/platform/ios/routes/spm.js +437 -0
- package/lib/platform/ios/snippet/PlaceholderConverter.js +55 -0
- package/lib/platform/ios/snippet/XcodeCodec.js +112 -0
- package/lib/{service → platform/ios}/spm/DependencyGraph.js +41 -17
- package/lib/{service → platform/ios}/spm/PackageSwiftParser.js +41 -14
- package/lib/{service → platform/ios}/spm/PolicyEngine.js +9 -4
- package/lib/platform/ios/spm/SpmDiscoverer.js +122 -0
- package/lib/{service → platform/ios}/spm/SpmService.js +385 -127
- package/lib/{service/automation → platform/ios/xcode}/SaveEventFilter.js +8 -7
- package/lib/platform/ios/xcode/XcodeAutomation.js +350 -0
- package/lib/{service/automation → platform/ios/xcode}/XcodeIntegration.js +325 -145
- package/lib/repository/base/BaseRepository.js +7 -9
- package/lib/repository/knowledge/KnowledgeRepository.impl.js +98 -75
- package/lib/repository/token/TokenUsageStore.js +4 -2
- package/lib/service/automation/ActionPipeline.js +1 -1
- package/lib/service/automation/AutomationOrchestrator.js +8 -4
- package/lib/service/automation/ContextCollector.js +7 -5
- package/lib/service/automation/DirectiveDetector.js +23 -16
- package/lib/service/automation/FileWatcher.js +112 -56
- package/lib/service/automation/TriggerResolver.js +6 -4
- package/lib/service/automation/handlers/AlinkHandler.js +24 -12
- package/lib/service/automation/handlers/CreateHandler.js +19 -20
- package/lib/service/automation/handlers/DraftHandler.js +14 -8
- package/lib/service/automation/handlers/GuardHandler.js +93 -63
- package/lib/service/automation/handlers/HeaderHandler.js +1 -6
- package/lib/service/automation/handlers/SearchHandler.js +155 -88
- package/lib/service/bootstrap/BootstrapTaskManager.js +77 -35
- package/lib/service/candidate/SimilarityService.js +25 -9
- package/lib/service/chat/AnalystAgent.js +50 -24
- package/lib/service/chat/CandidateGuardrail.js +143 -17
- package/lib/service/chat/ChatAgent.js +759 -243
- package/lib/service/chat/ContextWindow.js +116 -71
- package/lib/service/chat/ConversationStore.js +77 -36
- package/lib/service/chat/EpisodicConsolidator.js +47 -23
- package/lib/service/chat/HandoffProtocol.js +98 -22
- package/lib/service/chat/Memory.js +34 -14
- package/lib/service/chat/ProducerAgent.js +40 -20
- package/lib/service/chat/ProjectSemanticMemory.js +109 -78
- package/lib/service/chat/ReasoningLayer.js +148 -70
- package/lib/service/chat/ReasoningTrace.js +44 -32
- package/lib/service/chat/TaskPipeline.js +39 -19
- package/lib/service/chat/ToolRegistry.js +48 -29
- package/lib/service/chat/WorkingMemory.js +44 -18
- package/lib/service/chat/tools.js +1096 -494
- package/lib/service/context/RecipeExtractor.js +132 -51
- package/lib/service/cursor/CursorDeliveryPipeline.js +82 -37
- package/lib/service/cursor/KnowledgeCompressor.js +25 -22
- package/lib/service/cursor/RulesGenerator.js +13 -7
- package/lib/service/cursor/SkillsSyncer.js +77 -27
- package/lib/service/cursor/TokenBudget.js +2 -2
- package/lib/service/cursor/TopicClassifier.js +54 -20
- package/lib/service/guard/ComplianceReporter.js +55 -43
- package/lib/service/guard/ExclusionManager.js +67 -29
- package/lib/service/guard/GuardCheckEngine.js +381 -86
- package/lib/service/guard/GuardFeedbackLoop.js +22 -10
- package/lib/service/guard/GuardService.js +29 -19
- package/lib/service/guard/RuleLearner.js +55 -23
- package/lib/service/guard/SourceFileCollector.js +27 -20
- package/lib/service/guard/ViolationsStore.js +43 -38
- package/lib/service/knowledge/CodeEntityGraph.js +147 -82
- package/lib/service/knowledge/ConfidenceRouter.js +12 -10
- package/lib/service/knowledge/KnowledgeFileWriter.js +147 -56
- package/lib/service/knowledge/KnowledgeGraphService.js +81 -34
- package/lib/service/knowledge/KnowledgeService.js +222 -112
- package/lib/service/module/ModuleService.js +969 -0
- package/lib/service/quality/FeedbackCollector.js +27 -15
- package/lib/service/quality/QualityScorer.js +78 -24
- package/lib/service/recipe/RecipeCandidateValidator.js +110 -44
- package/lib/service/recipe/RecipeParser.js +78 -45
- package/lib/service/search/CoarseRanker.js +43 -28
- package/lib/service/search/CrossEncoderReranker.js +32 -21
- package/lib/service/search/InvertedIndex.js +21 -7
- package/lib/service/search/MultiSignalRanker.js +90 -28
- package/lib/service/search/RetrievalFunnel.js +45 -24
- package/lib/service/search/SearchEngine.js +255 -103
- package/lib/service/skills/EventAggregator.js +32 -15
- package/lib/service/skills/SignalCollector.js +140 -64
- package/lib/service/skills/SkillAdvisor.js +79 -42
- package/lib/service/skills/SkillHooks.js +16 -14
- package/lib/service/snippet/PlaceholderConverter.js +5 -0
- package/lib/service/snippet/SnippetFactory.js +116 -99
- package/lib/service/snippet/SnippetInstaller.js +234 -62
- package/lib/service/snippet/codecs/SnippetCodec.js +67 -0
- package/lib/service/snippet/codecs/VSCodeCodec.js +102 -0
- package/lib/service/snippet/codecs/XcodeCodec.js +5 -0
- package/lib/service/wiki/WikiGenerator.js +637 -263
- package/lib/shared/DimensionCopyRegistry.js +472 -0
- package/lib/shared/LanguageService.js +399 -0
- package/lib/shared/PathGuard.js +45 -28
- package/lib/shared/RecipeReadinessChecker.js +72 -12
- package/lib/shared/constants.js +41 -41
- package/lib/shared/errors/BaseError.js +2 -2
- package/lib/shared/errors/index.js +4 -4
- package/lib/shared/similarity.js +25 -8
- package/lib/shared/token-utils.js +6 -2
- package/lib/shared/utils/common.js +12 -4
- package/package.json +49 -13
- package/scripts/bench-real-projects.mjs +256 -0
- package/scripts/build-native-ui.js +30 -30
- package/scripts/clear-old-vector-index.js +5 -35
- package/scripts/clear-vector-cache.js +7 -37
- package/scripts/collect-test-project-stats.mjs +160 -0
- package/scripts/diagnose-mcp.js +41 -32
- package/scripts/ensure-parse-package.js +6 -9
- package/scripts/generate-recipe-drafts.js +116 -77
- package/scripts/init-db.js +3 -20
- package/scripts/init-snippets.js +305 -0
- package/scripts/init-vector-db.js +173 -170
- package/scripts/install-cursor-skill.js +148 -104
- package/scripts/install-full.js +8 -21
- package/scripts/install-vscode-copilot.js +146 -145
- package/scripts/migrate-md-to-knowledge.mjs +139 -151
- package/scripts/postinstall-safe.js +5 -17
- package/scripts/recipe-audit.js +106 -82
- package/scripts/release.js +283 -323
- package/scripts/setup-mcp-config.js +60 -52
- package/scripts/verify-context-api.js +20 -20
- package/skills/autosnippet-analysis/SKILL.md +10 -6
- package/skills/autosnippet-candidates/SKILL.md +27 -26
- package/skills/autosnippet-coldstart/SKILL.md +555 -38
- package/skills/autosnippet-concepts/SKILL.md +349 -337
- package/skills/autosnippet-create/SKILL.md +5 -5
- package/skills/autosnippet-reference-dart/SKILL.md +543 -0
- package/skills/autosnippet-reference-go/SKILL.md +539 -0
- package/skills/autosnippet-reference-java/SKILL.md +534 -0
- package/skills/autosnippet-reference-jsts/SKILL.md +41 -9
- package/skills/autosnippet-reference-kotlin/SKILL.md +526 -0
- package/skills/autosnippet-reference-objc/SKILL.md +29 -6
- package/skills/autosnippet-reference-python/SKILL.md +800 -0
- package/skills/autosnippet-reference-swift/SKILL.md +70 -14
- package/skills/autosnippet-structure/SKILL.md +4 -4
- package/templates/cursor-rules/autosnippet-conventions.mdc +2 -2
- package/templates/recipes-setup/README.md +2 -2
- package/templates/recipes-setup/_template.md +1 -1
- package/dashboard/dist/assets/index-Bun3ld_J.css +0 -1
- package/dashboard/dist/assets/index-_Sk_Dmg3.js +0 -143
- package/resources/asd-entry/main.swift +0 -159
- package/scripts/build-asd-entry.js +0 -51
- package/scripts/init-xcode-snippets.js +0 -311
- package/template.json +0 -39
|
@@ -0,0 +1,800 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: autosnippet-reference-python
|
|
3
|
+
description: Python 业界最佳实践参考。涵盖类型提示、模块组织、错误处理、异步编程、命名约定、上下文管理、推导式、数据类,为冷启动分析提供高质量参考标准。
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Python 最佳实践参考 (Industry Reference)
|
|
7
|
+
|
|
8
|
+
> 本 Skill 为 **autosnippet-coldstart** 的 Companion Skill。在冷启动分析 Python 项目时,请参考以下业界标准产出高质量候选。
|
|
9
|
+
> **来源**: PEP 8, PEP 484, PEP 257, Google Python Style Guide, Real Python Best Practices
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## 1. 模块与包结构
|
|
14
|
+
|
|
15
|
+
### 核心规则
|
|
16
|
+
|
|
17
|
+
```json
|
|
18
|
+
{
|
|
19
|
+
"title": "Python: 使用 __all__ 控制模块公开 API",
|
|
20
|
+
"content": {
|
|
21
|
+
"markdown": "## Python: 使用 __all__ 控制模块公开 API\n\n### 标准模式\n```python\n# ✅ 明确定义公开 API\n__all__ = ['UserService', 'parse_config', 'MAX_RETRY']\n\nclass UserService:\n ...\n\ndef parse_config(raw: str) -> Config:\n ...\n\ndef _internal_helper():\n \"\"\"以下划线开头表示内部函数\"\"\"\n ...\n\nMAX_RETRY = 3\n```",
|
|
22
|
+
"pattern": "# ✅ 明确定义公开 API\n__all__ = ['UserService', 'parse_config', 'MAX_RETRY']\n\nclass UserService:\n ...\n\ndef parse_config(raw: str) -> Config:\n ...\n\ndef _internal_helper():\n \"\"\"以下划线开头表示内部函数\"\"\"\n ...\n\nMAX_RETRY = 3",
|
|
23
|
+
"rationale": "__all__ 明确控制 from module import * 的行为,便于 IDE 自动补全和文档生成"
|
|
24
|
+
},
|
|
25
|
+
"description": "Python: 使用 __all__ 控制模块公开 API",
|
|
26
|
+
"kind": "rule",
|
|
27
|
+
"doClause": "Apply the Python pattern as described",
|
|
28
|
+
"language": "python",
|
|
29
|
+
"headers": [],
|
|
30
|
+
"category": "Tool",
|
|
31
|
+
"knowledgeType": "code-standard",
|
|
32
|
+
"usageGuide": "### 使用场景\\n触发 `@trigger` 获取Python: 使用 __all__ 控制模块公开 API的标准实现模式。",
|
|
33
|
+
"scope": "universal",
|
|
34
|
+
"antiPattern": {
|
|
35
|
+
"bad": "from utils import * # 没有 __all__,导入所有公开名称",
|
|
36
|
+
"why": "无法控制 API 边界,重构时容易意外暴露或破坏接口",
|
|
37
|
+
"fix": "在模块中定义 __all__ 列表,只导出需要的名称"
|
|
38
|
+
},
|
|
39
|
+
"reasoning": {
|
|
40
|
+
"whyStandard": "PEP 8 推荐使用 __all__ 来定义模块的公开接口",
|
|
41
|
+
"sources": [
|
|
42
|
+
"PEP 8 - Public and Internal Interfaces"
|
|
43
|
+
],
|
|
44
|
+
"confidence": 0.9
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### 导入顺序
|
|
50
|
+
|
|
51
|
+
```json
|
|
52
|
+
{
|
|
53
|
+
"title": "Python: PEP 8 / isort 标准导入顺序",
|
|
54
|
+
"content": {
|
|
55
|
+
"markdown": "## Python: PEP 8 / isort 标准导入顺序\n\n### 标准模式\n```python\n# ✅ 三段式导入,用空行分隔\n\n# 1. 标准库\nimport os\nimport sys\nfrom pathlib import Path\nfrom collections.abc import Sequence\n\n# 2. 第三方库\nimport fastapi\nfrom pydantic import BaseModel\nimport numpy as np # 标准缩写\n\n# 3. 本地模块(使用完整包路径)\nfrom myproject.models import User\nfrom myproject.utils import parse_config\n\n# ❌ 避免相对导入(Google Style Guide)\nfrom .models import User # 不推荐\n\n# ❌ 不要合并 import\nimport os, sys # 每个 import 一行\n\n# ❌ 不要 import 具体类/函数(除 typing/collections.abc)\nfrom os.path import join # 不推荐\nfrom os import path # 推荐\n```",
|
|
56
|
+
"pattern": "# ✅ 三段式导入,用空行分隔\n\n# 1. 标准库\nimport os\nimport sys\nfrom pathlib import Path\nfrom collections.abc import Sequence\n\n# 2. 第三方库\nimport fastapi\nfrom pydantic import BaseModel\nimport numpy as np # 标准缩写\n\n# 3. 本地模块(使用完整包路径)\nfrom myproject.models import User\nfrom myproject.utils import parse_config\n\n# ❌ 避免相对导入(Google Style Guide)\nfrom .models import User # 不推荐\n\n# ❌ 不要合并 import\nimport os, sys # 每个 import 一行\n\n# ❌ 不要 import 具体类/函数(除 typing/collections.abc)\nfrom os.path import join # 不推荐\nfrom os import path # 推荐",
|
|
57
|
+
"rationale": "isort 标准顺序,减少合并冲突,提高可读性。Google Style 推荐 import 模块而非具体符号"
|
|
58
|
+
},
|
|
59
|
+
"description": "Python: PEP 8 / isort 标准导入顺序",
|
|
60
|
+
"kind": "rule",
|
|
61
|
+
"doClause": "Apply the Python pattern as described",
|
|
62
|
+
"language": "python",
|
|
63
|
+
"headers": [],
|
|
64
|
+
"knowledgeType": "code-standard",
|
|
65
|
+
"usageGuide": "### 使用场景\\n触发 `@trigger` 获取Python: PEP 8 / isort 标准导入顺序的标准实现模式。",
|
|
66
|
+
"reasoning": {
|
|
67
|
+
"whyStandard": "PEP 8 + Google Python Style Guide §2.2",
|
|
68
|
+
"sources": [
|
|
69
|
+
"PEP 8 - Imports",
|
|
70
|
+
"Google Python Style Guide §2.2"
|
|
71
|
+
],
|
|
72
|
+
"confidence": 0.95
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### 包结构
|
|
78
|
+
|
|
79
|
+
```python
|
|
80
|
+
# ✅ 推荐的项目结构
|
|
81
|
+
myproject/
|
|
82
|
+
├── __init__.py # 包声明
|
|
83
|
+
├── __main__.py # python -m myproject 入口
|
|
84
|
+
├── models/
|
|
85
|
+
│ ├── __init__.py
|
|
86
|
+
│ ├── user.py
|
|
87
|
+
│ └── order.py
|
|
88
|
+
├── services/
|
|
89
|
+
│ ├── __init__.py
|
|
90
|
+
│ └── user_service.py
|
|
91
|
+
├── api/
|
|
92
|
+
│ ├── __init__.py
|
|
93
|
+
│ └── routes.py
|
|
94
|
+
├── utils/
|
|
95
|
+
│ ├── __init__.py
|
|
96
|
+
│ └── helpers.py
|
|
97
|
+
└── py.typed # PEP 561: 表示本包提供 inline type stubs
|
|
98
|
+
|
|
99
|
+
# ✅ __main__.py 入口
|
|
100
|
+
def main() -> None:
|
|
101
|
+
...
|
|
102
|
+
|
|
103
|
+
if __name__ == '__main__':
|
|
104
|
+
main()
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
---
|
|
108
|
+
|
|
109
|
+
## 2. 类型提示 (Type Hints)
|
|
110
|
+
|
|
111
|
+
### 函数签名
|
|
112
|
+
|
|
113
|
+
```json
|
|
114
|
+
{
|
|
115
|
+
"title": "Python: 函数参数和返回值必须标注类型",
|
|
116
|
+
"content": {
|
|
117
|
+
"markdown": "## Python: 函数参数和返回值必须标注类型\n\n### 标准模式\n```python\nfrom collections.abc import Sequence, Mapping\n\n# ✅ 完整的类型标注(Python 3.10+)\ndef find_users(\n query: str,\n limit: int = 10,\n include_inactive: bool = False,\n) -> list[User]:\n ...\n\n# ✅ Python 3.10+ 使用 X | None 替代 Optional\ndef get_user(user_id: int) -> User | None:\n ...\n\n# ✅ 参数使用抽象类型(Sequence, Mapping, Iterable)\ndef process_items(items: Sequence[Item]) -> Mapping[str, int]:\n ...\n\n# ✅ 返回类型使用具体类型\ndef get_names() -> list[str]:\n return [u.name for u in users]\n\n# ❌ 缺少类型标注\ndef find_users(query, limit=10):\n ...\n```",
|
|
118
|
+
"pattern": "from collections.abc import Sequence, Mapping\n\n# ✅ 完整的类型标注(Python 3.10+)\ndef find_users(\n query: str,\n limit: int = 10,\n include_inactive: bool = False,\n) -> list[User]:\n ...\n\n# ✅ Python 3.10+ 使用 X | None 替代 Optional\ndef get_user(user_id: int) -> User | None:\n ...\n\n# ✅ 参数使用抽象类型(Sequence, Mapping, Iterable)\ndef process_items(items: Sequence[Item]) -> Mapping[str, int]:\n ...\n\n# ✅ 返回类型使用具体类型\ndef get_names() -> list[str]:\n return [u.name for u in users]\n\n# ❌ 缺少类型标注\ndef find_users(query, limit=10):\n ...",
|
|
119
|
+
"rationale": "PEP 484 类型提示提升代码可读性,支持 mypy / pytype 静态检查"
|
|
120
|
+
},
|
|
121
|
+
"description": "Python: 函数参数和返回值必须标注类型",
|
|
122
|
+
"kind": "rule",
|
|
123
|
+
"doClause": "Apply the Python pattern as described",
|
|
124
|
+
"language": "python",
|
|
125
|
+
"headers": [],
|
|
126
|
+
"knowledgeType": "code-standard",
|
|
127
|
+
"usageGuide": "### 使用场景\\n触发 `@trigger` 获取Python: 函数参数和返回值必须标注类型的标准实现模式。",
|
|
128
|
+
"antiPattern": {
|
|
129
|
+
"bad": "def process(data): ...",
|
|
130
|
+
"why": "无法通过静态分析发现类型错误;IDE 无法提供补全和重构支持",
|
|
131
|
+
"fix": "def process(data: bytes) -> str: ..."
|
|
132
|
+
},
|
|
133
|
+
"reasoning": {
|
|
134
|
+
"whyStandard": "Google Python Style Guide §2.21: strongly encouraged",
|
|
135
|
+
"sources": [
|
|
136
|
+
"PEP 484",
|
|
137
|
+
"Google Python Style Guide §2.21"
|
|
138
|
+
],
|
|
139
|
+
"confidence": 0.95
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
### 高级类型模式
|
|
145
|
+
|
|
146
|
+
```python
|
|
147
|
+
from typing import TypeVar, Generic, Protocol, TypeAlias, overload
|
|
148
|
+
from collections.abc import Callable
|
|
149
|
+
|
|
150
|
+
# ✅ TypeVar 用于泛型函数
|
|
151
|
+
_T = TypeVar('_T')
|
|
152
|
+
|
|
153
|
+
def first(items: Sequence[_T]) -> _T | None:
|
|
154
|
+
return items[0] if items else None
|
|
155
|
+
|
|
156
|
+
# ✅ Protocol 用于结构化子类型(鸭子类型的类型安全版本)
|
|
157
|
+
class Renderable(Protocol):
|
|
158
|
+
def render(self) -> str: ...
|
|
159
|
+
|
|
160
|
+
def display(item: Renderable) -> None:
|
|
161
|
+
print(item.render())
|
|
162
|
+
|
|
163
|
+
# ✅ TypeAlias 简化复杂类型(Python 3.10+)
|
|
164
|
+
_JsonValue: TypeAlias = str | int | float | bool | None | list['_JsonValue'] | dict[str, '_JsonValue']
|
|
165
|
+
|
|
166
|
+
# ✅ @overload 为多签名函数提供精确类型
|
|
167
|
+
@overload
|
|
168
|
+
def get(key: str) -> str: ...
|
|
169
|
+
@overload
|
|
170
|
+
def get(key: str, default: _T) -> str | _T: ...
|
|
171
|
+
def get(key, default=...):
|
|
172
|
+
...
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
---
|
|
176
|
+
|
|
177
|
+
## 3. 命名约定
|
|
178
|
+
|
|
179
|
+
### 标准命名
|
|
180
|
+
|
|
181
|
+
```json
|
|
182
|
+
{
|
|
183
|
+
"title": "Python: PEP 8 / Google Style 命名约定",
|
|
184
|
+
"content": {
|
|
185
|
+
"markdown": "## Python: PEP 8 / Google Style 命名约定\n\n### 标准模式\n```python\n# ✅ 模块名: lower_with_under.py\n# user_service.py, http_client.py\n\n# ✅ 类名: CapWords\nclass UserService:\n pass\n\nclass HTTPClient: # 缩写全大写\n pass\n\n# ✅ 异常: CapWords + Error 后缀\nclass NotFoundError(Exception):\n pass\n\n# ✅ 函数/方法/变量: lower_with_under\ndef get_user_by_id(user_id: int) -> User:\n pass\n\nmax_retry_count = 3\n\n# ✅ 常量: CAPS_WITH_UNDER\nMAX_CONNECTIONS = 100\nDEFAULT_TIMEOUT_MS = 5000\n\n# ✅ 非公开: 单下划线前缀\ndef _internal_helper():\n pass\n\nclass _InternalCache:\n pass\n\n# ✅ TypeVar: CapWords,短名称\n_T = TypeVar('_T')\nAddableType = TypeVar('AddableType', int, float, str)\n```",
|
|
186
|
+
"pattern": "# ✅ 模块名: lower_with_under.py\n# user_service.py, http_client.py\n\n# ✅ 类名: CapWords\nclass UserService:\n pass\n\nclass HTTPClient: # 缩写全大写\n pass\n\n# ✅ 异常: CapWords + Error 后缀\nclass NotFoundError(Exception):\n pass\n\n# ✅ 函数/方法/变量: lower_with_under\ndef get_user_by_id(user_id: int) -> User:\n pass\n\nmax_retry_count = 3\n\n# ✅ 常量: CAPS_WITH_UNDER\nMAX_CONNECTIONS = 100\nDEFAULT_TIMEOUT_MS = 5000\n\n# ✅ 非公开: 单下划线前缀\ndef _internal_helper():\n pass\n\nclass _InternalCache:\n pass\n\n# ✅ TypeVar: CapWords,短名称\n_T = TypeVar('_T')\nAddableType = TypeVar('AddableType', int, float, str)",
|
|
187
|
+
"rationale": "统一的命名约定让代码可预测,降低认知负担"
|
|
188
|
+
},
|
|
189
|
+
"description": "Python: PEP 8 / Google Style 命名约定",
|
|
190
|
+
"kind": "rule",
|
|
191
|
+
"doClause": "Apply the Python pattern as described",
|
|
192
|
+
"language": "python",
|
|
193
|
+
"headers": [],
|
|
194
|
+
"knowledgeType": "code-standard",
|
|
195
|
+
"usageGuide": "### 使用场景\\n触发 `@trigger` 获取Python: PEP 8 / Google Style 命名约定的标准实现模式。",
|
|
196
|
+
"reasoning": {
|
|
197
|
+
"whyStandard": "PEP 8 §3.16 + Google Python Style Guide §3.16.4",
|
|
198
|
+
"sources": [
|
|
199
|
+
"PEP 8 - Naming Conventions",
|
|
200
|
+
"Google Python Style Guide §3.16"
|
|
201
|
+
],
|
|
202
|
+
"confidence": 0.95
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
### 命名速查表
|
|
208
|
+
|
|
209
|
+
| 标识符类型 | 风格 | 示例 |
|
|
210
|
+
|-----------|------|------|
|
|
211
|
+
| 模块文件 | `lower_with_under.py` | `user_service.py` |
|
|
212
|
+
| 包 | `lower_with_under` | `myproject` |
|
|
213
|
+
| 类 | `CapWords` | `UserService`, `HTTPClient` |
|
|
214
|
+
| 异常 | `CapWords` + `Error` | `NotFoundError` |
|
|
215
|
+
| 函数/方法 | `lower_with_under` | `get_user_by_id()` |
|
|
216
|
+
| 变量/参数 | `lower_with_under` | `max_count`, `user_id` |
|
|
217
|
+
| 常量 | `CAPS_WITH_UNDER` | `MAX_RETRIES` |
|
|
218
|
+
| 非公开 | `_leading_underscore` | `_helper()`, `_cache` |
|
|
219
|
+
| 名称修饰 | `__double_leading` | `__secret`(不推荐) |
|
|
220
|
+
| TypeVar | `_T` 或 `CapWordsType` | `_T`, `AddableType` |
|
|
221
|
+
|
|
222
|
+
### 命名反模式
|
|
223
|
+
|
|
224
|
+
| 反模式 | 问题 | 修正 |
|
|
225
|
+
|--------|------|------|
|
|
226
|
+
| `userList` (camelCase) | 非 Python 风格 | `user_list` |
|
|
227
|
+
| `class user_service:` | 类应 CapWords | `class UserService:` |
|
|
228
|
+
| `__private_var` | 双下划线触发名称修饰,仅在避免子类冲突时用 | `_private_var` |
|
|
229
|
+
| `from foo import *` | 污染命名空间,隐式依赖 | 显式导入 |
|
|
230
|
+
| `l = []`, `O = 0` | 与 1/0 易混淆 | 有意义名称 |
|
|
231
|
+
|
|
232
|
+
---
|
|
233
|
+
|
|
234
|
+
## 4. 错误处理
|
|
235
|
+
|
|
236
|
+
### 异常层级
|
|
237
|
+
|
|
238
|
+
```json
|
|
239
|
+
{
|
|
240
|
+
"title": "Python: 自定义异常体系 + 精确捕获",
|
|
241
|
+
"content": {
|
|
242
|
+
"markdown": "## Python: 自定义异常体系 + 精确捕获\n\n### 标准模式\n```python\n# ✅ 项目级异常基类\nclass AppError(Exception):\n \"\"\"项目所有自定义异常的基类。\"\"\"\n def __init__(self, message: str, code: str | None = None) -> None:\n super().__init__(message)\n self.code = code\n\nclass NotFoundError(AppError):\n \"\"\"资源不存在。\"\"\"\n\nclass ValidationError(AppError):\n \"\"\"输入校验失败。\"\"\"\n\n# ✅ 精确捕获 + 异常链\ntry:\n user = await user_repo.get(user_id)\nexcept NotFoundError:\n raise HTTPException(status_code=404, detail='User not found')\nexcept DatabaseError as e:\n # 异常链: 保留原始 traceback\n raise ServiceError('DB failure') from e\n\n# ✅ 最小化 try 块\ntry:\n value = collection[key] # 只包含可能抛异常的行\nexcept KeyError:\n return default\nelse:\n return transform(value) # 成功时的逻辑放 else\nfinally:\n cleanup() # 清理放 finally\n```",
|
|
243
|
+
"pattern": "# ✅ 项目级异常基类\nclass AppError(Exception):\n \"\"\"项目所有自定义异常的基类。\"\"\"\n def __init__(self, message: str, code: str | None = None) -> None:\n super().__init__(message)\n self.code = code\n\nclass NotFoundError(AppError):\n \"\"\"资源不存在。\"\"\"\n\nclass ValidationError(AppError):\n \"\"\"输入校验失败。\"\"\"\n\n# ✅ 精确捕获 + 异常链\ntry:\n user = await user_repo.get(user_id)\nexcept NotFoundError:\n raise HTTPException(status_code=404, detail='User not found')\nexcept DatabaseError as e:\n # 异常链: 保留原始 traceback\n raise ServiceError('DB failure') from e\n\n# ✅ 最小化 try 块\ntry:\n value = collection[key] # 只包含可能抛异常的行\nexcept KeyError:\n return default\nelse:\n return transform(value) # 成功时的逻辑放 else\nfinally:\n cleanup() # 清理放 finally",
|
|
244
|
+
"rationale": "Python: 自定义异常体系 + 精确捕获的标准实现模式。"
|
|
245
|
+
},
|
|
246
|
+
"description": "Python: 自定义异常体系 + 精确捕获",
|
|
247
|
+
"kind": "pattern",
|
|
248
|
+
"doClause": "Apply the Python pattern as described",
|
|
249
|
+
"language": "python",
|
|
250
|
+
"headers": [],
|
|
251
|
+
"knowledgeType": "best-practice",
|
|
252
|
+
"usageGuide": "### 使用场景\\n触发 `@trigger` 获取Python: 自定义异常体系 + 精确捕获的标准实现模式。",
|
|
253
|
+
"antiPattern": {
|
|
254
|
+
"bad": "try:\n ...\nexcept:\n pass",
|
|
255
|
+
"why": "bare except 捕获所有异常包括 KeyboardInterrupt / SystemExit;空 catch 吞掉错误",
|
|
256
|
+
"fix": "except SpecificError as e: handle(e)"
|
|
257
|
+
},
|
|
258
|
+
"reasoning": {
|
|
259
|
+
"whyStandard": "Google Python Style Guide §2.4; PEP 8 Programming Recommendations",
|
|
260
|
+
"sources": [
|
|
261
|
+
"Google Python Style Guide §2.4",
|
|
262
|
+
"PEP 8 - Programming Recommendations"
|
|
263
|
+
],
|
|
264
|
+
"confidence": 0.95
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
### 异常处理反模式
|
|
270
|
+
|
|
271
|
+
| 反模式 | 问题 | 修正 |
|
|
272
|
+
|--------|------|------|
|
|
273
|
+
| `except:` (bare except) | 捕获 SystemExit, KeyboardInterrupt | `except Exception:` |
|
|
274
|
+
| `except Exception: pass` | 吞掉所有错误 | 至少 log 或 reraise |
|
|
275
|
+
| `assert x > 0` (校验用) | `-O` 模式下 assert 被移除 | `if x <= 0: raise ValueError(...)` |
|
|
276
|
+
| 过宽 try 块 | 掩盖非预期异常 | 最小化 try 体 |
|
|
277
|
+
| `raise Exception('...')` | 无法精确捕获 | 自定义异常子类 |
|
|
278
|
+
|
|
279
|
+
---
|
|
280
|
+
|
|
281
|
+
## 5. 上下文管理 (Context Manager)
|
|
282
|
+
|
|
283
|
+
```json
|
|
284
|
+
{
|
|
285
|
+
"title": "Python: with 语句管理资源生命周期",
|
|
286
|
+
"content": {
|
|
287
|
+
"markdown": "## Python: with 语句管理资源生命周期\n\n### 标准模式\n```python\nimport contextlib\nfrom contextlib import asynccontextmanager\n\n# ✅ 文件操作必须使用 with\nwith open('data.json') as f:\n data = json.load(f)\n\n# ✅ 多个上下文管理器(Python 3.10+)\nwith (\n open('input.txt') as src,\n open('output.txt', 'w') as dst,\n):\n dst.write(src.read())\n\n# ✅ 自定义上下文管理器(生成器方式)\n@contextlib.contextmanager\ndef timer(label: str):\n t0 = time.perf_counter()\n try:\n yield\n finally:\n elapsed = time.perf_counter() - t0\n logger.info(f'{label}: {elapsed:.3f}s')\n\nwith timer('query'):\n results = db.execute(query)\n\n# ✅ 异步上下文管理器\n@asynccontextmanager\nasync def get_db_session():\n session = await create_session()\n try:\n yield session\n await session.commit()\n except Exception:\n await session.rollback()\n raise\n finally:\n await session.close()\n\n# ❌ 不使用 with 的资源管理\nf = open('data.json') # 忘记 close → 资源泄露\ndata = json.load(f)\nf.close()\n```",
|
|
288
|
+
"pattern": "import contextlib\nfrom contextlib import asynccontextmanager\n\n# ✅ 文件操作必须使用 with\nwith open('data.json') as f:\n data = json.load(f)\n\n# ✅ 多个上下文管理器(Python 3.10+)\nwith (\n open('input.txt') as src,\n open('output.txt', 'w') as dst,\n):\n dst.write(src.read())\n\n# ✅ 自定义上下文管理器(生成器方式)\n@contextlib.contextmanager\ndef timer(label: str):\n t0 = time.perf_counter()\n try:\n yield\n finally:\n elapsed = time.perf_counter() - t0\n logger.info(f'{label}: {elapsed:.3f}s')\n\nwith timer('query'):\n results = db.execute(query)\n\n# ✅ 异步上下文管理器\n@asynccontextmanager\nasync def get_db_session():\n session = await create_session()\n try:\n yield session\n await session.commit()\n except Exception:\n await session.rollback()\n raise\n finally:\n await session.close()\n\n# ❌ 不使用 with 的资源管理\nf = open('data.json') # 忘记 close → 资源泄露\ndata = json.load(f)\nf.close()",
|
|
289
|
+
"rationale": "with 语句确保资源在异常时也能正确释放,避免 fd 泄露"
|
|
290
|
+
},
|
|
291
|
+
"description": "Python: with 语句管理资源生命周期",
|
|
292
|
+
"kind": "pattern",
|
|
293
|
+
"doClause": "Apply the Python pattern as described",
|
|
294
|
+
"language": "python",
|
|
295
|
+
"headers": [],
|
|
296
|
+
"knowledgeType": "best-practice",
|
|
297
|
+
"usageGuide": "### 使用场景\\n触发 `@trigger` 获取Python: with 语句管理资源生命周期的标准实现模式。",
|
|
298
|
+
"reasoning": {
|
|
299
|
+
"whyStandard": "Google Python Style Guide §3.11: 'explicitly close files and sockets when done'",
|
|
300
|
+
"sources": [
|
|
301
|
+
"PEP 343",
|
|
302
|
+
"Google Python Style Guide §3.11"
|
|
303
|
+
],
|
|
304
|
+
"confidence": 0.95
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
---
|
|
310
|
+
|
|
311
|
+
## 6. 推导式与生成器
|
|
312
|
+
|
|
313
|
+
```json
|
|
314
|
+
{
|
|
315
|
+
"title": "Python: 推导式使用规范",
|
|
316
|
+
"content": {
|
|
317
|
+
"markdown": "## Python: 推导式使用规范\n\n### 标准模式\n```python\n# ✅ 简洁的列表推导\nresult = [transform(x) for x in iterable if is_valid(x)]\n\n# ✅ 字典推导\nname_to_user = {u.name: u for u in users}\n\n# ✅ 集合推导\nunique_tags = {tag for item in items for tag in item.tags}\n\n# ✅ 生成器表达式 — 惰性求值,节省内存\ntotal = sum(order.amount for order in orders if order.is_paid)\n\n# ✅ 复杂逻辑用传统循环 + append\nresult = []\nfor x in range(10):\n for y in range(5):\n if x * y > 10:\n result.append((x, y))\n\n# ❌ 多层 for + if 推导(可读性差)\nresult = [(x, y) for x in range(10) for y in range(5) if x * y > 10]\n\n# ❌ 有副作用的推导\n[print(x) for x in items] # 用 for 循环\n```",
|
|
318
|
+
"pattern": "# ✅ 简洁的列表推导\nresult = [transform(x) for x in iterable if is_valid(x)]\n\n# ✅ 字典推导\nname_to_user = {u.name: u for u in users}\n\n# ✅ 集合推导\nunique_tags = {tag for item in items for tag in item.tags}\n\n# ✅ 生成器表达式 — 惰性求值,节省内存\ntotal = sum(order.amount for order in orders if order.is_paid)\n\n# ✅ 复杂逻辑用传统循环 + append\nresult = []\nfor x in range(10):\n for y in range(5):\n if x * y > 10:\n result.append((x, y))\n\n# ❌ 多层 for + if 推导(可读性差)\nresult = [(x, y) for x in range(10) for y in range(5) if x * y > 10]\n\n# ❌ 有副作用的推导\n[print(x) for x in items] # 用 for 循环",
|
|
319
|
+
"rationale": "Google Style: 推导只用于简单场景,多个 for 或 filter 不允许"
|
|
320
|
+
},
|
|
321
|
+
"description": "Python: 推导式使用规范",
|
|
322
|
+
"kind": "pattern",
|
|
323
|
+
"doClause": "Apply the Python pattern as described",
|
|
324
|
+
"language": "python",
|
|
325
|
+
"headers": [],
|
|
326
|
+
"knowledgeType": "code-pattern",
|
|
327
|
+
"usageGuide": "### 使用场景\\n触发 `@trigger` 获取Python: 推导式使用规范的标准实现模式。",
|
|
328
|
+
"reasoning": {
|
|
329
|
+
"whyStandard": "Google Python Style Guide §2.7: 'multiple for clauses or filter expressions are not permitted'",
|
|
330
|
+
"sources": [
|
|
331
|
+
"Google Python Style Guide §2.7"
|
|
332
|
+
],
|
|
333
|
+
"confidence": 0.9
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
---
|
|
339
|
+
|
|
340
|
+
## 7. 异步编程
|
|
341
|
+
|
|
342
|
+
### async/await 模式
|
|
343
|
+
|
|
344
|
+
```json
|
|
345
|
+
{
|
|
346
|
+
"title": "Python: 正确使用 async/await",
|
|
347
|
+
"content": {
|
|
348
|
+
"markdown": "## Python: 正确使用 async/await\n\n### 标准模式\n```python\nimport asyncio\nfrom collections.abc import AsyncIterator\n\n# ✅ async 函数 + 资源管理\nasync def fetch_user(user_id: int) -> User:\n async with httpx.AsyncClient() as client:\n resp = await client.get(f'/users/{user_id}')\n resp.raise_for_status()\n return User(**resp.json())\n\n# ✅ 并发执行多个异步任务\nasync def fetch_dashboard(user_id: int) -> Dashboard:\n async with asyncio.TaskGroup() as tg:\n user_task = tg.create_task(fetch_user(user_id))\n orders_task = tg.create_task(fetch_orders(user_id))\n notifs_task = tg.create_task(fetch_notifications(user_id))\n return Dashboard(\n user=user_task.result(),\n orders=orders_task.result(),\n notifications=notifs_task.result(),\n )\n\n# ✅ async generator (流式处理)\nasync def stream_events(source: str) -> AsyncIterator[Event]:\n async with connect(source) as ws:\n async for message in ws:\n yield Event.parse(message)\n\n# ✅ 超时控制\nasync def fetch_with_timeout(url: str) -> bytes:\n async with asyncio.timeout(10):\n return await fetch(url)\n```",
|
|
349
|
+
"pattern": "import asyncio\nfrom collections.abc import AsyncIterator\n\n# ✅ async 函数 + 资源管理\nasync def fetch_user(user_id: int) -> User:\n async with httpx.AsyncClient() as client:\n resp = await client.get(f'/users/{user_id}')\n resp.raise_for_status()\n return User(**resp.json())\n\n# ✅ 并发执行多个异步任务\nasync def fetch_dashboard(user_id: int) -> Dashboard:\n async with asyncio.TaskGroup() as tg:\n user_task = tg.create_task(fetch_user(user_id))\n orders_task = tg.create_task(fetch_orders(user_id))\n notifs_task = tg.create_task(fetch_notifications(user_id))\n return Dashboard(\n user=user_task.result(),\n orders=orders_task.result(),\n notifications=notifs_task.result(),\n )\n\n# ✅ async generator (流式处理)\nasync def stream_events(source: str) -> AsyncIterator[Event]:\n async with connect(source) as ws:\n async for message in ws:\n yield Event.parse(message)\n\n# ✅ 超时控制\nasync def fetch_with_timeout(url: str) -> bytes:\n async with asyncio.timeout(10):\n return await fetch(url)",
|
|
350
|
+
"rationale": "Python: 正确使用 async/await的标准实现模式。"
|
|
351
|
+
},
|
|
352
|
+
"description": "Python: 正确使用 async/await",
|
|
353
|
+
"kind": "pattern",
|
|
354
|
+
"doClause": "Apply the Python pattern as described",
|
|
355
|
+
"language": "python",
|
|
356
|
+
"headers": [],
|
|
357
|
+
"knowledgeType": "best-practice",
|
|
358
|
+
"usageGuide": "### 使用场景\\n触发 `@trigger` 获取Python: 正确使用 async/await的标准实现模式。",
|
|
359
|
+
"reasoning": {
|
|
360
|
+
"whyStandard": "Python 3.11+ TaskGroup, 3.12+ asyncio.timeout 是官方推荐的结构化并发原语",
|
|
361
|
+
"sources": [
|
|
362
|
+
"Python asyncio docs",
|
|
363
|
+
"PEP 654 (ExceptionGroup)"
|
|
364
|
+
],
|
|
365
|
+
"confidence": 0.9
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
```
|
|
369
|
+
|
|
370
|
+
### async 反模式
|
|
371
|
+
|
|
372
|
+
| 反模式 | 问题 | 修正 |
|
|
373
|
+
|--------|------|------|
|
|
374
|
+
| `asyncio.gather(*tasks)` 无错误处理 | 一个失败全部取消 | `TaskGroup` 或 `return_exceptions=True` |
|
|
375
|
+
| 串行 `await a(); await b()` | 独立任务被串行化 | `TaskGroup` 并发 |
|
|
376
|
+
| `loop.run_until_complete()` | 手动事件循环管理 | `asyncio.run()` |
|
|
377
|
+
| 在 async 中调用阻塞 IO | 阻塞整个事件循环 | `await asyncio.to_thread(blocking_fn)` |
|
|
378
|
+
|
|
379
|
+
---
|
|
380
|
+
|
|
381
|
+
## 8. Decorator 模式
|
|
382
|
+
|
|
383
|
+
```json
|
|
384
|
+
{
|
|
385
|
+
"title": "Python: Decorator 最佳实践",
|
|
386
|
+
"content": {
|
|
387
|
+
"markdown": "## Python: Decorator 最佳实践\n\n### 标准模式\n```python\nimport functools\nfrom typing import TypeVar, ParamSpec\nfrom collections.abc import Callable\n\n_P = ParamSpec('_P')\n_T = TypeVar('_T')\n\n# ✅ 使用 functools.wraps 保留原函数元信息\ndef retry(max_attempts: int = 3, delay: float = 1.0):\n \"\"\"Decorator: 失败重试。\"\"\"\n def decorator(func: Callable[_P, _T]) -> Callable[_P, _T]:\n @functools.wraps(func)\n def wrapper(*args: _P.args, **kwargs: _P.kwargs) -> _T:\n last_exc: Exception | None = None\n for attempt in range(max_attempts):\n try:\n return func(*args, **kwargs)\n except Exception as e:\n last_exc = e\n time.sleep(delay * (2 ** attempt))\n raise last_exc # type: ignore[misc]\n return wrapper\n return decorator\n\n@retry(max_attempts=3, delay=0.5)\ndef fetch_data(url: str) -> dict:\n ...\n\n# ✅ 类级 decorator 替代继承\n@dataclass(frozen=True, slots=True)\nclass Point:\n x: float\n y: float\n```",
|
|
388
|
+
"pattern": "import functools\nfrom typing import TypeVar, ParamSpec\nfrom collections.abc import Callable\n\n_P = ParamSpec('_P')\n_T = TypeVar('_T')\n\n# ✅ 使用 functools.wraps 保留原函数元信息\ndef retry(max_attempts: int = 3, delay: float = 1.0):\n \"\"\"Decorator: 失败重试。\"\"\"\n def decorator(func: Callable[_P, _T]) -> Callable[_P, _T]:\n @functools.wraps(func)\n def wrapper(*args: _P.args, **kwargs: _P.kwargs) -> _T:\n last_exc: Exception | None = None\n for attempt in range(max_attempts):\n try:\n return func(*args, **kwargs)\n except Exception as e:\n last_exc = e\n time.sleep(delay * (2 ** attempt))\n raise last_exc # type: ignore[misc]\n return wrapper\n return decorator\n\n@retry(max_attempts=3, delay=0.5)\ndef fetch_data(url: str) -> dict:\n ...\n\n# ✅ 类级 decorator 替代继承\n@dataclass(frozen=True, slots=True)\nclass Point:\n x: float\n y: float",
|
|
389
|
+
"rationale": "Python: Decorator 最佳实践的标准实现模式。"
|
|
390
|
+
},
|
|
391
|
+
"description": "Python: Decorator 最佳实践",
|
|
392
|
+
"kind": "pattern",
|
|
393
|
+
"doClause": "Apply the Python pattern as described",
|
|
394
|
+
"language": "python",
|
|
395
|
+
"headers": [],
|
|
396
|
+
"knowledgeType": "code-pattern",
|
|
397
|
+
"usageGuide": "### 使用场景\\n触发 `@trigger` 获取Python: Decorator 最佳实践的标准实现模式。",
|
|
398
|
+
"antiPattern": {
|
|
399
|
+
"bad": "def my_decorator(func):\n def wrapper(*args, **kwargs): return func(*args, **kwargs)\n return wrapper",
|
|
400
|
+
"why": "未使用 @functools.wraps,丢失 __name__, __doc__, __module__",
|
|
401
|
+
"fix": "添加 @functools.wraps(func)"
|
|
402
|
+
},
|
|
403
|
+
"reasoning": {
|
|
404
|
+
"whyStandard": "Google Python Style Guide §2.17: 'use decorators judiciously, avoid staticmethod'",
|
|
405
|
+
"sources": [
|
|
406
|
+
"Google Python Style Guide §2.17"
|
|
407
|
+
],
|
|
408
|
+
"confidence": 0.9
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
```
|
|
412
|
+
|
|
413
|
+
---
|
|
414
|
+
|
|
415
|
+
## 9. 数据类
|
|
416
|
+
|
|
417
|
+
```json
|
|
418
|
+
{
|
|
419
|
+
"title": "Python: dataclass vs Pydantic vs NamedTuple",
|
|
420
|
+
"content": {
|
|
421
|
+
"markdown": "## Python: dataclass vs Pydantic vs NamedTuple\n\n### 标准模式\n```python\nfrom dataclasses import dataclass, field\nfrom typing import NamedTuple\nfrom pydantic import BaseModel, Field\n\n# ✅ dataclass: 内部可变数据结构\n@dataclass\nclass UserProfile:\n name: str\n age: int\n email: str = ''\n tags: list[str] = field(default_factory=list)\n\n# ✅ frozen dataclass: 不可变值对象\n@dataclass(frozen=True, slots=True)\nclass Coordinate:\n lat: float\n lon: float\n\n# ✅ NamedTuple: 轻量不可变记录\nclass Version(NamedTuple):\n major: int\n minor: int\n patch: int\n\n# ✅ Pydantic BaseModel: 外部输入校验\nclass CreateUserRequest(BaseModel):\n name: str = Field(..., min_length=1, max_length=100)\n age: int = Field(..., ge=0, le=200)\n email: str = Field(..., pattern=r'^[^@]+@[^@]+\\.[^@]+
|
|
422
|
+
|
|
423
|
+
---
|
|
424
|
+
|
|
425
|
+
## 10. Docstring 规范
|
|
426
|
+
|
|
427
|
+
```json
|
|
428
|
+
{
|
|
429
|
+
"title": "Python: Google Style Docstring",
|
|
430
|
+
"content": {
|
|
431
|
+
"markdown": "## Python: Google Style Docstring\n\n### 标准模式\n```python\ndef fetch_rows(\n table: str,\n keys: Sequence[str],\n require_all: bool = False,\n) -> Mapping[str, tuple[str, ...]]:\n \"\"\"从数据表获取指定行。\n\n 根据给定的 keys 从 table 中检索对应行数据。\n 字符串类型的 key 会被 UTF-8 编码。\n\n Args:\n table: 目标数据表名称。\n keys: 要检索的行 key 列表。\n require_all: 若为 True,仅在所有 key\n 都存在时返回结果。\n\n Returns:\n key → 行数据的映射。每行表示为字符串元组。\n 例如::\n\n {'row1': ('col_a', 'col_b'),\n 'row2': ('col_a', 'col_b')}\n\n Raises:\n IOError: 访问数据表时发生 I/O 错误。\n KeyError: require_all=True 且某 key 不存在。\n \"\"\"\n\nclass CheeseShop:\n \"\"\"奶酪商店的地址信息。\n\n Attributes:\n name: 商店名称。\n address: 完整地址。\n inventory: 库存奶酪种类数。\n \"\"\"\n\n def __init__(self, name: str, address: str) -> None:\n self.name = name\n self.address = address\n self.inventory: int = 0\n```",
|
|
432
|
+
"pattern": "def fetch_rows(\n table: str,\n keys: Sequence[str],\n require_all: bool = False,\n) -> Mapping[str, tuple[str, ...]]:\n \"\"\"从数据表获取指定行。\n\n 根据给定的 keys 从 table 中检索对应行数据。\n 字符串类型的 key 会被 UTF-8 编码。\n\n Args:\n table: 目标数据表名称。\n keys: 要检索的行 key 列表。\n require_all: 若为 True,仅在所有 key\n 都存在时返回结果。\n\n Returns:\n key → 行数据的映射。每行表示为字符串元组。\n 例如::\n\n {'row1': ('col_a', 'col_b'),\n 'row2': ('col_a', 'col_b')}\n\n Raises:\n IOError: 访问数据表时发生 I/O 错误。\n KeyError: require_all=True 且某 key 不存在。\n \"\"\"\n\nclass CheeseShop:\n \"\"\"奶酪商店的地址信息。\n\n Attributes:\n name: 商店名称。\n address: 完整地址。\n inventory: 库存奶酪种类数。\n \"\"\"\n\n def __init__(self, name: str, address: str) -> None:\n self.name = name\n self.address = address\n self.inventory: int = 0",
|
|
433
|
+
"rationale": "Google Style docstring 结构清晰,支持 Sphinx / pydoc 自动生成文档"
|
|
434
|
+
},
|
|
435
|
+
"description": "Python: Google Style Docstring",
|
|
436
|
+
"kind": "rule",
|
|
437
|
+
"doClause": "Follow Style Docstring conventions",
|
|
438
|
+
"language": "python",
|
|
439
|
+
"headers": [],
|
|
440
|
+
"knowledgeType": "code-standard",
|
|
441
|
+
"usageGuide": "### 使用场景\\n触发 `@trigger` 获取Python: Google Style Docstring的标准实现模式。",
|
|
442
|
+
"reasoning": {
|
|
443
|
+
"whyStandard": "Google Python Style Guide §3.8; PEP 257",
|
|
444
|
+
"sources": [
|
|
445
|
+
"Google Python Style Guide §3.8",
|
|
446
|
+
"PEP 257"
|
|
447
|
+
],
|
|
448
|
+
"confidence": 0.95
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
```
|
|
452
|
+
|
|
453
|
+
---
|
|
454
|
+
|
|
455
|
+
## 11. 真值判断与比较
|
|
456
|
+
|
|
457
|
+
```python
|
|
458
|
+
# ✅ 使用隐式布尔 — PEP 8 推荐
|
|
459
|
+
if not users: # 空列表
|
|
460
|
+
print('no users')
|
|
461
|
+
|
|
462
|
+
if name: # 非空字符串
|
|
463
|
+
greet(name)
|
|
464
|
+
|
|
465
|
+
# ✅ None 比较用 is / is not
|
|
466
|
+
if value is None:
|
|
467
|
+
value = default
|
|
468
|
+
|
|
469
|
+
if result is not None:
|
|
470
|
+
process(result)
|
|
471
|
+
|
|
472
|
+
# ✅ 整数比较用显式 ==
|
|
473
|
+
if count == 0: # 不要 `if not count:`(None 也为 False)
|
|
474
|
+
reset()
|
|
475
|
+
|
|
476
|
+
# ❌ 反模式
|
|
477
|
+
if len(users) == 0: # 冗余 → if not users:
|
|
478
|
+
if greeting == True: # 冗余 → if greeting:
|
|
479
|
+
if greeting is True: # 更糟
|
|
480
|
+
if not x is None: # 可读性差 → if x is not None:
|
|
481
|
+
```
|
|
482
|
+
|
|
483
|
+
---
|
|
484
|
+
|
|
485
|
+
## 12. 可变默认参数陷阱
|
|
486
|
+
|
|
487
|
+
```json
|
|
488
|
+
{
|
|
489
|
+
"title": "Python: 不要使用可变对象作为默认参数",
|
|
490
|
+
"content": {
|
|
491
|
+
"markdown": "## Python: 不要使用可变对象作为默认参数\n\n### 标准模式\n```python\n# ✅ 正确: None 哨兵 + 函数内创建\ndef append_to(item: int, target: list[int] | None = None) -> list[int]:\n if target is None:\n target = []\n target.append(item)\n return target\n\n# ✅ 正确: 不可变默认值\ndef process(items: Sequence[str] = ()) -> None:\n ...\n\n# ❌ 危险: 可变默认参数在模块加载时创建一次,所有调用共享同一个对象\ndef append_to(item: int, target: list[int] = []) -> list[int]:\n target.append(item)\n return target\n\n# append_to(1) → [1]\n# append_to(2) → [1, 2] ← 累积了!\n```",
|
|
492
|
+
"pattern": "# ✅ 正确: None 哨兵 + 函数内创建\ndef append_to(item: int, target: list[int] | None = None) -> list[int]:\n if target is None:\n target = []\n target.append(item)\n return target\n\n# ✅ 正确: 不可变默认值\ndef process(items: Sequence[str] = ()) -> None:\n ...\n\n# ❌ 危险: 可变默认参数在模块加载时创建一次,所有调用共享同一个对象\ndef append_to(item: int, target: list[int] = []) -> list[int]:\n target.append(item)\n return target\n\n# append_to(1) → [1]\n# append_to(2) → [1, 2] ← 累积了!",
|
|
493
|
+
"rationale": "Python 默认值在函数定义时求值一次,可变对象被所有调用共享"
|
|
494
|
+
},
|
|
495
|
+
"description": "Python: 不要使用可变对象作为默认参数",
|
|
496
|
+
"kind": "pattern",
|
|
497
|
+
"doClause": "Apply the Python pattern as described",
|
|
498
|
+
"language": "python",
|
|
499
|
+
"headers": [],
|
|
500
|
+
"knowledgeType": "best-practice",
|
|
501
|
+
"usageGuide": "### 使用场景\\n触发 `@trigger` 获取Python: 不要使用可变对象作为默认参数的标准实现模式。",
|
|
502
|
+
"reasoning": {
|
|
503
|
+
"whyStandard": "Google Python Style Guide §2.12; 最常见的 Python 陷阱之一",
|
|
504
|
+
"sources": [
|
|
505
|
+
"Google Python Style Guide §2.12",
|
|
506
|
+
"PEP 8"
|
|
507
|
+
],
|
|
508
|
+
"confidence": 0.95
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
```
|
|
512
|
+
|
|
513
|
+
---
|
|
514
|
+
|
|
515
|
+
## 13. Python 特有维度 (extraDimensions)
|
|
516
|
+
|
|
517
|
+
冷启动分析 Python 项目时,除了通用维度,还应额外关注:
|
|
518
|
+
|
|
519
|
+
| 额外维度 | 寻找什么 | 候选类型 |
|
|
520
|
+
|---------|---------|---------|
|
|
521
|
+
| **类型安全** | type hints 覆盖率、mypy strict、Protocol 使用 | `code-standard` |
|
|
522
|
+
| **包管理** | pyproject.toml vs setup.py、依赖分组、lock 文件 | `config` |
|
|
523
|
+
| **异步模式** | asyncio / TaskGroup / async generator | `code-pattern` |
|
|
524
|
+
| **数据校验** | Pydantic model、dataclass、NamedTuple 选择 | `code-pattern` |
|
|
525
|
+
| **上下文管理** | with 语句覆盖率、自定义 context manager | `best-practice` |
|
|
526
|
+
| **框架模式** | Django ORM/Views、FastAPI routes、Flask blueprints | `code-pattern` |
|
|
527
|
+
| **测试模式** | pytest fixtures、parametrize、mock patch | `best-practice` |
|
|
528
|
+
| **文档** | docstring 覆盖率、Google/NumPy style | `code-standard` |
|
|
529
|
+
|
|
530
|
+
---
|
|
531
|
+
|
|
532
|
+
## 关联 Skills
|
|
533
|
+
|
|
534
|
+
- **autosnippet-coldstart**: 冷启动分析模板
|
|
535
|
+
- **autosnippet-reference-objc**: Objective-C 业界最佳实践参考
|
|
536
|
+
- **autosnippet-reference-swift**: Swift 业界最佳实践参考
|
|
537
|
+
- **autosnippet-reference-jsts**: JavaScript/TypeScript 业界最佳实践参考
|
|
538
|
+
- **autosnippet-reference-java**: Java 业界最佳实践参考
|
|
539
|
+
- **autosnippet-reference-kotlin**: Kotlin 业界最佳实践参考
|
|
540
|
+
- **autosnippet-reference-dart**: Dart (Flutter) 业界最佳实践参考
|
|
541
|
+
)\n\n model_config = {'str_strip_whitespace': True}\n\n# 选择指南:\n# 内部数据 + 可变 → dataclass\n# 内部数据 + 不可变 → frozen dataclass 或 NamedTuple\n# 外部输入(API/文件) → Pydantic BaseModel (自带校验 + 序列化)\n```",
|
|
542
|
+
"pattern": "from dataclasses import dataclass, field\nfrom typing import NamedTuple\nfrom pydantic import BaseModel, Field\n\n# ✅ dataclass: 内部可变数据结构\n@dataclass\nclass UserProfile:\n name: str\n age: int\n email: str = ''\n tags: list[str] = field(default_factory=list)\n\n# ✅ frozen dataclass: 不可变值对象\n@dataclass(frozen=True, slots=True)\nclass Coordinate:\n lat: float\n lon: float\n\n# ✅ NamedTuple: 轻量不可变记录\nclass Version(NamedTuple):\n major: int\n minor: int\n patch: int\n\n# ✅ Pydantic BaseModel: 外部输入校验\nclass CreateUserRequest(BaseModel):\n name: str = Field(..., min_length=1, max_length=100)\n age: int = Field(..., ge=0, le=200)\n email: str = Field(..., pattern=r'^[^@]+@[^@]+\\.[^@]+
|
|
543
|
+
|
|
544
|
+
---
|
|
545
|
+
|
|
546
|
+
## 10. Docstring 规范
|
|
547
|
+
|
|
548
|
+
```json
|
|
549
|
+
{
|
|
550
|
+
"title": "Python: Google Style Docstring",
|
|
551
|
+
"content": {
|
|
552
|
+
"markdown": "## Python: Google Style Docstring\n\n### 标准模式\n```python\ndef fetch_rows(\n table: str,\n keys: Sequence[str],\n require_all: bool = False,\n) -> Mapping[str, tuple[str, ...]]:\n \"\"\"从数据表获取指定行。\n\n 根据给定的 keys 从 table 中检索对应行数据。\n 字符串类型的 key 会被 UTF-8 编码。\n\n Args:\n table: 目标数据表名称。\n keys: 要检索的行 key 列表。\n require_all: 若为 True,仅在所有 key\n 都存在时返回结果。\n\n Returns:\n key → 行数据的映射。每行表示为字符串元组。\n 例如::\n\n {'row1': ('col_a', 'col_b'),\n 'row2': ('col_a', 'col_b')}\n\n Raises:\n IOError: 访问数据表时发生 I/O 错误。\n KeyError: require_all=True 且某 key 不存在。\n \"\"\"\n\nclass CheeseShop:\n \"\"\"奶酪商店的地址信息。\n\n Attributes:\n name: 商店名称。\n address: 完整地址。\n inventory: 库存奶酪种类数。\n \"\"\"\n\n def __init__(self, name: str, address: str) -> None:\n self.name = name\n self.address = address\n self.inventory: int = 0\n```",
|
|
553
|
+
"pattern": "def fetch_rows(\n table: str,\n keys: Sequence[str],\n require_all: bool = False,\n) -> Mapping[str, tuple[str, ...]]:\n \"\"\"从数据表获取指定行。\n\n 根据给定的 keys 从 table 中检索对应行数据。\n 字符串类型的 key 会被 UTF-8 编码。\n\n Args:\n table: 目标数据表名称。\n keys: 要检索的行 key 列表。\n require_all: 若为 True,仅在所有 key\n 都存在时返回结果。\n\n Returns:\n key → 行数据的映射。每行表示为字符串元组。\n 例如::\n\n {'row1': ('col_a', 'col_b'),\n 'row2': ('col_a', 'col_b')}\n\n Raises:\n IOError: 访问数据表时发生 I/O 错误。\n KeyError: require_all=True 且某 key 不存在。\n \"\"\"\n\nclass CheeseShop:\n \"\"\"奶酪商店的地址信息。\n\n Attributes:\n name: 商店名称。\n address: 完整地址。\n inventory: 库存奶酪种类数。\n \"\"\"\n\n def __init__(self, name: str, address: str) -> None:\n self.name = name\n self.address = address\n self.inventory: int = 0",
|
|
554
|
+
"rationale": "Google Style docstring 结构清晰,支持 Sphinx / pydoc 自动生成文档"
|
|
555
|
+
},
|
|
556
|
+
"description": "Python: Google Style Docstring",
|
|
557
|
+
"kind": "rule",
|
|
558
|
+
"doClause": "Follow Style Docstring conventions",
|
|
559
|
+
"language": "python",
|
|
560
|
+
"headers": [],
|
|
561
|
+
"knowledgeType": "code-standard",
|
|
562
|
+
"usageGuide": "### 使用场景\\n触发 `@trigger` 获取Python: Google Style Docstring的标准实现模式。",
|
|
563
|
+
"reasoning": {
|
|
564
|
+
"whyStandard": "Google Python Style Guide §3.8; PEP 257",
|
|
565
|
+
"sources": [
|
|
566
|
+
"Google Python Style Guide §3.8",
|
|
567
|
+
"PEP 257"
|
|
568
|
+
],
|
|
569
|
+
"confidence": 0.95
|
|
570
|
+
}
|
|
571
|
+
}
|
|
572
|
+
```
|
|
573
|
+
|
|
574
|
+
---
|
|
575
|
+
|
|
576
|
+
## 11. 真值判断与比较
|
|
577
|
+
|
|
578
|
+
```python
|
|
579
|
+
# ✅ 使用隐式布尔 — PEP 8 推荐
|
|
580
|
+
if not users: # 空列表
|
|
581
|
+
print('no users')
|
|
582
|
+
|
|
583
|
+
if name: # 非空字符串
|
|
584
|
+
greet(name)
|
|
585
|
+
|
|
586
|
+
# ✅ None 比较用 is / is not
|
|
587
|
+
if value is None:
|
|
588
|
+
value = default
|
|
589
|
+
|
|
590
|
+
if result is not None:
|
|
591
|
+
process(result)
|
|
592
|
+
|
|
593
|
+
# ✅ 整数比较用显式 ==
|
|
594
|
+
if count == 0: # 不要 `if not count:`(None 也为 False)
|
|
595
|
+
reset()
|
|
596
|
+
|
|
597
|
+
# ❌ 反模式
|
|
598
|
+
if len(users) == 0: # 冗余 → if not users:
|
|
599
|
+
if greeting == True: # 冗余 → if greeting:
|
|
600
|
+
if greeting is True: # 更糟
|
|
601
|
+
if not x is None: # 可读性差 → if x is not None:
|
|
602
|
+
```
|
|
603
|
+
|
|
604
|
+
---
|
|
605
|
+
|
|
606
|
+
## 12. 可变默认参数陷阱
|
|
607
|
+
|
|
608
|
+
```json
|
|
609
|
+
{
|
|
610
|
+
"title": "Python: 不要使用可变对象作为默认参数",
|
|
611
|
+
"content": {
|
|
612
|
+
"markdown": "## Python: 不要使用可变对象作为默认参数\n\n### 标准模式\n```python\n# ✅ 正确: None 哨兵 + 函数内创建\ndef append_to(item: int, target: list[int] | None = None) -> list[int]:\n if target is None:\n target = []\n target.append(item)\n return target\n\n# ✅ 正确: 不可变默认值\ndef process(items: Sequence[str] = ()) -> None:\n ...\n\n# ❌ 危险: 可变默认参数在模块加载时创建一次,所有调用共享同一个对象\ndef append_to(item: int, target: list[int] = []) -> list[int]:\n target.append(item)\n return target\n\n# append_to(1) → [1]\n# append_to(2) → [1, 2] ← 累积了!\n```",
|
|
613
|
+
"pattern": "# ✅ 正确: None 哨兵 + 函数内创建\ndef append_to(item: int, target: list[int] | None = None) -> list[int]:\n if target is None:\n target = []\n target.append(item)\n return target\n\n# ✅ 正确: 不可变默认值\ndef process(items: Sequence[str] = ()) -> None:\n ...\n\n# ❌ 危险: 可变默认参数在模块加载时创建一次,所有调用共享同一个对象\ndef append_to(item: int, target: list[int] = []) -> list[int]:\n target.append(item)\n return target\n\n# append_to(1) → [1]\n# append_to(2) → [1, 2] ← 累积了!",
|
|
614
|
+
"rationale": "Python 默认值在函数定义时求值一次,可变对象被所有调用共享"
|
|
615
|
+
},
|
|
616
|
+
"description": "Python: 不要使用可变对象作为默认参数",
|
|
617
|
+
"kind": "pattern",
|
|
618
|
+
"doClause": "Apply the Python pattern as described",
|
|
619
|
+
"language": "python",
|
|
620
|
+
"headers": [],
|
|
621
|
+
"knowledgeType": "best-practice",
|
|
622
|
+
"usageGuide": "### 使用场景\\n触发 `@trigger` 获取Python: 不要使用可变对象作为默认参数的标准实现模式。",
|
|
623
|
+
"reasoning": {
|
|
624
|
+
"whyStandard": "Google Python Style Guide §2.12; 最常见的 Python 陷阱之一",
|
|
625
|
+
"sources": [
|
|
626
|
+
"Google Python Style Guide §2.12",
|
|
627
|
+
"PEP 8"
|
|
628
|
+
],
|
|
629
|
+
"confidence": 0.95
|
|
630
|
+
}
|
|
631
|
+
}
|
|
632
|
+
```
|
|
633
|
+
|
|
634
|
+
---
|
|
635
|
+
|
|
636
|
+
## 13. Python 特有维度 (extraDimensions)
|
|
637
|
+
|
|
638
|
+
冷启动分析 Python 项目时,除了通用维度,还应额外关注:
|
|
639
|
+
|
|
640
|
+
| 额外维度 | 寻找什么 | 候选类型 |
|
|
641
|
+
|---------|---------|---------|
|
|
642
|
+
| **类型安全** | type hints 覆盖率、mypy strict、Protocol 使用 | `code-standard` |
|
|
643
|
+
| **包管理** | pyproject.toml vs setup.py、依赖分组、lock 文件 | `config` |
|
|
644
|
+
| **异步模式** | asyncio / TaskGroup / async generator | `code-pattern` |
|
|
645
|
+
| **数据校验** | Pydantic model、dataclass、NamedTuple 选择 | `code-pattern` |
|
|
646
|
+
| **上下文管理** | with 语句覆盖率、自定义 context manager | `best-practice` |
|
|
647
|
+
| **框架模式** | Django ORM/Views、FastAPI routes、Flask blueprints | `code-pattern` |
|
|
648
|
+
| **测试模式** | pytest fixtures、parametrize、mock patch | `best-practice` |
|
|
649
|
+
| **文档** | docstring 覆盖率、Google/NumPy style | `code-standard` |
|
|
650
|
+
|
|
651
|
+
---
|
|
652
|
+
|
|
653
|
+
## 关联 Skills
|
|
654
|
+
|
|
655
|
+
- **autosnippet-coldstart**: 冷启动分析模板
|
|
656
|
+
- **autosnippet-reference-objc**: Objective-C 业界最佳实践参考
|
|
657
|
+
- **autosnippet-reference-swift**: Swift 业界最佳实践参考
|
|
658
|
+
- **autosnippet-reference-jsts**: JavaScript/TypeScript 业界最佳实践参考
|
|
659
|
+
- **autosnippet-reference-java**: Java 业界最佳实践参考
|
|
660
|
+
- **autosnippet-reference-kotlin**: Kotlin 业界最佳实践参考
|
|
661
|
+
- **autosnippet-reference-dart**: Dart (Flutter) 业界最佳实践参考
|
|
662
|
+
)\n\n model_config = {'str_strip_whitespace': True}\n\n# 选择指南:\n# 内部数据 + 可变 → dataclass\n# 内部数据 + 不可变 → frozen dataclass 或 NamedTuple\n# 外部输入(API/文件) → Pydantic BaseModel (自带校验 + 序列化)",
|
|
663
|
+
"rationale": "dataclass 减少样板代码,Pydantic 提供运行时校验,各有适用场景"
|
|
664
|
+
},
|
|
665
|
+
"description": "Python: dataclass vs Pydantic vs NamedTuple",
|
|
666
|
+
"kind": "pattern",
|
|
667
|
+
"doClause": "Follow vs Pydantic vs NamedTuple conventions",
|
|
668
|
+
"language": "python",
|
|
669
|
+
"headers": [],
|
|
670
|
+
"knowledgeType": "code-pattern",
|
|
671
|
+
"usageGuide": "### 使用场景\\n触发 `@trigger` 获取Python: dataclass vs Pydantic vs NamedTuple的标准实现模式。",
|
|
672
|
+
"reasoning": {
|
|
673
|
+
"whyStandard": "PEP 557 (dataclasses), Pydantic 是 FastAPI 生态标配",
|
|
674
|
+
"sources": [
|
|
675
|
+
"PEP 557",
|
|
676
|
+
"Pydantic docs"
|
|
677
|
+
],
|
|
678
|
+
"confidence": 0.9
|
|
679
|
+
}
|
|
680
|
+
}
|
|
681
|
+
```
|
|
682
|
+
|
|
683
|
+
---
|
|
684
|
+
|
|
685
|
+
## 10. Docstring 规范
|
|
686
|
+
|
|
687
|
+
```json
|
|
688
|
+
{
|
|
689
|
+
"title": "Python: Google Style Docstring",
|
|
690
|
+
"content": {
|
|
691
|
+
"markdown": "## Python: Google Style Docstring\n\n### 标准模式\n```python\ndef fetch_rows(\n table: str,\n keys: Sequence[str],\n require_all: bool = False,\n) -> Mapping[str, tuple[str, ...]]:\n \"\"\"从数据表获取指定行。\n\n 根据给定的 keys 从 table 中检索对应行数据。\n 字符串类型的 key 会被 UTF-8 编码。\n\n Args:\n table: 目标数据表名称。\n keys: 要检索的行 key 列表。\n require_all: 若为 True,仅在所有 key\n 都存在时返回结果。\n\n Returns:\n key → 行数据的映射。每行表示为字符串元组。\n 例如::\n\n {'row1': ('col_a', 'col_b'),\n 'row2': ('col_a', 'col_b')}\n\n Raises:\n IOError: 访问数据表时发生 I/O 错误。\n KeyError: require_all=True 且某 key 不存在。\n \"\"\"\n\nclass CheeseShop:\n \"\"\"奶酪商店的地址信息。\n\n Attributes:\n name: 商店名称。\n address: 完整地址。\n inventory: 库存奶酪种类数。\n \"\"\"\n\n def __init__(self, name: str, address: str) -> None:\n self.name = name\n self.address = address\n self.inventory: int = 0\n```",
|
|
692
|
+
"pattern": "def fetch_rows(\n table: str,\n keys: Sequence[str],\n require_all: bool = False,\n) -> Mapping[str, tuple[str, ...]]:\n \"\"\"从数据表获取指定行。\n\n 根据给定的 keys 从 table 中检索对应行数据。\n 字符串类型的 key 会被 UTF-8 编码。\n\n Args:\n table: 目标数据表名称。\n keys: 要检索的行 key 列表。\n require_all: 若为 True,仅在所有 key\n 都存在时返回结果。\n\n Returns:\n key → 行数据的映射。每行表示为字符串元组。\n 例如::\n\n {'row1': ('col_a', 'col_b'),\n 'row2': ('col_a', 'col_b')}\n\n Raises:\n IOError: 访问数据表时发生 I/O 错误。\n KeyError: require_all=True 且某 key 不存在。\n \"\"\"\n\nclass CheeseShop:\n \"\"\"奶酪商店的地址信息。\n\n Attributes:\n name: 商店名称。\n address: 完整地址。\n inventory: 库存奶酪种类数。\n \"\"\"\n\n def __init__(self, name: str, address: str) -> None:\n self.name = name\n self.address = address\n self.inventory: int = 0",
|
|
693
|
+
"rationale": "Google Style docstring 结构清晰,支持 Sphinx / pydoc 自动生成文档"
|
|
694
|
+
},
|
|
695
|
+
"description": "Python: Google Style Docstring",
|
|
696
|
+
"kind": "rule",
|
|
697
|
+
"doClause": "Follow Style Docstring conventions",
|
|
698
|
+
"language": "python",
|
|
699
|
+
"headers": [],
|
|
700
|
+
"knowledgeType": "code-standard",
|
|
701
|
+
"usageGuide": "### 使用场景\\n触发 `@trigger` 获取Python: Google Style Docstring的标准实现模式。",
|
|
702
|
+
"reasoning": {
|
|
703
|
+
"whyStandard": "Google Python Style Guide §3.8; PEP 257",
|
|
704
|
+
"sources": [
|
|
705
|
+
"Google Python Style Guide §3.8",
|
|
706
|
+
"PEP 257"
|
|
707
|
+
],
|
|
708
|
+
"confidence": 0.95
|
|
709
|
+
}
|
|
710
|
+
}
|
|
711
|
+
```
|
|
712
|
+
|
|
713
|
+
---
|
|
714
|
+
|
|
715
|
+
## 11. 真值判断与比较
|
|
716
|
+
|
|
717
|
+
```python
|
|
718
|
+
# ✅ 使用隐式布尔 — PEP 8 推荐
|
|
719
|
+
if not users: # 空列表
|
|
720
|
+
print('no users')
|
|
721
|
+
|
|
722
|
+
if name: # 非空字符串
|
|
723
|
+
greet(name)
|
|
724
|
+
|
|
725
|
+
# ✅ None 比较用 is / is not
|
|
726
|
+
if value is None:
|
|
727
|
+
value = default
|
|
728
|
+
|
|
729
|
+
if result is not None:
|
|
730
|
+
process(result)
|
|
731
|
+
|
|
732
|
+
# ✅ 整数比较用显式 ==
|
|
733
|
+
if count == 0: # 不要 `if not count:`(None 也为 False)
|
|
734
|
+
reset()
|
|
735
|
+
|
|
736
|
+
# ❌ 反模式
|
|
737
|
+
if len(users) == 0: # 冗余 → if not users:
|
|
738
|
+
if greeting == True: # 冗余 → if greeting:
|
|
739
|
+
if greeting is True: # 更糟
|
|
740
|
+
if not x is None: # 可读性差 → if x is not None:
|
|
741
|
+
```
|
|
742
|
+
|
|
743
|
+
---
|
|
744
|
+
|
|
745
|
+
## 12. 可变默认参数陷阱
|
|
746
|
+
|
|
747
|
+
```json
|
|
748
|
+
{
|
|
749
|
+
"title": "Python: 不要使用可变对象作为默认参数",
|
|
750
|
+
"content": {
|
|
751
|
+
"markdown": "## Python: 不要使用可变对象作为默认参数\n\n### 标准模式\n```python\n# ✅ 正确: None 哨兵 + 函数内创建\ndef append_to(item: int, target: list[int] | None = None) -> list[int]:\n if target is None:\n target = []\n target.append(item)\n return target\n\n# ✅ 正确: 不可变默认值\ndef process(items: Sequence[str] = ()) -> None:\n ...\n\n# ❌ 危险: 可变默认参数在模块加载时创建一次,所有调用共享同一个对象\ndef append_to(item: int, target: list[int] = []) -> list[int]:\n target.append(item)\n return target\n\n# append_to(1) → [1]\n# append_to(2) → [1, 2] ← 累积了!\n```",
|
|
752
|
+
"pattern": "# ✅ 正确: None 哨兵 + 函数内创建\ndef append_to(item: int, target: list[int] | None = None) -> list[int]:\n if target is None:\n target = []\n target.append(item)\n return target\n\n# ✅ 正确: 不可变默认值\ndef process(items: Sequence[str] = ()) -> None:\n ...\n\n# ❌ 危险: 可变默认参数在模块加载时创建一次,所有调用共享同一个对象\ndef append_to(item: int, target: list[int] = []) -> list[int]:\n target.append(item)\n return target\n\n# append_to(1) → [1]\n# append_to(2) → [1, 2] ← 累积了!",
|
|
753
|
+
"rationale": "Python 默认值在函数定义时求值一次,可变对象被所有调用共享"
|
|
754
|
+
},
|
|
755
|
+
"description": "Python: 不要使用可变对象作为默认参数",
|
|
756
|
+
"kind": "pattern",
|
|
757
|
+
"doClause": "Apply the Python pattern as described",
|
|
758
|
+
"language": "python",
|
|
759
|
+
"headers": [],
|
|
760
|
+
"knowledgeType": "best-practice",
|
|
761
|
+
"usageGuide": "### 使用场景\\n触发 `@trigger` 获取Python: 不要使用可变对象作为默认参数的标准实现模式。",
|
|
762
|
+
"reasoning": {
|
|
763
|
+
"whyStandard": "Google Python Style Guide §2.12; 最常见的 Python 陷阱之一",
|
|
764
|
+
"sources": [
|
|
765
|
+
"Google Python Style Guide §2.12",
|
|
766
|
+
"PEP 8"
|
|
767
|
+
],
|
|
768
|
+
"confidence": 0.95
|
|
769
|
+
}
|
|
770
|
+
}
|
|
771
|
+
```
|
|
772
|
+
|
|
773
|
+
---
|
|
774
|
+
|
|
775
|
+
## 13. Python 特有维度 (extraDimensions)
|
|
776
|
+
|
|
777
|
+
冷启动分析 Python 项目时,除了通用维度,还应额外关注:
|
|
778
|
+
|
|
779
|
+
| 额外维度 | 寻找什么 | 候选类型 |
|
|
780
|
+
|---------|---------|---------|
|
|
781
|
+
| **类型安全** | type hints 覆盖率、mypy strict、Protocol 使用 | `code-standard` |
|
|
782
|
+
| **包管理** | pyproject.toml vs setup.py、依赖分组、lock 文件 | `config` |
|
|
783
|
+
| **异步模式** | asyncio / TaskGroup / async generator | `code-pattern` |
|
|
784
|
+
| **数据校验** | Pydantic model、dataclass、NamedTuple 选择 | `code-pattern` |
|
|
785
|
+
| **上下文管理** | with 语句覆盖率、自定义 context manager | `best-practice` |
|
|
786
|
+
| **框架模式** | Django ORM/Views、FastAPI routes、Flask blueprints | `code-pattern` |
|
|
787
|
+
| **测试模式** | pytest fixtures、parametrize、mock patch | `best-practice` |
|
|
788
|
+
| **文档** | docstring 覆盖率、Google/NumPy style | `code-standard` |
|
|
789
|
+
|
|
790
|
+
---
|
|
791
|
+
|
|
792
|
+
## 关联 Skills
|
|
793
|
+
|
|
794
|
+
- **autosnippet-coldstart**: 冷启动分析模板
|
|
795
|
+
- **autosnippet-reference-objc**: Objective-C 业界最佳实践参考
|
|
796
|
+
- **autosnippet-reference-swift**: Swift 业界最佳实践参考
|
|
797
|
+
- **autosnippet-reference-jsts**: JavaScript/TypeScript 业界最佳实践参考
|
|
798
|
+
- **autosnippet-reference-java**: Java 业界最佳实践参考
|
|
799
|
+
- **autosnippet-reference-kotlin**: Kotlin 业界最佳实践参考
|
|
800
|
+
- **autosnippet-reference-dart**: Dart (Flutter) 业界最佳实践参考
|