summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Include/Python.h4
-rw-r--r--Lib/test/test_descr.py18
-rw-r--r--Objects/typeobject.c22
-rw-r--r--Python/compile.c12
4 files changed, 49 insertions, 7 deletions
diff --git a/Include/Python.h b/Include/Python.h
index 548ac75..ff21ad1 100644
--- a/Include/Python.h
+++ b/Include/Python.h
@@ -119,6 +119,10 @@
#include "abstract.h"
+/* _Py_Mangle is defined in compile.c */
+extern DL_IMPORT(int) _Py_Mangle(char *p, char *name, \
+ char *buffer, size_t maxlen);
+
/* PyArg_GetInt is deprecated and should not be used, use PyArg_Parse(). */
#define PyArg_GetInt(v, a) PyArg_Parse((v), "i", (a))
diff --git a/Lib/test/test_descr.py b/Lib/test/test_descr.py
index 2129a7b..dca8ea1 100644
--- a/Lib/test/test_descr.py
+++ b/Lib/test/test_descr.py
@@ -1060,6 +1060,24 @@ def slots():
vereq(x.b, 2)
vereq(x.c, 3)
+ class C4(object):
+ """Validate name mangling"""
+ __slots__ = ['__a']
+ def __init__(self, value):
+ self.__a = value
+ def get(self):
+ return self.__a
+ x = C4(5)
+ verify(not hasattr(x, '__dict__'))
+ verify(not hasattr(x, '__a'))
+ vereq(x.get(), 5)
+ try:
+ x.__a = 6
+ except AttributeError:
+ pass
+ else:
+ raise TestFailed, "Double underscored names not mangled"
+
# Make sure slot names are proper identifiers
try:
class C(object):
diff --git a/Objects/typeobject.c b/Objects/typeobject.c
index 7918af0..47613f5 100644
--- a/Objects/typeobject.c
+++ b/Objects/typeobject.c
@@ -1001,7 +1001,8 @@ type_new(PyTypeObject *metatype, PyObject *args, PyObject *kwds)
{
PyObject *name, *bases, *dict;
static char *kwlist[] = {"name", "bases", "dict", 0};
- PyObject *slots, *tmp;
+ static char buffer[256];
+ PyObject *slots, *tmp, *newslots;
PyTypeObject *type, *base, *tmptype, *winner;
etype *et;
PyMemberDef *mp;
@@ -1115,6 +1116,25 @@ type_new(PyTypeObject *metatype, PyObject *args, PyObject *kwds)
return NULL;
}
}
+
+ newslots = PyTuple_New(nslots);
+ if (newslots == NULL)
+ return NULL;
+ for (i = 0; i < nslots; i++) {
+ tmp = PyTuple_GET_ITEM(slots, i);
+ if (_Py_Mangle(PyString_AS_STRING(name),
+ PyString_AS_STRING(tmp),
+ buffer, sizeof(buffer)))
+ {
+ tmp = PyString_FromString(buffer);
+ } else {
+ Py_INCREF(tmp);
+ }
+ PyTuple_SET_ITEM(newslots, i, tmp);
+ }
+ Py_DECREF(slots);
+ slots = newslots;
+
}
if (slots != NULL) {
/* See if *this* class defines __getstate__ */
diff --git a/Python/compile.c b/Python/compile.c
index b0e125d..fa53b1e 100644
--- a/Python/compile.c
+++ b/Python/compile.c
@@ -928,8 +928,8 @@ com_addname(struct compiling *c, PyObject *v)
return com_add(c, c->c_names, c->c_name_dict, v);
}
-static int
-mangle(char *p, char *name, char *buffer, size_t maxlen)
+int
+_Py_Mangle(char *p, char *name, char *buffer, size_t maxlen)
{
/* Name mangling: __private becomes _classname__private.
This is independent from how the name is used. */
@@ -963,7 +963,7 @@ com_addop_name(struct compiling *c, int op, char *name)
int i;
char buffer[MANGLE_LEN];
- if (mangle(c->c_private, name, buffer, sizeof(buffer)))
+ if (_Py_Mangle(c->c_private, name, buffer, sizeof(buffer)))
name = buffer;
if (name == NULL || (v = PyString_InternFromString(name)) == NULL) {
c->c_errors++;
@@ -1000,7 +1000,7 @@ com_addop_varname(struct compiling *c, int kind, char *name)
int op = STOP_CODE;
char buffer[MANGLE_LEN];
- if (mangle(c->c_private, name, buffer, sizeof(buffer)))
+ if (_Py_Mangle(c->c_private, name, buffer, sizeof(buffer)))
name = buffer;
if (name == NULL || (v = PyString_InternFromString(name)) == NULL) {
c->c_errors++;
@@ -4956,7 +4956,7 @@ symtable_lookup(struct symtable *st, char *name)
PyObject *v;
int flags;
- if (mangle(st->st_private, name, buffer, sizeof(buffer)))
+ if (_Py_Mangle(st->st_private, name, buffer, sizeof(buffer)))
name = buffer;
v = PyDict_GetItemString(st->st_cur->ste_symbols, name);
if (v == NULL) {
@@ -4977,7 +4977,7 @@ symtable_add_def(struct symtable *st, char *name, int flag)
char buffer[MANGLE_LEN];
int ret;
- if (mangle(st->st_private, name, buffer, sizeof(buffer)))
+ if (_Py_Mangle(st->st_private, name, buffer, sizeof(buffer)))
name = buffer;
if ((s = PyString_InternFromString(name)) == NULL)
return -1;