Skip to content

Commit ae73e53

Browse files
committed
Build InteractiveShell.logger on first access
`IPython.core.logger.Logger` writes the `%logstart` session transcript; sessions that never start one never need it, but it was imported and instantiated during shell initialization. Like `db`, it becomes a lazy property with a setter. Its module also carried, at import time, a global mutation belonging to something else entirely: # prevent jedi/parso's debug messages pipe into interactiveshell logging.getLogger("parso").setLevel(logging.WARNING) That has nothing to do with session transcripts, and it only ever ran because `core.logger` happened to be imported eagerly -- deferring the import silently stops parso being silenced. Move it to `_get_jedi()` in `core/completer.py`, where jedi is imported and configured, which is still before any parso record can be emitted since parso is only reached through jedi. The `logging` import goes with it; `core/logger.py` had no other use for it. In a clean interpreter `import IPython.terminal.ipapp` goes from 489 to 488 modules.
1 parent f51f6d8 commit ae73e53

3 files changed

Lines changed: 35 additions & 10 deletions

File tree

IPython/core/completer.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,19 @@ def _get_jedi() -> ModuleType:
269269
import jedi.api.helpers
270270

271271
jedi.settings.case_insensitive_completion = False
272+
273+
# parso, which jedi parses with, logs copiously at DEBUG level; without
274+
# this those records reach the user's session whenever IPython runs with
275+
# a debug log level. This lived at the top of `IPython.core.logger` --
276+
# a module about `%logstart` session transcripts, nothing to do with
277+
# jedi -- where it worked only because that module happened to be
278+
# imported eagerly at startup. Configure it where jedi itself is
279+
# configured instead, which is still before any parso record can be
280+
# emitted, since parso is only reached through jedi.
281+
import logging
282+
283+
logging.getLogger("parso").setLevel(logging.WARNING)
284+
272285
return jedi
273286

274287

IPython/core/interactiveshell.py

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,6 @@
6666
from IPython.core.formatters import DisplayFormatter
6767
from IPython.core.history import HistoryManager, HistoryOutput
6868
from IPython.core.inputtransformer2 import ESC_MAGIC, ESC_MAGIC2
69-
from IPython.core.logger import Logger
7069
from IPython.core.macro import Macro
7170
from IPython.core.payload import PayloadManager
7271
from IPython.core.prefilter import PrefilterManager
@@ -658,7 +657,6 @@ def __init__(self, ipython_dir=None, profile_dir=None,
658657
self.init_events()
659658
self.init_pushd_popd_magic()
660659
self.init_user_ns()
661-
self.init_logger()
662660
self.init_builtins()
663661

664662
# The following was in post_config_initialization
@@ -858,9 +856,28 @@ def init_pushd_popd_magic(self):
858856

859857
self.dir_stack = []
860858

861-
def init_logger(self) -> None:
862-
self.logger = Logger(self.home_dir, logfname='ipython_log.py',
863-
logmode='rotate')
859+
_logger = None
860+
861+
@property
862+
def logger(self):
863+
"""The session transcript logger behind `%logstart` and friends.
864+
865+
This is *not* the traitlets `log` trait (`self.log`), which is an
866+
ordinary `logging.Logger` for diagnostics; this one writes the
867+
session to a replayable `ipython_log.py`. Sessions that never run
868+
`%logstart` never need it, so it is built on first access.
869+
"""
870+
if self._logger is None:
871+
from IPython.core.logger import Logger
872+
873+
self._logger = Logger(
874+
self.home_dir, logfname="ipython_log.py", logmode="rotate"
875+
)
876+
return self._logger
877+
878+
@logger.setter
879+
def logger(self, value):
880+
self._logger = value
864881

865882
def init_logstart(self) -> None:
866883
"""Initialize logging in case it was requested at the command line.

IPython/core/logger.py

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,10 @@
1717
# Python standard modules
1818
import glob
1919
import io
20-
import logging
2120
import os
2221
import time
2322
from typing import IO
2423

25-
26-
# prevent jedi/parso's debug messages pipe into interactiveshell
27-
logging.getLogger("parso").setLevel(logging.WARNING)
28-
2924
#****************************************************************************
3025
# FIXME: This class isn't a mixin anymore, but it still needs attributes from
3126
# ipython and does input cache management. Finish cleanup later...

0 commit comments

Comments
 (0)