This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: pdb 'run' crashes when the it's first argument is non-string
Type: behavior Stage: test needed
Components: Library (Lib) Versions: Python 3.0, Python 2.4, Python 3.1, Python 3.2, Python 2.7, Python 2.6, Python 2.5
process
Status: closed Resolution: fixed
Dependencies: 1472257 Superseder:
Assigned To: Nosy List: ajaksu2, georg.brandl, isandler, jakamkon
Priority: low Keywords: patch

Created on 2006-04-18 12:16 by jakamkon, last changed 2022-04-11 14:56 by admin. This issue is now closed.

Files
File name Uploaded Description Edit
bdb-run.patch jakamkon, 2009-09-23 14:43
Messages (15)
msg28277 - (view) Author: Kuba Kończyk (jakamkon) Date: 2006-04-18 12:16
Pdb 'run/runeval' commands fails to check the type of
given argument.When argument to 'run/runeval' is
non-string the functions crashes with further
impilications on (correctly)invoking this functions: 

Python 2.5a1 (trunk:45527, Apr 18 2006, 11:12:31)

>>> def x(): pass
>>> import pdb
>>> pdb.run(x())
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/jkk/python/python-svn/Lib/pdb.py", line
1113, in run
    Pdb().run(statement, globals, locals)
  File "/home/jkk/python/python-svn/Lib/bdb.py", line
363, in run
    cmd = cmd+'\n'
TypeError: unsupported operand type(s) for +:
'NoneType' and 'str'
>>> pdb.run('x()')
> /home/jkk/python/python-svn/Lib/pdb.py(1113)run()
-> Pdb().run(statement, globals, locals)
(Pdb)
# CTRL-D pressed
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/jkk/python/python-svn/Lib/pdb.py", line
1113, in run
    Pdb().run(statement, globals, locals)
  File "/home/jkk/python/python-svn/Lib/pdb.py", line
1113, in run
    Pdb().run(statement, globals, locals)
  File "/home/jkk/python/python-svn/Lib/bdb.py", line
48, in trace_dispatch
    return self.dispatch_line(frame)
  File "/home/jkk/python/python-svn/Lib/bdb.py", line
67, in dispatch_line
    if self.quitting: raise BdbQuit
bdb.BdbQuit

The solution is to simply ensure that the first
argument passed to the 'run/runeval' functions is string.
msg28278 - (view) Author: Kuba Kończyk (jakamkon) Date: 2006-04-18 12:36
Logged In: YES 
user_id=1491175

Patch is in #1472257
msg28279 - (view) Author: Ilya Sandler (isandler) Date: 2006-05-21 23:25
Logged In: YES 
user_id=971153


I would not classify your example as a crash. You passed a
wrong value (None in your case) into pdb.run() and got back
a TypeError...Isn't it an expected response?

E.g if you do:  >>>max(13)

You'll also get: "TypeError"


Am I missing something? Could you clarify?

msg28280 - (view) Author: Kuba Kończyk (jakamkon) Date: 2006-05-22 09:20
Logged In: YES 
user_id=1491175

The point is that when you want to invoke pdb.run correctly
(with string argument) after getting TypeError as in above
example,
your namespace is probably overwritten or deleted so that
you don't have access to previously defined symbols.

>>> def x():pass
>>> import pdb
>>> pdb.run(x())
TypeError
>>> pdb.run('x()')
> /home/jkk/python-svn/Lib/pdb.py(1122)run()
-> Pdb().run(statement, globals, locals)
(Pdb) pdb
*** NameError: name 'pdb' is not defined
(Pdb) x
*** NameError: name 'x' is not defined
msg28281 - (view) Author: Ilya Sandler (isandler) Date: 2006-05-23 03:36
Logged In: YES 
user_id=971153


Well, I don't see anything in bdb's run which could
overwrite your namespace..

What seems to be happenning in your example is that bdb's
first line event happens while bdb is still in run(), so you
when you see pdb's prompt, are in bdb's namespace not in
yours.. If you do "next" you will get where you should be..

 bagira:~> python2.4
 Python 2.4.1 (#2, May  5 2005, 11:32:06) 
 >>> def x(): print "in x"
 >>> import pdb
 >>> pdb.run( x())
 in x
 TypeError: unsupported operand type(s) for +: 'NoneType'
and 'str'
 >>> pdb.run( 'x()' )
 > /usr/lib/python2.4/pdb.py(987)run()
 -> Pdb().run(statement, globals, locals)
 (Pdb) n          #now you are back in your namespace
 > <string>(1)?()
 (Pdb) p x        #and you get your symbols back
 <function x at 0x4021be2c>
 (Pdb) p pdb
 <module 'pdb' from '/usr/lib/python2.4/pdb.pyc'>
 (Pdb) n
 in x
 --Return--
 > <string>(1)?()->None


What do you think?
msg28282 - (view) Author: Kuba Kończyk (jakamkon) Date: 2006-06-19 13:48
Logged In: YES 
user_id=1491175

You're right,but don't you think that this kind of switching
between namespaces could confuse users?
msg28283 - (view) Author: Ilya Sandler (isandler) Date: 2006-06-25 18:54
Logged In: YES 
user_id=971153

I have looked at what's happening in a bit more detail and
now I agree that the current behaviour seems wrong.

Apparently, when one passes a nonstring to bdb's run(), bdb
sets tracing first and only then throws an exception...
Leaving tracing on seems like a bad thing to do 

Would calling settrace() a couple lines later be the
simplest solution then?

so relevant fragment of  bdb.py's run() becomes:
        if not isinstance(cmd, types.CodeType):
            cmd = cmd+'\n'
        sys.settrace(self.trace_dispatch)

This should prevent bdb from turning tracing too early.
What do you think?
msg28284 - (view) Author: Kuba Kończyk (jakamkon) Date: 2006-07-11 14:02
Logged In: YES 
user_id=1491175

Is your comment directly related to this bug?
Maybe you should create separete bug tracker item to discuss
problem presented in your comment?
msg28285 - (view) Author: Kuba Kończyk (jakamkon) Date: 2006-07-11 15:02
Logged In: YES 
user_id=1491175

Simple solution is to catch TypeError in bdb's run function:
         try:
            if not isinstance(cmd, types.CodeType):
                    cmd = cmd+'\n'
         except TypeError:
                    pass

Now it seems that handling nonstring arguments is better:

>>> import pdb
>>> def x():pass
...
>>> pdb.run(x())
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/jkk/python-svn/Lib/pdb.py", line 1122, in run
    Pdb().run(statement, globals, locals)
  File "/home/jkk/python-svn/Lib/bdb.py", line 369, in run
    exec cmd in globals, locals
TypeError: exec: arg 1 must be a string, file, or code object
>>> pdb.run('x()')
> <string>(1)<module>()
(Pdb) x
<function x at 0x4024a9cc>
(Pdb) pdb.run('x()')
(Pdb)
>>>

msg28286 - (view) Author: Ilya Sandler (isandler) Date: 2006-07-22 17:46
Logged In: YES 
user_id=971153

>> Is your comment directly related to this bug?

Yes, my suggestion was to call settrace() after 

  cmd = cmd+'\n'

which should solve the original (bdb leaving tracing on)
problem.. Your latest suggestion would do the same thing by
different means..

However, I think there an even better way: can we simply remove

-    if not isinstance(cmd, types.CodeType):
-        cmd = cmd+'\n'

from bdb.py???

This would both solve the original problem and make error
message more meaningful IMO..

 > exec: arg 1 must be a string, file, or code object

Rather than:

 >Unsupported operand type(s) for +: 'NoneType' and 'str'

This seems to work for me, would you be interested in
testing and submitting a patch for this?


A bit more information: it appears that older versions of
python in some cases required string passed to exec to end
with '\n', this was even mentioned in python FAQ.. E.g if I
feed  
  
 exec 'for i in range(4):\nx=i'

into python2.1, I get a Syntax error..

However, this does work in python2.3.3, 2.4,2.5...

So was this + '\n' indeed a workaround for a deficiency in exec?





apparently older versions of python required the string
passed to exec to end with '\n'. It was even mentioned in
older FAQs... However, latest versions of python seem to
accept strings without new line... Eg. even
msg28287 - (view) Author: Kuba Kończyk (jakamkon) Date: 2006-07-26 11:25
Logged In: YES 
user_id=1491175

I think your solution works for me too;)I attached patch
which modify run and runeval function according to your
suggestion.

I tested both run and runeval functions with string and code
object as   
an argument,and also run with file object.
It appears that patch works fine.
msg83909 - (view) Author: Daniel Diniz (ajaksu2) * (Python triager) Date: 2009-03-21 02:13
Issue 1472257 was rejected.
msg93041 - (view) Author: Kuba Kończyk (jakamkon) Date: 2009-09-23 14:43
Updated patch with tests and documentation.It fixes the issue by leaving
argument checking to exec and eval functions.The result is a more
readable error messages when invoking run/runeval with incorrect
arguments (see discussion above) and also ability to run pdb on an open
file objects.
msg93042 - (view) Author: Kuba Kończyk (jakamkon) Date: 2009-09-23 15:07
BTW, patch is based on trunk.
msg112052 - (view) Author: Georg Brandl (georg.brandl) * (Python committer) Date: 2010-07-30 09:14
Committed in trunk r83266; file objects are no longer allowed for exec(), therefore I dropped mentions of that.
History
Date User Action Args
2022-04-11 14:56:16adminsetgithub: 43239
2010-07-30 09:14:45georg.brandlsetstatus: open -> closed

nosy: + georg.brandl
messages: + msg112052

resolution: fixed
2009-09-23 15:07:30jakamkonsetmessages: + msg93042
2009-09-23 14:43:47jakamkonsetfiles: - bdb-run.patch
2009-09-23 14:43:14jakamkonsetfiles: + bdb-run.patch
keywords: + patch
messages: + msg93041

versions: + Python 2.5, Python 2.4, Python 3.0, Python 3.1, Python 2.7, Python 3.2
2009-03-21 02:13:27ajaksu2setdependencies: + pdb: fix for #1472251('run/runeval' commands bug)
type: behavior
versions: + Python 2.6, - Python 2.5
nosy: + ajaksu2

messages: + msg83909
stage: test needed
2006-04-18 12:16:13jakamkoncreate