Commit d881105c authored by Stefan Behnel's avatar Stefan Behnel

Mark "__eq__" and friends as special methods to correctly distinguish them from attributes etc.

Replace closure class special casing from slot generation code and replace it with saner and more general "is_special" check.
parent c062260b
......@@ -1200,32 +1200,30 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
self.generate_traverse_function(scope, code, entry)
if scope.needs_tp_clear():
self.generate_clear_function(scope, code, entry)
if not scope.is_closure_class_scope:
# in closure classes, these are user defined variable names
if scope.defines_any(["__getitem__"]):
if scope.defines_any_special(["__getitem__"]):
self.generate_getitem_int_function(scope, code)
if scope.defines_any(["__setitem__", "__delitem__"]):
if scope.defines_any_special(["__setitem__", "__delitem__"]):
self.generate_ass_subscript_function(scope, code)
if scope.defines_any(["__getslice__", "__setslice__", "__delslice__"]):
if scope.defines_any_special(["__getslice__", "__setslice__", "__delslice__"]):
warning(self.pos,
"__getslice__, __setslice__, and __delslice__ are not supported by Python 3, "
"use __getitem__, __setitem__, and __delitem__ instead", 1)
code.putln("#if PY_MAJOR_VERSION >= 3")
code.putln("#error __getslice__, __setslice__, and __delslice__ not supported in Python 3.")
code.putln("#endif")
if scope.defines_any(["__setslice__", "__delslice__"]):
if scope.defines_any_special(["__setslice__", "__delslice__"]):
self.generate_ass_slice_function(scope, code)
if scope.defines_any(["__getattr__", "__getattribute__"]):
if scope.defines_any_special(["__getattr__", "__getattribute__"]):
self.generate_getattro_function(scope, code)
if scope.defines_any(["__setattr__", "__delattr__"]):
if scope.defines_any_special(["__setattr__", "__delattr__"]):
self.generate_setattro_function(scope, code)
if scope.defines_any(["__get__"]):
if scope.defines_any_special(["__get__"]):
self.generate_descr_get_function(scope, code)
if scope.defines_any(["__set__", "__delete__"]):
if scope.defines_any_special(["__set__", "__delete__"]):
self.generate_descr_set_function(scope, code)
if scope.defines_any(["__dict__"]):
if not scope.is_closure_class_scope and scope.defines_any(["__dict__"]):
self.generate_dict_getter_function(scope, code)
if scope.defines_any(TypeSlots.richcmp_special_methods):
if scope.defines_any_special(TypeSlots.richcmp_special_methods):
self.generate_richcmp_function(scope, code)
self.generate_property_accessors(scope, code)
self.generate_method_table(scope, code)
......
......@@ -892,13 +892,19 @@ class Scope(object):
pass
def defines_any(self, names):
# Test whether any of the given names are
# defined in this scope.
# Test whether any of the given names are defined in this scope.
for name in names:
if name in self.entries:
return 1
return 0
def defines_any_special(self, names):
# Test whether any of the given names are defined as special methods in this scope.
for name in names:
if name in self.entries and self.entries[name].is_special:
return 1
return 0
def infer_types(self):
from .TypeInference import get_type_inferer
get_type_inferer().infer_types(self)
......
......@@ -304,14 +304,12 @@ class MethodSlot(SlotDescriptor):
method_name_to_slot[method_name] = self
def slot_code(self, scope):
if scope.is_closure_class_scope:
return "0"
entry = scope.lookup_here(self.method_name)
if entry and entry.func_cname:
if entry and entry.is_special and entry.func_cname:
return entry.func_cname
for method_name in self.alternatives:
entry = scope.lookup_here(method_name)
if entry and entry.func_cname:
if entry and entry.is_special and entry.func_cname:
return entry.func_cname
return "0"
......@@ -367,14 +365,13 @@ class ConstructorSlot(InternalMethodSlot):
self.method = method
def slot_code(self, scope):
if scope.is_closure_class_scope:
return "0"
entry = scope.lookup_here(self.method)
if (self.slot_name != 'tp_new'
and scope.parent_type.base_type
and not scope.has_pyobject_attrs
and not scope.has_memoryview_attrs
and not scope.has_cpp_class_attrs
and not scope.lookup_here(self.method)):
and not (entry and entry.is_special)):
# if the type does not have object attributes, it can
# delegate GC methods to its parent - iff the parent
# functions are defined in the same module
......@@ -383,6 +380,8 @@ class ConstructorSlot(InternalMethodSlot):
entry = scope.parent_scope.lookup_here(scope.parent_type.base_type.name)
if entry.visibility != 'extern':
return self.slot_code(parent_type_scope)
if entry and not entry.is_special:
return "0"
return InternalMethodSlot.slot_code(self, scope)
......@@ -400,9 +399,7 @@ class SyntheticSlot(InternalMethodSlot):
self.default_value = default_value
def slot_code(self, scope):
if scope.is_closure_class_scope:
return "0"
if scope.defines_any(self.user_methods):
if scope.defines_any_special(self.user_methods):
return InternalMethodSlot.slot_code(self, scope)
else:
return self.default_value
......@@ -410,12 +407,10 @@ class SyntheticSlot(InternalMethodSlot):
class RichcmpSlot(MethodSlot):
def slot_code(self, scope):
if scope.is_closure_class_scope:
return "0"
entry = scope.lookup_here(self.method_name)
if entry and entry.func_cname:
if entry and entry.is_special and entry.func_cname:
return entry.func_cname
elif scope.defines_any(richcmp_special_methods):
elif scope.defines_any_special(richcmp_special_methods):
return scope.mangle_internal(self.slot_name)
else:
return "0"
......@@ -464,8 +459,6 @@ class SuiteSlot(SlotDescriptor):
substructures.append(self)
def is_empty(self, scope):
if scope.is_closure_class_scope:
return True
for slot in self.sub_slots:
if slot.slot_code(scope) != "0":
return False
......@@ -582,6 +575,8 @@ def get_special_method_signature(name):
slot = method_name_to_slot.get(name)
if slot:
return slot.signature
elif name in richcmp_special_methods:
return binaryfunc
else:
return None
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment