Skip to content

Commit

Permalink
fix ticket #5: mangle private '__xyz' attribute names inside of Pytho…
Browse files Browse the repository at this point in the history
…n classes

--HG--
rename : tests/run/methodmangling_T5.pyx => tests/run/methodmangling_T5.py
  • Loading branch information
Stefan Behnel committed Sep 10, 2011
1 parent 57b5f0c commit bce8b98
Show file tree
Hide file tree
Showing 6 changed files with 101 additions and 25 deletions.
2 changes: 2 additions & 0 deletions Cython/Compiler/ExprNodes.py
Expand Up @@ -3800,6 +3800,8 @@ def analyse_attribute(self, env, obj_type = None):
def analyse_as_python_attribute(self, env, obj_type = None):
if obj_type is None:
obj_type = self.obj.type
# mangle private '__*' Python attributes used inside of a class
self.attribute = env.mangle_class_private_name(self.attribute)
self.member = self.attribute
self.type = py_object_type
self.is_py_attr = 1
Expand Down
1 change: 1 addition & 0 deletions Cython/Compiler/Nodes.py
Expand Up @@ -1222,6 +1222,7 @@ def create_local_scope(self, env):
if self.needs_closure:
lenv = ClosureScope(name=self.entry.name,
outer_scope = genv,
parent_scope = env,
scope_name=self.entry.cname)
else:
lenv = LocalScope(name=self.entry.name,
Expand Down
22 changes: 20 additions & 2 deletions Cython/Compiler/Symtab.py
Expand Up @@ -329,6 +329,11 @@ def mangle_internal(self, name):
return self.mangle(prefix)
#return self.parent_scope.mangle(prefix, self.name)

def mangle_class_private_name(self, name):
if self.parent_scope:
return self.parent_scope.mangle_class_private_name(name)
return name

def next_id(self, name=None):
# Return a cname fragment that is unique for this module
counters = self.global_scope().id_counters
Expand Down Expand Up @@ -1535,8 +1540,8 @@ class ClosureScope(LocalScope):

is_closure_scope = True

def __init__(self, name, scope_name, outer_scope):
LocalScope.__init__(self, name, outer_scope)
def __init__(self, name, scope_name, outer_scope, parent_scope=None):
LocalScope.__init__(self, name, outer_scope, parent_scope)
self.closure_cname = "%s%s" % (Naming.closure_scope_prefix, scope_name)

# def mangle_closure_cnames(self, scope_var):
Expand Down Expand Up @@ -1626,9 +1631,22 @@ class PyClassScope(ClassScope):

is_py_class_scope = 1

def mangle_class_private_name(self, name):
return self.mangle_special_name(name)

def mangle_special_name(self, name):
if name and name.startswith('__') and not name.endswith('__'):
name = EncodedString('_%s%s' % (self.class_name, name))
return name

def lookup_here(self, name):
name = self.mangle_special_name(name)
return ClassScope.lookup_here(self, name)

def declare_var(self, name, type, pos,
cname = None, visibility = 'private',
api = 0, in_pxd = 0, is_cdef = 0):
name = self.mangle_special_name(name)
if type is unspecified_type:
type = py_object_type
# Add an entry for a class attribute.
Expand Down
1 change: 0 additions & 1 deletion tests/bugs.txt
@@ -1,7 +1,6 @@
# This file contains tests corresponding to unresolved bugs,
# which will be skipped in the normal testing run.

methodmangling_T5
class_attribute_init_values_T18
numpy_ValueError_T172
unsignedbehaviour_T184
Expand Down
78 changes: 78 additions & 0 deletions tests/run/methodmangling_T5.py
@@ -0,0 +1,78 @@
# mode: run
# ticket: 5

class CyTest(object):
"""
>>> cy = CyTest()
>>> '_CyTest__private' in dir(cy)
True
>>> cy._CyTest__private()
8
>>> '__private' in dir(cy)
False
>>> '_CyTest__x' in dir(cy)
True
>>> '__x' in dir(cy)
False
"""
__x = 1
def __private(self): return 8

def get(self):
"""
>>> CyTest().get()
(1, 1, 8)
"""
return self._CyTest__x, self.__x, self.__private()

def get_inner(self):
"""
>>> CyTest().get_inner()
(1, 1, 8)
"""
def get(o):
return o._CyTest__x, o.__x, o.__private()
return get(self)

class CyTestSub(CyTest):
"""
>>> cy = CyTestSub()
>>> '_CyTestSub__private' in dir(cy)
True
>>> cy._CyTestSub__private()
9
>>> '_CyTest__private' in dir(cy)
True
>>> cy._CyTest__private()
8
>>> '__private' in dir(cy)
False
>>> '_CyTestSub__x' in dir(cy)
False
>>> '_CyTestSub__y' in dir(cy)
True
>>> '_CyTest__x' in dir(cy)
True
>>> '__x' in dir(cy)
False
"""
__y = 2
def __private(self): return 9

def get(self):
"""
>>> CyTestSub().get()
(1, 2, 2, 9)
"""
return self._CyTest__x, self._CyTestSub__y, self.__y, self.__private()

def get_inner(self):
"""
>>> CyTestSub().get_inner()
(1, 2, 2, 9)
"""
def get(o):
return o._CyTest__x, o._CyTestSub__y, o.__y, o.__private()
return get(self)
22 changes: 0 additions & 22 deletions tests/run/methodmangling_T5.pyx

This file was deleted.

0 comments on commit bce8b98

Please sign in to comment.