[Python-checkins] r53968 - in python/branches/twouters-dictviews-backport: Lib/__future__.py Lib/compiler/consts.py Lib/compiler/future.py Lib/compiler/pyassem.py Lib/compiler/pycodegen.py Lib/test/test_compiler.py Lib/test/test_dict.py Python/bltinmodule.c
thomas.wouters
python-checkins at python.org
Mon Feb 26 23:24:32 CET 2007
Author: thomas.wouters
Date: Mon Feb 26 23:24:25 2007
New Revision: 53968
Modified:
python/branches/twouters-dictviews-backport/Lib/__future__.py
python/branches/twouters-dictviews-backport/Lib/compiler/consts.py
python/branches/twouters-dictviews-backport/Lib/compiler/future.py
python/branches/twouters-dictviews-backport/Lib/compiler/pyassem.py
python/branches/twouters-dictviews-backport/Lib/compiler/pycodegen.py
python/branches/twouters-dictviews-backport/Lib/test/test_compiler.py
python/branches/twouters-dictviews-backport/Lib/test/test_dict.py
python/branches/twouters-dictviews-backport/Python/bltinmodule.c
Log:
Add some dictview tests, and compiler support plus tests.
Modified: python/branches/twouters-dictviews-backport/Lib/__future__.py
==============================================================================
--- python/branches/twouters-dictviews-backport/Lib/__future__.py (original)
+++ python/branches/twouters-dictviews-backport/Lib/__future__.py Mon Feb 26 23:24:25 2007
@@ -53,6 +53,7 @@
"division",
"absolute_import",
"with_statement",
+ "dictviews",
]
__all__ = ["all_feature_names"] + all_feature_names
Modified: python/branches/twouters-dictviews-backport/Lib/compiler/consts.py
==============================================================================
--- python/branches/twouters-dictviews-backport/Lib/compiler/consts.py (original)
+++ python/branches/twouters-dictviews-backport/Lib/compiler/consts.py Mon Feb 26 23:24:25 2007
@@ -19,3 +19,4 @@
CO_FUTURE_DIVISION = 0x2000
CO_FUTURE_ABSIMPORT = 0x4000
CO_FUTURE_WITH_STATEMENT = 0x8000
+CO_FUTURE_DICTVIEWS = 0x10000
Modified: python/branches/twouters-dictviews-backport/Lib/compiler/future.py
==============================================================================
--- python/branches/twouters-dictviews-backport/Lib/compiler/future.py (original)
+++ python/branches/twouters-dictviews-backport/Lib/compiler/future.py Mon Feb 26 23:24:25 2007
@@ -16,7 +16,7 @@
class FutureParser:
features = ("nested_scopes", "generators", "division",
- "absolute_import", "with_statement")
+ "absolute_import", "with_statement", "dictviews")
def __init__(self):
self.found = {} # set
Modified: python/branches/twouters-dictviews-backport/Lib/compiler/pyassem.py
==============================================================================
--- python/branches/twouters-dictviews-backport/Lib/compiler/pyassem.py (original)
+++ python/branches/twouters-dictviews-backport/Lib/compiler/pyassem.py Mon Feb 26 23:24:25 2007
@@ -533,6 +533,9 @@
_convert_STORE_ATTR = _convert_NAME
_convert_LOAD_ATTR = _convert_NAME
_convert_DELETE_ATTR = _convert_NAME
+ _convert_STORE_VIEWATTR = _convert_NAME
+ _convert_LOAD_VIEWATTR = _convert_NAME
+ _convert_DELETE_VIEWATTR = _convert_NAME
_convert_LOAD_GLOBAL = _convert_NAME
_convert_STORE_GLOBAL = _convert_NAME
_convert_DELETE_GLOBAL = _convert_NAME
@@ -766,7 +769,9 @@
'BUILD_CLASS': -2,
'STORE_NAME': -1,
'STORE_ATTR': -2,
+ 'STORE_VIEWATTR': -2,
'DELETE_ATTR': -1,
+ 'DELETE_VIEWATTR': -1,
'STORE_GLOBAL': -1,
'BUILD_MAP': 1,
'COMPARE_OP': -1,
@@ -775,6 +780,7 @@
'IMPORT_NAME': -1,
'IMPORT_FROM': 1,
'LOAD_ATTR': 0, # unlike other loads
+ 'LOAD_VIEWATTR': 0,
# close enough...
'SETUP_EXCEPT': 3,
'SETUP_FINALLY': 3,
Modified: python/branches/twouters-dictviews-backport/Lib/compiler/pycodegen.py
==============================================================================
--- python/branches/twouters-dictviews-backport/Lib/compiler/pycodegen.py (original)
+++ python/branches/twouters-dictviews-backport/Lib/compiler/pycodegen.py Mon Feb 26 23:24:25 2007
@@ -10,7 +10,7 @@
from compiler.consts import SC_LOCAL, SC_GLOBAL, SC_FREE, SC_CELL
from compiler.consts import (CO_VARARGS, CO_VARKEYWORDS, CO_NEWLOCALS,
CO_NESTED, CO_GENERATOR, CO_FUTURE_DIVISION,
- CO_FUTURE_ABSIMPORT, CO_FUTURE_WITH_STATEMENT)
+ CO_FUTURE_ABSIMPORT, CO_FUTURE_WITH_STATEMENT, CO_FUTURE_DICTVIEWS)
from compiler.pyassem import TupleArg
# XXX The version-specific code can go, since this code only works with 2.x.
@@ -218,6 +218,8 @@
self.graph.setFlag(CO_FUTURE_ABSIMPORT)
elif feature == "with_statement":
self.graph.setFlag(CO_FUTURE_WITH_STATEMENT)
+ elif feature == "dictviews":
+ self.graph.setFlag(CO_FUTURE_DICTVIEWS)
def initClass(self):
"""This method is called once for each class"""
@@ -929,9 +931,18 @@
for elt in elts[1:]:
self.emit('LOAD_ATTR', elt)
+ def _checkViewAttr(self, regop, viewop, attrname):
+ if (self.graph.checkFlag(CO_FUTURE_DICTVIEWS) and
+ attrname in ('keys', 'items', 'values')):
+ return viewop
+ else:
+ return regop
+
def visitGetattr(self, node):
self.visit(node.expr)
- self.emit('LOAD_ATTR', self.mangle(node.attrname))
+ load_op = self._checkViewAttr('LOAD_ATTR', 'LOAD_VIEWATTR',
+ node.attrname)
+ self.emit(load_op, self.mangle(node.attrname))
# next five implement assignments
@@ -958,9 +969,13 @@
def visitAssAttr(self, node):
self.visit(node.expr)
if node.flags == 'OP_ASSIGN':
- self.emit('STORE_ATTR', self.mangle(node.attrname))
+ op = self._checkViewAttr('STORE_ATTR', 'STORE_VIEWATTR',
+ node.attrname)
+ self.emit(op, self.mangle(node.attrname))
elif node.flags == 'OP_DELETE':
- self.emit('DELETE_ATTR', self.mangle(node.attrname))
+ op = self._checkViewAttr('DELETE_ATTR', 'DELETE_VIEWATTR',
+ node.attrname)
+ self.emit(op, self.mangle(node.attrname))
else:
print "warning: unexpected flags:", node.flags
print node
@@ -1016,10 +1031,14 @@
if mode == "load":
self.visit(node.expr)
self.emit('DUP_TOP')
- self.emit('LOAD_ATTR', self.mangle(node.attrname))
+ op = self._checkViewAttr('LOAD_ATTR', 'LOAD_VIEWATTR',
+ node.attrname)
+ self.emit(op, self.mangle(node.attrname))
elif mode == "store":
self.emit('ROT_TWO')
- self.emit('STORE_ATTR', self.mangle(node.attrname))
+ op = self._checkViewAttr('STORE_ATTR', 'STORE_VIEWATTR',
+ node.attrname)
+ self.emit(op, self.mangle(node.attrname))
def visitAugSlice(self, node, mode):
if mode == "load":
Modified: python/branches/twouters-dictviews-backport/Lib/test/test_compiler.py
==============================================================================
--- python/branches/twouters-dictviews-backport/Lib/test/test_compiler.py (original)
+++ python/branches/twouters-dictviews-backport/Lib/test/test_compiler.py Mon Feb 26 23:24:25 2007
@@ -154,6 +154,40 @@
exec c in dct
self.assertEquals(dct.get('result'), 1)
+ def testDictViews(self):
+ class Dict(dict): pass
+ class NonDict:
+ def keys(self): pass
+ def items(self): pass
+ def values(self): pass
+ def viewkeys(self): pass
+ def viewitems(self): pass
+ def viewvalues(self): pass
+ c = compiler.compile('from __future__ import dictviews\n'
+ 'keys, items, values = d.keys, d.items, d.values\n',
+ '<string>',
+ 'exec')
+ obj = {}
+ dct = {'d': obj}
+ exec c in dct
+ self.assertEquals(dct['keys'].__name__, obj.viewkeys.__name__)
+ self.assertEquals(dct['items'].__name__, obj.viewitems.__name__)
+ self.assertEquals(dct['values'].__name__, obj.viewvalues.__name__)
+
+ obj = Dict()
+ dct = {'d': obj}
+ exec c in dct
+ self.assertEquals(dct['keys'].__name__, obj.viewkeys.__name__)
+ self.assertEquals(dct['items'].__name__, obj.viewitems.__name__)
+ self.assertEquals(dct['values'].__name__, obj.viewvalues.__name__)
+
+ obj = NonDict()
+ dct = {'d': obj}
+ exec c in dct
+ self.assertEquals(dct['keys'].__name__, obj.keys.__name__)
+ self.assertEquals(dct['items'].__name__, obj.items.__name__)
+ self.assertEquals(dct['values'].__name__, obj.values.__name__)
+
NOLINENO = (compiler.ast.Module, compiler.ast.Stmt, compiler.ast.Discard)
Modified: python/branches/twouters-dictviews-backport/Lib/test/test_dict.py
==============================================================================
--- python/branches/twouters-dictviews-backport/Lib/test/test_dict.py (original)
+++ python/branches/twouters-dictviews-backport/Lib/test/test_dict.py Mon Feb 26 23:24:25 2007
@@ -56,7 +56,7 @@
def test_items(self):
d = {}
- self.assertEqual(list(d.items(), [])
+ self.assertEqual(list(d.items()), [])
d = {1:2}
self.assertEqual(d.items(), [(1, 2)])
@@ -491,6 +491,89 @@
else:
self.fail("missing KeyError")
+ def test_dictviews_future(self):
+ import __future__
+
+ d = {'a': 1, 'b': 2, 'c': 3}
+ c = compile("d.keys", "d.keys", "eval", 0)
+ k = eval(c, locals())
+ self.assertEquals(k.__name__, d.keys.__name__)
+ c = compile("d.items", "d.items", "eval", 0)
+ k = eval(c, locals())
+ self.assertEquals(k.__name__, d.items.__name__)
+ c = compile("d.values", "d.values", "eval", 0)
+ k = eval(c, locals())
+ self.assertEquals(k.__name__, d.values.__name__)
+ c = compile("d.keys", "d.keys", "eval",
+ __future__.CO_FUTURE_DICTVIEWS)
+ k = eval(c, locals())
+ self.assertEquals(k.__name__, d.viewkeys.__name__)
+ c = compile("d.items", "d.items", "eval",
+ __future__.CO_FUTURE_DICTVIEWS)
+ k = eval(c, locals())
+ self.assertEquals(k.__name__, d.viewitems.__name__)
+ c = compile("d.values", "d.values", "eval",
+ __future__.CO_FUTURE_DICTVIEWS)
+ k = eval(c, locals())
+ self.assertEquals(k.__name__, d.viewvalues.__name__)
+
+ d = Dict(a=1, b=2, c=3)
+ c = compile("d.keys", "d.keys", "eval", 0)
+ k = eval(c, locals())
+ self.assertEquals(k.__name__, d.keys.__name__)
+ c = compile("d.items", "d.items", "eval", 0)
+ k = eval(c, locals())
+ self.assertEquals(k.__name__, d.items.__name__)
+ c = compile("d.values", "d.values", "eval", 0)
+ k = eval(c, locals())
+ self.assertEquals(k.__name__, d.values.__name__)
+ c = compile("d.keys", "d.keys", "eval",
+ __future__.CO_FUTURE_DICTVIEWS)
+ k = eval(c, locals())
+ self.assertEquals(k.__name__, d.viewkeys.__name__)
+ c = compile("d.items", "d.items", "eval",
+ __future__.CO_FUTURE_DICTVIEWS)
+ k = eval(c, locals())
+ self.assertEquals(k.__name__, d.viewitems.__name__)
+ c = compile("d.values", "d.values", "eval",
+ __future__.CO_FUTURE_DICTVIEWS)
+ k = eval(c, locals())
+ self.assertEquals(k.__name__, d.viewvalues.__name__)
+
+ class NonDict:
+ def __init__(self, *args, **kwargs):
+ self.d = dict(*args, **kwargs)
+ def keys(self): return self.d.keys()
+ def items(self): return self.d.items()
+ def values(self): return self.d.values()
+ # these should *not* end up being used
+ def viewkeys(self): pass
+ def viewitems(self): pass
+ def viewvalues(self): pass
+
+ d = NonDict(a=1, b=2, c=3)
+ c = compile("d.keys", "d.keys", "eval", 0)
+ k = eval(c, locals())
+ self.assertEquals(k.__name__, d.keys.__name__)
+ c = compile("d.items", "d.items", "eval", 0)
+ k = eval(c, locals())
+ self.assertEquals(k.__name__, d.items.__name__)
+ c = compile("d.values", "d.values", "eval", 0)
+ k = eval(c, locals())
+ self.assertEquals(k.__name__, d.values.__name__)
+ c = compile("d.keys", "d.keys", "eval",
+ __future__.CO_FUTURE_DICTVIEWS)
+ k = eval(c, locals())
+ self.assertEquals(k.__name__, d.keys.__name__)
+ c = compile("d.items", "d.items", "eval",
+ __future__.CO_FUTURE_DICTVIEWS)
+ k = eval(c, locals())
+ self.assertEquals(k.__name__, d.items.__name__)
+ c = compile("d.values", "d.values", "eval",
+ __future__.CO_FUTURE_DICTVIEWS)
+ k = eval(c, locals())
+ self.assertEquals(k.__name__, d.values.__name__)
+
from test import mapping_tests
Modified: python/branches/twouters-dictviews-backport/Python/bltinmodule.c
==============================================================================
--- python/branches/twouters-dictviews-backport/Python/bltinmodule.c (original)
+++ python/branches/twouters-dictviews-backport/Python/bltinmodule.c Mon Feb 26 23:24:25 2007
@@ -1079,6 +1079,8 @@
result = _PyObject_SetViewAttr(v, name, (PyObject *)NULL);
} else
result = PyObject_SetAttr(v, name, (PyObject *)NULL);
+ if (result != 0)
+ return NULL;
Py_INCREF(Py_None);
return Py_None;
}
More information about the Python-checkins
mailing list