Skip to content

Commit

Permalink
pdb debugging now recognizes SConstruct/SConscript
Browse files Browse the repository at this point in the history
Make it possible (once the project path has been added to sys.path)
to set/clear breakpoints using file paths that end in SConstruct and
SConscript - specializing pdb.Pdb to override the need for all paths
that are not absolute to end in .py.

Man: tried to address some surprise that pdb can't find the SConstruct
when you start up in debugger mode.

Signed-off-by: Mats Wichmann <[email protected]>
  • Loading branch information
mwichmann committed May 6, 2023
1 parent fcb92c4 commit 38453a3
Show file tree
Hide file tree
Showing 4 changed files with 90 additions and 2 deletions.
3 changes: 3 additions & 0 deletions CHANGES.txt
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER
calls dunder method __call__. Invoke instance directly."
- Python 3.9 dropped the alias base64.decodestring, deprecated since 3.1.
Only used in msvs.py. Use base64.decodebytes instead.
- When debugging (--debug=pdb), the filenames SConstruct and SConscript
are now recognized when manipulating breakpoints. Previously, only a
full pathname worked, as otherwise pdb required a .py extension on files.


RELEASE 4.5.2 - Sun, 21 Mar 2023 14:08:29 -0700
Expand Down
5 changes: 5 additions & 0 deletions NEWS.d/changes/4306.bugfix
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@

When debugging (--debug=pdb), the filenames SConstruct and SConscript
are now recognized when manipulating breakpoints. Previously, only a
full pathname worked, as otherwise pdb required a .py extension on files.

38 changes: 37 additions & 1 deletion SCons/Script/Main.py
Original file line number Diff line number Diff line change
Expand Up @@ -1390,7 +1390,42 @@ def _exec_main(parser, values) -> None:

if isinstance(options.debug, list) and "pdb" in options.debug:
import pdb
pdb.Pdb().runcall(_main, parser)

class SConsPdb(pdb.Pdb):
"""Specialization of Pdb to help find SConscript files."""

def lookupmodule(self, filename: str) -> Optional[str]:
"""Helper function for break/clear parsing -- SCons version.
Copy of the original, but recognizes common names for
SConstruct/SConscript without having to have them end in ``.py``
.. versionadded:: 4.5.0
"""
if os.path.isabs(filename) and os.path.exists(filename):
return filename
f = os.path.join(sys.path[0], filename)
if os.path.exists(f) and self.canonic(f) == self.mainpyfile:
return f
root, ext = os.path.splitext(filename)
SCONSCRIPTS = (
"SConstruct Sconstruct sconstruct SConscript sconscript".split()
)
base = os.path.split(filename)[-1]
if ext == '' and base not in SCONSCRIPTS:
filename = filename + '.py'
if os.path.isabs(filename):
return filename
for dirname in sys.path:
while os.path.islink(dirname):
dirname = os.readlink(dirname)
fullname = os.path.join(dirname, filename)
if os.path.exists(fullname):
return fullname
return None

SConsPdb().runcall(_main, parser)

elif options.profile_file:
from cProfile import Profile

Expand All @@ -1399,6 +1434,7 @@ def _exec_main(parser, values) -> None:
prof.runcall(_main, parser)
finally:
prof.dump_stats(options.profile_file)

else:
_main(parser)

Expand Down
46 changes: 45 additions & 1 deletion doc/man/scons.xml
Original file line number Diff line number Diff line change
Expand Up @@ -959,9 +959,53 @@ of the various classes used internally by SCons.</para>
<varlistentry>
<term><emphasis role="bold">pdb</emphasis></term>
<listitem>
<para>Re-run &scons; under the control of the
<para>Run &scons; under control of the
<systemitem>pdb</systemitem>
&Python; debugger.</para>
<screen>
$ <userinput>scons --debug=pdb</userinput>
> /usr/lib/python3.11/site-packages/SCons/Script/Main.py(869)_main()
-> options = parser.values
(Pdb)
</screen>
<note>
<para><systemitem>pdb</systemitem> will stop at the
beginning of the &scons; main routine on startup.
The search path (<systemitem>sys.path</systemitem>)
at that point will include the location of the running &scons;,
but not of the project itself -
if you need to set breakpoints in your project files,
you will either need to add to the path,
or use absolute pathnames when referring to project files.
A <filename>.pdbrc</filename> file in the project root
can be used to add the current directory to the search path
to avoid having to enter it by hand,
along these lines:
</para>
<programlisting language="python">
sys.path.append('.')
</programlisting>
<para>
Due to the implementation of the
<systemitem>pdb</systemitem> module,
the <command>break</command>,
<command>tbreak</command>
and <command>clear</command>
commands only understand references to filenames
which end in a <filename>.py</filename> suffix
(although that suffix does not have to be typed),
<emphasis>except</emphasis> if you use an absolute path.
As a special exception to that rule, the names
&SConstruct; and &SConscript; are recognized without
needing the <filename>.py</filename> extension.
</para>
<para>
<emphasis>Changed in version 4.5.0</emphasis>:
The names &SConstruct; and &SConscript; are now
recognized without needing to have a
<filename>.py</filename> suffix.
</para>
</note>
</listitem>
</varlistentry>

Expand Down

0 comments on commit 38453a3

Please sign in to comment.