[Patches] [ python-Patches-1402289 ] Fix dictionary subclass semantics when used as global dicts.
SourceForge.net
noreply at sourceforge.net
Thu Jan 12 07:11:02 CET 2006
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
Submitted By: crutcher (crutcher_gmail)
Assigned to: Raymond Hettinger (rhettinger)
Summary: Fix dictionary subclass semantics when used as global dicts.
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: 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