alita-sdk 0.3.257__py3-none-any.whl → 0.3.584__py3-none-any.whl
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.
Potentially problematic release.
This version of alita-sdk might be problematic. Click here for more details.
- alita_sdk/cli/__init__.py +10 -0
- alita_sdk/cli/__main__.py +17 -0
- alita_sdk/cli/agent/__init__.py +5 -0
- alita_sdk/cli/agent/default.py +258 -0
- alita_sdk/cli/agent_executor.py +155 -0
- alita_sdk/cli/agent_loader.py +215 -0
- alita_sdk/cli/agent_ui.py +228 -0
- alita_sdk/cli/agents.py +3794 -0
- alita_sdk/cli/callbacks.py +647 -0
- alita_sdk/cli/cli.py +168 -0
- alita_sdk/cli/config.py +306 -0
- alita_sdk/cli/context/__init__.py +30 -0
- alita_sdk/cli/context/cleanup.py +198 -0
- alita_sdk/cli/context/manager.py +731 -0
- alita_sdk/cli/context/message.py +285 -0
- alita_sdk/cli/context/strategies.py +289 -0
- alita_sdk/cli/context/token_estimation.py +127 -0
- alita_sdk/cli/formatting.py +182 -0
- alita_sdk/cli/input_handler.py +419 -0
- alita_sdk/cli/inventory.py +1073 -0
- alita_sdk/cli/mcp_loader.py +315 -0
- alita_sdk/cli/toolkit.py +327 -0
- alita_sdk/cli/toolkit_loader.py +85 -0
- alita_sdk/cli/tools/__init__.py +43 -0
- alita_sdk/cli/tools/approval.py +224 -0
- alita_sdk/cli/tools/filesystem.py +1751 -0
- alita_sdk/cli/tools/planning.py +389 -0
- alita_sdk/cli/tools/terminal.py +414 -0
- alita_sdk/community/__init__.py +72 -12
- alita_sdk/community/inventory/__init__.py +236 -0
- alita_sdk/community/inventory/config.py +257 -0
- alita_sdk/community/inventory/enrichment.py +2137 -0
- alita_sdk/community/inventory/extractors.py +1469 -0
- alita_sdk/community/inventory/ingestion.py +3172 -0
- alita_sdk/community/inventory/knowledge_graph.py +1457 -0
- alita_sdk/community/inventory/parsers/__init__.py +218 -0
- alita_sdk/community/inventory/parsers/base.py +295 -0
- alita_sdk/community/inventory/parsers/csharp_parser.py +907 -0
- alita_sdk/community/inventory/parsers/go_parser.py +851 -0
- alita_sdk/community/inventory/parsers/html_parser.py +389 -0
- alita_sdk/community/inventory/parsers/java_parser.py +593 -0
- alita_sdk/community/inventory/parsers/javascript_parser.py +629 -0
- alita_sdk/community/inventory/parsers/kotlin_parser.py +768 -0
- alita_sdk/community/inventory/parsers/markdown_parser.py +362 -0
- alita_sdk/community/inventory/parsers/python_parser.py +604 -0
- alita_sdk/community/inventory/parsers/rust_parser.py +858 -0
- alita_sdk/community/inventory/parsers/swift_parser.py +832 -0
- alita_sdk/community/inventory/parsers/text_parser.py +322 -0
- alita_sdk/community/inventory/parsers/yaml_parser.py +370 -0
- alita_sdk/community/inventory/patterns/__init__.py +61 -0
- alita_sdk/community/inventory/patterns/ast_adapter.py +380 -0
- alita_sdk/community/inventory/patterns/loader.py +348 -0
- alita_sdk/community/inventory/patterns/registry.py +198 -0
- alita_sdk/community/inventory/presets.py +535 -0
- alita_sdk/community/inventory/retrieval.py +1403 -0
- alita_sdk/community/inventory/toolkit.py +173 -0
- alita_sdk/community/inventory/toolkit_utils.py +176 -0
- alita_sdk/community/inventory/visualize.py +1370 -0
- alita_sdk/configurations/__init__.py +11 -0
- alita_sdk/configurations/ado.py +148 -2
- alita_sdk/configurations/azure_search.py +1 -1
- alita_sdk/configurations/bigquery.py +1 -1
- alita_sdk/configurations/bitbucket.py +94 -2
- alita_sdk/configurations/browser.py +18 -0
- alita_sdk/configurations/carrier.py +19 -0
- alita_sdk/configurations/confluence.py +130 -1
- alita_sdk/configurations/delta_lake.py +1 -1
- alita_sdk/configurations/figma.py +76 -5
- alita_sdk/configurations/github.py +65 -1
- alita_sdk/configurations/gitlab.py +81 -0
- alita_sdk/configurations/google_places.py +17 -0
- alita_sdk/configurations/jira.py +103 -0
- alita_sdk/configurations/openapi.py +323 -0
- alita_sdk/configurations/postman.py +1 -1
- alita_sdk/configurations/qtest.py +72 -3
- alita_sdk/configurations/report_portal.py +115 -0
- alita_sdk/configurations/salesforce.py +19 -0
- alita_sdk/configurations/service_now.py +1 -12
- alita_sdk/configurations/sharepoint.py +167 -0
- alita_sdk/configurations/sonar.py +18 -0
- alita_sdk/configurations/sql.py +20 -0
- alita_sdk/configurations/testio.py +101 -0
- alita_sdk/configurations/testrail.py +88 -0
- alita_sdk/configurations/xray.py +94 -1
- alita_sdk/configurations/zephyr_enterprise.py +94 -1
- alita_sdk/configurations/zephyr_essential.py +95 -0
- alita_sdk/runtime/clients/artifact.py +21 -4
- alita_sdk/runtime/clients/client.py +458 -67
- alita_sdk/runtime/clients/mcp_discovery.py +342 -0
- alita_sdk/runtime/clients/mcp_manager.py +262 -0
- alita_sdk/runtime/clients/sandbox_client.py +352 -0
- alita_sdk/runtime/langchain/_constants_bkup.py +1318 -0
- alita_sdk/runtime/langchain/assistant.py +183 -43
- alita_sdk/runtime/langchain/constants.py +647 -1
- alita_sdk/runtime/langchain/document_loaders/AlitaDocxMammothLoader.py +315 -3
- alita_sdk/runtime/langchain/document_loaders/AlitaExcelLoader.py +209 -31
- alita_sdk/runtime/langchain/document_loaders/AlitaImageLoader.py +1 -1
- alita_sdk/runtime/langchain/document_loaders/AlitaJSONLinesLoader.py +77 -0
- alita_sdk/runtime/langchain/document_loaders/AlitaJSONLoader.py +10 -3
- alita_sdk/runtime/langchain/document_loaders/AlitaMarkdownLoader.py +66 -0
- alita_sdk/runtime/langchain/document_loaders/AlitaPDFLoader.py +79 -10
- alita_sdk/runtime/langchain/document_loaders/AlitaPowerPointLoader.py +52 -15
- alita_sdk/runtime/langchain/document_loaders/AlitaPythonLoader.py +9 -0
- alita_sdk/runtime/langchain/document_loaders/AlitaTableLoader.py +1 -4
- alita_sdk/runtime/langchain/document_loaders/AlitaTextLoader.py +15 -2
- alita_sdk/runtime/langchain/document_loaders/ImageParser.py +30 -0
- alita_sdk/runtime/langchain/document_loaders/constants.py +189 -41
- alita_sdk/runtime/langchain/interfaces/llm_processor.py +4 -2
- alita_sdk/runtime/langchain/langraph_agent.py +493 -105
- alita_sdk/runtime/langchain/utils.py +118 -8
- alita_sdk/runtime/llms/preloaded.py +2 -6
- alita_sdk/runtime/models/mcp_models.py +61 -0
- alita_sdk/runtime/skills/__init__.py +91 -0
- alita_sdk/runtime/skills/callbacks.py +498 -0
- alita_sdk/runtime/skills/discovery.py +540 -0
- alita_sdk/runtime/skills/executor.py +610 -0
- alita_sdk/runtime/skills/input_builder.py +371 -0
- alita_sdk/runtime/skills/models.py +330 -0
- alita_sdk/runtime/skills/registry.py +355 -0
- alita_sdk/runtime/skills/skill_runner.py +330 -0
- alita_sdk/runtime/toolkits/__init__.py +28 -0
- alita_sdk/runtime/toolkits/application.py +14 -4
- alita_sdk/runtime/toolkits/artifact.py +25 -9
- alita_sdk/runtime/toolkits/datasource.py +13 -6
- alita_sdk/runtime/toolkits/mcp.py +782 -0
- alita_sdk/runtime/toolkits/planning.py +178 -0
- alita_sdk/runtime/toolkits/skill_router.py +238 -0
- alita_sdk/runtime/toolkits/subgraph.py +11 -6
- alita_sdk/runtime/toolkits/tools.py +314 -70
- alita_sdk/runtime/toolkits/vectorstore.py +11 -5
- alita_sdk/runtime/tools/__init__.py +24 -0
- alita_sdk/runtime/tools/application.py +16 -4
- alita_sdk/runtime/tools/artifact.py +367 -33
- alita_sdk/runtime/tools/data_analysis.py +183 -0
- alita_sdk/runtime/tools/function.py +100 -4
- alita_sdk/runtime/tools/graph.py +81 -0
- alita_sdk/runtime/tools/image_generation.py +218 -0
- alita_sdk/runtime/tools/llm.py +1032 -177
- alita_sdk/runtime/tools/loop.py +3 -1
- alita_sdk/runtime/tools/loop_output.py +3 -1
- alita_sdk/runtime/tools/mcp_inspect_tool.py +284 -0
- alita_sdk/runtime/tools/mcp_remote_tool.py +181 -0
- alita_sdk/runtime/tools/mcp_server_tool.py +3 -1
- alita_sdk/runtime/tools/planning/__init__.py +36 -0
- alita_sdk/runtime/tools/planning/models.py +246 -0
- alita_sdk/runtime/tools/planning/wrapper.py +607 -0
- alita_sdk/runtime/tools/router.py +2 -1
- alita_sdk/runtime/tools/sandbox.py +375 -0
- alita_sdk/runtime/tools/skill_router.py +776 -0
- alita_sdk/runtime/tools/tool.py +3 -1
- alita_sdk/runtime/tools/vectorstore.py +69 -65
- alita_sdk/runtime/tools/vectorstore_base.py +163 -90
- alita_sdk/runtime/utils/AlitaCallback.py +137 -21
- alita_sdk/runtime/utils/constants.py +5 -1
- alita_sdk/runtime/utils/mcp_client.py +492 -0
- alita_sdk/runtime/utils/mcp_oauth.py +361 -0
- alita_sdk/runtime/utils/mcp_sse_client.py +434 -0
- alita_sdk/runtime/utils/mcp_tools_discovery.py +124 -0
- alita_sdk/runtime/utils/streamlit.py +41 -14
- alita_sdk/runtime/utils/toolkit_utils.py +28 -9
- alita_sdk/runtime/utils/utils.py +48 -0
- alita_sdk/tools/__init__.py +135 -37
- alita_sdk/tools/ado/__init__.py +2 -2
- alita_sdk/tools/ado/repos/__init__.py +16 -19
- alita_sdk/tools/ado/repos/repos_wrapper.py +12 -20
- alita_sdk/tools/ado/test_plan/__init__.py +27 -8
- alita_sdk/tools/ado/test_plan/test_plan_wrapper.py +56 -28
- alita_sdk/tools/ado/wiki/__init__.py +28 -12
- alita_sdk/tools/ado/wiki/ado_wrapper.py +114 -40
- alita_sdk/tools/ado/work_item/__init__.py +28 -12
- alita_sdk/tools/ado/work_item/ado_wrapper.py +95 -11
- alita_sdk/tools/advanced_jira_mining/__init__.py +13 -8
- alita_sdk/tools/aws/delta_lake/__init__.py +15 -11
- alita_sdk/tools/aws/delta_lake/tool.py +5 -1
- alita_sdk/tools/azure_ai/search/__init__.py +14 -8
- alita_sdk/tools/base/tool.py +5 -1
- alita_sdk/tools/base_indexer_toolkit.py +454 -110
- alita_sdk/tools/bitbucket/__init__.py +28 -19
- alita_sdk/tools/bitbucket/api_wrapper.py +285 -27
- alita_sdk/tools/bitbucket/cloud_api_wrapper.py +5 -5
- alita_sdk/tools/browser/__init__.py +41 -16
- alita_sdk/tools/browser/crawler.py +3 -1
- alita_sdk/tools/browser/utils.py +15 -6
- alita_sdk/tools/carrier/__init__.py +18 -17
- alita_sdk/tools/carrier/backend_reports_tool.py +8 -4
- alita_sdk/tools/carrier/excel_reporter.py +8 -4
- alita_sdk/tools/chunkers/__init__.py +3 -1
- alita_sdk/tools/chunkers/code/codeparser.py +1 -1
- alita_sdk/tools/chunkers/sematic/json_chunker.py +2 -1
- alita_sdk/tools/chunkers/sematic/markdown_chunker.py +97 -6
- alita_sdk/tools/chunkers/sematic/proposal_chunker.py +1 -1
- alita_sdk/tools/chunkers/universal_chunker.py +270 -0
- alita_sdk/tools/cloud/aws/__init__.py +12 -7
- alita_sdk/tools/cloud/azure/__init__.py +12 -7
- alita_sdk/tools/cloud/gcp/__init__.py +12 -7
- alita_sdk/tools/cloud/k8s/__init__.py +12 -7
- alita_sdk/tools/code/linter/__init__.py +10 -8
- alita_sdk/tools/code/loaders/codesearcher.py +3 -2
- alita_sdk/tools/code/sonar/__init__.py +21 -13
- alita_sdk/tools/code_indexer_toolkit.py +199 -0
- alita_sdk/tools/confluence/__init__.py +22 -14
- alita_sdk/tools/confluence/api_wrapper.py +197 -58
- alita_sdk/tools/confluence/loader.py +14 -2
- alita_sdk/tools/custom_open_api/__init__.py +12 -5
- alita_sdk/tools/elastic/__init__.py +11 -8
- alita_sdk/tools/elitea_base.py +546 -64
- alita_sdk/tools/figma/__init__.py +60 -11
- alita_sdk/tools/figma/api_wrapper.py +1400 -167
- alita_sdk/tools/figma/figma_client.py +73 -0
- alita_sdk/tools/figma/toon_tools.py +2748 -0
- alita_sdk/tools/github/__init__.py +18 -17
- alita_sdk/tools/github/api_wrapper.py +9 -26
- alita_sdk/tools/github/github_client.py +81 -12
- alita_sdk/tools/github/schemas.py +2 -1
- alita_sdk/tools/github/tool.py +5 -1
- alita_sdk/tools/gitlab/__init__.py +19 -13
- alita_sdk/tools/gitlab/api_wrapper.py +256 -80
- alita_sdk/tools/gitlab_org/__init__.py +14 -10
- alita_sdk/tools/google/bigquery/__init__.py +14 -13
- alita_sdk/tools/google/bigquery/tool.py +5 -1
- alita_sdk/tools/google_places/__init__.py +21 -11
- alita_sdk/tools/jira/__init__.py +22 -11
- alita_sdk/tools/jira/api_wrapper.py +315 -168
- alita_sdk/tools/keycloak/__init__.py +11 -8
- alita_sdk/tools/localgit/__init__.py +9 -3
- alita_sdk/tools/localgit/local_git.py +62 -54
- alita_sdk/tools/localgit/tool.py +5 -1
- alita_sdk/tools/memory/__init__.py +38 -14
- alita_sdk/tools/non_code_indexer_toolkit.py +7 -2
- alita_sdk/tools/ocr/__init__.py +11 -8
- alita_sdk/tools/openapi/__init__.py +491 -106
- alita_sdk/tools/openapi/api_wrapper.py +1357 -0
- alita_sdk/tools/openapi/tool.py +20 -0
- alita_sdk/tools/pandas/__init__.py +20 -12
- alita_sdk/tools/pandas/api_wrapper.py +40 -45
- alita_sdk/tools/pandas/dataframe/generator/base.py +3 -1
- alita_sdk/tools/postman/__init__.py +11 -11
- alita_sdk/tools/postman/api_wrapper.py +19 -8
- alita_sdk/tools/postman/postman_analysis.py +8 -1
- alita_sdk/tools/pptx/__init__.py +11 -10
- alita_sdk/tools/qtest/__init__.py +22 -14
- alita_sdk/tools/qtest/api_wrapper.py +1784 -88
- alita_sdk/tools/rally/__init__.py +13 -10
- alita_sdk/tools/report_portal/__init__.py +23 -16
- alita_sdk/tools/salesforce/__init__.py +22 -16
- alita_sdk/tools/servicenow/__init__.py +21 -16
- alita_sdk/tools/servicenow/api_wrapper.py +1 -1
- alita_sdk/tools/sharepoint/__init__.py +17 -14
- alita_sdk/tools/sharepoint/api_wrapper.py +179 -39
- alita_sdk/tools/sharepoint/authorization_helper.py +191 -1
- alita_sdk/tools/sharepoint/utils.py +8 -2
- alita_sdk/tools/slack/__init__.py +13 -8
- alita_sdk/tools/sql/__init__.py +22 -19
- alita_sdk/tools/sql/api_wrapper.py +71 -23
- alita_sdk/tools/testio/__init__.py +21 -13
- alita_sdk/tools/testrail/__init__.py +13 -11
- alita_sdk/tools/testrail/api_wrapper.py +214 -46
- alita_sdk/tools/utils/__init__.py +28 -4
- alita_sdk/tools/utils/content_parser.py +241 -55
- alita_sdk/tools/utils/text_operations.py +254 -0
- alita_sdk/tools/vector_adapters/VectorStoreAdapter.py +83 -27
- alita_sdk/tools/xray/__init__.py +18 -14
- alita_sdk/tools/xray/api_wrapper.py +58 -113
- alita_sdk/tools/yagmail/__init__.py +9 -3
- alita_sdk/tools/zephyr/__init__.py +12 -7
- alita_sdk/tools/zephyr_enterprise/__init__.py +16 -9
- alita_sdk/tools/zephyr_enterprise/api_wrapper.py +30 -15
- alita_sdk/tools/zephyr_essential/__init__.py +16 -10
- alita_sdk/tools/zephyr_essential/api_wrapper.py +297 -54
- alita_sdk/tools/zephyr_essential/client.py +6 -4
- alita_sdk/tools/zephyr_scale/__init__.py +13 -8
- alita_sdk/tools/zephyr_scale/api_wrapper.py +39 -31
- alita_sdk/tools/zephyr_squad/__init__.py +12 -7
- {alita_sdk-0.3.257.dist-info → alita_sdk-0.3.584.dist-info}/METADATA +184 -37
- alita_sdk-0.3.584.dist-info/RECORD +452 -0
- alita_sdk-0.3.584.dist-info/entry_points.txt +2 -0
- alita_sdk/tools/bitbucket/tools.py +0 -304
- alita_sdk-0.3.257.dist-info/RECORD +0 -343
- {alita_sdk-0.3.257.dist-info → alita_sdk-0.3.584.dist-info}/WHEEL +0 -0
- {alita_sdk-0.3.257.dist-info → alita_sdk-0.3.584.dist-info}/licenses/LICENSE +0 -0
- {alita_sdk-0.3.257.dist-info → alita_sdk-0.3.584.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Code and Document Parsers Module for Inventory Graph.
|
|
3
|
+
|
|
4
|
+
This module provides AST-based and regex-based parsers for extracting
|
|
5
|
+
symbols and relationships from source code and document files.
|
|
6
|
+
|
|
7
|
+
Supported Code Languages:
|
|
8
|
+
- Python: Full AST parsing using built-in ast module
|
|
9
|
+
- JavaScript/TypeScript: Regex-based parsing
|
|
10
|
+
- Java: Regex-based parsing
|
|
11
|
+
- Kotlin: Regex-based parsing (data classes, sealed classes, coroutines)
|
|
12
|
+
- C#/.NET: Regex-based parsing (records, async/await, LINQ)
|
|
13
|
+
- Rust: Regex-based parsing (traits, lifetimes, macros)
|
|
14
|
+
- Swift: Regex-based parsing (protocols, actors, property wrappers)
|
|
15
|
+
- Go: Regex-based parsing (goroutines, channels, embedding)
|
|
16
|
+
|
|
17
|
+
Supported Document Types:
|
|
18
|
+
- Markdown/RST: Links, wiki links, images, ADR/RFC references
|
|
19
|
+
- HTML: Anchors, scripts, stylesheets, media
|
|
20
|
+
- YAML/JSON: $ref, !include, Kubernetes, GitHub Actions
|
|
21
|
+
- Text: Universal patterns ("See X", "Depends on Y", URLs, Jira tickets, etc.)
|
|
22
|
+
|
|
23
|
+
The parsers extract:
|
|
24
|
+
- Symbols: classes, functions, methods, variables, headings, etc.
|
|
25
|
+
- Relationships: imports, calls, inheritance, references, etc.
|
|
26
|
+
|
|
27
|
+
Usage:
|
|
28
|
+
from alita_sdk.community.inventory.parsers import (
|
|
29
|
+
# Code Parsers
|
|
30
|
+
PythonParser,
|
|
31
|
+
JavaScriptParser,
|
|
32
|
+
JavaParser,
|
|
33
|
+
KotlinParser,
|
|
34
|
+
CSharpParser,
|
|
35
|
+
RustParser,
|
|
36
|
+
SwiftParser,
|
|
37
|
+
GoParser,
|
|
38
|
+
# Document Parsers
|
|
39
|
+
MarkdownParser,
|
|
40
|
+
HTMLParser,
|
|
41
|
+
YAMLParser,
|
|
42
|
+
TextParser,
|
|
43
|
+
# Functions
|
|
44
|
+
get_parser_for_file,
|
|
45
|
+
parse_file,
|
|
46
|
+
parse_files,
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
# Parse a single file
|
|
50
|
+
result = parse_file("/path/to/file.py")
|
|
51
|
+
|
|
52
|
+
# Get parser by extension
|
|
53
|
+
parser = get_parser_for_file("example.js")
|
|
54
|
+
|
|
55
|
+
# Get all supported languages
|
|
56
|
+
languages = parser_registry.get_supported_languages()
|
|
57
|
+
"""
|
|
58
|
+
|
|
59
|
+
from .base import (
|
|
60
|
+
# Enums
|
|
61
|
+
RelationshipType,
|
|
62
|
+
SymbolType,
|
|
63
|
+
Scope,
|
|
64
|
+
# Data classes
|
|
65
|
+
Position,
|
|
66
|
+
Range,
|
|
67
|
+
Symbol,
|
|
68
|
+
Relationship,
|
|
69
|
+
ParseResult,
|
|
70
|
+
# Base class
|
|
71
|
+
BaseParser,
|
|
72
|
+
# Registry
|
|
73
|
+
ParserRegistry,
|
|
74
|
+
parser_registry,
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
# Code language parsers
|
|
78
|
+
from .python_parser import PythonParser
|
|
79
|
+
from .javascript_parser import JavaScriptParser
|
|
80
|
+
from .java_parser import JavaParser
|
|
81
|
+
from .kotlin_parser import KotlinParser
|
|
82
|
+
from .csharp_parser import CSharpParser
|
|
83
|
+
from .rust_parser import RustParser
|
|
84
|
+
from .swift_parser import SwiftParser
|
|
85
|
+
from .go_parser import GoParser
|
|
86
|
+
|
|
87
|
+
# Document parsers
|
|
88
|
+
from .markdown_parser import MarkdownParser
|
|
89
|
+
from .html_parser import HTMLParser
|
|
90
|
+
from .yaml_parser import YAMLParser
|
|
91
|
+
from .text_parser import TextParser
|
|
92
|
+
|
|
93
|
+
# Convenience functions
|
|
94
|
+
def get_parser_for_file(file_path: str) -> "BaseParser | None":
|
|
95
|
+
"""Get appropriate parser for a file based on extension."""
|
|
96
|
+
return parser_registry.get_parser_for_file(file_path)
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
def parse_file(file_path: str, content: str = None) -> ParseResult:
|
|
100
|
+
"""
|
|
101
|
+
Parse a file and extract symbols and relationships.
|
|
102
|
+
|
|
103
|
+
Args:
|
|
104
|
+
file_path: Path to the file
|
|
105
|
+
content: Optional file content
|
|
106
|
+
|
|
107
|
+
Returns:
|
|
108
|
+
ParseResult with symbols and relationships
|
|
109
|
+
"""
|
|
110
|
+
parser = get_parser_for_file(file_path)
|
|
111
|
+
if parser:
|
|
112
|
+
return parser.parse_file(file_path, content=content)
|
|
113
|
+
|
|
114
|
+
# Return empty result for unsupported file types
|
|
115
|
+
return ParseResult(
|
|
116
|
+
file_path=file_path,
|
|
117
|
+
language="unknown",
|
|
118
|
+
symbols=[],
|
|
119
|
+
relationships=[]
|
|
120
|
+
)
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
def parse_files(file_paths: list, file_contents: dict = None, max_workers: int = 4) -> dict:
|
|
124
|
+
"""
|
|
125
|
+
Parse multiple files with cross-file resolution.
|
|
126
|
+
|
|
127
|
+
Groups files by language and uses multi-file parsing when available.
|
|
128
|
+
|
|
129
|
+
Args:
|
|
130
|
+
file_paths: List of file paths to parse
|
|
131
|
+
file_contents: Optional dict mapping paths to content
|
|
132
|
+
max_workers: Number of parallel workers
|
|
133
|
+
|
|
134
|
+
Returns:
|
|
135
|
+
Dict mapping file paths to ParseResult
|
|
136
|
+
"""
|
|
137
|
+
from pathlib import Path
|
|
138
|
+
from typing import Dict, List
|
|
139
|
+
|
|
140
|
+
file_contents = file_contents or {}
|
|
141
|
+
results: Dict[str, ParseResult] = {}
|
|
142
|
+
|
|
143
|
+
# Group files by parser
|
|
144
|
+
files_by_parser: Dict[str, List[str]] = {}
|
|
145
|
+
|
|
146
|
+
for fp in file_paths:
|
|
147
|
+
parser = get_parser_for_file(fp)
|
|
148
|
+
if parser:
|
|
149
|
+
lang = parser.language
|
|
150
|
+
files_by_parser.setdefault(lang, []).append(fp)
|
|
151
|
+
else:
|
|
152
|
+
results[fp] = ParseResult(
|
|
153
|
+
file_path=fp,
|
|
154
|
+
language="unknown",
|
|
155
|
+
symbols=[],
|
|
156
|
+
relationships=[]
|
|
157
|
+
)
|
|
158
|
+
|
|
159
|
+
# Parse each language group
|
|
160
|
+
for lang, lang_files in files_by_parser.items():
|
|
161
|
+
parser = parser_registry.get_parser(lang)
|
|
162
|
+
if not parser:
|
|
163
|
+
continue
|
|
164
|
+
|
|
165
|
+
if hasattr(parser, 'parse_multiple_files'):
|
|
166
|
+
# Use multi-file parsing for cross-file resolution
|
|
167
|
+
try:
|
|
168
|
+
lang_results = parser.parse_multiple_files(lang_files, max_workers=max_workers)
|
|
169
|
+
results.update(lang_results)
|
|
170
|
+
except Exception:
|
|
171
|
+
# Fall back to single file parsing
|
|
172
|
+
for fp in lang_files:
|
|
173
|
+
content = file_contents.get(fp)
|
|
174
|
+
results[fp] = parser.parse_file(fp, content=content)
|
|
175
|
+
else:
|
|
176
|
+
# Single file parsing
|
|
177
|
+
for fp in lang_files:
|
|
178
|
+
content = file_contents.get(fp)
|
|
179
|
+
results[fp] = parser.parse_file(fp, content=content)
|
|
180
|
+
|
|
181
|
+
return results
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
__all__ = [
|
|
185
|
+
# Enums
|
|
186
|
+
'RelationshipType',
|
|
187
|
+
'SymbolType',
|
|
188
|
+
'Scope',
|
|
189
|
+
# Data classes
|
|
190
|
+
'Position',
|
|
191
|
+
'Range',
|
|
192
|
+
'Symbol',
|
|
193
|
+
'Relationship',
|
|
194
|
+
'ParseResult',
|
|
195
|
+
# Base class
|
|
196
|
+
'BaseParser',
|
|
197
|
+
# Registry
|
|
198
|
+
'ParserRegistry',
|
|
199
|
+
'parser_registry',
|
|
200
|
+
# Code Parsers
|
|
201
|
+
'PythonParser',
|
|
202
|
+
'JavaScriptParser',
|
|
203
|
+
'JavaParser',
|
|
204
|
+
'KotlinParser',
|
|
205
|
+
'CSharpParser',
|
|
206
|
+
'RustParser',
|
|
207
|
+
'SwiftParser',
|
|
208
|
+
'GoParser',
|
|
209
|
+
# Document Parsers
|
|
210
|
+
'MarkdownParser',
|
|
211
|
+
'HTMLParser',
|
|
212
|
+
'YAMLParser',
|
|
213
|
+
'TextParser',
|
|
214
|
+
# Functions
|
|
215
|
+
'get_parser_for_file',
|
|
216
|
+
'parse_file',
|
|
217
|
+
'parse_files',
|
|
218
|
+
]
|
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Base Parser Interface and Data Structures.
|
|
3
|
+
|
|
4
|
+
This module defines the core interfaces and data classes for language-specific
|
|
5
|
+
AST parsers that extract symbols, relationships, and context from source code.
|
|
6
|
+
|
|
7
|
+
Simplified from deepwiki_plugin for self-contained use in inventory graph.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
import logging
|
|
11
|
+
from abc import ABC, abstractmethod
|
|
12
|
+
from dataclasses import dataclass, field
|
|
13
|
+
from enum import Enum
|
|
14
|
+
from typing import Dict, List, Optional, Set, Any, Union
|
|
15
|
+
from pathlib import Path
|
|
16
|
+
|
|
17
|
+
logger = logging.getLogger(__name__)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class RelationshipType(Enum):
|
|
21
|
+
"""Types of relationships between code elements."""
|
|
22
|
+
# Module relationships
|
|
23
|
+
IMPORTS = "imports" # import statements
|
|
24
|
+
EXPORTS = "exports" # module exports
|
|
25
|
+
|
|
26
|
+
# Function/method relationships
|
|
27
|
+
CALLS = "calls" # function/method calls
|
|
28
|
+
RETURNS = "returns" # return value relationships
|
|
29
|
+
|
|
30
|
+
# Object-oriented relationships
|
|
31
|
+
INHERITANCE = "inheritance" # class inheritance (extends)
|
|
32
|
+
IMPLEMENTATION = "implementation" # interface implementation
|
|
33
|
+
COMPOSITION = "composition" # has-a relationships (strong ownership)
|
|
34
|
+
AGGREGATION = "aggregation" # has-a relationships (weak ownership)
|
|
35
|
+
|
|
36
|
+
# Structural relationships
|
|
37
|
+
DEFINES = "defines" # contains definition
|
|
38
|
+
CONTAINS = "contains" # structural containment
|
|
39
|
+
DECORATES = "decorates" # decorator relationships
|
|
40
|
+
ANNOTATES = "annotates" # type annotations
|
|
41
|
+
|
|
42
|
+
# References
|
|
43
|
+
REFERENCES = "references" # general symbol references
|
|
44
|
+
USES = "uses" # uses a type/symbol
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
class SymbolType(Enum):
|
|
48
|
+
"""Types of symbols that can be extracted from code."""
|
|
49
|
+
FUNCTION = "function"
|
|
50
|
+
METHOD = "method"
|
|
51
|
+
CLASS = "class"
|
|
52
|
+
INTERFACE = "interface"
|
|
53
|
+
VARIABLE = "variable"
|
|
54
|
+
CONSTANT = "constant"
|
|
55
|
+
PROPERTY = "property"
|
|
56
|
+
FIELD = "field"
|
|
57
|
+
PARAMETER = "parameter"
|
|
58
|
+
MODULE = "module"
|
|
59
|
+
NAMESPACE = "namespace"
|
|
60
|
+
ENUM = "enum"
|
|
61
|
+
TYPE_ALIAS = "type_alias"
|
|
62
|
+
DECORATOR = "decorator"
|
|
63
|
+
IMPORT = "import"
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
class Scope(Enum):
|
|
67
|
+
"""Unified scoping model across languages."""
|
|
68
|
+
GLOBAL = "global" # Global/module scope
|
|
69
|
+
CLASS = "class" # Class scope
|
|
70
|
+
FUNCTION = "function" # Function/method scope
|
|
71
|
+
BLOCK = "block" # Block scope
|
|
72
|
+
LOCAL = "local" # Local variable scope
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
@dataclass
|
|
76
|
+
class Position:
|
|
77
|
+
"""Source code position information."""
|
|
78
|
+
line: int
|
|
79
|
+
column: int
|
|
80
|
+
|
|
81
|
+
def __str__(self) -> str:
|
|
82
|
+
return f"{self.line}:{self.column}"
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
@dataclass
|
|
86
|
+
class Range:
|
|
87
|
+
"""Source code range information."""
|
|
88
|
+
start: Position
|
|
89
|
+
end: Position
|
|
90
|
+
|
|
91
|
+
def __str__(self) -> str:
|
|
92
|
+
return f"{self.start}-{self.end}"
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
@dataclass
|
|
96
|
+
class Symbol:
|
|
97
|
+
"""Extracted symbol information."""
|
|
98
|
+
name: str
|
|
99
|
+
symbol_type: SymbolType
|
|
100
|
+
scope: Scope
|
|
101
|
+
range: Range
|
|
102
|
+
file_path: str
|
|
103
|
+
|
|
104
|
+
# Hierarchical context
|
|
105
|
+
parent_symbol: Optional[str] = None
|
|
106
|
+
full_name: Optional[str] = None
|
|
107
|
+
|
|
108
|
+
# Metadata
|
|
109
|
+
visibility: Optional[str] = None
|
|
110
|
+
is_static: bool = False
|
|
111
|
+
is_async: bool = False
|
|
112
|
+
is_exported: bool = False
|
|
113
|
+
|
|
114
|
+
# Documentation
|
|
115
|
+
docstring: Optional[str] = None
|
|
116
|
+
|
|
117
|
+
# Type information
|
|
118
|
+
return_type: Optional[str] = None
|
|
119
|
+
parameter_types: List[str] = field(default_factory=list)
|
|
120
|
+
|
|
121
|
+
# Source
|
|
122
|
+
source_text: Optional[str] = None
|
|
123
|
+
signature: Optional[str] = None
|
|
124
|
+
metadata: Dict[str, Any] = field(default_factory=dict)
|
|
125
|
+
|
|
126
|
+
def get_qualified_name(self) -> str:
|
|
127
|
+
"""Get the fully qualified name of the symbol."""
|
|
128
|
+
if self.full_name:
|
|
129
|
+
return self.full_name
|
|
130
|
+
if self.parent_symbol:
|
|
131
|
+
return f"{self.parent_symbol}.{self.name}"
|
|
132
|
+
return self.name
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
@dataclass
|
|
136
|
+
class Relationship:
|
|
137
|
+
"""Extracted relationship between symbols."""
|
|
138
|
+
source_symbol: str
|
|
139
|
+
target_symbol: str
|
|
140
|
+
relationship_type: RelationshipType
|
|
141
|
+
source_file: str
|
|
142
|
+
|
|
143
|
+
target_file: Optional[str] = None
|
|
144
|
+
source_range: Optional[Range] = None
|
|
145
|
+
|
|
146
|
+
confidence: float = 1.0
|
|
147
|
+
is_cross_file: bool = False
|
|
148
|
+
|
|
149
|
+
context: Optional[str] = None
|
|
150
|
+
metadata: Dict[str, Any] = field(default_factory=dict)
|
|
151
|
+
|
|
152
|
+
def get_key(self) -> str:
|
|
153
|
+
"""Get unique key for this relationship."""
|
|
154
|
+
loc = f"{self.source_range.start.line}" if self.source_range else "0"
|
|
155
|
+
return f"{self.source_symbol}->{self.target_symbol}:{self.relationship_type.value}@{loc}"
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
@dataclass
|
|
159
|
+
class ParseResult:
|
|
160
|
+
"""Result of parsing a source file."""
|
|
161
|
+
file_path: str
|
|
162
|
+
language: str
|
|
163
|
+
symbols: List[Symbol]
|
|
164
|
+
relationships: List[Relationship]
|
|
165
|
+
|
|
166
|
+
imports: List[str] = field(default_factory=list)
|
|
167
|
+
exports: List[str] = field(default_factory=list)
|
|
168
|
+
dependencies: Set[str] = field(default_factory=set)
|
|
169
|
+
|
|
170
|
+
module_docstring: Optional[str] = None
|
|
171
|
+
parse_time: Optional[float] = None
|
|
172
|
+
|
|
173
|
+
errors: List[str] = field(default_factory=list)
|
|
174
|
+
warnings: List[str] = field(default_factory=list)
|
|
175
|
+
|
|
176
|
+
def get_symbols_by_type(self, symbol_type: SymbolType) -> List[Symbol]:
|
|
177
|
+
"""Get all symbols of a specific type."""
|
|
178
|
+
return [s for s in self.symbols if s.symbol_type == symbol_type]
|
|
179
|
+
|
|
180
|
+
def get_relationships_by_type(self, rel_type: RelationshipType) -> List[Relationship]:
|
|
181
|
+
"""Get all relationships of a specific type."""
|
|
182
|
+
return [r for r in self.relationships if r.relationship_type == rel_type]
|
|
183
|
+
|
|
184
|
+
def get_cross_file_relationships(self) -> List[Relationship]:
|
|
185
|
+
"""Get only cross-file relationships."""
|
|
186
|
+
return [r for r in self.relationships if r.is_cross_file or r.target_file]
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
class BaseParser(ABC):
|
|
190
|
+
"""
|
|
191
|
+
Abstract base class for language-specific parsers.
|
|
192
|
+
|
|
193
|
+
All language parsers must inherit from this class and implement
|
|
194
|
+
the abstract methods.
|
|
195
|
+
"""
|
|
196
|
+
|
|
197
|
+
def __init__(self, language: str):
|
|
198
|
+
self.language = language
|
|
199
|
+
self.logger = logging.getLogger(f"{__name__}.{language}")
|
|
200
|
+
|
|
201
|
+
@abstractmethod
|
|
202
|
+
def parse_file(self, file_path: Union[str, Path], content: Optional[str] = None) -> ParseResult:
|
|
203
|
+
"""
|
|
204
|
+
Parse a source file and extract symbols and relationships.
|
|
205
|
+
|
|
206
|
+
Args:
|
|
207
|
+
file_path: Path to the source file
|
|
208
|
+
content: Optional file content
|
|
209
|
+
|
|
210
|
+
Returns:
|
|
211
|
+
ParseResult containing extracted symbols and relationships
|
|
212
|
+
"""
|
|
213
|
+
pass
|
|
214
|
+
|
|
215
|
+
@abstractmethod
|
|
216
|
+
def _get_supported_extensions(self) -> Set[str]:
|
|
217
|
+
"""
|
|
218
|
+
Get set of supported file extensions.
|
|
219
|
+
|
|
220
|
+
Returns:
|
|
221
|
+
Set of file extensions (including the dot, e.g., {'.py'})
|
|
222
|
+
"""
|
|
223
|
+
pass
|
|
224
|
+
|
|
225
|
+
def supports_file(self, file_path: Union[str, Path]) -> bool:
|
|
226
|
+
"""Check if this parser can handle the given file."""
|
|
227
|
+
path = Path(file_path)
|
|
228
|
+
return path.suffix.lower() in self._get_supported_extensions()
|
|
229
|
+
|
|
230
|
+
def validate_result(self, result: ParseResult) -> ParseResult:
|
|
231
|
+
"""Validate and clean up parse result."""
|
|
232
|
+
# Remove duplicate symbols
|
|
233
|
+
unique_symbols = []
|
|
234
|
+
seen = set()
|
|
235
|
+
for s in result.symbols:
|
|
236
|
+
key = f"{s.name}:{s.symbol_type.value}:{s.range}"
|
|
237
|
+
if key not in seen:
|
|
238
|
+
unique_symbols.append(s)
|
|
239
|
+
seen.add(key)
|
|
240
|
+
result.symbols = unique_symbols
|
|
241
|
+
|
|
242
|
+
# Remove duplicate relationships
|
|
243
|
+
unique_rels = []
|
|
244
|
+
seen_rels = set()
|
|
245
|
+
for r in result.relationships:
|
|
246
|
+
key = r.get_key()
|
|
247
|
+
if key not in seen_rels:
|
|
248
|
+
unique_rels.append(r)
|
|
249
|
+
seen_rels.add(key)
|
|
250
|
+
result.relationships = unique_rels
|
|
251
|
+
|
|
252
|
+
return result
|
|
253
|
+
|
|
254
|
+
|
|
255
|
+
class ParserRegistry:
|
|
256
|
+
"""Registry for managing language-specific parsers."""
|
|
257
|
+
|
|
258
|
+
def __init__(self):
|
|
259
|
+
self._parsers: Dict[str, BaseParser] = {}
|
|
260
|
+
self._extension_map: Dict[str, str] = {}
|
|
261
|
+
|
|
262
|
+
def register_parser(self, parser: BaseParser) -> None:
|
|
263
|
+
"""Register a language parser."""
|
|
264
|
+
language = parser.language.lower()
|
|
265
|
+
self._parsers[language] = parser
|
|
266
|
+
|
|
267
|
+
for ext in parser._get_supported_extensions():
|
|
268
|
+
self._extension_map[ext.lower()] = language
|
|
269
|
+
|
|
270
|
+
logger.debug(f"Registered parser for {language}")
|
|
271
|
+
|
|
272
|
+
def get_parser(self, language: str) -> Optional[BaseParser]:
|
|
273
|
+
"""Get parser for specific language."""
|
|
274
|
+
return self._parsers.get(language.lower())
|
|
275
|
+
|
|
276
|
+
def get_parser_for_file(self, file_path: Union[str, Path]) -> Optional[BaseParser]:
|
|
277
|
+
"""Get appropriate parser for a file based on extension."""
|
|
278
|
+
path = Path(file_path)
|
|
279
|
+
extension = path.suffix.lower()
|
|
280
|
+
language = self._extension_map.get(extension)
|
|
281
|
+
if language:
|
|
282
|
+
return self._parsers.get(language)
|
|
283
|
+
return None
|
|
284
|
+
|
|
285
|
+
def get_supported_languages(self) -> List[str]:
|
|
286
|
+
"""Get list of supported languages."""
|
|
287
|
+
return list(self._parsers.keys())
|
|
288
|
+
|
|
289
|
+
def get_supported_extensions(self) -> Set[str]:
|
|
290
|
+
"""Get set of all supported file extensions."""
|
|
291
|
+
return set(self._extension_map.keys())
|
|
292
|
+
|
|
293
|
+
|
|
294
|
+
# Global parser registry instance
|
|
295
|
+
parser_registry = ParserRegistry()
|