[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