aiecs 1.5.1__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.
- aiecs/__init__.py +72 -0
- aiecs/__main__.py +41 -0
- aiecs/aiecs_client.py +469 -0
- aiecs/application/__init__.py +10 -0
- aiecs/application/executors/__init__.py +10 -0
- aiecs/application/executors/operation_executor.py +363 -0
- aiecs/application/knowledge_graph/__init__.py +7 -0
- aiecs/application/knowledge_graph/builder/__init__.py +37 -0
- aiecs/application/knowledge_graph/builder/document_builder.py +375 -0
- aiecs/application/knowledge_graph/builder/graph_builder.py +356 -0
- aiecs/application/knowledge_graph/builder/schema_mapping.py +531 -0
- aiecs/application/knowledge_graph/builder/structured_pipeline.py +443 -0
- aiecs/application/knowledge_graph/builder/text_chunker.py +319 -0
- aiecs/application/knowledge_graph/extractors/__init__.py +27 -0
- aiecs/application/knowledge_graph/extractors/base.py +100 -0
- aiecs/application/knowledge_graph/extractors/llm_entity_extractor.py +327 -0
- aiecs/application/knowledge_graph/extractors/llm_relation_extractor.py +349 -0
- aiecs/application/knowledge_graph/extractors/ner_entity_extractor.py +244 -0
- aiecs/application/knowledge_graph/fusion/__init__.py +23 -0
- aiecs/application/knowledge_graph/fusion/entity_deduplicator.py +387 -0
- aiecs/application/knowledge_graph/fusion/entity_linker.py +343 -0
- aiecs/application/knowledge_graph/fusion/knowledge_fusion.py +580 -0
- aiecs/application/knowledge_graph/fusion/relation_deduplicator.py +189 -0
- aiecs/application/knowledge_graph/pattern_matching/__init__.py +21 -0
- aiecs/application/knowledge_graph/pattern_matching/pattern_matcher.py +344 -0
- aiecs/application/knowledge_graph/pattern_matching/query_executor.py +378 -0
- aiecs/application/knowledge_graph/profiling/__init__.py +12 -0
- aiecs/application/knowledge_graph/profiling/query_plan_visualizer.py +199 -0
- aiecs/application/knowledge_graph/profiling/query_profiler.py +223 -0
- aiecs/application/knowledge_graph/reasoning/__init__.py +27 -0
- aiecs/application/knowledge_graph/reasoning/evidence_synthesis.py +347 -0
- aiecs/application/knowledge_graph/reasoning/inference_engine.py +504 -0
- aiecs/application/knowledge_graph/reasoning/logic_form_parser.py +167 -0
- aiecs/application/knowledge_graph/reasoning/logic_parser/__init__.py +79 -0
- aiecs/application/knowledge_graph/reasoning/logic_parser/ast_builder.py +513 -0
- aiecs/application/knowledge_graph/reasoning/logic_parser/ast_nodes.py +630 -0
- aiecs/application/knowledge_graph/reasoning/logic_parser/ast_validator.py +654 -0
- aiecs/application/knowledge_graph/reasoning/logic_parser/error_handler.py +477 -0
- aiecs/application/knowledge_graph/reasoning/logic_parser/parser.py +390 -0
- aiecs/application/knowledge_graph/reasoning/logic_parser/query_context.py +217 -0
- aiecs/application/knowledge_graph/reasoning/logic_query_integration.py +169 -0
- aiecs/application/knowledge_graph/reasoning/query_planner.py +872 -0
- aiecs/application/knowledge_graph/reasoning/reasoning_engine.py +554 -0
- aiecs/application/knowledge_graph/retrieval/__init__.py +19 -0
- aiecs/application/knowledge_graph/retrieval/retrieval_strategies.py +596 -0
- aiecs/application/knowledge_graph/search/__init__.py +59 -0
- aiecs/application/knowledge_graph/search/hybrid_search.py +423 -0
- aiecs/application/knowledge_graph/search/reranker.py +295 -0
- aiecs/application/knowledge_graph/search/reranker_strategies.py +553 -0
- aiecs/application/knowledge_graph/search/text_similarity.py +398 -0
- aiecs/application/knowledge_graph/traversal/__init__.py +15 -0
- aiecs/application/knowledge_graph/traversal/enhanced_traversal.py +329 -0
- aiecs/application/knowledge_graph/traversal/path_scorer.py +269 -0
- aiecs/application/knowledge_graph/validators/__init__.py +13 -0
- aiecs/application/knowledge_graph/validators/relation_validator.py +189 -0
- aiecs/application/knowledge_graph/visualization/__init__.py +11 -0
- aiecs/application/knowledge_graph/visualization/graph_visualizer.py +321 -0
- aiecs/common/__init__.py +9 -0
- aiecs/common/knowledge_graph/__init__.py +17 -0
- aiecs/common/knowledge_graph/runnable.py +484 -0
- aiecs/config/__init__.py +16 -0
- aiecs/config/config.py +498 -0
- aiecs/config/graph_config.py +137 -0
- aiecs/config/registry.py +23 -0
- aiecs/core/__init__.py +46 -0
- aiecs/core/interface/__init__.py +34 -0
- aiecs/core/interface/execution_interface.py +152 -0
- aiecs/core/interface/storage_interface.py +171 -0
- aiecs/domain/__init__.py +289 -0
- aiecs/domain/agent/__init__.py +189 -0
- aiecs/domain/agent/base_agent.py +697 -0
- aiecs/domain/agent/exceptions.py +103 -0
- aiecs/domain/agent/graph_aware_mixin.py +559 -0
- aiecs/domain/agent/hybrid_agent.py +490 -0
- aiecs/domain/agent/integration/__init__.py +26 -0
- aiecs/domain/agent/integration/context_compressor.py +222 -0
- aiecs/domain/agent/integration/context_engine_adapter.py +252 -0
- aiecs/domain/agent/integration/retry_policy.py +219 -0
- aiecs/domain/agent/integration/role_config.py +213 -0
- aiecs/domain/agent/knowledge_aware_agent.py +646 -0
- aiecs/domain/agent/lifecycle.py +296 -0
- aiecs/domain/agent/llm_agent.py +300 -0
- aiecs/domain/agent/memory/__init__.py +12 -0
- aiecs/domain/agent/memory/conversation.py +197 -0
- aiecs/domain/agent/migration/__init__.py +14 -0
- aiecs/domain/agent/migration/conversion.py +160 -0
- aiecs/domain/agent/migration/legacy_wrapper.py +90 -0
- aiecs/domain/agent/models.py +317 -0
- aiecs/domain/agent/observability.py +407 -0
- aiecs/domain/agent/persistence.py +289 -0
- aiecs/domain/agent/prompts/__init__.py +29 -0
- aiecs/domain/agent/prompts/builder.py +161 -0
- aiecs/domain/agent/prompts/formatters.py +189 -0
- aiecs/domain/agent/prompts/template.py +255 -0
- aiecs/domain/agent/registry.py +260 -0
- aiecs/domain/agent/tool_agent.py +257 -0
- aiecs/domain/agent/tools/__init__.py +12 -0
- aiecs/domain/agent/tools/schema_generator.py +221 -0
- aiecs/domain/community/__init__.py +155 -0
- aiecs/domain/community/agent_adapter.py +477 -0
- aiecs/domain/community/analytics.py +481 -0
- aiecs/domain/community/collaborative_workflow.py +642 -0
- aiecs/domain/community/communication_hub.py +645 -0
- aiecs/domain/community/community_builder.py +320 -0
- aiecs/domain/community/community_integration.py +800 -0
- aiecs/domain/community/community_manager.py +813 -0
- aiecs/domain/community/decision_engine.py +879 -0
- aiecs/domain/community/exceptions.py +225 -0
- aiecs/domain/community/models/__init__.py +33 -0
- aiecs/domain/community/models/community_models.py +268 -0
- aiecs/domain/community/resource_manager.py +457 -0
- aiecs/domain/community/shared_context_manager.py +603 -0
- aiecs/domain/context/__init__.py +58 -0
- aiecs/domain/context/context_engine.py +989 -0
- aiecs/domain/context/conversation_models.py +354 -0
- aiecs/domain/context/graph_memory.py +467 -0
- aiecs/domain/execution/__init__.py +12 -0
- aiecs/domain/execution/model.py +57 -0
- aiecs/domain/knowledge_graph/__init__.py +19 -0
- aiecs/domain/knowledge_graph/models/__init__.py +52 -0
- aiecs/domain/knowledge_graph/models/entity.py +130 -0
- aiecs/domain/knowledge_graph/models/evidence.py +194 -0
- aiecs/domain/knowledge_graph/models/inference_rule.py +186 -0
- aiecs/domain/knowledge_graph/models/path.py +179 -0
- aiecs/domain/knowledge_graph/models/path_pattern.py +173 -0
- aiecs/domain/knowledge_graph/models/query.py +272 -0
- aiecs/domain/knowledge_graph/models/query_plan.py +187 -0
- aiecs/domain/knowledge_graph/models/relation.py +136 -0
- aiecs/domain/knowledge_graph/schema/__init__.py +23 -0
- aiecs/domain/knowledge_graph/schema/entity_type.py +135 -0
- aiecs/domain/knowledge_graph/schema/graph_schema.py +271 -0
- aiecs/domain/knowledge_graph/schema/property_schema.py +155 -0
- aiecs/domain/knowledge_graph/schema/relation_type.py +171 -0
- aiecs/domain/knowledge_graph/schema/schema_manager.py +496 -0
- aiecs/domain/knowledge_graph/schema/type_enums.py +205 -0
- aiecs/domain/task/__init__.py +13 -0
- aiecs/domain/task/dsl_processor.py +613 -0
- aiecs/domain/task/model.py +62 -0
- aiecs/domain/task/task_context.py +268 -0
- aiecs/infrastructure/__init__.py +24 -0
- aiecs/infrastructure/graph_storage/__init__.py +11 -0
- aiecs/infrastructure/graph_storage/base.py +601 -0
- aiecs/infrastructure/graph_storage/batch_operations.py +449 -0
- aiecs/infrastructure/graph_storage/cache.py +429 -0
- aiecs/infrastructure/graph_storage/distributed.py +226 -0
- aiecs/infrastructure/graph_storage/error_handling.py +390 -0
- aiecs/infrastructure/graph_storage/graceful_degradation.py +306 -0
- aiecs/infrastructure/graph_storage/health_checks.py +378 -0
- aiecs/infrastructure/graph_storage/in_memory.py +514 -0
- aiecs/infrastructure/graph_storage/index_optimization.py +483 -0
- aiecs/infrastructure/graph_storage/lazy_loading.py +410 -0
- aiecs/infrastructure/graph_storage/metrics.py +357 -0
- aiecs/infrastructure/graph_storage/migration.py +413 -0
- aiecs/infrastructure/graph_storage/pagination.py +471 -0
- aiecs/infrastructure/graph_storage/performance_monitoring.py +466 -0
- aiecs/infrastructure/graph_storage/postgres.py +871 -0
- aiecs/infrastructure/graph_storage/query_optimizer.py +635 -0
- aiecs/infrastructure/graph_storage/schema_cache.py +290 -0
- aiecs/infrastructure/graph_storage/sqlite.py +623 -0
- aiecs/infrastructure/graph_storage/streaming.py +495 -0
- aiecs/infrastructure/messaging/__init__.py +13 -0
- aiecs/infrastructure/messaging/celery_task_manager.py +383 -0
- aiecs/infrastructure/messaging/websocket_manager.py +298 -0
- aiecs/infrastructure/monitoring/__init__.py +34 -0
- aiecs/infrastructure/monitoring/executor_metrics.py +174 -0
- aiecs/infrastructure/monitoring/global_metrics_manager.py +213 -0
- aiecs/infrastructure/monitoring/structured_logger.py +48 -0
- aiecs/infrastructure/monitoring/tracing_manager.py +410 -0
- aiecs/infrastructure/persistence/__init__.py +24 -0
- aiecs/infrastructure/persistence/context_engine_client.py +187 -0
- aiecs/infrastructure/persistence/database_manager.py +333 -0
- aiecs/infrastructure/persistence/file_storage.py +754 -0
- aiecs/infrastructure/persistence/redis_client.py +220 -0
- aiecs/llm/__init__.py +86 -0
- aiecs/llm/callbacks/__init__.py +11 -0
- aiecs/llm/callbacks/custom_callbacks.py +264 -0
- aiecs/llm/client_factory.py +420 -0
- aiecs/llm/clients/__init__.py +33 -0
- aiecs/llm/clients/base_client.py +193 -0
- aiecs/llm/clients/googleai_client.py +181 -0
- aiecs/llm/clients/openai_client.py +131 -0
- aiecs/llm/clients/vertex_client.py +437 -0
- aiecs/llm/clients/xai_client.py +184 -0
- aiecs/llm/config/__init__.py +51 -0
- aiecs/llm/config/config_loader.py +275 -0
- aiecs/llm/config/config_validator.py +236 -0
- aiecs/llm/config/model_config.py +151 -0
- aiecs/llm/utils/__init__.py +10 -0
- aiecs/llm/utils/validate_config.py +91 -0
- aiecs/main.py +363 -0
- aiecs/scripts/__init__.py +3 -0
- aiecs/scripts/aid/VERSION_MANAGEMENT.md +97 -0
- aiecs/scripts/aid/__init__.py +19 -0
- aiecs/scripts/aid/version_manager.py +215 -0
- aiecs/scripts/dependance_check/DEPENDENCY_SYSTEM_SUMMARY.md +242 -0
- aiecs/scripts/dependance_check/README_DEPENDENCY_CHECKER.md +310 -0
- aiecs/scripts/dependance_check/__init__.py +17 -0
- aiecs/scripts/dependance_check/dependency_checker.py +938 -0
- aiecs/scripts/dependance_check/dependency_fixer.py +391 -0
- aiecs/scripts/dependance_check/download_nlp_data.py +396 -0
- aiecs/scripts/dependance_check/quick_dependency_check.py +270 -0
- aiecs/scripts/dependance_check/setup_nlp_data.sh +217 -0
- aiecs/scripts/dependance_patch/__init__.py +7 -0
- aiecs/scripts/dependance_patch/fix_weasel/README_WEASEL_PATCH.md +126 -0
- aiecs/scripts/dependance_patch/fix_weasel/__init__.py +11 -0
- aiecs/scripts/dependance_patch/fix_weasel/fix_weasel_validator.py +128 -0
- aiecs/scripts/dependance_patch/fix_weasel/fix_weasel_validator.sh +82 -0
- aiecs/scripts/dependance_patch/fix_weasel/patch_weasel_library.sh +188 -0
- aiecs/scripts/dependance_patch/fix_weasel/run_weasel_patch.sh +41 -0
- aiecs/scripts/tools_develop/README.md +449 -0
- aiecs/scripts/tools_develop/TOOL_AUTO_DISCOVERY.md +234 -0
- aiecs/scripts/tools_develop/__init__.py +21 -0
- aiecs/scripts/tools_develop/check_type_annotations.py +259 -0
- aiecs/scripts/tools_develop/validate_tool_schemas.py +422 -0
- aiecs/scripts/tools_develop/verify_tools.py +356 -0
- aiecs/tasks/__init__.py +1 -0
- aiecs/tasks/worker.py +172 -0
- aiecs/tools/__init__.py +299 -0
- aiecs/tools/apisource/__init__.py +99 -0
- aiecs/tools/apisource/intelligence/__init__.py +19 -0
- aiecs/tools/apisource/intelligence/data_fusion.py +381 -0
- aiecs/tools/apisource/intelligence/query_analyzer.py +413 -0
- aiecs/tools/apisource/intelligence/search_enhancer.py +388 -0
- aiecs/tools/apisource/monitoring/__init__.py +9 -0
- aiecs/tools/apisource/monitoring/metrics.py +303 -0
- aiecs/tools/apisource/providers/__init__.py +115 -0
- aiecs/tools/apisource/providers/base.py +664 -0
- aiecs/tools/apisource/providers/census.py +401 -0
- aiecs/tools/apisource/providers/fred.py +564 -0
- aiecs/tools/apisource/providers/newsapi.py +412 -0
- aiecs/tools/apisource/providers/worldbank.py +357 -0
- aiecs/tools/apisource/reliability/__init__.py +12 -0
- aiecs/tools/apisource/reliability/error_handler.py +375 -0
- aiecs/tools/apisource/reliability/fallback_strategy.py +391 -0
- aiecs/tools/apisource/tool.py +850 -0
- aiecs/tools/apisource/utils/__init__.py +9 -0
- aiecs/tools/apisource/utils/validators.py +338 -0
- aiecs/tools/base_tool.py +201 -0
- aiecs/tools/docs/__init__.py +121 -0
- aiecs/tools/docs/ai_document_orchestrator.py +599 -0
- aiecs/tools/docs/ai_document_writer_orchestrator.py +2403 -0
- aiecs/tools/docs/content_insertion_tool.py +1333 -0
- aiecs/tools/docs/document_creator_tool.py +1317 -0
- aiecs/tools/docs/document_layout_tool.py +1166 -0
- aiecs/tools/docs/document_parser_tool.py +994 -0
- aiecs/tools/docs/document_writer_tool.py +1818 -0
- aiecs/tools/knowledge_graph/__init__.py +17 -0
- aiecs/tools/knowledge_graph/graph_reasoning_tool.py +734 -0
- aiecs/tools/knowledge_graph/graph_search_tool.py +923 -0
- aiecs/tools/knowledge_graph/kg_builder_tool.py +476 -0
- aiecs/tools/langchain_adapter.py +542 -0
- aiecs/tools/schema_generator.py +275 -0
- aiecs/tools/search_tool/__init__.py +100 -0
- aiecs/tools/search_tool/analyzers.py +589 -0
- aiecs/tools/search_tool/cache.py +260 -0
- aiecs/tools/search_tool/constants.py +128 -0
- aiecs/tools/search_tool/context.py +216 -0
- aiecs/tools/search_tool/core.py +749 -0
- aiecs/tools/search_tool/deduplicator.py +123 -0
- aiecs/tools/search_tool/error_handler.py +271 -0
- aiecs/tools/search_tool/metrics.py +371 -0
- aiecs/tools/search_tool/rate_limiter.py +178 -0
- aiecs/tools/search_tool/schemas.py +277 -0
- aiecs/tools/statistics/__init__.py +80 -0
- aiecs/tools/statistics/ai_data_analysis_orchestrator.py +643 -0
- aiecs/tools/statistics/ai_insight_generator_tool.py +505 -0
- aiecs/tools/statistics/ai_report_orchestrator_tool.py +694 -0
- aiecs/tools/statistics/data_loader_tool.py +564 -0
- aiecs/tools/statistics/data_profiler_tool.py +658 -0
- aiecs/tools/statistics/data_transformer_tool.py +573 -0
- aiecs/tools/statistics/data_visualizer_tool.py +495 -0
- aiecs/tools/statistics/model_trainer_tool.py +487 -0
- aiecs/tools/statistics/statistical_analyzer_tool.py +459 -0
- aiecs/tools/task_tools/__init__.py +86 -0
- aiecs/tools/task_tools/chart_tool.py +732 -0
- aiecs/tools/task_tools/classfire_tool.py +922 -0
- aiecs/tools/task_tools/image_tool.py +447 -0
- aiecs/tools/task_tools/office_tool.py +684 -0
- aiecs/tools/task_tools/pandas_tool.py +635 -0
- aiecs/tools/task_tools/report_tool.py +635 -0
- aiecs/tools/task_tools/research_tool.py +392 -0
- aiecs/tools/task_tools/scraper_tool.py +715 -0
- aiecs/tools/task_tools/stats_tool.py +688 -0
- aiecs/tools/temp_file_manager.py +130 -0
- aiecs/tools/tool_executor/__init__.py +37 -0
- aiecs/tools/tool_executor/tool_executor.py +881 -0
- aiecs/utils/LLM_output_structor.py +445 -0
- aiecs/utils/__init__.py +34 -0
- aiecs/utils/base_callback.py +47 -0
- aiecs/utils/cache_provider.py +695 -0
- aiecs/utils/execution_utils.py +184 -0
- aiecs/utils/logging.py +1 -0
- aiecs/utils/prompt_loader.py +14 -0
- aiecs/utils/token_usage_repository.py +323 -0
- aiecs/ws/__init__.py +0 -0
- aiecs/ws/socket_server.py +52 -0
- aiecs-1.5.1.dist-info/METADATA +608 -0
- aiecs-1.5.1.dist-info/RECORD +302 -0
- aiecs-1.5.1.dist-info/WHEEL +5 -0
- aiecs-1.5.1.dist-info/entry_points.txt +10 -0
- aiecs-1.5.1.dist-info/licenses/LICENSE +225 -0
- aiecs-1.5.1.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,496 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Schema Manager
|
|
3
|
+
|
|
4
|
+
Service for managing knowledge graph schemas with CRUD operations.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from typing import Optional, List, Dict, Any, Type
|
|
8
|
+
from enum import Enum
|
|
9
|
+
import json
|
|
10
|
+
from pathlib import Path
|
|
11
|
+
from aiecs.domain.knowledge_graph.schema.graph_schema import GraphSchema
|
|
12
|
+
from aiecs.domain.knowledge_graph.schema.entity_type import EntityType
|
|
13
|
+
from aiecs.domain.knowledge_graph.schema.relation_type import RelationType
|
|
14
|
+
from aiecs.domain.knowledge_graph.schema.property_schema import PropertySchema
|
|
15
|
+
from aiecs.domain.knowledge_graph.schema.type_enums import TypeEnumGenerator
|
|
16
|
+
from aiecs.infrastructure.graph_storage.schema_cache import LRUCache
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class SchemaManager:
|
|
20
|
+
"""
|
|
21
|
+
Schema Manager Service
|
|
22
|
+
|
|
23
|
+
Manages knowledge graph schemas with support for:
|
|
24
|
+
- Creating, reading, updating, deleting entity and relation types
|
|
25
|
+
- Schema persistence (save/load from JSON)
|
|
26
|
+
- Schema validation
|
|
27
|
+
- Transaction-like operations (commit/rollback)
|
|
28
|
+
- LRU caching with TTL for performance optimization
|
|
29
|
+
|
|
30
|
+
Example:
|
|
31
|
+
```python
|
|
32
|
+
manager = SchemaManager(cache_size=1000, ttl_seconds=3600)
|
|
33
|
+
|
|
34
|
+
# Add entity type
|
|
35
|
+
person_type = EntityType(name="Person", ...)
|
|
36
|
+
manager.create_entity_type(person_type)
|
|
37
|
+
|
|
38
|
+
# Get entity type (cached)
|
|
39
|
+
person = manager.get_entity_type("Person")
|
|
40
|
+
|
|
41
|
+
# Check cache stats
|
|
42
|
+
stats = manager.get_cache_stats()
|
|
43
|
+
print(f"Cache hit rate: {stats['hit_rate']:.2%}")
|
|
44
|
+
|
|
45
|
+
# Save schema
|
|
46
|
+
manager.save("./schema.json")
|
|
47
|
+
```
|
|
48
|
+
"""
|
|
49
|
+
|
|
50
|
+
def __init__(
|
|
51
|
+
self,
|
|
52
|
+
schema: Optional[GraphSchema] = None,
|
|
53
|
+
cache_size: int = 1000,
|
|
54
|
+
ttl_seconds: Optional[int] = 3600,
|
|
55
|
+
enable_cache: bool = True,
|
|
56
|
+
):
|
|
57
|
+
"""
|
|
58
|
+
Initialize schema manager
|
|
59
|
+
|
|
60
|
+
Args:
|
|
61
|
+
schema: Initial schema (default: empty schema)
|
|
62
|
+
cache_size: Maximum cache size (default: 1000)
|
|
63
|
+
ttl_seconds: Cache TTL in seconds (default: 3600, None = no expiration)
|
|
64
|
+
enable_cache: Whether to enable caching (default: True)
|
|
65
|
+
"""
|
|
66
|
+
self.schema = schema if schema is not None else GraphSchema()
|
|
67
|
+
self._transaction_schema: Optional[GraphSchema] = None
|
|
68
|
+
|
|
69
|
+
# Initialize caches
|
|
70
|
+
self._enable_cache = enable_cache
|
|
71
|
+
if enable_cache:
|
|
72
|
+
self._entity_type_cache: LRUCache[EntityType] = LRUCache(
|
|
73
|
+
max_size=cache_size, ttl_seconds=ttl_seconds
|
|
74
|
+
)
|
|
75
|
+
self._relation_type_cache: LRUCache[RelationType] = LRUCache(
|
|
76
|
+
max_size=cache_size, ttl_seconds=ttl_seconds
|
|
77
|
+
)
|
|
78
|
+
self._property_cache: LRUCache[PropertySchema] = LRUCache(
|
|
79
|
+
max_size=cache_size, ttl_seconds=ttl_seconds
|
|
80
|
+
)
|
|
81
|
+
else:
|
|
82
|
+
self._entity_type_cache = None
|
|
83
|
+
self._relation_type_cache = None
|
|
84
|
+
self._property_cache = None
|
|
85
|
+
|
|
86
|
+
# Entity Type Operations
|
|
87
|
+
|
|
88
|
+
def create_entity_type(self, entity_type: EntityType) -> None:
|
|
89
|
+
"""
|
|
90
|
+
Create a new entity type
|
|
91
|
+
|
|
92
|
+
Args:
|
|
93
|
+
entity_type: Entity type to create
|
|
94
|
+
|
|
95
|
+
Raises:
|
|
96
|
+
ValueError: If entity type already exists
|
|
97
|
+
"""
|
|
98
|
+
self.schema.add_entity_type(entity_type)
|
|
99
|
+
|
|
100
|
+
# Cache the new entity type
|
|
101
|
+
if self._enable_cache and self._entity_type_cache:
|
|
102
|
+
self._entity_type_cache.set(entity_type.name, entity_type)
|
|
103
|
+
|
|
104
|
+
def update_entity_type(self, entity_type: EntityType) -> None:
|
|
105
|
+
"""
|
|
106
|
+
Update an existing entity type
|
|
107
|
+
|
|
108
|
+
Args:
|
|
109
|
+
entity_type: Updated entity type
|
|
110
|
+
|
|
111
|
+
Raises:
|
|
112
|
+
ValueError: If entity type doesn't exist
|
|
113
|
+
"""
|
|
114
|
+
self.schema.update_entity_type(entity_type)
|
|
115
|
+
|
|
116
|
+
# Invalidate cache for this entity type
|
|
117
|
+
if self._enable_cache and self._entity_type_cache:
|
|
118
|
+
self._entity_type_cache.delete(entity_type.name)
|
|
119
|
+
|
|
120
|
+
def delete_entity_type(self, type_name: str) -> None:
|
|
121
|
+
"""
|
|
122
|
+
Delete an entity type
|
|
123
|
+
|
|
124
|
+
Args:
|
|
125
|
+
type_name: Name of entity type to delete
|
|
126
|
+
|
|
127
|
+
Raises:
|
|
128
|
+
ValueError: If entity type doesn't exist or is in use
|
|
129
|
+
"""
|
|
130
|
+
self.schema.delete_entity_type(type_name)
|
|
131
|
+
|
|
132
|
+
# Invalidate cache for this entity type
|
|
133
|
+
if self._enable_cache and self._entity_type_cache:
|
|
134
|
+
self._entity_type_cache.delete(type_name)
|
|
135
|
+
|
|
136
|
+
def get_entity_type(self, type_name: str) -> Optional[EntityType]:
|
|
137
|
+
"""
|
|
138
|
+
Get an entity type by name (with caching)
|
|
139
|
+
|
|
140
|
+
Args:
|
|
141
|
+
type_name: Name of entity type
|
|
142
|
+
|
|
143
|
+
Returns:
|
|
144
|
+
Entity type or None if not found
|
|
145
|
+
"""
|
|
146
|
+
# Try cache first
|
|
147
|
+
if self._enable_cache and self._entity_type_cache:
|
|
148
|
+
cached = self._entity_type_cache.get(type_name)
|
|
149
|
+
if cached is not None:
|
|
150
|
+
return cached
|
|
151
|
+
|
|
152
|
+
# Load from schema
|
|
153
|
+
entity_type = self.schema.get_entity_type(type_name)
|
|
154
|
+
|
|
155
|
+
# Cache the result if found
|
|
156
|
+
if entity_type is not None and self._enable_cache and self._entity_type_cache:
|
|
157
|
+
self._entity_type_cache.set(type_name, entity_type)
|
|
158
|
+
|
|
159
|
+
return entity_type
|
|
160
|
+
|
|
161
|
+
def list_entity_types(self) -> List[str]:
|
|
162
|
+
"""
|
|
163
|
+
List all entity type names
|
|
164
|
+
|
|
165
|
+
Returns:
|
|
166
|
+
List of entity type names
|
|
167
|
+
"""
|
|
168
|
+
return self.schema.get_entity_type_names()
|
|
169
|
+
|
|
170
|
+
# Relation Type Operations
|
|
171
|
+
|
|
172
|
+
def create_relation_type(self, relation_type: RelationType) -> None:
|
|
173
|
+
"""
|
|
174
|
+
Create a new relation type
|
|
175
|
+
|
|
176
|
+
Args:
|
|
177
|
+
relation_type: Relation type to create
|
|
178
|
+
|
|
179
|
+
Raises:
|
|
180
|
+
ValueError: If relation type already exists
|
|
181
|
+
"""
|
|
182
|
+
self.schema.add_relation_type(relation_type)
|
|
183
|
+
|
|
184
|
+
# Cache the new relation type
|
|
185
|
+
if self._enable_cache and self._relation_type_cache:
|
|
186
|
+
self._relation_type_cache.set(relation_type.name, relation_type)
|
|
187
|
+
|
|
188
|
+
def update_relation_type(self, relation_type: RelationType) -> None:
|
|
189
|
+
"""
|
|
190
|
+
Update an existing relation type
|
|
191
|
+
|
|
192
|
+
Args:
|
|
193
|
+
relation_type: Updated relation type
|
|
194
|
+
|
|
195
|
+
Raises:
|
|
196
|
+
ValueError: If relation type doesn't exist
|
|
197
|
+
"""
|
|
198
|
+
self.schema.update_relation_type(relation_type)
|
|
199
|
+
|
|
200
|
+
# Invalidate cache for this relation type
|
|
201
|
+
if self._enable_cache and self._relation_type_cache:
|
|
202
|
+
self._relation_type_cache.delete(relation_type.name)
|
|
203
|
+
|
|
204
|
+
def delete_relation_type(self, type_name: str) -> None:
|
|
205
|
+
"""
|
|
206
|
+
Delete a relation type
|
|
207
|
+
|
|
208
|
+
Args:
|
|
209
|
+
type_name: Name of relation type to delete
|
|
210
|
+
|
|
211
|
+
Raises:
|
|
212
|
+
ValueError: If relation type doesn't exist
|
|
213
|
+
"""
|
|
214
|
+
self.schema.delete_relation_type(type_name)
|
|
215
|
+
|
|
216
|
+
# Invalidate cache for this relation type
|
|
217
|
+
if self._enable_cache and self._relation_type_cache:
|
|
218
|
+
self._relation_type_cache.delete(type_name)
|
|
219
|
+
|
|
220
|
+
def get_relation_type(self, type_name: str) -> Optional[RelationType]:
|
|
221
|
+
"""
|
|
222
|
+
Get a relation type by name (with caching)
|
|
223
|
+
|
|
224
|
+
Args:
|
|
225
|
+
type_name: Name of relation type
|
|
226
|
+
|
|
227
|
+
Returns:
|
|
228
|
+
Relation type or None if not found
|
|
229
|
+
"""
|
|
230
|
+
# Try cache first
|
|
231
|
+
if self._enable_cache and self._relation_type_cache:
|
|
232
|
+
cached = self._relation_type_cache.get(type_name)
|
|
233
|
+
if cached is not None:
|
|
234
|
+
return cached
|
|
235
|
+
|
|
236
|
+
# Load from schema
|
|
237
|
+
relation_type = self.schema.get_relation_type(type_name)
|
|
238
|
+
|
|
239
|
+
# Cache the result if found
|
|
240
|
+
if relation_type is not None and self._enable_cache and self._relation_type_cache:
|
|
241
|
+
self._relation_type_cache.set(type_name, relation_type)
|
|
242
|
+
|
|
243
|
+
return relation_type
|
|
244
|
+
|
|
245
|
+
def list_relation_types(self) -> List[str]:
|
|
246
|
+
"""
|
|
247
|
+
List all relation type names
|
|
248
|
+
|
|
249
|
+
Returns:
|
|
250
|
+
List of relation type names
|
|
251
|
+
"""
|
|
252
|
+
return self.schema.get_relation_type_names()
|
|
253
|
+
|
|
254
|
+
# Schema Validation
|
|
255
|
+
|
|
256
|
+
def validate_entity(self, entity_type_name: str, properties: dict) -> bool:
|
|
257
|
+
"""
|
|
258
|
+
Validate entity properties against schema
|
|
259
|
+
|
|
260
|
+
Args:
|
|
261
|
+
entity_type_name: Name of entity type
|
|
262
|
+
properties: Dictionary of properties to validate
|
|
263
|
+
|
|
264
|
+
Returns:
|
|
265
|
+
True if validation passes
|
|
266
|
+
|
|
267
|
+
Raises:
|
|
268
|
+
ValueError: If validation fails
|
|
269
|
+
"""
|
|
270
|
+
entity_type = self.get_entity_type(entity_type_name)
|
|
271
|
+
if entity_type is None:
|
|
272
|
+
raise ValueError(f"Entity type '{entity_type_name}' not found in schema")
|
|
273
|
+
|
|
274
|
+
return entity_type.validate_properties(properties)
|
|
275
|
+
|
|
276
|
+
def validate_relation(
|
|
277
|
+
self,
|
|
278
|
+
relation_type_name: str,
|
|
279
|
+
source_entity_type: str,
|
|
280
|
+
target_entity_type: str,
|
|
281
|
+
properties: dict,
|
|
282
|
+
) -> bool:
|
|
283
|
+
"""
|
|
284
|
+
Validate relation against schema
|
|
285
|
+
|
|
286
|
+
Args:
|
|
287
|
+
relation_type_name: Name of relation type
|
|
288
|
+
source_entity_type: Source entity type name
|
|
289
|
+
target_entity_type: Target entity type name
|
|
290
|
+
properties: Dictionary of properties to validate
|
|
291
|
+
|
|
292
|
+
Returns:
|
|
293
|
+
True if validation passes
|
|
294
|
+
|
|
295
|
+
Raises:
|
|
296
|
+
ValueError: If validation fails
|
|
297
|
+
"""
|
|
298
|
+
relation_type = self.get_relation_type(relation_type_name)
|
|
299
|
+
if relation_type is None:
|
|
300
|
+
raise ValueError(f"Relation type '{relation_type_name}' not found in schema")
|
|
301
|
+
|
|
302
|
+
# Validate entity types
|
|
303
|
+
relation_type.validate_entity_types(source_entity_type, target_entity_type)
|
|
304
|
+
|
|
305
|
+
# Validate properties
|
|
306
|
+
return relation_type.validate_properties(properties)
|
|
307
|
+
|
|
308
|
+
# Schema Persistence
|
|
309
|
+
|
|
310
|
+
def save(self, file_path: str) -> None:
|
|
311
|
+
"""
|
|
312
|
+
Save schema to JSON file
|
|
313
|
+
|
|
314
|
+
Args:
|
|
315
|
+
file_path: Path to save schema
|
|
316
|
+
"""
|
|
317
|
+
schema_dict = self.schema.model_dump(mode="json")
|
|
318
|
+
|
|
319
|
+
path = Path(file_path)
|
|
320
|
+
path.parent.mkdir(parents=True, exist_ok=True)
|
|
321
|
+
|
|
322
|
+
with open(path, "w", encoding="utf-8") as f:
|
|
323
|
+
json.dump(schema_dict, f, indent=2, ensure_ascii=False)
|
|
324
|
+
|
|
325
|
+
@classmethod
|
|
326
|
+
def load(cls, file_path: str) -> "SchemaManager":
|
|
327
|
+
"""
|
|
328
|
+
Load schema from JSON file
|
|
329
|
+
|
|
330
|
+
Args:
|
|
331
|
+
file_path: Path to load schema from
|
|
332
|
+
|
|
333
|
+
Returns:
|
|
334
|
+
New SchemaManager instance with loaded schema
|
|
335
|
+
"""
|
|
336
|
+
with open(file_path, "r", encoding="utf-8") as f:
|
|
337
|
+
schema_dict = json.load(f)
|
|
338
|
+
|
|
339
|
+
schema = GraphSchema(**schema_dict)
|
|
340
|
+
return cls(schema=schema)
|
|
341
|
+
|
|
342
|
+
# Transaction Support (Simple)
|
|
343
|
+
|
|
344
|
+
def begin_transaction(self) -> None:
|
|
345
|
+
"""Begin a schema transaction"""
|
|
346
|
+
# Create a deep copy of the current schema
|
|
347
|
+
schema_json = self.schema.model_dump_json()
|
|
348
|
+
self._transaction_schema = GraphSchema(**json.loads(schema_json))
|
|
349
|
+
|
|
350
|
+
def commit(self) -> None:
|
|
351
|
+
"""Commit the current transaction"""
|
|
352
|
+
self._transaction_schema = None
|
|
353
|
+
|
|
354
|
+
def rollback(self) -> None:
|
|
355
|
+
"""
|
|
356
|
+
Rollback to the state at transaction start
|
|
357
|
+
|
|
358
|
+
Raises:
|
|
359
|
+
RuntimeError: If no transaction is active
|
|
360
|
+
"""
|
|
361
|
+
if self._transaction_schema is None:
|
|
362
|
+
raise RuntimeError("No active transaction to rollback")
|
|
363
|
+
|
|
364
|
+
self.schema = self._transaction_schema
|
|
365
|
+
self._transaction_schema = None
|
|
366
|
+
|
|
367
|
+
@property
|
|
368
|
+
def is_in_transaction(self) -> bool:
|
|
369
|
+
"""Check if a transaction is active"""
|
|
370
|
+
return self._transaction_schema is not None
|
|
371
|
+
|
|
372
|
+
# Cache Management
|
|
373
|
+
|
|
374
|
+
def invalidate_cache(self, type_name: Optional[str] = None) -> None:
|
|
375
|
+
"""
|
|
376
|
+
Invalidate cache entries
|
|
377
|
+
|
|
378
|
+
Args:
|
|
379
|
+
type_name: Specific type to invalidate (None = invalidate all)
|
|
380
|
+
"""
|
|
381
|
+
if not self._enable_cache:
|
|
382
|
+
return
|
|
383
|
+
|
|
384
|
+
if type_name is None:
|
|
385
|
+
# Clear all caches
|
|
386
|
+
if self._entity_type_cache:
|
|
387
|
+
self._entity_type_cache.clear()
|
|
388
|
+
if self._relation_type_cache:
|
|
389
|
+
self._relation_type_cache.clear()
|
|
390
|
+
if self._property_cache:
|
|
391
|
+
self._property_cache.clear()
|
|
392
|
+
else:
|
|
393
|
+
# Invalidate specific type
|
|
394
|
+
if self._entity_type_cache:
|
|
395
|
+
self._entity_type_cache.delete(type_name)
|
|
396
|
+
if self._relation_type_cache:
|
|
397
|
+
self._relation_type_cache.delete(type_name)
|
|
398
|
+
|
|
399
|
+
def cleanup_expired_cache(self) -> Dict[str, int]:
|
|
400
|
+
"""
|
|
401
|
+
Remove expired cache entries
|
|
402
|
+
|
|
403
|
+
Returns:
|
|
404
|
+
Dictionary with number of entries removed per cache
|
|
405
|
+
"""
|
|
406
|
+
if not self._enable_cache:
|
|
407
|
+
return {"entity_types": 0, "relation_types": 0, "properties": 0}
|
|
408
|
+
|
|
409
|
+
return {
|
|
410
|
+
"entity_types": (
|
|
411
|
+
self._entity_type_cache.cleanup_expired() if self._entity_type_cache else 0
|
|
412
|
+
),
|
|
413
|
+
"relation_types": (
|
|
414
|
+
self._relation_type_cache.cleanup_expired() if self._relation_type_cache else 0
|
|
415
|
+
),
|
|
416
|
+
"properties": (self._property_cache.cleanup_expired() if self._property_cache else 0),
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
def get_cache_stats(self) -> Dict[str, Any]:
|
|
420
|
+
"""
|
|
421
|
+
Get cache statistics
|
|
422
|
+
|
|
423
|
+
Returns:
|
|
424
|
+
Dictionary with cache statistics for all caches
|
|
425
|
+
"""
|
|
426
|
+
if not self._enable_cache:
|
|
427
|
+
return {
|
|
428
|
+
"enabled": False,
|
|
429
|
+
"entity_types": {},
|
|
430
|
+
"relation_types": {},
|
|
431
|
+
"properties": {},
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
return {
|
|
435
|
+
"enabled": True,
|
|
436
|
+
"entity_types": (
|
|
437
|
+
self._entity_type_cache.get_stats() if self._entity_type_cache else {}
|
|
438
|
+
),
|
|
439
|
+
"relation_types": (
|
|
440
|
+
self._relation_type_cache.get_stats() if self._relation_type_cache else {}
|
|
441
|
+
),
|
|
442
|
+
"properties": (self._property_cache.get_stats() if self._property_cache else {}),
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
def reset_cache_metrics(self) -> None:
|
|
446
|
+
"""Reset cache metrics (hits, misses, etc.)"""
|
|
447
|
+
if not self._enable_cache:
|
|
448
|
+
return
|
|
449
|
+
|
|
450
|
+
if self._entity_type_cache:
|
|
451
|
+
self._entity_type_cache.reset_metrics()
|
|
452
|
+
if self._relation_type_cache:
|
|
453
|
+
self._relation_type_cache.reset_metrics()
|
|
454
|
+
if self._property_cache:
|
|
455
|
+
self._property_cache.reset_metrics()
|
|
456
|
+
|
|
457
|
+
# Type Enum Generation (Task 3.4)
|
|
458
|
+
|
|
459
|
+
def generate_enums(self) -> Dict[str, Dict[str, Type[Enum]]]:
|
|
460
|
+
"""
|
|
461
|
+
Generate type enums from schema
|
|
462
|
+
|
|
463
|
+
Creates Python Enum classes for all entity types and relation types
|
|
464
|
+
defined in the schema. The generated enums are string-based for
|
|
465
|
+
backward compatibility with existing code.
|
|
466
|
+
|
|
467
|
+
Returns:
|
|
468
|
+
Dictionary with "entity_types" and "relation_types" keys,
|
|
469
|
+
each containing a dictionary mapping type names to enum classes
|
|
470
|
+
|
|
471
|
+
Example:
|
|
472
|
+
>>> enums = schema_manager.generate_enums()
|
|
473
|
+
>>> PersonEnum = enums["entity_types"]["Person"]
|
|
474
|
+
>>> PersonEnum.PERSON # "Person"
|
|
475
|
+
>>>
|
|
476
|
+
>>> WorksForEnum = enums["relation_types"]["WORKS_FOR"]
|
|
477
|
+
>>> WorksForEnum.WORKS_FOR # "WORKS_FOR"
|
|
478
|
+
|
|
479
|
+
Note:
|
|
480
|
+
The generated enums are backward compatible with string literals:
|
|
481
|
+
>>> str(PersonEnum.PERSON) == "Person" # True
|
|
482
|
+
>>> PersonEnum.PERSON == "Person" # True
|
|
483
|
+
"""
|
|
484
|
+
generator = TypeEnumGenerator(self.schema)
|
|
485
|
+
return generator.generate_all_enums()
|
|
486
|
+
|
|
487
|
+
def __str__(self) -> str:
|
|
488
|
+
cache_info = ""
|
|
489
|
+
if self._enable_cache and self._entity_type_cache:
|
|
490
|
+
stats = self.get_cache_stats()
|
|
491
|
+
entity_hit_rate = stats["entity_types"].get("hit_rate", 0)
|
|
492
|
+
cache_info = f", cache_hit_rate={entity_hit_rate:.2%}"
|
|
493
|
+
return f"SchemaManager({self.schema}{cache_info})"
|
|
494
|
+
|
|
495
|
+
def __repr__(self) -> str:
|
|
496
|
+
return self.__str__()
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Type Enums
|
|
3
|
+
|
|
4
|
+
Dynamic enum generation for entity and relation types from schema.
|
|
5
|
+
|
|
6
|
+
Phase: 3.4 - Type Enums
|
|
7
|
+
Version: 1.0
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from enum import Enum
|
|
11
|
+
from typing import Type, Dict
|
|
12
|
+
from aiecs.domain.knowledge_graph.schema.graph_schema import GraphSchema
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class EntityTypeEnum(str, Enum):
|
|
16
|
+
"""
|
|
17
|
+
Base class for entity type enums
|
|
18
|
+
|
|
19
|
+
Dynamically generated enums inherit from this class.
|
|
20
|
+
Enums are string-based for backward compatibility.
|
|
21
|
+
|
|
22
|
+
Example:
|
|
23
|
+
>>> PersonType = EntityTypeEnum("PersonType", {"PERSON": "Person"})
|
|
24
|
+
>>> PersonType.PERSON
|
|
25
|
+
'Person'
|
|
26
|
+
>>> str(PersonType.PERSON)
|
|
27
|
+
'Person'
|
|
28
|
+
"""
|
|
29
|
+
|
|
30
|
+
def __str__(self) -> str:
|
|
31
|
+
"""Return the enum value (for backward compatibility)"""
|
|
32
|
+
return self.value
|
|
33
|
+
|
|
34
|
+
def __repr__(self) -> str:
|
|
35
|
+
"""Return the enum representation"""
|
|
36
|
+
return f"{self.__class__.__name__}.{self.name}"
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
class RelationTypeEnum(str, Enum):
|
|
40
|
+
"""
|
|
41
|
+
Base class for relation type enums
|
|
42
|
+
|
|
43
|
+
Dynamically generated enums inherit from this class.
|
|
44
|
+
Enums are string-based for backward compatibility.
|
|
45
|
+
|
|
46
|
+
Example:
|
|
47
|
+
>>> WorksForType = RelationTypeEnum("WorksForType", {"WORKS_FOR": "WORKS_FOR"})
|
|
48
|
+
>>> WorksForType.WORKS_FOR
|
|
49
|
+
'WORKS_FOR'
|
|
50
|
+
>>> str(WorksForType.WORKS_FOR)
|
|
51
|
+
'WORKS_FOR'
|
|
52
|
+
"""
|
|
53
|
+
|
|
54
|
+
def __str__(self) -> str:
|
|
55
|
+
"""Return the enum value (for backward compatibility)"""
|
|
56
|
+
return self.value
|
|
57
|
+
|
|
58
|
+
def __repr__(self) -> str:
|
|
59
|
+
"""Return the enum representation"""
|
|
60
|
+
return f"{self.__class__.__name__}.{self.name}"
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
class TypeEnumGenerator:
|
|
64
|
+
"""
|
|
65
|
+
Utility for generating type enums from schema
|
|
66
|
+
|
|
67
|
+
Generates Python Enum classes for entity types and relation types
|
|
68
|
+
defined in a GraphSchema. The generated enums are string-based for
|
|
69
|
+
backward compatibility with existing code that uses string literals.
|
|
70
|
+
|
|
71
|
+
Example:
|
|
72
|
+
>>> generator = TypeEnumGenerator(schema)
|
|
73
|
+
>>> entity_enums = generator.generate_entity_type_enums()
|
|
74
|
+
>>> relation_enums = generator.generate_relation_type_enums()
|
|
75
|
+
>>>
|
|
76
|
+
>>> # Use generated enums
|
|
77
|
+
>>> PersonType = entity_enums["Person"]
|
|
78
|
+
>>> person_type = PersonType.PERSON # "Person"
|
|
79
|
+
"""
|
|
80
|
+
|
|
81
|
+
def __init__(self, schema: GraphSchema):
|
|
82
|
+
"""
|
|
83
|
+
Initialize enum generator
|
|
84
|
+
|
|
85
|
+
Args:
|
|
86
|
+
schema: Graph schema to generate enums from
|
|
87
|
+
"""
|
|
88
|
+
self.schema = schema
|
|
89
|
+
|
|
90
|
+
def generate_entity_type_enums(self) -> Dict[str, Type[EntityTypeEnum]]:
|
|
91
|
+
"""
|
|
92
|
+
Generate entity type enums from schema
|
|
93
|
+
|
|
94
|
+
Creates an enum class for each entity type in the schema.
|
|
95
|
+
The enum name is the entity type name, and the enum value
|
|
96
|
+
is also the entity type name (for backward compatibility).
|
|
97
|
+
|
|
98
|
+
Returns:
|
|
99
|
+
Dictionary mapping entity type names to enum classes
|
|
100
|
+
|
|
101
|
+
Example:
|
|
102
|
+
>>> enums = generator.generate_entity_type_enums()
|
|
103
|
+
>>> PersonEnum = enums["Person"]
|
|
104
|
+
>>> PersonEnum.PERSON # "Person"
|
|
105
|
+
"""
|
|
106
|
+
enums = {}
|
|
107
|
+
|
|
108
|
+
for entity_type_name in self.schema.get_entity_type_names():
|
|
109
|
+
# Create enum name (convert to uppercase with underscores)
|
|
110
|
+
enum_member_name = self._to_enum_name(entity_type_name)
|
|
111
|
+
|
|
112
|
+
# Create enum class
|
|
113
|
+
enum_class = EntityTypeEnum(
|
|
114
|
+
entity_type_name + "Enum", {enum_member_name: entity_type_name}
|
|
115
|
+
)
|
|
116
|
+
|
|
117
|
+
enums[entity_type_name] = enum_class
|
|
118
|
+
|
|
119
|
+
return enums
|
|
120
|
+
|
|
121
|
+
def generate_relation_type_enums(
|
|
122
|
+
self,
|
|
123
|
+
) -> Dict[str, Type[RelationTypeEnum]]:
|
|
124
|
+
"""
|
|
125
|
+
Generate relation type enums from schema
|
|
126
|
+
|
|
127
|
+
Creates an enum class for each relation type in the schema.
|
|
128
|
+
The enum name is the relation type name, and the enum value
|
|
129
|
+
is also the relation type name (for backward compatibility).
|
|
130
|
+
|
|
131
|
+
Returns:
|
|
132
|
+
Dictionary mapping relation type names to enum classes
|
|
133
|
+
|
|
134
|
+
Example:
|
|
135
|
+
>>> enums = generator.generate_relation_type_enums()
|
|
136
|
+
>>> WorksForEnum = enums["WORKS_FOR"]
|
|
137
|
+
>>> WorksForEnum.WORKS_FOR # "WORKS_FOR"
|
|
138
|
+
"""
|
|
139
|
+
enums = {}
|
|
140
|
+
|
|
141
|
+
for relation_type_name in self.schema.get_relation_type_names():
|
|
142
|
+
# Create enum name (convert to uppercase with underscores)
|
|
143
|
+
enum_member_name = self._to_enum_name(relation_type_name)
|
|
144
|
+
|
|
145
|
+
# Create enum class
|
|
146
|
+
enum_class = RelationTypeEnum(
|
|
147
|
+
relation_type_name + "Enum",
|
|
148
|
+
{enum_member_name: relation_type_name},
|
|
149
|
+
)
|
|
150
|
+
|
|
151
|
+
enums[relation_type_name] = enum_class
|
|
152
|
+
|
|
153
|
+
return enums
|
|
154
|
+
|
|
155
|
+
def generate_all_enums(self) -> Dict[str, Dict[str, Type[Enum]]]:
|
|
156
|
+
"""
|
|
157
|
+
Generate all type enums from schema
|
|
158
|
+
|
|
159
|
+
Returns:
|
|
160
|
+
Dictionary with "entity_types" and "relation_types" keys,
|
|
161
|
+
each containing a dictionary of enum classes
|
|
162
|
+
|
|
163
|
+
Example:
|
|
164
|
+
>>> enums = generator.generate_all_enums()
|
|
165
|
+
>>> PersonEnum = enums["entity_types"]["Person"]
|
|
166
|
+
>>> WorksForEnum = enums["relation_types"]["WORKS_FOR"]
|
|
167
|
+
"""
|
|
168
|
+
return {
|
|
169
|
+
"entity_types": self.generate_entity_type_enums(),
|
|
170
|
+
"relation_types": self.generate_relation_type_enums(),
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
@staticmethod
|
|
174
|
+
def _to_enum_name(type_name: str) -> str:
|
|
175
|
+
"""
|
|
176
|
+
Convert type name to enum member name
|
|
177
|
+
|
|
178
|
+
Converts CamelCase or snake_case to UPPER_CASE.
|
|
179
|
+
|
|
180
|
+
Args:
|
|
181
|
+
type_name: Type name to convert
|
|
182
|
+
|
|
183
|
+
Returns:
|
|
184
|
+
Enum member name in UPPER_CASE
|
|
185
|
+
|
|
186
|
+
Example:
|
|
187
|
+
>>> TypeEnumGenerator._to_enum_name("Person")
|
|
188
|
+
'PERSON'
|
|
189
|
+
>>> TypeEnumGenerator._to_enum_name("WorksFor")
|
|
190
|
+
'WORKS_FOR'
|
|
191
|
+
>>> TypeEnumGenerator._to_enum_name("WORKS_FOR")
|
|
192
|
+
'WORKS_FOR'
|
|
193
|
+
"""
|
|
194
|
+
# If already uppercase, return as-is
|
|
195
|
+
if type_name.isupper():
|
|
196
|
+
return type_name
|
|
197
|
+
|
|
198
|
+
# Convert CamelCase to UPPER_CASE
|
|
199
|
+
result = []
|
|
200
|
+
for i, char in enumerate(type_name):
|
|
201
|
+
if char.isupper() and i > 0 and type_name[i - 1].islower():
|
|
202
|
+
result.append("_")
|
|
203
|
+
result.append(char.upper())
|
|
204
|
+
|
|
205
|
+
return "".join(result)
|