Skip to content

Commit

Permalink
Improve session.is_interactive
Browse files Browse the repository at this point in the history
Try to figure out from inspecting the stack whether the immediate caller
is in the __main__ module. Let's see how brittle this turns out to be in
practice.
  • Loading branch information
hoelzl committed Dec 12, 2020
1 parent 08c9387 commit d3b1484
Showing 1 changed file with 41 additions and 3 deletions.
44 changes: 41 additions & 3 deletions nbex/interactive.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@
# writing code that outputs interesting information when being run
# interactively without being annoying when batch processing data.

# %%
import sys
import inspect
from IPython.core.display import display
from pprint import pprint

Expand All @@ -16,12 +18,45 @@ class Session:
"""Control behavior in interactive vs. batch mode"""

def __init__(self) -> None:
self.is_interactive = self.python_is_interactive
self._is_interactive_forced_false = False

@property
def python_is_interactive(self):
def python_is_interactive(self) -> bool:
return hasattr(sys, "ps1")

@staticmethod
def _find_first_non_nbex_stack_frame():
caller_frame = inspect.currentframe().f_back

# Walk up at most 100 stack frames to find one that is not from
# nbex.interactive
for _ in range(100):
if caller_frame.f_globals["__name__"] == "nbex.interactive":
caller_frame = caller_frame.f_back
else:
break
else:
print("Walked 100 stack frames inside nbex.interactive?")

return caller_frame

@property
def _is_called_from_main(self):
caller_frame = self._find_first_non_nbex_stack_frame()
return caller_frame.f_globals["__name__"] == "__main__"

@property
def is_interactive(self) -> bool:
if self._is_interactive_forced_false:
return False


return self._is_called_from_main and self.python_is_interactive

@is_interactive.setter
def set_is_interactive(self, value: bool) -> None:
self._is_interactive_forced_false = not value


session = Session()

Expand All @@ -42,3 +77,6 @@ def print_interactive(*obj: object):
"""Print `obj` when in interactive mode."""
if session.is_interactive:
print(*obj)


# %%

0 comments on commit d3b1484

Please sign in to comment.