code-graph-builder 0.2.0__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.
Files changed (93) hide show
  1. code_graph_builder/__init__.py +82 -0
  2. code_graph_builder/builder.py +366 -0
  3. code_graph_builder/cgb_cli.py +32 -0
  4. code_graph_builder/cli.py +564 -0
  5. code_graph_builder/commands_cli.py +1288 -0
  6. code_graph_builder/config.py +340 -0
  7. code_graph_builder/constants.py +708 -0
  8. code_graph_builder/embeddings/__init__.py +40 -0
  9. code_graph_builder/embeddings/qwen3_embedder.py +573 -0
  10. code_graph_builder/embeddings/vector_store.py +584 -0
  11. code_graph_builder/examples/__init__.py +0 -0
  12. code_graph_builder/examples/example_configuration.py +276 -0
  13. code_graph_builder/examples/example_kuzu_usage.py +109 -0
  14. code_graph_builder/examples/example_semantic_search_full.py +347 -0
  15. code_graph_builder/examples/generate_wiki.py +915 -0
  16. code_graph_builder/examples/graph_export_example.py +100 -0
  17. code_graph_builder/examples/rag_example.py +206 -0
  18. code_graph_builder/examples/test_cli_demo.py +129 -0
  19. code_graph_builder/examples/test_embedding_api.py +153 -0
  20. code_graph_builder/examples/test_kuzu_local.py +190 -0
  21. code_graph_builder/examples/test_rag_redis.py +390 -0
  22. code_graph_builder/graph_updater.py +605 -0
  23. code_graph_builder/guidance/__init__.py +1 -0
  24. code_graph_builder/guidance/agent.py +123 -0
  25. code_graph_builder/guidance/prompts.py +74 -0
  26. code_graph_builder/guidance/toolset.py +264 -0
  27. code_graph_builder/language_spec.py +536 -0
  28. code_graph_builder/mcp/__init__.py +21 -0
  29. code_graph_builder/mcp/api_doc_generator.py +764 -0
  30. code_graph_builder/mcp/file_editor.py +207 -0
  31. code_graph_builder/mcp/pipeline.py +777 -0
  32. code_graph_builder/mcp/server.py +161 -0
  33. code_graph_builder/mcp/tools.py +1800 -0
  34. code_graph_builder/models.py +115 -0
  35. code_graph_builder/parser_loader.py +344 -0
  36. code_graph_builder/parsers/__init__.py +7 -0
  37. code_graph_builder/parsers/call_processor.py +306 -0
  38. code_graph_builder/parsers/call_resolver.py +139 -0
  39. code_graph_builder/parsers/definition_processor.py +796 -0
  40. code_graph_builder/parsers/factory.py +119 -0
  41. code_graph_builder/parsers/import_processor.py +293 -0
  42. code_graph_builder/parsers/structure_processor.py +145 -0
  43. code_graph_builder/parsers/type_inference.py +143 -0
  44. code_graph_builder/parsers/utils.py +134 -0
  45. code_graph_builder/rag/__init__.py +68 -0
  46. code_graph_builder/rag/camel_agent.py +429 -0
  47. code_graph_builder/rag/client.py +298 -0
  48. code_graph_builder/rag/config.py +239 -0
  49. code_graph_builder/rag/cypher_generator.py +67 -0
  50. code_graph_builder/rag/llm_backend.py +210 -0
  51. code_graph_builder/rag/markdown_generator.py +352 -0
  52. code_graph_builder/rag/prompt_templates.py +440 -0
  53. code_graph_builder/rag/rag_engine.py +640 -0
  54. code_graph_builder/rag/review_report.md +172 -0
  55. code_graph_builder/rag/tests/__init__.py +3 -0
  56. code_graph_builder/rag/tests/test_camel_agent.py +313 -0
  57. code_graph_builder/rag/tests/test_client.py +221 -0
  58. code_graph_builder/rag/tests/test_config.py +177 -0
  59. code_graph_builder/rag/tests/test_markdown_generator.py +240 -0
  60. code_graph_builder/rag/tests/test_prompt_templates.py +160 -0
  61. code_graph_builder/services/__init__.py +39 -0
  62. code_graph_builder/services/graph_service.py +465 -0
  63. code_graph_builder/services/kuzu_service.py +665 -0
  64. code_graph_builder/services/memory_service.py +171 -0
  65. code_graph_builder/settings.py +75 -0
  66. code_graph_builder/tests/ACCEPTANCE_CRITERIA_PHASE2.md +401 -0
  67. code_graph_builder/tests/__init__.py +1 -0
  68. code_graph_builder/tests/run_acceptance_check.py +378 -0
  69. code_graph_builder/tests/test_api_find.py +231 -0
  70. code_graph_builder/tests/test_api_find_integration.py +226 -0
  71. code_graph_builder/tests/test_basic.py +78 -0
  72. code_graph_builder/tests/test_c_api_extraction.py +388 -0
  73. code_graph_builder/tests/test_call_resolution_scenarios.py +504 -0
  74. code_graph_builder/tests/test_embedder.py +411 -0
  75. code_graph_builder/tests/test_integration_semantic.py +434 -0
  76. code_graph_builder/tests/test_mcp_protocol.py +298 -0
  77. code_graph_builder/tests/test_mcp_user_flow.py +190 -0
  78. code_graph_builder/tests/test_rag.py +404 -0
  79. code_graph_builder/tests/test_settings.py +135 -0
  80. code_graph_builder/tests/test_step1_graph_build.py +264 -0
  81. code_graph_builder/tests/test_step2_api_docs.py +323 -0
  82. code_graph_builder/tests/test_step3_embedding.py +278 -0
  83. code_graph_builder/tests/test_vector_store.py +552 -0
  84. code_graph_builder/tools/__init__.py +40 -0
  85. code_graph_builder/tools/graph_query.py +495 -0
  86. code_graph_builder/tools/semantic_search.py +387 -0
  87. code_graph_builder/types.py +333 -0
  88. code_graph_builder/utils/__init__.py +0 -0
  89. code_graph_builder/utils/path_utils.py +30 -0
  90. code_graph_builder-0.2.0.dist-info/METADATA +321 -0
  91. code_graph_builder-0.2.0.dist-info/RECORD +93 -0
  92. code_graph_builder-0.2.0.dist-info/WHEEL +4 -0
  93. code_graph_builder-0.2.0.dist-info/entry_points.txt +3 -0
@@ -0,0 +1,115 @@
1
+ """Code Graph Builder - Data Models."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from dataclasses import dataclass, field
6
+ from pathlib import Path
7
+ from typing import TYPE_CHECKING, Callable, NamedTuple
8
+
9
+ from .constants import SupportedLanguage
10
+
11
+ if TYPE_CHECKING:
12
+ from tree_sitter import Node
13
+
14
+
15
+ @dataclass(frozen=True)
16
+ class LanguageSpec:
17
+ """Specification for a programming language."""
18
+
19
+ language: SupportedLanguage | str
20
+ file_extensions: tuple[str, ...]
21
+ function_node_types: tuple[str, ...]
22
+ class_node_types: tuple[str, ...]
23
+ module_node_types: tuple[str, ...]
24
+ call_node_types: tuple[str, ...] = ()
25
+ import_node_types: tuple[str, ...] = ()
26
+ import_from_node_types: tuple[str, ...] = ()
27
+ name_field: str = "name"
28
+ body_field: str = "body"
29
+ package_indicators: tuple[str, ...] = ()
30
+ function_query: str | None = None
31
+ class_query: str | None = None
32
+ call_query: str | None = None
33
+ typedef_query: str | None = None
34
+ macro_query: str | None = None
35
+
36
+
37
+ class FQNSpec(NamedTuple):
38
+ """Specification for building fully qualified names."""
39
+
40
+ scope_node_types: frozenset[str]
41
+ function_node_types: frozenset[str]
42
+ get_name: Callable[["Node"], str | None]
43
+ file_to_module_parts: Callable[[Path, Path], list[str]]
44
+
45
+
46
+ @dataclass
47
+ class Dependency:
48
+ """Represents a project dependency."""
49
+
50
+ name: str
51
+ spec: str
52
+ properties: dict[str, str] = field(default_factory=dict)
53
+
54
+
55
+ @dataclass
56
+ class GraphNode:
57
+ """Represents a node in the graph."""
58
+
59
+ node_id: int
60
+ labels: list[str]
61
+ properties: dict[str, PropertyValue]
62
+
63
+
64
+ @dataclass
65
+ class GraphRelationship:
66
+ """Represents a relationship in the graph."""
67
+
68
+ from_id: int
69
+ to_id: int
70
+ type: str
71
+ properties: dict[str, PropertyValue]
72
+
73
+
74
+ @dataclass
75
+ class FunctionInfo:
76
+ """Information about a function."""
77
+
78
+ name: str
79
+ qualified_name: str
80
+ start_line: int
81
+ end_line: int
82
+ docstring: str | None
83
+ decorators: list[str]
84
+ is_method: bool
85
+ parent_class: str | None
86
+ return_type: str | None = None
87
+ parameters: list[str] | None = None
88
+ signature: str | None = None
89
+ visibility: str | None = None
90
+
91
+
92
+ @dataclass
93
+ class ClassInfo:
94
+ """Information about a class."""
95
+
96
+ name: str
97
+ qualified_name: str
98
+ start_line: int
99
+ end_line: int
100
+ parent_classes: list[str]
101
+ decorators: list[str]
102
+
103
+
104
+ @dataclass
105
+ class CallInfo:
106
+ """Information about a function call."""
107
+
108
+ caller_qualified_name: str
109
+ callee_name: str
110
+ callee_qualified_name: str | None
111
+ line_number: int
112
+
113
+
114
+ # Type alias for property values
115
+ PropertyValue = str | int | float | bool | list[str] | None
@@ -0,0 +1,344 @@
1
+ """Code Graph Builder - Parser Loader."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import importlib
6
+ import subprocess
7
+ import sys
8
+ from copy import deepcopy
9
+ from pathlib import Path
10
+ from typing import TYPE_CHECKING
11
+
12
+ from loguru import logger
13
+ from tree_sitter import Language, Parser, Query
14
+
15
+ from . import constants as cs
16
+ from .language_spec import LANGUAGE_SPECS, LanguageSpec
17
+ from .types import LanguageImport, LanguageLoader, LanguageQueries
18
+
19
+ if TYPE_CHECKING:
20
+ pass
21
+
22
+
23
+ # Log messages
24
+ BUILDING_BINDINGS = "Building Python bindings for {lang}..."
25
+ BUILD_FAILED = "Failed to build {lang} bindings: stdout={stdout}, stderr={stderr}"
26
+ BUILD_SUCCESS = "Successfully built {lang} bindings"
27
+ IMPORTING_MODULE = "Attempting to import module: {module}"
28
+ LOADED_FROM_SUBMODULE = "Successfully loaded {lang} from submodule bindings using {attr}"
29
+ NO_LANG_ATTR = "Module {module} imported but has no language attribute. Available: {available}"
30
+ SUBMODULE_LOAD_FAILED = "Failed to load {lang} from submodule bindings: {error}"
31
+ LIB_NOT_AVAILABLE = "Tree-sitter library for {lang} not available."
32
+ LOCALS_QUERY_FAILED = "Failed to create locals query for {lang}: {error}"
33
+ GRAMMAR_LOADED = "Successfully loaded {lang} grammar."
34
+ GRAMMAR_LOAD_FAILED = "Failed to load {lang} grammar: {error}"
35
+ INITIALIZED_PARSERS = "Initialized parsers for: {languages}"
36
+ NO_LANGUAGES = "No language parsers could be loaded. Please install tree-sitter language packages."
37
+
38
+
39
+ def _try_load_from_submodule(lang_name: cs.SupportedLanguage) -> LanguageLoader:
40
+ """Try to load language from submodule bindings."""
41
+ submodule_path = Path(cs.GRAMMARS_DIR) / f"{cs.TREE_SITTER_PREFIX}{lang_name}"
42
+ python_bindings_path = (
43
+ submodule_path / cs.BINDINGS_DIR / cs.SupportedLanguage.PYTHON
44
+ )
45
+
46
+ if not python_bindings_path.exists():
47
+ return None
48
+
49
+ python_bindings_str = str(python_bindings_path)
50
+ try:
51
+ if python_bindings_str not in sys.path:
52
+ sys.path.insert(0, python_bindings_str)
53
+
54
+ try:
55
+ module_name = f"{cs.TREE_SITTER_MODULE_PREFIX}{lang_name.replace('-', '_')}"
56
+
57
+ setup_py_path = submodule_path / cs.SETUP_PY
58
+ if setup_py_path.exists():
59
+ logger.debug(BUILDING_BINDINGS.format(lang=lang_name))
60
+ result = subprocess.run(
61
+ [sys.executable, cs.SETUP_PY, cs.BUILD_EXT_CMD, cs.INPLACE_FLAG],
62
+ check=False,
63
+ cwd=str(submodule_path),
64
+ capture_output=True,
65
+ text=True,
66
+ )
67
+
68
+ if result.returncode != 0:
69
+ logger.debug(
70
+ BUILD_FAILED.format(
71
+ lang=lang_name, stdout=result.stdout, stderr=result.stderr
72
+ )
73
+ )
74
+ return None
75
+ logger.debug(BUILD_SUCCESS.format(lang=lang_name))
76
+
77
+ logger.debug(IMPORTING_MODULE.format(module=module_name))
78
+ module = importlib.import_module(module_name)
79
+
80
+ language_attrs: list[str] = [
81
+ cs.QUERY_LANGUAGE,
82
+ f"{cs.LANG_ATTR_PREFIX}{lang_name}",
83
+ f"{cs.LANG_ATTR_PREFIX}{lang_name.replace('-', '_')}",
84
+ ]
85
+
86
+ for attr_name in language_attrs:
87
+ if hasattr(module, attr_name):
88
+ logger.debug(
89
+ LOADED_FROM_SUBMODULE.format(lang=lang_name, attr=attr_name)
90
+ )
91
+ loader: LanguageLoader = getattr(module, attr_name)
92
+ return loader
93
+
94
+ logger.debug(
95
+ NO_LANG_ATTR.format(module=module_name, available=dir(module))
96
+ )
97
+
98
+ finally:
99
+ if python_bindings_str in sys.path:
100
+ sys.path.remove(python_bindings_str)
101
+
102
+ except Exception as e:
103
+ logger.debug(SUBMODULE_LOAD_FAILED.format(lang=lang_name, error=e))
104
+
105
+ return None
106
+
107
+
108
+ def _try_import_language(
109
+ module_path: str, attr_name: str, lang_name: cs.SupportedLanguage
110
+ ) -> LanguageLoader:
111
+ """Try to import language from pip package."""
112
+ try:
113
+ module = importlib.import_module(module_path)
114
+ loader: LanguageLoader = getattr(module, attr_name)
115
+ return loader
116
+ except ImportError:
117
+ return _try_load_from_submodule(lang_name)
118
+
119
+
120
+ def _import_language_loaders() -> dict[cs.SupportedLanguage, LanguageLoader]:
121
+ """Import all language loaders."""
122
+ language_imports: list[LanguageImport] = [
123
+ LanguageImport(
124
+ cs.SupportedLanguage.PYTHON,
125
+ cs.TreeSitterModule.PYTHON,
126
+ cs.QUERY_LANGUAGE,
127
+ cs.SupportedLanguage.PYTHON,
128
+ ),
129
+ LanguageImport(
130
+ cs.SupportedLanguage.JS,
131
+ cs.TreeSitterModule.JS,
132
+ cs.QUERY_LANGUAGE,
133
+ cs.SupportedLanguage.JS,
134
+ ),
135
+ LanguageImport(
136
+ cs.SupportedLanguage.TS,
137
+ cs.TreeSitterModule.TS,
138
+ cs.LANG_ATTR_TYPESCRIPT,
139
+ cs.SupportedLanguage.TS,
140
+ ),
141
+ LanguageImport(
142
+ cs.SupportedLanguage.RUST,
143
+ cs.TreeSitterModule.RUST,
144
+ cs.QUERY_LANGUAGE,
145
+ cs.SupportedLanguage.RUST,
146
+ ),
147
+ LanguageImport(
148
+ cs.SupportedLanguage.GO,
149
+ cs.TreeSitterModule.GO,
150
+ cs.QUERY_LANGUAGE,
151
+ cs.SupportedLanguage.GO,
152
+ ),
153
+ LanguageImport(
154
+ cs.SupportedLanguage.SCALA,
155
+ cs.TreeSitterModule.SCALA,
156
+ cs.QUERY_LANGUAGE,
157
+ cs.SupportedLanguage.SCALA,
158
+ ),
159
+ LanguageImport(
160
+ cs.SupportedLanguage.JAVA,
161
+ cs.TreeSitterModule.JAVA,
162
+ cs.QUERY_LANGUAGE,
163
+ cs.SupportedLanguage.JAVA,
164
+ ),
165
+ LanguageImport(
166
+ cs.SupportedLanguage.C,
167
+ cs.TreeSitterModule.C,
168
+ cs.QUERY_LANGUAGE,
169
+ cs.SupportedLanguage.C,
170
+ ),
171
+ LanguageImport(
172
+ cs.SupportedLanguage.CPP,
173
+ cs.TreeSitterModule.CPP,
174
+ cs.QUERY_LANGUAGE,
175
+ cs.SupportedLanguage.CPP,
176
+ ),
177
+ LanguageImport(
178
+ cs.SupportedLanguage.LUA,
179
+ cs.TreeSitterModule.LUA,
180
+ cs.QUERY_LANGUAGE,
181
+ cs.SupportedLanguage.LUA,
182
+ ),
183
+ ]
184
+
185
+ loaders: dict[cs.SupportedLanguage, LanguageLoader] = {
186
+ lang_import.lang_key: _try_import_language(
187
+ lang_import.module_path,
188
+ lang_import.attr_name,
189
+ lang_import.submodule_name,
190
+ )
191
+ for lang_import in language_imports
192
+ }
193
+ for lang_key in LANGUAGE_SPECS:
194
+ lang_name = cs.SupportedLanguage(lang_key)
195
+ if lang_name not in loaders or loaders[lang_name] is None:
196
+ loaders[lang_name] = _try_load_from_submodule(lang_name)
197
+
198
+ return loaders
199
+
200
+
201
+ _language_loaders = _import_language_loaders()
202
+
203
+ LANGUAGE_LIBRARIES: dict[cs.SupportedLanguage, LanguageLoader] = _language_loaders
204
+
205
+
206
+ def _build_query_pattern(node_types: tuple[str, ...], capture_name: str) -> str:
207
+ """Build a query pattern for the given node types."""
208
+ return " ".join([f"({node_type}) @{capture_name}" for node_type in node_types])
209
+
210
+
211
+ def _get_locals_pattern(lang_name: cs.SupportedLanguage) -> str | None:
212
+ """Get the locals query pattern for a language."""
213
+ match lang_name:
214
+ case cs.SupportedLanguage.JS:
215
+ return cs.JS_LOCALS_PATTERN
216
+ case cs.SupportedLanguage.TS:
217
+ return cs.TS_LOCALS_PATTERN
218
+ case _:
219
+ return None
220
+
221
+
222
+ def _build_combined_import_pattern(lang_config: LanguageSpec) -> str:
223
+ """Build combined import pattern for a language."""
224
+ import_patterns = _build_query_pattern(
225
+ lang_config.import_node_types, cs.CAPTURE_IMPORT
226
+ )
227
+ import_from_patterns = _build_query_pattern(
228
+ lang_config.import_from_node_types, cs.CAPTURE_IMPORT_FROM
229
+ )
230
+
231
+ all_patterns: list[str] = []
232
+ if import_patterns.strip():
233
+ all_patterns.append(import_patterns)
234
+ if import_from_patterns.strip() and import_from_patterns != import_patterns:
235
+ all_patterns.append(import_from_patterns)
236
+ return " ".join(all_patterns)
237
+
238
+
239
+ def _create_optional_query(language: Language, pattern: str | None) -> Query | None:
240
+ """Create a query if pattern is provided."""
241
+ return Query(language, pattern) if pattern else None
242
+
243
+
244
+ def _create_locals_query(
245
+ language: Language, lang_name: cs.SupportedLanguage
246
+ ) -> Query | None:
247
+ """Create a locals query for a language."""
248
+ locals_pattern = _get_locals_pattern(lang_name)
249
+ if not locals_pattern:
250
+ return None
251
+ try:
252
+ return Query(language, locals_pattern)
253
+ except Exception as e:
254
+ logger.debug(LOCALS_QUERY_FAILED.format(lang=lang_name, error=e))
255
+ return None
256
+
257
+
258
+ def _create_language_queries(
259
+ language: Language,
260
+ parser: Parser,
261
+ lang_config: LanguageSpec,
262
+ lang_name: cs.SupportedLanguage,
263
+ ) -> LanguageQueries:
264
+ """Create all queries for a language."""
265
+ function_patterns = lang_config.function_query or _build_query_pattern(
266
+ lang_config.function_node_types, cs.CAPTURE_FUNCTION
267
+ )
268
+ class_patterns = lang_config.class_query or _build_query_pattern(
269
+ lang_config.class_node_types, cs.CAPTURE_CLASS
270
+ )
271
+ call_patterns = lang_config.call_query or _build_query_pattern(
272
+ lang_config.call_node_types, cs.CAPTURE_CALL
273
+ )
274
+ combined_import_patterns = _build_combined_import_pattern(lang_config)
275
+
276
+ # Build optional typedef/macro queries (currently C-specific)
277
+ typedef_query = _create_optional_query(language, lang_config.typedef_query)
278
+ macro_query = _create_optional_query(language, lang_config.macro_query)
279
+
280
+ return LanguageQueries(
281
+ functions=_create_optional_query(language, function_patterns),
282
+ classes=_create_optional_query(language, class_patterns),
283
+ calls=_create_optional_query(language, call_patterns),
284
+ imports=_create_optional_query(language, combined_import_patterns),
285
+ locals=_create_locals_query(language, lang_name),
286
+ typedefs=typedef_query,
287
+ macros=macro_query,
288
+ config=lang_config,
289
+ language=language,
290
+ parser=parser,
291
+ )
292
+
293
+
294
+ def _process_language(
295
+ lang_name: cs.SupportedLanguage,
296
+ lang_config: LanguageSpec,
297
+ parsers: dict[cs.SupportedLanguage, Parser],
298
+ queries: dict[cs.SupportedLanguage, LanguageQueries],
299
+ ) -> bool:
300
+ """Process a single language and add to parsers/queries dicts."""
301
+ lang_lib = LANGUAGE_LIBRARIES.get(lang_name)
302
+ if not lang_lib:
303
+ logger.debug(LIB_NOT_AVAILABLE.format(lang=lang_name))
304
+ return False
305
+
306
+ try:
307
+ language = Language(lang_lib())
308
+ parser = Parser(language)
309
+ parsers[lang_name] = parser
310
+ queries[lang_name] = _create_language_queries(
311
+ language, parser, lang_config, lang_name
312
+ )
313
+ logger.success(GRAMMAR_LOADED.format(lang=lang_name))
314
+ return True
315
+ except Exception as e:
316
+ logger.warning(GRAMMAR_LOAD_FAILED.format(lang=lang_name, error=e))
317
+ return False
318
+
319
+
320
+ def load_parsers() -> tuple[
321
+ dict[cs.SupportedLanguage, Parser], dict[cs.SupportedLanguage, LanguageQueries]
322
+ ]:
323
+ """Load all available Tree-sitter parsers.
324
+
325
+ Returns:
326
+ Tuple of (parsers dict, queries dict)
327
+
328
+ Raises:
329
+ RuntimeError: If no language parsers could be loaded
330
+ """
331
+ parsers: dict[cs.SupportedLanguage, Parser] = {}
332
+ queries: dict[cs.SupportedLanguage, LanguageQueries] = {}
333
+ available_languages: list[cs.SupportedLanguage] = []
334
+
335
+ for lang_key, lang_config in deepcopy(LANGUAGE_SPECS).items():
336
+ lang_name = cs.SupportedLanguage(lang_key)
337
+ if _process_language(lang_name, lang_config, parsers, queries):
338
+ available_languages.append(lang_name)
339
+
340
+ if not available_languages:
341
+ raise RuntimeError(NO_LANGUAGES)
342
+
343
+ logger.info(INITIALIZED_PARSERS.format(languages=", ".join(available_languages)))
344
+ return parsers, queries
@@ -0,0 +1,7 @@
1
+ """Code Graph Builder - Parsers."""
2
+
3
+ from .factory import ProcessorFactory
4
+ from .structure_processor import StructureProcessor
5
+ from .definition_processor import DefinitionProcessor
6
+
7
+ __all__ = ["ProcessorFactory", "StructureProcessor", "DefinitionProcessor"]