/ bootstrap.py
bootstrap.py
1 """ 2 DreamTalk Bootstrap - Path Resolution for Holarchic Submodules 3 4 This module enables the holarchic submodule pattern for DreamTalk symbols. 5 It finds the nearest initialized DreamTalk library by walking up the directory 6 tree, ensuring all code in a symbol holarchy uses the same module instance. 7 8 USAGE IN DREAMNODE FILES: 9 ========================= 10 11 Replace the old dreamtalk_init.py pattern with this simple import: 12 13 # Old pattern (requires dreamtalk_init.py in each DreamNode): 14 from dreamtalk_init import init; init() 15 from DreamTalk.imports import * 16 17 # New pattern (no extra file needed): 18 from pathlib import Path; import sys 19 sys.path.insert(0, str(Path(__file__).resolve().parent / 'submodules')) 20 from DreamTalk.bootstrap import init; init() 21 from DreamTalk.imports import * 22 23 Or even simpler, just add submodules to path and import directly: 24 25 from pathlib import Path; import sys 26 sys.path.insert(0, str(Path(__file__).resolve().parent / 'submodules')) 27 from DreamTalk.imports import * 28 29 The bootstrap.init() call is only needed for complex nested holarchies 30 where you want to ensure all nested submodules use the same DreamTalk. 31 """ 32 33 import sys 34 from pathlib import Path 35 36 _initialized = False 37 _dreamtalk_path = None 38 39 40 def find_dreamtalk(start_path=None): 41 """ 42 Walk up the directory tree to find an initialized DreamTalk submodule. 43 44 An initialized DreamTalk is identified by the presence of imports.py 45 (empty submodule pointers won't have this file). 46 47 Args: 48 start_path: Starting directory for search. Defaults to caller's location. 49 50 Returns: 51 Path to the submodules/ directory containing initialized DreamTalk. 52 53 Raises: 54 ImportError: If no initialized DreamTalk is found. 55 """ 56 if start_path is None: 57 # Get the caller's file location by walking up the stack 58 import inspect 59 frame = inspect.currentframe() 60 if frame: 61 caller_frame = frame.f_back 62 while caller_frame: 63 caller_file = caller_frame.f_globals.get('__file__') 64 if caller_file and 'DreamTalk' not in str(caller_file): 65 start_path = Path(caller_file).parent 66 break 67 caller_frame = caller_frame.f_back 68 if start_path is None: 69 start_path = Path.cwd() 70 71 current = Path(start_path).resolve() 72 73 while current != current.parent: 74 # Check for DreamTalk in submodules/ 75 candidate = current / "submodules" / "DreamTalk" 76 if (candidate / "imports.py").exists(): 77 return current / "submodules" 78 79 # Also check if we ARE in DreamTalk (for development/testing) 80 if (current / "imports.py").exists() and current.name == "DreamTalk": 81 return current.parent 82 83 current = current.parent 84 85 raise ImportError( 86 "No initialized DreamTalk found in parent hierarchy.\n" 87 "Ensure DreamTalk is added as a submodule and initialized:\n" 88 " git submodule add <dreamtalk-url> submodules/DreamTalk\n" 89 " git submodule update --init submodules/DreamTalk" 90 ) 91 92 93 def init(start_path=None): 94 """ 95 Initialize the Python path to use the nearest DreamTalk. 96 97 This ensures all nested submodules use the same DreamTalk instance, 98 preventing module duplication in complex holarchies. 99 100 Args: 101 start_path: Starting directory for search. Defaults to caller's location. 102 103 Returns: 104 Path to the DreamTalk directory that was added to sys.path. 105 """ 106 global _initialized, _dreamtalk_path 107 108 if _initialized: 109 return _dreamtalk_path 110 111 submodules_path = find_dreamtalk(start_path) 112 113 # Add to sys.path if not already present 114 submodules_str = str(submodules_path) 115 if submodules_str not in sys.path: 116 sys.path.insert(0, submodules_str) 117 118 _dreamtalk_path = submodules_path / "DreamTalk" 119 _initialized = True 120 121 return _dreamtalk_path 122 123 124 def get_dreamtalk_path(): 125 """Get the path to the initialized DreamTalk, or None if not yet initialized.""" 126 return _dreamtalk_path 127 128 129 def is_initialized(): 130 """Check if DreamTalk path resolution has been performed.""" 131 return _initialized