Skip to content

Commit 2a1a779

Browse files
committed
Fixing init order t resolve recursion in first rebuild in certain edge cases.
The bubble_manager is now guaranteed to exist before _check_and_run_pending_rebuild is ever called, resolving the AttributeError and breaking the infinite loop.
1 parent b2a14b8 commit 2a1a779

1 file changed

Lines changed: 39 additions & 40 deletions

File tree

src/omnipkg/core.py

Lines changed: 39 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -4241,12 +4241,13 @@ def get_quantum_healing_context(self) -> dict:
42414241
}
42424242

42434243
class omnipkg:
4244-
4244+
42454245
def __init__(self, config_manager: ConfigManager, minimal_mode: bool = False):
42464246
"""
42474247
Initializes Omnipkg with optional minimal mode for lightweight commands.
42484248

42494249
Args:
4250+
config_manager: The configuration manager instance.
42504251
minimal_mode: If True, skips database/cache initialization for commands
42514252
that only need config access (swap, version, etc.)
42524253
"""
@@ -4257,64 +4258,62 @@ def __init__(self, config_manager: ConfigManager, minimal_mode: bool = False):
42574258
if not self.config:
42584259
if len(sys.argv) > 1 and sys.argv[1] in ['reset-config', 'doctor']:
42594260
pass
4260-
else:
4261-
raise RuntimeError('OmnipkgCore cannot initialize: Configuration is missing or invalid.')
4262-
4263-
# 🎯 CRITICAL FIX: Set these IMMEDIATELY like multiversion_base
4264-
# These are used by check_package_installed_fast during preflight
4265-
self.env_id = self._get_env_id()
4266-
self.multiversion_base = Path(self.config['multiversion_base'])
4267-
self.site_packages_root = Path(self.config['site_packages_path']) # 🎯 ADD THIS!
4268-
4269-
# Minimal initialization for lightweight commands
4270-
if minimal_mode:
4271-
self.interpreter_manager = InterpreterManager(self.config_manager)
4272-
safe_print(_('✅ Omnipkg core initialized (minimal mode).'))
4273-
return # EXIT EARLY
4274-
self._self_heal_omnipkg_installation()
4261+
elif not minimal_mode:
4262+
raise RuntimeError('OmnipkgCore cannot initialize: Configuration is missing or invalid.')
4263+
4264+
# --- CORE ATTRIBUTES (Needed early) ---
42754265
self.env_id = self._get_env_id()
42764266
self.multiversion_base = Path(self.config['multiversion_base'])
4277-
self.cache_client = None
4278-
self._cache_connection_status = None
4279-
self.initialize_pypi_cache()
4280-
self._check_and_run_pending_rebuild()
4267+
self.site_packages_root = Path(self.config['site_packages_path'])
42814268
self._info_cache = {}
4282-
self._prime_loader_cache()
42834269
self._installed_packages_cache = None
42844270
self.http_session = http_requests.Session()
4285-
self.multiversion_base.mkdir(parents=True, exist_ok=True)
4271+
self.cache_client = None
4272+
self._cache_connection_status = None
4273+
4274+
# --- PHASE 1: INITIALIZE MANAGERS ---
4275+
# These are needed by almost all commands, including minimal ones.
4276+
self.interpreter_manager = InterpreterManager(self.config_manager)
4277+
4278+
# Minimal mode exits here. Commands like 'swap' or 'list python' now have what they need.
4279+
if minimal_mode:
4280+
safe_print(_('✅ Omnipkg core initialized (minimal mode).'))
4281+
return
4282+
4283+
# --- PHASE 2: FULL INITIALIZATION FOR HEAVY COMMANDS ---
4284+
# Connect to the cache (Redis or SQLite)
42864285
if not self._connect_cache():
42874286
sys.exit(1)
4288-
# --- ADD THE MIGRATION LOGIC HERE ---
4289-
# V2 MIGRATION: Automatically upgrade legacy global keys to be environment-aware.
4290-
migration_flag_key = f'omnipkg:env_{self.env_id}:migration_v2_env_aware_keys_complete'
4291-
4292-
# We check the flag *before* the expensive scan.
4293-
if not self.cache_client.get(migration_flag_key):
4294-
# Check if there are any old keys that *need* migrating.
4295-
# We use scan_iter for performance, only needing to find one key.
4296-
old_keys_iterator = self.cache_client.scan_iter('omnipkg:pkg:*', count=1)
4297-
if next(old_keys_iterator, None):
4298-
self._perform_redis_key_migration(migration_flag_key)
4299-
else:
4300-
# No old keys found, so we can just set the flag.
4301-
self.cache_client.set(migration_flag_key, 'true')
4302-
# --- END MIGRATION LOGIC ---
4303-
self.interpreter_manager = InterpreterManager(self.config_manager)
4304-
self.hook_manager = ImportHookManager(str(self.config.get('multiversion_base')), config=self.config, cache_client=None)
4305-
self.bubble_manager = BubbleIsolationManager(self.config, self)
43064287

4288+
# Now that we have a cache, initialize other managers that depend on it.
4289+
self.hook_manager = ImportHookManager(str(self.config.get('multiversion_base')), config=self.config, cache_client=self.cache_client)
4290+
self.bubble_manager = BubbleIsolationManager(self.config, self) # <-- CRITICAL: Now exists before rebuild
4291+
4292+
# --- PHASE 3: POST-INITIALIZATION AND SELF-HEALING ---
4293+
# These tasks may depend on the fully initialized managers.
4294+
self._self_heal_omnipkg_installation()
4295+
self.initialize_pypi_cache()
4296+
4297+
# Run database migrations
43074298
migration_flag_key = f'omnipkg:env_{self.env_id}:migration_v2_env_aware_keys_complete'
43084299
if not self.cache_client.get(migration_flag_key):
43094300
old_keys_iterator = self.cache_client.scan_iter('omnipkg:pkg:*', count=1)
43104301
if next(old_keys_iterator, None):
43114302
self._perform_redis_key_migration(migration_flag_key)
43124303
else:
43134304
self.cache_client.set(migration_flag_key, 'true')
4305+
43144306
migration_v3_flag_key = f'{self.redis_env_prefix}migration_v3_install_type_complete'
43154307
if not self.cache_client.get(migration_v3_flag_key):
43164308
self._perform_v3_metadata_migration(migration_v3_flag_key)
43174309

4310+
# Proactively build the loader cache if needed.
4311+
self._prime_loader_cache()
4312+
4313+
# CRITICAL: Run the pending rebuild check LAST, after everything is initialized.
4314+
self._check_and_run_pending_rebuild()
4315+
4316+
# Finally, load the import hooks.
43184317
self.hook_manager.load_version_map()
43194318
self.hook_manager.install_import_hook()
43204319
safe_print(_('✅ Omnipkg core initialized successfully.'))

0 commit comments

Comments
 (0)