[Python-bugs-list] [ python-Bugs-446645 ] rexec and function attributes

noreply@sourceforge.net noreply@sourceforge.net
Tue, 14 Aug 2001 11:27:43 -0700


Bugs item #446645, was opened at 2001-07-31 19:21
You can respond by visiting: 
http://sourceforge.net/tracker/?func=detail&atid=105470&aid=446645&group_id=5470

Category: Python Interpreter Core
Group: None
>Status: Closed
>Resolution: Fixed
Priority: 5
Submitted By: Matthew Brecknell (brecknell)
Assigned to: Barry Warsaw (bwarsaw)
Summary: rexec and function attributes

Initial Comment:
The behaviour of the rexec module seems to be 
inconsistent with respect to function attributes. The 
function attribute dictionary is read-only in the 
restricted environment until you go and write to it 
outside the restricted environment. After that, the 
dictionary becomes writable in the restricted 
environment too. See the following examples:

Python 2.1 (#1, Jun 29 2001, 15:51:00) 
[GCC 2.95.3 19991030 (prerelease)] on openbsd2
Type "copyright", "credits" or "license" for more 
information.
>>> import rexec
>>> r = rexec.RExec()
>>> def f(): pass
... 
>>> r.modules['__main__'].f = f
>>> r.r_exec('f.__dict__["attr"] = "value"')
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
  File "/opt/python/lib/python2.1/rexec.py", line 264, 
in r_exec
    exec code in m.__dict__
  File "<string>", line 1, in ?
TypeError: object does not support item assignment
>>> f.attr = "value"
>>> r.r_exec('f.__dict__["attr"] = "new value"')
>>> f.attr
'new value'
>>> 

Or, looking at it another way:

Python 2.1 (#1, Jun 29 2001, 15:51:00) 
[GCC 2.95.3 19991030 (prerelease)] on openbsd2
Type "copyright", "credits" or "license" for more 
information.
>>> import rexec
>>> r = rexec.RExec()
>>> r.r_exec("def f(): pass")
>>> r.r_exec('f.__dict__["attr"] = "value"')
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
  File "/opt/python/lib/python2.1/rexec.py", line 264, 
in r_exec
    exec code in m.__dict__
  File "<string>", line 1, in ?
TypeError: object does not support item assignment
>>> f = r.modules['__main__'].f
>>> f.attr = "value"
>>> r.r_exec('f.__dict__["attr"] = "new value"')
>>> f.attr
'new value'
>>> 

Please don't abuse me too much for still being on 
Python 2.1, since I haven't had time to try 2.1.1 or 
2.2a1! If I don't put this in now, I'll forget. I'm 
guessing that neither rexec nor function attributes 
are widely used, so not too many people would have 
come across this. If I get more time down the track, 
I'll look into it further.

Regards,
Matt.


----------------------------------------------------------------------

>Comment By: Barry Warsaw (bwarsaw)
Date: 2001-08-14 11:27

Message:
Logged In: YES 
user_id=12800

Done.  funcobject.c 2.40, Python 2.2


----------------------------------------------------------------------

Comment By: Guido van Rossum (gvanrossum)
Date: 2001-08-14 09:01

Message:
Logged In: YES 
user_id=6380

OK, you've convinced me.  A __dict__ that appears to be
always there is fine. Please update the PEP and fix the bug!

Back to Barry.


----------------------------------------------------------------------

Comment By: Barry Warsaw (bwarsaw)
Date: 2001-08-13 16:36

Message:
Logged In: YES 
user_id=12800

I'm bouncing this one back to Guido for BDFL pronouncement.  

Back when PEP 232 was being finalized (circa Feb 2001), Greg
Ball brought up this very point in a private thread entitled
"Update to PEP 232".  Greg also thought that allowing
func.__dict__ to be None was confusing, and I agreed.  Guido
disagreed; he actually liked the current semantics, so it
was documented in the PEP and implementation.

Thinking about this again, I still think that 
1) del f.__dict__ should raise a TypeError
2) f.__dict__ = not_a_concrete_dict should raise TypeError
3) f.__dict__ before any attribute assignment should
initialize the attribute to the empty dict and return it.
One way to think about it is modeling func.__dict__ after
instance.__dict__.  del'ing the latter, or setting it to
None both result in TypeError.  Same for module.__dict__. 
Should func.__dict__ act the same way?

Guido: if you still agree with the semantics in PEP 232,
please close this as Wont Fix.  Otherwise, reassign it back
to me and I'll update both the PEP and the implementation.

----------------------------------------------------------------------

Comment By: Jeremy Hylton (jhylton)
Date: 2001-08-01 13:00

Message:
Logged In: YES 
user_id=31392

You can see this behavior without using rexec.  The problem
you're seeing is that a function's __dict__ is None until
you set an attribute on the function.  Then the __dict__
slot is created and a new dictionary bound there.  The error
you see, which you attributed to rexec, is attempting to
execute f.__dict__["attr"] => None["attr"].

There are two policy questions here, which Barry can better
answer:

1. Should a function's __dict__ be accessible in restricted
mode?  A class's __dict__ is not, but it's a horse of a
different color.

2. Is it okay for __dict__ to occasionally return None?  I
don't think it is.  It's fine to be lazy about the creation
of __dict__, but it should be created as soon as it is
referenced.  Otherwise, any code that wants to use __dict__
should be prepared to deal with None.


----------------------------------------------------------------------

You can respond by visiting: 
http://sourceforge.net/tracker/?func=detail&atid=105470&aid=446645&group_id=5470