additory 0.1.0a4__py3-none-any.whl → 0.1.1a2__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 (121) hide show
  1. additory/__init__.py +58 -14
  2. additory/common/__init__.py +31 -147
  3. additory/common/column_selector.py +255 -0
  4. additory/common/distributions.py +286 -613
  5. additory/common/extractors.py +313 -0
  6. additory/common/knn_imputation.py +332 -0
  7. additory/common/result.py +390 -0
  8. additory/common/strategy_parser.py +243 -0
  9. additory/common/unit_conversions.py +338 -0
  10. additory/common/validation.py +283 -103
  11. additory/core/__init__.py +34 -22
  12. additory/core/backend.py +258 -0
  13. additory/core/config.py +177 -305
  14. additory/core/logging.py +230 -24
  15. additory/core/memory_manager.py +157 -495
  16. additory/expressions/__init__.py +2 -23
  17. additory/expressions/compiler.py +457 -0
  18. additory/expressions/engine.py +264 -487
  19. additory/expressions/integrity.py +179 -0
  20. additory/expressions/loader.py +263 -0
  21. additory/expressions/parser.py +363 -167
  22. additory/expressions/resolver.py +274 -0
  23. additory/functions/__init__.py +1 -0
  24. additory/functions/analyze/__init__.py +144 -0
  25. additory/functions/analyze/cardinality.py +58 -0
  26. additory/functions/analyze/correlations.py +66 -0
  27. additory/functions/analyze/distributions.py +53 -0
  28. additory/functions/analyze/duplicates.py +49 -0
  29. additory/functions/analyze/features.py +61 -0
  30. additory/functions/analyze/imputation.py +66 -0
  31. additory/functions/analyze/outliers.py +65 -0
  32. additory/functions/analyze/patterns.py +65 -0
  33. additory/functions/analyze/presets.py +72 -0
  34. additory/functions/analyze/quality.py +59 -0
  35. additory/functions/analyze/timeseries.py +53 -0
  36. additory/functions/analyze/types.py +45 -0
  37. additory/functions/expressions/__init__.py +161 -0
  38. additory/functions/snapshot/__init__.py +82 -0
  39. additory/functions/snapshot/filter.py +119 -0
  40. additory/functions/synthetic/__init__.py +113 -0
  41. additory/functions/synthetic/mode_detector.py +47 -0
  42. additory/functions/synthetic/strategies/__init__.py +1 -0
  43. additory/functions/synthetic/strategies/advanced.py +35 -0
  44. additory/functions/synthetic/strategies/augmentative.py +160 -0
  45. additory/functions/synthetic/strategies/generative.py +168 -0
  46. additory/functions/synthetic/strategies/presets.py +116 -0
  47. additory/functions/to/__init__.py +188 -0
  48. additory/functions/to/lookup.py +351 -0
  49. additory/functions/to/merge.py +189 -0
  50. additory/functions/to/sort.py +91 -0
  51. additory/functions/to/summarize.py +170 -0
  52. additory/functions/transform/__init__.py +140 -0
  53. additory/functions/transform/datetime.py +79 -0
  54. additory/functions/transform/extract.py +85 -0
  55. additory/functions/transform/harmonize.py +105 -0
  56. additory/functions/transform/knn.py +62 -0
  57. additory/functions/transform/onehotencoding.py +68 -0
  58. additory/functions/transform/transpose.py +42 -0
  59. additory-0.1.1a2.dist-info/METADATA +84 -0
  60. additory-0.1.1a2.dist-info/RECORD +62 -0
  61. additory/analysis/__init__.py +0 -48
  62. additory/analysis/cardinality.py +0 -126
  63. additory/analysis/correlations.py +0 -124
  64. additory/analysis/distributions.py +0 -376
  65. additory/analysis/quality.py +0 -158
  66. additory/analysis/scan.py +0 -400
  67. additory/common/backend.py +0 -371
  68. additory/common/column_utils.py +0 -191
  69. additory/common/exceptions.py +0 -62
  70. additory/common/lists.py +0 -229
  71. additory/common/patterns.py +0 -240
  72. additory/common/resolver.py +0 -567
  73. additory/common/sample_data.py +0 -182
  74. additory/core/ast_builder.py +0 -165
  75. additory/core/backends/__init__.py +0 -23
  76. additory/core/backends/arrow_bridge.py +0 -483
  77. additory/core/backends/cudf_bridge.py +0 -355
  78. additory/core/column_positioning.py +0 -358
  79. additory/core/compiler_polars.py +0 -166
  80. additory/core/enhanced_cache_manager.py +0 -1119
  81. additory/core/enhanced_matchers.py +0 -473
  82. additory/core/enhanced_version_manager.py +0 -325
  83. additory/core/executor.py +0 -59
  84. additory/core/integrity_manager.py +0 -477
  85. additory/core/loader.py +0 -190
  86. additory/core/namespace_manager.py +0 -657
  87. additory/core/parser.py +0 -176
  88. additory/core/polars_expression_engine.py +0 -601
  89. additory/core/registry.py +0 -177
  90. additory/core/sample_data_manager.py +0 -492
  91. additory/core/user_namespace.py +0 -751
  92. additory/core/validator.py +0 -27
  93. additory/dynamic_api.py +0 -352
  94. additory/expressions/proxy.py +0 -549
  95. additory/expressions/registry.py +0 -313
  96. additory/expressions/samples.py +0 -492
  97. additory/synthetic/__init__.py +0 -13
  98. additory/synthetic/column_name_resolver.py +0 -149
  99. additory/synthetic/deduce.py +0 -259
  100. additory/synthetic/distributions.py +0 -22
  101. additory/synthetic/forecast.py +0 -1132
  102. additory/synthetic/linked_list_parser.py +0 -415
  103. additory/synthetic/namespace_lookup.py +0 -129
  104. additory/synthetic/smote.py +0 -320
  105. additory/synthetic/strategies.py +0 -926
  106. additory/synthetic/synthesizer.py +0 -713
  107. additory/utilities/__init__.py +0 -53
  108. additory/utilities/encoding.py +0 -600
  109. additory/utilities/games.py +0 -300
  110. additory/utilities/keys.py +0 -8
  111. additory/utilities/lookup.py +0 -103
  112. additory/utilities/matchers.py +0 -216
  113. additory/utilities/resolvers.py +0 -286
  114. additory/utilities/settings.py +0 -167
  115. additory/utilities/units.py +0 -749
  116. additory/utilities/validators.py +0 -153
  117. additory-0.1.0a4.dist-info/METADATA +0 -311
  118. additory-0.1.0a4.dist-info/RECORD +0 -72
  119. additory-0.1.0a4.dist-info/licenses/LICENSE +0 -21
  120. {additory-0.1.0a4.dist-info → additory-0.1.1a2.dist-info}/WHEEL +0 -0
  121. {additory-0.1.0a4.dist-info → additory-0.1.1a2.dist-info}/top_level.txt +0 -0
@@ -1,567 +0,0 @@
1
- """
2
- Pattern Resolution with Fallback Logic
3
-
4
- Implements the fallback resolution hierarchy for pattern lookup:
5
- 1. User namespace patterns (if enabled, based on priority)
6
- 2. Imported .list files (non-global)
7
- 3. global.list (built-in)
8
- 4. Imported .properties files (non-global)
9
- 5. global.properties (built-in)
10
- 6. Error if not found
11
-
12
- User namespace priority options:
13
- - "highest": Check user namespace first (before everything)
14
- - "before_imports": Check user namespace before imports (default)
15
- - "after_imports": Check user namespace after imports
16
- - "lowest": Check user namespace last (after everything)
17
-
18
- Usage:
19
- from additory.common.resolver import resolve_pattern, PreferMode
20
-
21
- # Without user namespace
22
- result = resolve_pattern(
23
- pattern_name="first_names",
24
- imports=["global", "finance"],
25
- prefer_mode=PreferMode.DEFAULT,
26
- base_path="reference/schema_definitions"
27
- )
28
-
29
- # With user namespace
30
- from additory.common.resolver import PatternResolver
31
-
32
- resolver = PatternResolver(
33
- base_path="reference/schema_definitions",
34
- enable_user_namespace=True,
35
- user_namespace_priority="before_imports"
36
- )
37
-
38
- result = resolver.resolve("my_custom_pattern", ["global"])
39
-
40
- if result.found:
41
- print(f"Found in: {result.source}")
42
- print(f"Type: {result.pattern_type}")
43
- print(f"Value: {result.value}")
44
- """
45
-
46
- from typing import Union, List, Optional, Dict
47
- from pathlib import Path
48
- from dataclasses import dataclass
49
- from enum import Enum
50
- import logging
51
-
52
- from .lists import load_list_file, get_list_values, ListFileError
53
- from .patterns import load_properties_file, get_pattern, PatternFileError
54
-
55
-
56
- # Configure logging
57
- logger = logging.getLogger(__name__)
58
-
59
-
60
- class PreferMode(Enum):
61
- """Pattern resolution preference modes."""
62
- DEFAULT = "default" # Lists first, regex fallback
63
- LIST_ONLY = "list_only" # Lists only, error if not found
64
- REGEX_ONLY = "regex_only" # Regex only, error if not found
65
- USER_ONLY = "user_only" # User namespace only (Phase II)
66
- BUILTIN_ONLY = "builtin_only" # Built-in patterns only (no user namespace)
67
-
68
-
69
- @dataclass
70
- class PatternResolutionResult:
71
- """Result of pattern resolution."""
72
- found: bool
73
- value: Optional[Union[List[str], str]] = None
74
- pattern_type: Optional[str] = None # "list" or "regex"
75
- source: Optional[str] = None # File where pattern was found
76
- fallback_used: bool = False
77
- error_message: Optional[str] = None
78
-
79
-
80
- class PatternResolver:
81
- """
82
- Resolves patterns with fallback logic.
83
-
84
- Implements the fallback hierarchy:
85
- 1. User namespace patterns (if enabled)
86
- 2. Imported .list files (non-global)
87
- 3. global.list
88
- 4. Imported .properties files (non-global)
89
- 5. global.properties
90
- """
91
-
92
- def __init__(
93
- self,
94
- base_path: str = "reference/schema_definitions",
95
- enable_user_namespace: bool = False,
96
- user_namespace_priority: str = "before_imports",
97
- user_namespace_manager=None
98
- ):
99
- """
100
- Initialize resolver.
101
-
102
- Args:
103
- base_path: Base directory for .list and .properties files
104
- enable_user_namespace: Enable user namespace resolution
105
- user_namespace_priority: User namespace priority
106
- - "before_imports": Check user namespace before imports
107
- - "after_imports": Check user namespace after imports
108
- - "highest": Check user namespace first (before everything)
109
- - "lowest": Check user namespace last (after everything)
110
- user_namespace_manager: Optional UserNamespaceManager instance
111
- """
112
- self.base_path = Path(base_path)
113
- self.enable_user_namespace = enable_user_namespace
114
- self.user_namespace_priority = user_namespace_priority
115
- self._list_cache: Dict[str, Dict[str, List[str]]] = {}
116
- self._pattern_cache: Dict[str, Dict[str, str]] = {}
117
- self._user_namespace_manager = user_namespace_manager
118
-
119
- # Initialize user namespace if enabled and not provided
120
- if self.enable_user_namespace and self._user_namespace_manager is None:
121
- try:
122
- from additory.core.user_namespace import get_user_namespace_manager
123
- self._user_namespace_manager = get_user_namespace_manager()
124
- if self._user_namespace_manager.is_initialized():
125
- logger.info("User namespace enabled and initialized")
126
- else:
127
- logger.warning("User namespace enabled but not initialized")
128
- except ImportError:
129
- logger.warning("User namespace module not available")
130
- self.enable_user_namespace = False
131
-
132
- def _load_list_file_cached(self, filename: str) -> Optional[Dict[str, List[str]]]:
133
- """Load .list file with caching."""
134
- if filename in self._list_cache:
135
- return self._list_cache[filename]
136
-
137
- filepath = self.base_path / filename
138
-
139
- try:
140
- lists = load_list_file(str(filepath))
141
- self._list_cache[filename] = lists
142
- return lists
143
- except ListFileError as e:
144
- logger.debug(f"Failed to load {filename}: {e}")
145
- return None
146
-
147
- def _load_properties_file_cached(self, filename: str) -> Optional[Dict[str, str]]:
148
- """Load .properties file with caching."""
149
- if filename in self._pattern_cache:
150
- return self._pattern_cache[filename]
151
-
152
- filepath = self.base_path / filename
153
-
154
- try:
155
- patterns = load_properties_file(str(filepath))
156
- self._pattern_cache[filename] = patterns
157
- return patterns
158
- except PatternFileError as e:
159
- logger.debug(f"Failed to load {filename}: {e}")
160
- return None
161
-
162
- def resolve_from_lists(
163
- self,
164
- pattern_name: str,
165
- imports: List[str]
166
- ) -> PatternResolutionResult:
167
- """
168
- Resolve pattern from .list files.
169
-
170
- Priority:
171
- 1. Imported .list files (non-global)
172
- 2. global.list
173
- """
174
- # Check imported .list files (non-global)
175
- for import_name in imports:
176
- if import_name == "global":
177
- continue # Skip global, check it last
178
-
179
- filename = f"{import_name}.list"
180
- lists = self._load_list_file_cached(filename)
181
-
182
- if lists:
183
- values = get_list_values(pattern_name, lists)
184
- if values:
185
- logger.info(f"✓ Found '{pattern_name}' in {filename}")
186
- return PatternResolutionResult(
187
- found=True,
188
- value=values,
189
- pattern_type="list",
190
- source=filename,
191
- fallback_used=False
192
- )
193
-
194
- # Check global.list (fallback)
195
- lists = self._load_list_file_cached("global.list")
196
- if lists:
197
- values = get_list_values(pattern_name, lists)
198
- if values:
199
- logger.info(f"✓ Found '{pattern_name}' in global.list (fallback)")
200
- return PatternResolutionResult(
201
- found=True,
202
- value=values,
203
- pattern_type="list",
204
- source="global.list",
205
- fallback_used=True
206
- )
207
-
208
- return PatternResolutionResult(found=False)
209
-
210
- def resolve_from_patterns(
211
- self,
212
- pattern_name: str,
213
- imports: List[str]
214
- ) -> PatternResolutionResult:
215
- """
216
- Resolve pattern from .properties files.
217
-
218
- Priority:
219
- 1. Imported .properties files (non-global)
220
- 2. global.properties
221
- """
222
- # Check imported .properties files (non-global)
223
- for import_name in imports:
224
- if import_name == "global":
225
- continue # Skip global, check it last
226
-
227
- filename = f"{import_name}.properties"
228
- patterns = self._load_properties_file_cached(filename)
229
-
230
- if patterns:
231
- pattern = get_pattern(pattern_name, patterns)
232
- if pattern:
233
- logger.info(f"✓ Found '{pattern_name}' in {filename}")
234
- return PatternResolutionResult(
235
- found=True,
236
- value=pattern,
237
- pattern_type="regex",
238
- source=filename,
239
- fallback_used=False
240
- )
241
-
242
- # Check global.properties (fallback)
243
- patterns = self._load_properties_file_cached("global.properties")
244
- if patterns:
245
- pattern = get_pattern(pattern_name, patterns)
246
- if pattern:
247
- logger.info(f"✓ Found '{pattern_name}' in global.properties (fallback)")
248
- return PatternResolutionResult(
249
- found=True,
250
- value=pattern,
251
- pattern_type="regex",
252
- source="global.properties",
253
- fallback_used=True
254
- )
255
-
256
- return PatternResolutionResult(found=False)
257
-
258
- def resolve(
259
- self,
260
- pattern_name: str,
261
- imports: List[str],
262
- prefer_mode: PreferMode = PreferMode.DEFAULT
263
- ) -> PatternResolutionResult:
264
- """
265
- Resolve pattern with fallback logic including user namespace.
266
-
267
- Resolution hierarchy (with user namespace enabled):
268
- 1. User namespace (if priority = "highest" or "before_imports")
269
- 2. Imported .list files (non-global)
270
- 3. global.list
271
- 4. User namespace (if priority = "after_imports")
272
- 5. Imported .properties files (non-global)
273
- 6. global.properties
274
- 7. User namespace (if priority = "lowest")
275
-
276
- Args:
277
- pattern_name: Name of pattern to resolve
278
- imports: List of imports from TOML (e.g., ["global", "finance"])
279
- prefer_mode: Resolution preference mode
280
-
281
- Returns:
282
- PatternResolutionResult with resolution details
283
- """
284
- logger.info(f"Resolving pattern '{pattern_name}' with mode {prefer_mode.value}")
285
-
286
- # Mode: user_only
287
- if prefer_mode == PreferMode.USER_ONLY:
288
- result = self.resolve_from_user_namespace(pattern_name)
289
- if not result.found:
290
- result.error_message = f"Pattern '{pattern_name}' not found in user namespace"
291
- return result
292
-
293
- # Mode: builtin_only (disable user namespace for this resolution)
294
- elif prefer_mode == PreferMode.BUILTIN_ONLY:
295
- # Temporarily disable user namespace
296
- original_enable = self.enable_user_namespace
297
- self.enable_user_namespace = False
298
-
299
- try:
300
- # Use default resolution without user namespace
301
- result = self._resolve_builtin(pattern_name, imports)
302
- return result
303
- finally:
304
- self.enable_user_namespace = original_enable
305
-
306
- # Mode: list_only
307
- elif prefer_mode == PreferMode.LIST_ONLY:
308
- result = self._resolve_with_user_namespace(
309
- pattern_name, imports, lists_only=True
310
- )
311
- if not result.found:
312
- result.error_message = f"Pattern '{pattern_name}' not found in any .list file"
313
- return result
314
-
315
- # Mode: regex_only
316
- elif prefer_mode == PreferMode.REGEX_ONLY:
317
- result = self._resolve_with_user_namespace(
318
- pattern_name, imports, regex_only=True
319
- )
320
- if not result.found:
321
- result.error_message = f"Pattern '{pattern_name}' not found in any .properties file"
322
- return result
323
-
324
- # Mode: default (lists first, regex fallback, with user namespace)
325
- else:
326
- result = self._resolve_with_user_namespace(pattern_name, imports)
327
-
328
- if not result.found:
329
- result.error_message = (
330
- f"Pattern '{pattern_name}' not found in any .list or .properties file"
331
- )
332
-
333
- return result
334
-
335
- def _resolve_builtin(
336
- self,
337
- pattern_name: str,
338
- imports: List[str]
339
- ) -> PatternResolutionResult:
340
- """
341
- Resolve pattern from built-in patterns only (no user namespace).
342
-
343
- Used for BUILTIN_ONLY mode.
344
- """
345
- # Try lists first
346
- result = self.resolve_from_lists(pattern_name, imports)
347
- if result.found:
348
- return result
349
-
350
- # Fallback to regex
351
- logger.warning(f"'{pattern_name}' not found in any .list file, trying .properties")
352
- result = self.resolve_from_patterns(pattern_name, imports)
353
-
354
- if result.found:
355
- result.fallback_used = True
356
-
357
- return result
358
-
359
- def _resolve_with_user_namespace(
360
- self,
361
- pattern_name: str,
362
- imports: List[str],
363
- lists_only: bool = False,
364
- regex_only: bool = False
365
- ) -> PatternResolutionResult:
366
- """
367
- Resolve pattern with user namespace support.
368
-
369
- Implements the full resolution hierarchy based on user_namespace_priority.
370
- """
371
- # Priority: highest (check user namespace first)
372
- if self.enable_user_namespace and self.user_namespace_priority == "highest":
373
- result = self.resolve_from_user_namespace(pattern_name)
374
- if result.found:
375
- return result
376
-
377
- # Priority: before_imports (check user namespace before imports)
378
- if self.enable_user_namespace and self.user_namespace_priority == "before_imports":
379
- result = self.resolve_from_user_namespace(pattern_name)
380
- if result.found:
381
- return result
382
-
383
- # Check lists (unless regex_only)
384
- if not regex_only:
385
- result = self.resolve_from_lists(pattern_name, imports)
386
- if result.found:
387
- return result
388
-
389
- # Priority: after_imports (check user namespace after imports, before global)
390
- if self.enable_user_namespace and self.user_namespace_priority == "after_imports":
391
- result = self.resolve_from_user_namespace(pattern_name)
392
- if result.found:
393
- result.fallback_used = True
394
- return result
395
-
396
- # Check regex patterns (unless lists_only)
397
- if not lists_only:
398
- logger.warning(f"'{pattern_name}' not found in any .list file, trying .properties")
399
- result = self.resolve_from_patterns(pattern_name, imports)
400
- if result.found:
401
- result.fallback_used = True
402
- return result
403
-
404
- # Priority: lowest (check user namespace last)
405
- if self.enable_user_namespace and self.user_namespace_priority == "lowest":
406
- result = self.resolve_from_user_namespace(pattern_name)
407
- if result.found:
408
- result.fallback_used = True
409
- return result
410
-
411
- # Not found anywhere
412
- return PatternResolutionResult(found=False)
413
-
414
- def clear_cache(self):
415
- """Clear cached files (useful for testing)."""
416
- self._list_cache.clear()
417
- self._pattern_cache.clear()
418
- if self._user_namespace_manager:
419
- self._user_namespace_manager.clear_cache()
420
-
421
- def resolve_from_user_namespace(
422
- self,
423
- pattern_name: str
424
- ) -> PatternResolutionResult:
425
- """
426
- Resolve pattern from user namespace.
427
-
428
- Checks user .list and .properties files.
429
- """
430
- if not self.enable_user_namespace or not self._user_namespace_manager:
431
- return PatternResolutionResult(found=False)
432
-
433
- try:
434
- # Get all user patterns
435
- user_lists, user_properties = self._user_namespace_manager.get_all_user_patterns()
436
-
437
- # Check user lists first
438
- if pattern_name in user_lists:
439
- logger.info(f"✓ Found '{pattern_name}' in user namespace (list)")
440
- return PatternResolutionResult(
441
- found=True,
442
- value=user_lists[pattern_name],
443
- pattern_type="list",
444
- source="user:namespace",
445
- fallback_used=False
446
- )
447
-
448
- # Check user properties
449
- if pattern_name in user_properties:
450
- logger.info(f"✓ Found '{pattern_name}' in user namespace (regex)")
451
- return PatternResolutionResult(
452
- found=True,
453
- value=user_properties[pattern_name],
454
- pattern_type="regex",
455
- source="user:namespace",
456
- fallback_used=False
457
- )
458
-
459
- except Exception as e:
460
- logger.warning(f"Error resolving from user namespace: {e}")
461
-
462
- return PatternResolutionResult(found=False)
463
-
464
-
465
- # Global resolver instance
466
- _resolver = None
467
-
468
-
469
- def get_resolver(
470
- base_path: str = "reference/schema_definitions",
471
- enable_user_namespace: bool = False,
472
- user_namespace_priority: str = "before_imports"
473
- ) -> PatternResolver:
474
- """
475
- Get or create global resolver instance.
476
-
477
- Args:
478
- base_path: Base directory for pattern files
479
- enable_user_namespace: Enable user namespace resolution
480
- user_namespace_priority: User namespace priority
481
-
482
- Returns:
483
- PatternResolver instance
484
- """
485
- global _resolver
486
- if _resolver is None:
487
- _resolver = PatternResolver(
488
- base_path,
489
- enable_user_namespace,
490
- user_namespace_priority
491
- )
492
- return _resolver
493
-
494
-
495
- def resolve_pattern(
496
- pattern_name: str,
497
- imports: List[str],
498
- prefer_mode: PreferMode = PreferMode.DEFAULT,
499
- base_path: str = "reference/schema_definitions",
500
- enable_user_namespace: bool = False,
501
- user_namespace_priority: str = "before_imports"
502
- ) -> PatternResolutionResult:
503
- """
504
- Resolve pattern with fallback logic (convenience function).
505
-
506
- Args:
507
- pattern_name: Name of pattern to resolve
508
- imports: List of imports from TOML
509
- prefer_mode: Resolution preference mode
510
- base_path: Base directory for pattern files
511
- enable_user_namespace: Enable user namespace resolution
512
- user_namespace_priority: User namespace priority
513
-
514
- Returns:
515
- PatternResolutionResult
516
-
517
- Example:
518
- >>> result = resolve_pattern("first_names", ["global"], PreferMode.DEFAULT)
519
- >>> if result.found:
520
- ... print(f"Found in {result.source}: {result.value[:3]}")
521
- Found in global.list: ['Arjun', 'Vikram', 'Samuel']
522
-
523
- >>> # With user namespace
524
- >>> result = resolve_pattern(
525
- ... "my_custom_pattern",
526
- ... ["global"],
527
- ... enable_user_namespace=True
528
- ... )
529
- >>> if result.found:
530
- ... print(f"Found in {result.source}")
531
- Found in user:namespace
532
- """
533
- resolver = get_resolver(base_path, enable_user_namespace, user_namespace_priority)
534
- return resolver.resolve(pattern_name, imports, prefer_mode)
535
-
536
-
537
- def resolve_with_logging(
538
- pattern_name: str,
539
- imports: List[str],
540
- prefer_mode: PreferMode = PreferMode.DEFAULT,
541
- base_path: str = "reference/schema_definitions"
542
- ) -> PatternResolutionResult:
543
- """
544
- Resolve pattern with detailed logging (convenience function).
545
-
546
- Same as resolve_pattern but with INFO-level logging enabled.
547
- """
548
- # Temporarily set logging level to INFO
549
- original_level = logger.level
550
- logger.setLevel(logging.INFO)
551
-
552
- try:
553
- result = resolve_pattern(pattern_name, imports, prefer_mode, base_path)
554
-
555
- # Log result
556
- if result.found:
557
- logger.info(f"Resolution successful:")
558
- logger.info(f" Pattern: {pattern_name}")
559
- logger.info(f" Source: {result.source}")
560
- logger.info(f" Type: {result.pattern_type}")
561
- logger.info(f" Fallback used: {result.fallback_used}")
562
- else:
563
- logger.error(f"Resolution failed: {result.error_message}")
564
-
565
- return result
566
- finally:
567
- logger.setLevel(original_level)