Skip to content

Commit f67801a

Browse files
committed
Update config usage to Pydantic Object
1 parent 0d68702 commit f67801a

File tree

32 files changed

+595
-432
lines changed

32 files changed

+595
-432
lines changed

lib/idp_common_pkg/idp_common/__init__.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,22 @@
22
# SPDX-License-Identifier: MIT-0
33

44
# Use true lazy loading for all submodules
5+
from typing import TYPE_CHECKING
6+
57
__version__ = "0.1.0"
68

79
# Cache for lazy-loaded submodules
810
_submodules = {}
911

12+
# Type hints are only evaluated during type checking, not at runtime
13+
if TYPE_CHECKING:
14+
from .config import get_config as get_config
15+
from .config.models import IDPConfig as IDPConfig
16+
from .models import Document as Document
17+
from .models import Page as Page
18+
from .models import Section as Section
19+
from .models import Status as Status
20+
1021

1122
def __getattr__(name):
1223
"""Lazy load submodules only when accessed"""
@@ -65,6 +76,7 @@ def __getattr__(name):
6576
"reporting",
6677
"agents",
6778
"get_config",
79+
"IDPConfig",
6880
"Document",
6981
"Page",
7082
"Section",

lib/idp_common_pkg/idp_common/agents/analytics/schema_provider.py

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
from typing import Any, Dict, Generator, Optional
1010

1111
from idp_common.config import get_config
12+
from idp_common.config.models import IDPConfig
1213
from idp_common.config.schema_constants import (
1314
SCHEMA_DESCRIPTION,
1415
SCHEMA_ITEMS,
@@ -211,7 +212,7 @@ def get_evaluation_tables_description() -> str:
211212

212213

213214
def get_dynamic_document_sections_description(
214-
config: Optional[Dict[str, Any]] = None,
215+
config: Optional[IDPConfig] = None,
215216
) -> str:
216217
"""
217218
Generate deployment-specific description of document sections tables based on actual configuration.
@@ -224,10 +225,10 @@ def get_dynamic_document_sections_description(
224225
"""
225226
try:
226227
if config is None:
227-
config = get_config()
228+
config = get_config(as_model=True)
228229

229230
# Get document classes from config
230-
classes = config.get("classes", [])
231+
classes = config.classes
231232

232233
if not classes:
233234
logger.warning("No classes found in configuration")
@@ -251,7 +252,7 @@ def get_dynamic_document_sections_description(
251252
# Generate table list
252253
table_names = []
253254
for doc_class in classes:
254-
class_name = doc_class.get("name", "Unknown")
255+
class_name = doc_class.get(X_AWS_IDP_DOCUMENT_TYPE, "Unknown")
255256
# Apply exact table name transformation logic
256257
table_name = f"document_sections_{_get_table_suffix(class_name)}"
257258
table_names.append(table_name)
@@ -500,7 +501,7 @@ def _get_error_aware_fallback(
500501
"""
501502

502503

503-
def get_database_overview(config: Optional[Dict[str, Any]] = None) -> str:
504+
def get_database_overview(config: Optional[IDPConfig] = None) -> str:
504505
"""
505506
Get a fast, lightweight overview of available tables with brief descriptions.
506507
This is the first step in the two-step progressive disclosure system.
@@ -513,10 +514,10 @@ def get_database_overview(config: Optional[Dict[str, Any]] = None) -> str:
513514
"""
514515
try:
515516
if config is None:
516-
config = get_config()
517+
config = get_config(as_model=True)
517518

518519
# Get document classes from config
519-
classes = config.get("classes", [])
520+
classes = config.classes
520521

521522
overview = """# Database Overview - Available Tables
522523
@@ -570,9 +571,7 @@ def get_database_overview(config: Optional[Dict[str, Any]] = None) -> str:
570571
return """# Database Overview - Error Loading Configuration"""
571572

572573

573-
def get_table_info(
574-
table_names: list[str], config: Optional[Dict[str, Any]] = None
575-
) -> str:
574+
def get_table_info(table_names: list[str], config: Optional[IDPConfig] = None) -> str:
576575
"""
577576
Get detailed schema information for specific tables.
578577
This is the second step in the two-step progressive disclosure system.
@@ -620,7 +619,7 @@ def get_table_info(
620619

621620

622621
def _get_specific_document_sections_table_info(
623-
table_suffix: str, config: Optional[Dict[str, Any]] = None
622+
table_suffix: str, config: Optional[IDPConfig] = None
624623
) -> str:
625624
"""
626625
Get detailed information for a specific document sections table.
@@ -634,9 +633,9 @@ def _get_specific_document_sections_table_info(
634633
"""
635634
try:
636635
if config is None:
637-
config = get_config()
636+
config = get_config(as_model=True)
638637

639-
classes = config.get("classes", [])
638+
classes = config.classes
640639
table_name = f"document_sections_{table_suffix}"
641640

642641
# Find the matching class for this table

lib/idp_common_pkg/idp_common/agents/error_analyzer/tools/xray_tool.py

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,11 @@
1313
import boto3
1414
from strands import tool
1515

16+
from idp_common.config import get_config
17+
1618
from ..config import (
1719
create_error_response,
1820
create_response,
19-
get_config_with_fallback,
2021
safe_int_conversion,
2122
)
2223

@@ -81,8 +82,10 @@ def _analyze_trace_segments(segments: List[Dict[str, Any]]) -> Dict[str, Any]:
8182
error_segments = []
8283
slow_segments = []
8384

84-
config = get_config_with_fallback()
85-
slow_threshold = config.get("xray_slow_segment_threshold_ms", 5000)
85+
config = get_config(as_model=True)
86+
slow_threshold = (
87+
config.agents.error_analyzer.parameters.xray_slow_segment_threshold_ms
88+
)
8689

8790
for segment in segments:
8891
segment_doc = _parse_segment_document(segment.get("Document", {}))
@@ -338,9 +341,13 @@ def _analyze_service_performance(
338341
if not services:
339342
return {"services_found": 0, "message": "No service map data available"}
340343

341-
config = get_config_with_fallback()
342-
error_rate_threshold = config.get("xray_error_rate_threshold", 0.05)
343-
response_time_threshold = config.get("xray_response_time_threshold_ms", 10000)
344+
config = get_config(as_model=True)
345+
error_rate_threshold = (
346+
config.agents.error_analyzer.parameters.xray_error_rate_threshold
347+
)
348+
response_time_threshold = (
349+
config.agents.error_analyzer.parameters.xray_response_time_threshold_ms
350+
)
344351

345352
service_analysis = []
346353
high_error_services = []

lib/idp_common_pkg/idp_common/assessment/__init__.py

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,9 @@
1313
"""
1414

1515
import logging
16-
from typing import Any, Dict
16+
from typing import Optional
1717

18-
from idp_common.utils import normalize_boolean_value
18+
from idp_common.config.models import IDPConfig
1919

2020
from .granular_service import GranularAssessmentService
2121
from .models import AssessmentResult, AttributeAssessment
@@ -32,7 +32,7 @@ class AssessmentService:
3232
chooses between the original and granular implementations based on configuration.
3333
"""
3434

35-
def __init__(self, region: str = None, config: Dict[str, Any] = None):
35+
def __init__(self, region: str = None, config: IDPConfig = None):
3636
"""
3737
Initialize the assessment service with automatic implementation selection.
3838
@@ -60,7 +60,9 @@ def _format_attribute_descriptions(self, attributes):
6060
return self._service._format_attribute_descriptions(attributes)
6161

6262

63-
def create_assessment_service(region: str = None, config: Dict[str, Any] = None):
63+
def create_assessment_service(
64+
region: Optional[str] = None, config: Optional[IDPConfig] = None
65+
):
6466
"""
6567
Factory function to create the appropriate assessment service based on configuration.
6668
@@ -72,22 +74,19 @@ def create_assessment_service(region: str = None, config: Dict[str, Any] = None)
7274
OriginalAssessmentService or GranularAssessmentService based on configuration
7375
"""
7476
if not config:
77+
config = IDPConfig()
7578
logger.info("No config provided, using original AssessmentService")
7679
return OriginalAssessmentService(region=region, config=config)
7780

7881
# Check if granular assessment is enabled (default: False for backward compatibility)
79-
assessment_config = config.get("assessment", {})
80-
granular_config = assessment_config.get("granular", {})
81-
granular_enabled_raw = granular_config.get("enabled", False)
8282

8383
# Normalize the enabled value to handle both boolean and string values
84-
granular_enabled = normalize_boolean_value(granular_enabled_raw)
8584

8685
logger.info(
87-
f"Granular assessment enabled check: raw_value={granular_enabled_raw} (type: {type(granular_enabled_raw)}), normalized={granular_enabled}"
86+
f"Granular assessment enabled check: raw_value={config.assessment.granular.enabled} (type: {type(config.assessment.granular.enabled)})"
8887
)
8988

90-
if granular_enabled:
89+
if config.assessment.granular.enabled:
9190
logger.info("Granular assessment enabled, using GranularAssessmentService")
9291
return GranularAssessmentService(region=region, config=config)
9392
else:

lib/idp_common_pkg/idp_common/config/__init__.py

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -160,28 +160,47 @@ def get_merged_configuration(
160160

161161
@overload
162162
def get_config(
163-
table_name: Optional[str] = None, *, as_model: Literal[True]
164-
) -> IDPConfig: ...
163+
*, table_name: Optional[str] = None, as_model: Literal[True]
164+
) -> IDPConfig:
165+
"""
166+
Get configuration as Pydantic model.
167+
168+
Use config.to_dict() to convert to mutable dict with extra fields:
169+
config = get_config(as_model=True)
170+
config_dict = config.to_dict(sagemaker_endpoint_name=endpoint)
171+
"""
172+
...
165173

166174

167175
@overload
168176
def get_config(
169-
table_name: Optional[str] = None, *, as_model: Literal[False]
170-
) -> Dict[str, Any]: ...
177+
*, table_name: Optional[str] = None, as_model: Literal[False] = False
178+
) -> Dict[str, Any]:
179+
"""Get configuration as mutable dictionary."""
180+
...
171181

172182

173183
def get_config(
174-
table_name: Optional[str] = None, *, as_model: bool = False
184+
*, table_name: Optional[str] = None, as_model: bool = False
175185
) -> Union[IDPConfig, Dict[str, Any]]:
176186
"""
177-
Get the merged configuration using the environment variable for table name
187+
Get the merged configuration using the environment variable for table name.
178188
179189
Args:
180190
table_name: Optional override for configuration table name
181191
as_model: If True, return IDPConfig Pydantic model. If False (default), return dict.
182192
183193
Returns:
184-
Merged configuration as IDPConfig or dictionary
194+
Merged configuration as IDPConfig (with .to_dict() helper) or mutable dictionary.
195+
196+
Examples:
197+
# Get as dict for direct manipulation
198+
config = get_config(as_model=False)
199+
config["extra_field"] = "value"
200+
201+
# Get as model, convert to dict with extras
202+
config = get_config(as_model=True)
203+
config_dict = config.to_dict(sagemaker_endpoint_name=endpoint)
185204
"""
186205
reader = ConfigurationReader(table_name)
187206
return reader.get_merged_configuration(as_model=as_model)

0 commit comments

Comments
 (0)