Skip to content

Commit

Permalink
Merge from 2.x: PR #389
Browse files Browse the repository at this point in the history
  • Loading branch information
ccordoba12 committed Jul 1, 2022
2 parents 8a161f6 + f35d7bc commit d44c859
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 61 deletions.
86 changes: 41 additions & 45 deletions spyder_kernels/customize/spydercustomize.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,17 +24,15 @@
import time
import warnings

from IPython import __version__ as ipy_version
from IPython.core.getipython import get_ipython
from IPython.core.inputtransformer2 import (
TransformerManager, leading_indent, leading_empty_lines)

from spyder_kernels.comms.frontendcomm import CommError, frontend_request
from spyder_kernels.comms.frontendcomm import frontend_request
from spyder_kernels.customize.namespace_manager import NamespaceManager
from spyder_kernels.customize.spyderpdb import SpyderPdb, get_new_debugger
from spyder_kernels.customize.umr import UserModuleReloader
from spyder_kernels.customize.utils import (
capture_last_Expr, normalise_filename)
from spyder_kernels.customize.utils import capture_last_Expr, canonic


logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -446,18 +444,23 @@ def exec_code(code, filename, ns_globals, ns_locals=None, post_mortem=False,
__tracebackhide__ = "__pdb_exit__"


def get_file_code(filename, save_all=True):
"""Retrive the content of a file."""
def get_file_code(filename, save_all=True, raise_exception=False):
"""Retrieve the content of a file."""
# Get code from spyder
try:
file_code = frontend_request(blocking=True).get_file_code(
return frontend_request(blocking=True).get_file_code(
filename, save_all=save_all)
except (CommError, TimeoutError, RuntimeError, FileNotFoundError):
file_code = None
if file_code is None:
with open(filename, 'r') as f:
return f.read()
return file_code
except Exception:
# Maybe this is a local file
try:
with open(filename, 'r') as f:
return f.read()
except FileNotFoundError:
pass
if raise_exception:
raise
# Else return None
return None


def runfile(filename=None, args=None, wdir=None, namespace=None,
Expand All @@ -477,40 +480,35 @@ def runfile(filename=None, args=None, wdir=None, namespace=None,

def _exec_file(filename=None, args=None, wdir=None, namespace=None,
post_mortem=False, current_namespace=False, stack_depth=0,
exec_fun=None):
exec_fun=None, canonic_filename=None):
# Tell IPython to hide this frame (>7.16)
__tracebackhide__ = True
ipython_shell = get_ipython()
if filename is None:
filename = get_current_file_name()
if filename is None:
return
else:
# get_debugger replaces \\ by / so we must undo that here
# Otherwise code caching doesn't work
if os.name == 'nt':
filename = filename.replace('/', '\\')

if __umr__.enabled:
__umr__.run()
if args is not None and not isinstance(args, str):
raise TypeError("expected a character buffer object")

try:
file_code = get_file_code(filename)
file_code = get_file_code(filename, raise_exception=True)
except Exception:
print(
"This command failed to be executed because an error occurred"
" while trying to get the file code from Spyder's"
" editor. The error was:\n\n")
get_ipython().showtraceback(exception_only=True)
return
if file_code is None:
print("Could not get code from editor.\n")
return

# Normalise the filename
filename = os.path.abspath(filename)
filename = os.path.normcase(filename)
# Here the remote filename has been used. It must now be valid locally.
if canonic_filename is not None:
filename = canonic_filename
else:
filename = canonic(filename)

with NamespaceManager(filename, namespace, current_namespace,
file_code=file_code, stack_depth=stack_depth + 1
Expand Down Expand Up @@ -580,7 +578,7 @@ def debugfile(filename=None, args=None, wdir=None, post_mortem=False,
if shell.is_debugging():
# Recursive
code = (
"runfile({}".format(repr(normalise_filename(filename))) +
"runfile({}".format(repr(filename)) +
", args=%r, wdir=%r, current_namespace=%r)" % (
args, wdir, current_namespace)
)
Expand All @@ -591,11 +589,13 @@ def debugfile(filename=None, args=None, wdir=None, post_mortem=False,
else:
debugger = get_new_debugger(filename, True)
_exec_file(
filename=debugger.canonic(filename),
args=args, wdir=wdir,
filename=filename,
canonic_filename=debugger.canonic(filename),
args=args,
wdir=wdir,
current_namespace=current_namespace,
exec_fun=debugger.run,
stack_depth=1
stack_depth=1,
)


Expand All @@ -621,7 +621,7 @@ def runcell(cellname, filename=None, post_mortem=False):


def _exec_cell(cellname, filename=None, post_mortem=False, stack_depth=0,
exec_fun=None):
exec_fun=None, canonic_filename=None):
"""
Execute a code cell with a given exec function.
"""
Expand All @@ -631,11 +631,6 @@ def _exec_cell(cellname, filename=None, post_mortem=False, stack_depth=0,
filename = get_current_file_name()
if filename is None:
return
else:
# get_debugger replaces \\ by / so we must undo that here
# Otherwise code caching doesn't work
if os.name == 'nt':
filename = filename.replace('/', '\\')
ipython_shell = get_ipython()
try:
# Get code from spyder
Expand All @@ -655,14 +650,14 @@ def _exec_cell(cellname, filename=None, post_mortem=False, stack_depth=0,
# Trigger `post_execute` to exit the additional pre-execution.
# See Spyder PR #7310.
ipython_shell.events.trigger('post_execute')
try:
file_code = get_file_code(filename, save_all=False)
except Exception:
file_code = None
file_code = get_file_code(filename, save_all=False)

# Normalise the filename
filename = os.path.abspath(filename)
filename = os.path.normcase(filename)
# Here the remote filename has been used. It must now be valid locally.
if canonic_filename is not None:
filename = canonic_filename
else:
# Normalise the filename
filename = canonic(filename)

with NamespaceManager(filename, current_namespace=True,
file_code=file_code, stack_depth=stack_depth + 1
Expand All @@ -689,7 +684,7 @@ def debugcell(cellname, filename=None, post_mortem=False):
# Recursive
code = (
"runcell({}, ".format(repr(cellname)) +
"{})".format(repr(normalise_filename(filename)))
"{})".format(repr(filename))
)
shell.pdb_session.enter_recursive_debugger(
code, filename, False,
Expand All @@ -698,7 +693,8 @@ def debugcell(cellname, filename=None, post_mortem=False):
debugger = get_new_debugger(filename, False)
_exec_cell(
cellname=cellname,
filename=debugger.canonic(filename),
filename=filename,
canonic_filename=debugger.canonic(filename),
exec_fun=debugger.run,
stack_depth=1
)
Expand Down
23 changes: 13 additions & 10 deletions spyder_kernels/customize/spyderpdb.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
import bdb
import builtins
import logging
import os
import sys
import traceback
from collections import namedtuple
Expand Down Expand Up @@ -93,6 +92,9 @@ def __init__(self, completekey='tab', stdin=None, stdout=None,
# has no effect in previous versions.
self.report_skipped = False

# Keep track of remote filename
self.remote_filename = None

# --- Methods overriden for code execution
def print_exclamation_warning(self):
"""Print pdb warning for exclamation mark."""
Expand Down Expand Up @@ -713,6 +715,8 @@ def publish_pdb_state(self):

# Get filename and line number of the current frame
fname = self.canonic(frame.f_code.co_filename)
if fname == self.mainpyfile and self.remote_filename is not None:
fname = self.remote_filename
lineno = frame.f_lineno

if self._previous_step == (fname, lineno):
Expand Down Expand Up @@ -792,11 +796,8 @@ def enter_recursive_debugger(self, code, filename,
debugger.use_rawinput = self.use_rawinput
debugger.prompt = "(%s) " % self.prompt.strip()

filename = debugger.canonic(filename)
debugger._wait_for_mainpyfile = True
debugger.mainpyfile = filename
debugger.set_remote_filename(filename)
debugger.continue_if_has_breakpoints = continue_if_has_breakpoints
debugger._user_requested_quit = False

# Enter recursive debugger
sys.call_tracing(debugger.run, (code, globals, locals))
Expand All @@ -811,14 +812,16 @@ def enter_recursive_debugger(self, code, filename,
# but the parent debugger (self) is not aware of this.
self._previous_step = None

def set_remote_filename(self, filename):
"""Set remote filename to signal Spyder on mainpyfile."""
self.remote_filename = filename
self.mainpyfile = self.canonic(filename)
self._wait_for_mainpyfile = True


def get_new_debugger(filename, continue_if_has_breakpoints):
"""Get a new debugger."""
debugger = SpyderPdb()

filename = debugger.canonic(filename)
debugger._wait_for_mainpyfile = True
debugger.mainpyfile = filename
debugger.set_remote_filename(filename)
debugger.continue_if_has_breakpoints = continue_if_has_breakpoints
debugger._user_requested_quit = False
return debugger
18 changes: 12 additions & 6 deletions spyder_kernels/customize/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -117,9 +117,15 @@ def capture_last_Expr(code_ast, out_varname):
return code_ast, capture_last_expression


def normalise_filename(filename):
"""Normalise path for window."""
# Recursive
if os.name == 'nt':
return filename.replace('\\', '/')
return filename
def canonic(filename):
"""
Return canonical form of filename.
This is a copy of bdb.canonic, so that the debugger will process
filenames in the same way
"""
if filename == "<" + filename[1:-1] + ">":
return filename
canonic = os.path.abspath(filename)
canonic = os.path.normcase(canonic)
return canonic

0 comments on commit d44c859

Please sign in to comment.