[Patches] [ python-Patches-1402289 ] Allow mappings as globals (was: Fix dictionary subclass ...)
SourceForge.net
noreply at sourceforge.net
Thu Feb 15 10:55:19 CET 2007
Patches item #1402289, was opened at 2006-01-11 01:24
Message generated for change (Comment added) made by loewis
You can respond by visiting:
https://sourceforge.net/tracker/?func=detail&atid=305470&aid=1402289&group_id=5470
Please note that this message will contain a full copy of the comment thread,
including the initial issue submission, for this request,
not just the latest update.
Category: Core (C code)
Group: Python 2.5
Status: Open
Resolution: None
Priority: 5
Private: No
Submitted By: crutcher (crutcher_gmail)
Assigned to: Raymond Hettinger (rhettinger)
Summary: Allow mappings as globals (was: Fix dictionary subclass ...)
Initial Comment:
There is an inconsistancy in the way that dictionary
subclasses behave
when they are used as as namespaces in execs.
Basically, while python 2.4 permits the usage of
dictionary subclasses
for local environments, it still bypasses the subclass
functions and
uses the C API for global environments. The attached
patch (and
unittest!) addresses this issue.
I'm pretty sure we keep the fast path in this.
----------------------------------------------------------------------
>Comment By: Martin v. Löwis (loewis)
Date: 2007-02-15 10:55
Message:
Logged In: YES
user_id=21627
Originator: NO
Raymond, do you think you can make it this March? If not, please unassign.
----------------------------------------------------------------------
Comment By: crutcher (crutcher_gmail)
Date: 2006-03-30 20:12
Message:
Logged In: YES
user_id=1424288
Are you going to get to this?
----------------------------------------------------------------------
Comment By: Raymond Hettinger (rhettinger)
Date: 2006-02-21 14:28
Message:
Logged In: YES
user_id=80475
Crutcher, this looked good on my first read-through. Will
go through it in detail sometime in March.
----------------------------------------------------------------------
Comment By: crutcher (crutcher_gmail)
Date: 2006-01-30 20:10
Message:
Logged In: YES
user_id=1424288
doh, forgot to check the 'upload' box
----------------------------------------------------------------------
Comment By: crutcher (crutcher_gmail)
Date: 2006-01-30 18:08
Message:
Logged In: YES
user_id=1424288
I have reworked and extended this patch so that arbitrary
mappings are permitted for globals, not just dictionary
subtypes. This touched a good deal more code.
Please use the updated version.
----------------------------------------------------------------------
Comment By: Armin Rigo (arigo)
Date: 2006-01-25 19:20
Message:
Logged In: YES
user_id=4771
I will review and check-in your patch, I think it's a good
idea despite the added code complexity.
----------------------------------------------------------------------
Comment By: crutcher (crutcher_gmail)
Date: 2006-01-25 04:38
Message:
Logged In: YES
user_id=1424288
currently chasing through the PyFrame code and the EXEC_STMT
code to make globals generic mappings, will update this
patch yet again.
----------------------------------------------------------------------
Comment By: crutcher (crutcher_gmail)
Date: 2006-01-22 10:19
Message:
Logged In: YES
user_id=1424288
I've fixed up the exception case, and extended the test case
to check for it. Is there anything else I can do to get this in?
----------------------------------------------------------------------
Comment By: crutcher (crutcher_gmail)
Date: 2006-01-22 06:11
Message:
Logged In: YES
user_id=1424288
I'm going to fix the missed exception test this weekend, and
try to get an updated patch to you.
----------------------------------------------------------------------
Comment By: Armin Rigo (arigo)
Date: 2006-01-14 10:54
Message:
Logged In: YES
user_id=4771
Provided this can be done with no measurable performance hit,
I guess that I'm fine with the idea. The patch needs a bit
more work, though: I don't see why it should accept dict
subclasses as globals but not arbitrary mappings (as it now
does for the locals). This is mainly an issue of removing
a few checks in various places, like EXEC_STMT and the eval()
and execfile() built-ins.
There is a missing exception check/clear in the part about
LOAD_NAME, after the PyObject_GetItem(f->f_globals, w).
A side note: in the current trunk already, LOAD_GLOBAL
contains a couple of checks, namely PyString_CheckExact()
and hash != -1. We might be able to prove in advance that
these two conditions are always true. We could then remove
the checks. Not sure the difference measurable, though.
----------------------------------------------------------------------
Comment By: crutcher (crutcher_gmail)
Date: 2006-01-12 08:50
Message:
Logged In: YES
user_id=1424288
Well, why fix it for eval but not for exec? I don't think
the time hit is noticeable, I ran 'time make test' twice
each on the trunk with and without the patch. Here are the
results:
Trunk:
real 9m17.117s
user 3m30.930s
sys 0m35.417s
real 9m9.471s
user 3m31.484s
sys 0m34.978s
Patch:
real 9m32.469s
user 3m40.134s
sys 0m36.140s
real 9m6.779s
user 3m27.529s
sys 0m34.716s
----------------------------------------------------------------------
Comment By: Martin v. Löwis (loewis)
Date: 2006-01-12 07:11
Message:
Logged In: YES
user_id=21627
I think the history is this: it originates from
python.org/sf/215126, which requested that you can pass dict
subtypes to eval. Armin noted that eval will always produce
LOAD/STORE_NAME, so just modifying these opcodes is
sufficient to fulfil the feature request.
----------------------------------------------------------------------
Comment By: Raymond Hettinger (rhettinger)
Date: 2006-01-12 02:21
Message:
Logged In: YES
user_id=80475
Okay, I will take it under consideration. Also, I'll try to
remember the reason it wasn't done the first time around.
No promises though -- by itself consistency is a weak
motivation.
----------------------------------------------------------------------
Comment By: crutcher (crutcher_gmail)
Date: 2006-01-12 00:11
Message:
Logged In: YES
user_id=1424288
Here's a more interesting example. This works fine, unless
the variables fall through to the global dictionary, or some
code marks them global.
import code
class ManagedVariable:
def get(self):
return None
def set(self, value):
pass
def delete(self):
# Return false to stop the delete.
return True
class ManagedEnvironment(dict):
def __setitem__(self, key, value):
if self.has_key(key):
if isinstance(dict.__getitem__(self, key),
ManagedVariable):
dict.__getitem__(self, key).set(value)
return
dict.__setitem__(self, key, value)
def __getitem__(self, key):
if self.has_key(key):
if isinstance(dict.__getitem__(self, key),
ManagedVariable):
return dict.__getitem__(self, key).get()
return dict.__getitem__(self, key)
def __delitem__(self, key):
if self.has_key(key):
if isinstance(dict.__getitem__(self, key),
ManagedVariable):
if not dict.__getitem__(self, key).delete():
return
dict.__delitem__(self, key)
class RangedInt(ManagedVariable):
def __init__(self, value, (low, high)):
self.value = value
self.low = low
self.high = high
def get(self):
return self.value
def set(self, value):
if value < self.low:
value = self.low
if value > self.high:
value = self.high
self.value = value
class FunctionValue(ManagedVariable):
def __init__(self, get_func = None, set_func = None,
del_func = None):
self.get_func = get_func
self.set_func = set_func
self.del_func = del_func
def get(self):
if self.get_func:
return self.get_func()
return None
def set(self, value):
if self.set_func:
self.set_func(value)
def delete(self):
if self.del_func:
return self.del_func()
return True
class Constant(ManagedVariable):
def __init__(self, value):
self.value = value
def get(self):
return self.value
def delete(self):
return False
import time
d = ManagedEnvironment()
d['ranged'] = RangedInt(1, (0, 100))
d['time'] = FunctionValue(lambda: time.time())
d['constant'] = Constant(42)
code.interact(local=d)
----------------------------------------------------------------------
Comment By: crutcher (crutcher_gmail)
Date: 2006-01-11 19:12
Message:
Logged In: YES
user_id=1424288
Here's an example of a little typed environment. It's not
the most robust, but it gets you thinking.
import code
class TypedDictionary(dict):
def __setitem__(self, key, value):
if self.has_key(key):
t = type(self[key])
if t != type(value):
try:
value = t(value)
except Exception:
raise TypeError, \
"illegal assignment to '%s':" \
" %s cannot be coerced to %s" \
% (key, type(value), t)
dict.__setitem__(self, key, value)
code.interact(local=TypedDictionary())
----------------------------------------------------------------------
Comment By: crutcher (crutcher_gmail)
Date: 2006-01-11 03:16
Message:
Logged In: YES
user_id=1424288
With the ability to use dictionary subclasses for local and
global environments, it becomes very easy to implement
execution environments with extended variable semantics for
special purposes.
This includes driving interactive processes, config file
processors, type checking, lazy object construction, and
read-only variables.
As it currently stands, the semantics are inconsistent. The
local case should not have been changed if the global case
was not going to be changed.
----------------------------------------------------------------------
Comment By: Raymond Hettinger (rhettinger)
Date: 2006-01-11 03:03
Message:
Logged In: YES
user_id=80475
Do you have any use cases? AFAICT, there were no unmet
needs with locals option.
Also, there was a reason that globals weren't included but I
remember what it was.
----------------------------------------------------------------------
You can respond by visiting:
https://sourceforge.net/tracker/?func=detail&atid=305470&aid=1402289&group_id=5470
More information about the Patches
mailing list