/ 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