Skip to content
Draft

Lazy #15138

Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Try to breakup some import cycles dependencies.
  • Loading branch information
Carreau committed Feb 20, 2026
commit 739be9e1654680d378675ef9992277e03a7156c0
14 changes: 3 additions & 11 deletions IPython/core/debugger.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,6 @@
from contextlib import contextmanager
from functools import lru_cache

from IPython import get_ipython
from IPython.core.debugger_backport import PdbClosureBackport
from IPython.utils import PyColorize
from IPython.utils.PyColorize import TokenStream
Expand Down Expand Up @@ -243,6 +242,8 @@ def __init__(
stdin=None,
stdout=None,
context: int | None | str = 5,
*,
shell: TerminalInteractiveShell = None,
**kwargs,
):
"""Create a new IPython debugger.
Expand All @@ -258,6 +259,7 @@ def __init__(
context : int
Number of lines of source code context to show when
displaying stacktrace information.
shell : InteractiveShell
**kwargs
Passed to pdb.Pdb.
Expand All @@ -283,16 +285,6 @@ def __init__(
# IPython changes...
self.shell = get_ipython()

if self.shell is None:
save_main = sys.modules["__main__"]
# No IPython instance running, we must create one
from IPython.terminal.interactiveshell import TerminalInteractiveShell

self.shell = TerminalInteractiveShell.instance()
# needed by any code which calls __import__("__main__") after
# the debugger was entered. See also #9941.
sys.modules["__main__"] = save_main

self.aliases = {}

theme_name = self.shell.colors
Expand Down
8 changes: 1 addition & 7 deletions IPython/core/display.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

from typing import Optional

from IPython.core.pylabtools import _pngxy
from IPython.testing.skipdoctest import skip_doctest
from . import display_functions

Expand Down Expand Up @@ -799,13 +800,6 @@ def _repr_javascript_(self):
_WEBP = b"WEBP"


def _pngxy(data):
"""read the (width, height) from a PNG header"""
ihdr = data.index(b'IHDR')
# next 8 bytes are width/height
return struct.unpack('>ii', data[ihdr+4:ihdr+12])


def _jpegxy(data):
"""read the (width, height) from a JPEG header"""
# adapted from http://www.64lines.com/jpeg-width-height
Expand Down
5 changes: 3 additions & 2 deletions IPython/core/interactiveshell.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,6 @@
from IPython.core.displayhook import DisplayHook
from IPython.core.displaypub import DisplayPublisher
from IPython.core.error import InputRejected, UsageError
from IPython.core.events import EventManager, available_events
from IPython.core.extensions import ExtensionManager
from IPython.core.formatters import DisplayFormatter
from IPython.core.history import HistoryManager, HistoryOutput
Expand All @@ -83,7 +82,7 @@
from IPython.core.profiledir import ProfileDir
from IPython.core.tips import pick_tip
from IPython.core.usage import default_banner
from IPython.display import display
from IPython.core.display_functions import display
from IPython.paths import get_ipython_dir
from IPython.testing.skipdoctest import skip_doctest
from IPython.utils import PyColorize, io, openpy, py3compat
Expand Down Expand Up @@ -1103,6 +1102,8 @@ def set_hook(self, name, hook, priority=50, str_key=None, re_key=None):
#-------------------------------------------------------------------------

def init_events(self):
# Import here to break circular dependency with IPython.core.events
from IPython.core.events import EventManager, available_events
self.events = EventManager(self, available_events)

self.events.register("pre_execute", self._clear_warning_registry)
Expand Down
10 changes: 8 additions & 2 deletions IPython/core/profiledir.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
# encoding: utf-8
"""An object for managing IPython profile directories."""

# Copyright (c) IPython Development Team.
Expand All @@ -7,10 +6,10 @@
import os
import shutil
import errno
import IPython
from pathlib import Path

from traitlets.config.configurable import LoggingConfigurable
from ..paths import get_ipython_package_dir
from ..utils.path import expand_path, ensure_dir_exists
from traitlets import Unicode, Bool, observe

Expand Down Expand Up @@ -242,3 +241,10 @@ def find_profile_dir(cls, profile_dir, config=None):
if not os.path.isdir(profile_dir):
raise ProfileDirError('Profile directory not found: %s' % profile_dir)
return cls(location=profile_dir, config=config)


def get_ipython_package_dir() -> str:
"""Get the base directory where IPython itself is installed."""
ipdir = os.path.dirname(IPython.__file__)
assert isinstance(ipdir, str)
return ipdir
11 changes: 9 additions & 2 deletions IPython/core/pylabtools.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,19 @@
from io import BytesIO
from binascii import b2a_base64
from functools import partial
import struct
import warnings

from IPython.core.display import _pngxy
from IPython.utils.decorators import flag_calls


def _pngxy(data):
"""read the (width, height) from a PNG header"""
ihdr = data.index(b'IHDR')
# next 8 bytes are width/height
return struct.unpack('>ii', data[ihdr+4:ihdr+12])


# Matplotlib backend resolution functionality moved from IPython to Matplotlib
# in IPython 8.24 and Matplotlib 3.9.0. Need to keep `backends` and `backend2gui`
# here for earlier Matplotlib and for external backend libraries such as
Expand Down Expand Up @@ -441,7 +448,7 @@ def import_pylab(user_ns, import_all=True):

# IPython symbols to add
user_ns['figsize'] = figsize
from IPython.display import display
from IPython.core.display_functions import display
# Add display and getfigs to the user's namespace
user_ns['display'] = display
user_ns['getfigs'] = getfigs
Expand Down
7 changes: 1 addition & 6 deletions IPython/paths.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from warnings import warn

import IPython
from IPython.core.profiledir import ProfileDir, ProfileDirError, get_ipython_package_dir
from IPython.utils.importstring import import_item
from IPython.utils.path import (
get_home_dir,
Expand Down Expand Up @@ -86,11 +87,6 @@ def get_ipython_cache_dir() -> str:
return ipdir


def get_ipython_package_dir() -> str:
"""Get the base directory where IPython itself is installed."""
ipdir = os.path.dirname(IPython.__file__)
assert isinstance(ipdir, str)
return ipdir


def get_ipython_module_path(module_str):
Expand All @@ -113,7 +109,6 @@ def locate_profile(profile='default'):

I.e. find $IPYTHONDIR/profile_whatever.
"""
from IPython.core.profiledir import ProfileDir, ProfileDirError
try:
pd = ProfileDir.find_profile_dir_by_name(get_ipython_dir(), profile)
except ProfileDirError as e:
Expand Down
13 changes: 12 additions & 1 deletion IPython/terminal/debugger.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@
import os
import sys

from IPython import get_ipython
from IPython.core.debugger import Pdb
from IPython.core.completer import IPCompleter
from IPython.terminal.interactiveshell import TerminalInteractiveShell
from .ptutils import IPythonPTCompleter
from .shortcuts import create_ipython_shortcuts
from . import embed
Expand All @@ -26,7 +28,16 @@ class TerminalPdb(Pdb):
"""Standalone IPython debugger."""

def __init__(self, *args, pt_session_options=None, **kwargs):
Pdb.__init__(self, *args, **kwargs)
shell = get_ipython()
if shell is None:
save_main = sys.modules["__main__"]
# No IPython instance running, we must create one
shell = TerminalInteractiveShell.instance()
# needed by any code which calls __import__("__main__") after
# the debugger was entered. See also #9941.
sys.modules["__main__"] = save_main

Pdb.__init__(self, *args, shell=shell, **kwargs)
self._ptcomp = None
self.pt_init(pt_session_options)
self.thread_executor = ThreadPoolExecutor(1)
Expand Down
2 changes: 1 addition & 1 deletion IPython/terminal/interactiveshell.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@
from pygments.styles import get_style_by_name
from pygments.style import Style

from .debugger import TerminalPdb, Pdb
from .magics import TerminalMagics
from .pt_inputhooks import get_inputhook_name_and_func
from .prompts import Prompts, ClassicPrompts, RichPromptDisplayHook
Expand Down Expand Up @@ -246,6 +245,7 @@ class TerminalInteractiveShell(InteractiveShell):

@property
def debugger_cls(self):
from .debugger import TerminalPdb, Pdb
return Pdb if self.simple_prompt else TerminalPdb

confirm_exit = Bool(True,
Expand Down
4 changes: 0 additions & 4 deletions IPython/utils/io.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,6 @@
from pathlib import Path
from warnings import warn

from IPython.utils.decorators import undoc
from .capture import CapturedIO, capture_output


class Tee:
"""A class to duplicate an output stream to stdout/err.

Expand Down
Loading