[Python-checkins] r53958 - in python/branches/twouters-dictviews-backport: Include/code.h Include/compile.h Include/object.h Include/opcode.h Include/pythonrun.h Lib/__future__.py Lib/opcode.py Objects/object.c Python/ceval.c Python/compile.c Python/future.c

thomas.wouters python-checkins at python.org
Mon Feb 26 21:27:09 CET 2007


Author: thomas.wouters
Date: Mon Feb 26 21:27:03 2007
New Revision: 53958

Modified:
   python/branches/twouters-dictviews-backport/Include/code.h
   python/branches/twouters-dictviews-backport/Include/compile.h
   python/branches/twouters-dictviews-backport/Include/object.h
   python/branches/twouters-dictviews-backport/Include/opcode.h
   python/branches/twouters-dictviews-backport/Include/pythonrun.h
   python/branches/twouters-dictviews-backport/Lib/__future__.py
   python/branches/twouters-dictviews-backport/Lib/opcode.py
   python/branches/twouters-dictviews-backport/Objects/object.c
   python/branches/twouters-dictviews-backport/Python/ceval.c
   python/branches/twouters-dictviews-backport/Python/compile.c
   python/branches/twouters-dictviews-backport/Python/future.c
Log:

Future statement for d.keys() to return a keys view (and similar for items
and values.) Works by specialcasing dicts (and subclasses), but dict-alikes
(even those with both 'keys' and 'viewkeys' attributes) won't feel the
magic; they don't automatically get it in Python 3.0 either.

Still to do: fixing getattr() to do the same thing.



Modified: python/branches/twouters-dictviews-backport/Include/code.h
==============================================================================
--- python/branches/twouters-dictviews-backport/Include/code.h	(original)
+++ python/branches/twouters-dictviews-backport/Include/code.h	Mon Feb 26 21:27:03 2007
@@ -48,6 +48,7 @@
 #define CO_FUTURE_DIVISION    	0x2000
 #define CO_FUTURE_ABSOLUTE_IMPORT 0x4000 /* do absolute imports by default */
 #define CO_FUTURE_WITH_STATEMENT  0x8000
+#define CO_FUTURE_DICTVIEWS	0x10000
 
 /* This should be defined if a future statement modifies the syntax.
    For example, when a keyword is added.

Modified: python/branches/twouters-dictviews-backport/Include/compile.h
==============================================================================
--- python/branches/twouters-dictviews-backport/Include/compile.h	(original)
+++ python/branches/twouters-dictviews-backport/Include/compile.h	Mon Feb 26 21:27:03 2007
@@ -24,6 +24,7 @@
 #define FUTURE_DIVISION "division"
 #define FUTURE_ABSOLUTE_IMPORT "absolute_import"
 #define FUTURE_WITH_STATEMENT "with_statement"
+#define FUTURE_DICTVIEWS "dictviews"
 
 struct _mod; /* Declare the existence of this type */
 PyAPI_FUNC(PyCodeObject *) PyAST_Compile(struct _mod *, const char *,

Modified: python/branches/twouters-dictviews-backport/Include/object.h
==============================================================================
--- python/branches/twouters-dictviews-backport/Include/object.h	(original)
+++ python/branches/twouters-dictviews-backport/Include/object.h	Mon Feb 26 21:27:03 2007
@@ -402,7 +402,9 @@
 PyAPI_FUNC(int) PyObject_SetAttrString(PyObject *, const char *, PyObject *);
 PyAPI_FUNC(int) PyObject_HasAttrString(PyObject *, const char *);
 PyAPI_FUNC(PyObject *) PyObject_GetAttr(PyObject *, PyObject *);
+PyAPI_FUNC(PyObject *) _PyObject_GetViewAttr(PyObject *, PyObject *);
 PyAPI_FUNC(int) PyObject_SetAttr(PyObject *, PyObject *, PyObject *);
+PyAPI_FUNC(int) _PyObject_SetViewAttr(PyObject *, PyObject *, PyObject *);
 PyAPI_FUNC(int) PyObject_HasAttr(PyObject *, PyObject *);
 PyAPI_FUNC(PyObject **) _PyObject_GetDictPtr(PyObject *);
 PyAPI_FUNC(PyObject *) PyObject_SelfIter(PyObject *);

Modified: python/branches/twouters-dictviews-backport/Include/opcode.h
==============================================================================
--- python/branches/twouters-dictviews-backport/Include/opcode.h	(original)
+++ python/branches/twouters-dictviews-backport/Include/opcode.h	Mon Feb 26 21:27:03 2007
@@ -103,12 +103,13 @@
 #define COMPARE_OP	106	/* Comparison operator */
 #define IMPORT_NAME	107	/* Index in name list */
 #define IMPORT_FROM	108	/* Index in name list */
-
+#define LOAD_VIEWATTR   109	/* Index in name list */
 #define JUMP_FORWARD	110	/* Number of bytes to skip */
 #define JUMP_IF_FALSE	111	/* "" */
 #define JUMP_IF_TRUE	112	/* "" */
 #define JUMP_ABSOLUTE	113	/* Target byte offset from beginning of code */
-
+#define STORE_VIEWATTR  114	/* Index in name list */
+#define DELETE_VIEWATTR 115	/* Index in name list */
 #define LOAD_GLOBAL	116	/* Index in name list */
 
 #define CONTINUE_LOOP	119	/* Start of loop (absolute) */

Modified: python/branches/twouters-dictviews-backport/Include/pythonrun.h
==============================================================================
--- python/branches/twouters-dictviews-backport/Include/pythonrun.h	(original)
+++ python/branches/twouters-dictviews-backport/Include/pythonrun.h	Mon Feb 26 21:27:03 2007
@@ -8,7 +8,7 @@
 #endif
 
 #define PyCF_MASK (CO_FUTURE_DIVISION | CO_FUTURE_ABSOLUTE_IMPORT | \
-                   CO_FUTURE_WITH_STATEMENT)
+                   CO_FUTURE_WITH_STATEMENT | CO_FUTURE_DICTVIEWS)
 #define PyCF_MASK_OBSOLETE (CO_NESTED)
 #define PyCF_SOURCE_IS_UTF8  0x0100
 #define PyCF_DONT_IMPLY_DEDENT 0x0200

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 21:27:03 2007
@@ -66,6 +66,7 @@
 CO_FUTURE_DIVISION   = 0x2000   # division
 CO_FUTURE_ABSOLUTE_IMPORT = 0x4000 # perform absolute imports by default
 CO_FUTURE_WITH_STATEMENT  = 0x8000   # with statement
+CO_FUTURE_DICTVIEWS  = 0x10000
 
 class _Feature:
     def __init__(self, optionalRelease, mandatoryRelease, compiler_flag):
@@ -114,3 +115,7 @@
 with_statement = _Feature((2, 5, 0, "alpha", 1),
                           (2, 6, 0, "alpha", 0),
                           CO_FUTURE_WITH_STATEMENT)
+
+dictviews = _Feature((2, 6, 0, "alpha", 1),
+                     (3, 0, 0, "alpha", 0),
+                     CO_FUTURE_DICTVIEWS)

Modified: python/branches/twouters-dictviews-backport/Lib/opcode.py
==============================================================================
--- python/branches/twouters-dictviews-backport/Lib/opcode.py	(original)
+++ python/branches/twouters-dictviews-backport/Lib/opcode.py	Mon Feb 26 21:27:03 2007
@@ -144,12 +144,13 @@
 hascompare.append(106)
 name_op('IMPORT_NAME', 107)     # Index in name list
 name_op('IMPORT_FROM', 108)     # Index in name list
-
+name_op('LOAD_VIEWATTR', 109)	# Index in name list
 jrel_op('JUMP_FORWARD', 110)    # Number of bytes to skip
 jrel_op('JUMP_IF_FALSE', 111)   # ""
 jrel_op('JUMP_IF_TRUE', 112)    # ""
 jabs_op('JUMP_ABSOLUTE', 113)   # Target byte offset from beginning of code
-
+name_op('STORE_VIEWATTR', 114)	# Index in name list
+name_op('DELETE_VIEWATTR', 115) # Index in name list
 name_op('LOAD_GLOBAL', 116)     # Index in name list
 
 jabs_op('CONTINUE_LOOP', 119)   # Target address

Modified: python/branches/twouters-dictviews-backport/Objects/object.c
==============================================================================
--- python/branches/twouters-dictviews-backport/Objects/object.c	(original)
+++ python/branches/twouters-dictviews-backport/Objects/object.c	Mon Feb 26 21:27:03 2007
@@ -1100,6 +1100,33 @@
 }
 
 PyObject *
+_PyObject_GetViewAttr(PyObject *v, PyObject *name)
+{
+	/* Wrapper around PyObject_GetAttr that translates
+	   dict.keys/items/values into dict.viewkeys/viewitems/viewvalues
+	   for all subclasses of dict. It doesn't care about dict-like
+	   objects even if they have view* attrs, and doesn't check
+	   whether the attribute is actually one of keys/items/values */
+	if (PyDict_Check(v)) {
+		static PyObject *viewstr;
+		PyObject *result;
+
+		if (viewstr == NULL) {
+			viewstr = PyString_InternFromString("view");
+			if (viewstr == NULL)
+				return NULL;
+		}
+		name = PyNumber_Add(viewstr, name);
+		if (name == NULL)
+			return NULL;
+		result = PyObject_GetAttr(v, name);
+		Py_DECREF(name);
+		return result;
+	}
+	return PyObject_GetAttr(v, name);
+}
+
+PyObject *
 PyObject_GetAttr(PyObject *v, PyObject *name)
 {
 	PyTypeObject *tp = v->ob_type;
@@ -1146,6 +1173,29 @@
 }
 
 int
+_PyObject_SetViewAttr(PyObject *v, PyObject *name, PyObject *value)
+{
+	/* Like _PyObject_GetViewAttr(), but for setting/deleting */
+	if (PyDict_Check(v)) {
+		static PyObject *viewstr;
+		int result;
+
+		if (viewstr == NULL) {
+			viewstr = PyString_InternFromString("view");
+			if (viewstr == NULL)
+				return -1;
+		}
+		name = PyNumber_Add(viewstr, name);
+		if (name == NULL)
+			return -1;
+		result = PyObject_SetAttr(v, name, value);
+		Py_DECREF(name);
+		return result;
+	}
+	return PyObject_SetAttr(v, name, value);
+}
+
+int
 PyObject_SetAttr(PyObject *v, PyObject *name, PyObject *value)
 {
 	PyTypeObject *tp = v->ob_type;

Modified: python/branches/twouters-dictviews-backport/Python/ceval.c
==============================================================================
--- python/branches/twouters-dictviews-backport/Python/ceval.c	(original)
+++ python/branches/twouters-dictviews-backport/Python/ceval.c	Mon Feb 26 21:27:03 2007
@@ -1796,6 +1796,17 @@
 			if (err == 0) continue;
 			break;
 
+		case STORE_VIEWATTR:
+			w = GETITEM(names, oparg);
+			v = TOP();
+			u = SECOND();
+			STACKADJ(-2);
+			err = _PyObject_SetViewAttr(v, w, u); /* v.w = u */
+			Py_DECREF(v);
+			Py_DECREF(u);
+			if (err == 0) continue;
+			break;
+
 		case DELETE_ATTR:
 			w = GETITEM(names, oparg);
 			v = POP();
@@ -1804,6 +1815,13 @@
 			Py_DECREF(v);
 			break;
 
+		case DELETE_VIEWATTR:
+			w = GETITEM(names, oparg);
+			v = POP();
+			err = _PyObject_SetViewAttr(v, w, (PyObject *)NULL);
+			Py_DECREF(v);
+			break;
+
 		case STORE_GLOBAL:
 			w = GETITEM(names, oparg);
 			v = POP();
@@ -2003,6 +2021,16 @@
 			if (x != NULL) continue;
 			break;
 
+		case LOAD_VIEWATTR:
+			w = GETITEM(names, oparg);
+			v = TOP();
+			x = _PyObject_GetViewAttr(v, w);
+			Py_DECREF(v);
+			SET_TOP(x);
+			if (x != NULL)
+				continue;
+			break;
+
 		case COMPARE_OP:
 			w = POP();
 			v = TOP();

Modified: python/branches/twouters-dictviews-backport/Python/compile.c
==============================================================================
--- python/branches/twouters-dictviews-backport/Python/compile.c	(original)
+++ python/branches/twouters-dictviews-backport/Python/compile.c	Mon Feb 26 21:27:03 2007
@@ -155,6 +155,7 @@
 static basicblock *compiler_use_new_block(struct compiler *);
 static int compiler_error(struct compiler *, const char *);
 static int compiler_nameop(struct compiler *, identifier, expr_context_ty);
+static int compiler_attrop(struct compiler *, expr_ty);
 
 static PyCodeObject *compiler_mod(struct compiler *, mod_ty);
 static int compiler_visit_stmt(struct compiler *, stmt_ty);
@@ -781,8 +782,10 @@
 			return 1;
 
 		case STORE_ATTR:
+		case STORE_VIEWATTR:
 			return -2;
 		case DELETE_ATTR:
+		case DELETE_VIEWATTR:
 			return -1;
 		case STORE_GLOBAL:
 			return -1;
@@ -800,6 +803,7 @@
 		case BUILD_MAP:
 			return 1;
 		case LOAD_ATTR:
+		case LOAD_VIEWATTR:
 			return 0;
 		case COMPARE_OP:
 			return -1;
@@ -2942,31 +2946,7 @@
 		break;
 	/* The following exprs can be assignment targets. */
 	case Attribute_kind:
-		if (e->v.Attribute.ctx != AugStore)
-			VISIT(c, expr, e->v.Attribute.value);
-		switch (e->v.Attribute.ctx) {
-		case AugLoad:
-			ADDOP(c, DUP_TOP);
-			/* Fall through to load */
-		case Load:
-			ADDOP_NAME(c, LOAD_ATTR, e->v.Attribute.attr, names);
-			break;
-		case AugStore:
-			ADDOP(c, ROT_TWO);
-			/* Fall through to save */
-		case Store:
-			ADDOP_NAME(c, STORE_ATTR, e->v.Attribute.attr, names);
-			break;
-		case Del:
-			ADDOP_NAME(c, DELETE_ATTR, e->v.Attribute.attr, names);
-			break;
-		case Param:
-		default:
-			PyErr_SetString(PyExc_SystemError,
-					"param invalid in attribute expression");
-			return 0;
-		}
-		break;
+		return compiler_attrop(c, e);
 	case Subscript_kind:
 		switch (e->v.Subscript.ctx) {
 		case AugLoad:
@@ -3052,6 +3032,50 @@
 	return 1;
 }
 
+	/* Helper to handle dictviews future-import magic */
+static int
+compiler_attrop(struct compiler *c, expr_ty e)
+{
+	int needviews = 0;
+	
+	if (c->c_flags && (c->c_flags->cf_flags & CO_FUTURE_DICTVIEWS)) {
+		const char *attrstr = PyString_AS_STRING(e->v.Attribute.attr);
+		if (strcmp(attrstr, "keys") == 0 ||
+		    strcmp(attrstr, "items") == 0 ||
+		    strcmp(attrstr, "values") == 0)
+			needviews = 1;
+	}
+
+	if (e->v.Attribute.ctx != AugStore)
+		VISIT(c, expr, e->v.Attribute.value);
+	switch (e->v.Attribute.ctx) {
+	case AugLoad:
+		ADDOP(c, DUP_TOP);
+		/* Fall through to load */
+	case Load:
+		ADDOP_NAME(c, needviews ? LOAD_VIEWATTR : LOAD_ATTR,
+			   e->v.Attribute.attr, names);
+		break;
+	case AugStore:
+		ADDOP(c, ROT_TWO);
+		/* Fall through to save */
+	case Store:
+		ADDOP_NAME(c, needviews ? STORE_VIEWATTR : STORE_ATTR,
+			   e->v.Attribute.attr, names);
+		break;
+	case Del:
+		ADDOP_NAME(c, needviews ? DELETE_VIEWATTR : DELETE_ATTR,
+		           e->v.Attribute.attr, names);
+		break;
+	case Param:
+	default:
+		PyErr_SetString(PyExc_SystemError,
+				"param invalid in attribute expression");
+		return 0;
+	}
+	return 1;
+}
+
 static int
 compiler_push_fblock(struct compiler *c, enum fblocktype t, basicblock *b)
 {

Modified: python/branches/twouters-dictviews-backport/Python/future.c
==============================================================================
--- python/branches/twouters-dictviews-backport/Python/future.c	(original)
+++ python/branches/twouters-dictviews-backport/Python/future.c	Mon Feb 26 21:27:03 2007
@@ -33,6 +33,8 @@
 			ff->ff_features |= CO_FUTURE_ABSOLUTE_IMPORT;
 		} else if (strcmp(feature, FUTURE_WITH_STATEMENT) == 0) {
 			ff->ff_features |= CO_FUTURE_WITH_STATEMENT;
+		} else if (strcmp(feature, FUTURE_DICTVIEWS) == 0) {
+			ff->ff_features |= CO_FUTURE_DICTVIEWS;
 		} else if (strcmp(feature, "braces") == 0) {
 			PyErr_SetString(PyExc_SyntaxError,
 					"not a chance");


More information about the Python-checkins mailing list