[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