Author: Ronan Lamy <ronan.l...@gmail.com>
Branch: online-transforms
Changeset: r74194:8cff090d32af
Date: 2014-10-24 22:57 +0200
http://bitbucket.org/pypy/pypy/changeset/8cff090d32af/

Log:    Use normalize_method in bk.immutablevalue()

diff --git a/rpython/annotator/bookkeeper.py b/rpython/annotator/bookkeeper.py
--- a/rpython/annotator/bookkeeper.py
+++ b/rpython/annotator/bookkeeper.py
@@ -21,6 +21,7 @@
 from rpython.annotator.argument import simple_args
 from rpython.rlib.objectmodel import r_dict, Symbolic
 from rpython.tool.algo.unionfind import UnionFind
+from rpython.tool.descriptor import normalize_method, InstanceMethod
 from rpython.rtyper import extregistry
 
 
@@ -223,6 +224,11 @@
     def immutablevalue(self, x):
         """The most precise SomeValue instance that contains the
         immutable value x."""
+        if callable(x):
+            try:
+                x = normalize_method(x)
+            except ValueError:
+                pass
         tp = type(x)
         if issubclass(tp, Symbolic): # symbolic constants support
             result = x.annotation()
@@ -314,19 +320,15 @@
         elif tp is type:
             result = SomeConstantType(x, self)
         elif callable(x):
-            if hasattr(x, '__self__'):
-                if x.__self__ is not None:
+            if isinstance(x, InstanceMethod):
+                if x.im_self is not None:
                     # bound instance method
-                    s_self = self.immutablevalue(x.__self__)
-                    result = s_self.find_method(x.__name__)
+                    s_self = self.immutablevalue(x.im_self)
+                    result = s_self.find_method(x.im_func.__name__)
                 else:
                     # unbound method
                     cls_s = self.annotationclass(x.im_class)
-                    result = cls_s.find_unboundmethod(x.__name__)
-            elif hasattr(x, '__objclass__'):
-                # builtin unbound method on CPython (aka 'method_descriptor')
-                cls_s = self.annotationclass(x.__objclass__)
-                result = cls_s.find_unboundmethod(x.__name__)
+                    result = cls_s.find_unboundmethod(x.im_func.__name__)
             else:
                 result = None
             if result is None:
@@ -371,7 +373,7 @@
                     result = self.getfrozen(pyobj)
                 else:
                     result = description.ClassDesc(self, pyobj)
-            elif isinstance(pyobj, types.MethodType):
+            elif isinstance(pyobj, InstanceMethod):
                 if pyobj.im_self is None:   # unbound
                     return self.getdesc(pyobj.im_func)
                 if hasattr(pyobj.im_self, '_cleanup_'):
@@ -382,10 +384,9 @@
                         self.getdesc(pyobj.im_func),            # funcdesc
                         self.getdesc(pyobj.im_self))            # frozendesc
                 else: # regular method
-                    origincls, name = origin_of_meth(pyobj)
+                    origincls = pyobj.im_class
+                    name = pyobj.im_func.__name__
                     self.see_mutable(pyobj.im_self)
-                    assert pyobj == getattr(pyobj.im_self, name), (
-                        "%r is not %s.%s ??" % (pyobj, pyobj.im_self, name))
                     # emulate a getattr to make sure it's on the classdef
                     classdef = self.getuniqueclassdef(pyobj.im_class)
                     classdef.find_attribute(name)
diff --git a/rpython/annotator/builtin.py b/rpython/annotator/builtin.py
--- a/rpython/annotator/builtin.py
+++ b/rpython/annotator/builtin.py
@@ -3,6 +3,7 @@
 """
 import sys
 
+from rpython.tool.descriptor import normalize_method
 from rpython.annotator.model import (
     SomeInteger, SomeObject, SomeChar, SomeBool, SomeString, SomeTuple,
     SomeUnicodeCodePoint, SomeFloat, unionof, SomeUnicodeString,
@@ -255,12 +256,12 @@
         BUILTIN_ANALYZERS[original] = value
 
 
-@analyzer_for(getattr(object.__init__, 'im_func', object.__init__))
+@analyzer_for(normalize_method(object.__init__))
 def object_init(s_self, *args):
     # ignore - mostly used for abstract classes initialization
     pass
 
-@analyzer_for(getattr(EnvironmentError.__init__, 'im_func', 
EnvironmentError.__init__))
+@analyzer_for(normalize_method(EnvironmentError.__init__))
 def EnvironmentError_init(s_self, *args):
     pass
 
@@ -269,7 +270,7 @@
 except NameError:
     pass
 else:
-    @analyzer_for(getattr(WindowsError.__init__, 'im_func', 
WindowsError.__init__))
+    @analyzer_for(normalize_method(WindowsError.__init__))
     def WindowsError_init(s_self, *args):
         pass
 
diff --git a/rpython/tool/descriptor.py b/rpython/tool/descriptor.py
--- a/rpython/tool/descriptor.py
+++ b/rpython/tool/descriptor.py
@@ -30,6 +30,10 @@
     def __hash__(self):
         return hash((self.im_func, self.im_self))
 
+    @property
+    def __name__(self):
+        return self.im_func.__name__
+
 if '__pypy__' in sys.modules:
     def normalize_method(method):
         '''Turn everything that behaves like a method into an InstanceMethod 
object'''
@@ -49,8 +53,9 @@
             return InstanceMethod(method.__func__, method.__self__, 
method.im_class)
         elif isinstance(method, types.BuiltinMethodType):
             im_self = method.__self__
-            desc = getattr(type(im_self), method.__name__)
-            return InstanceMethod(desc, im_self, type(im_self))
+            if im_self is not None:
+                desc = getattr(type(im_self), method.__name__)
+                return InstanceMethod(desc, im_self, type(im_self))
         elif isinstance(method, slot_wrapper):
             baseslot = getattr(method.__objclass__, method.__name__)
             cls = method.__objclass__
@@ -61,7 +66,6 @@
         elif isinstance(method, method_descriptor):
             cls = method.__objclass__
             return InstanceMethod(method, None, method.__objclass__)
-        else:
-            raise ValueError('Not a method')
+        raise ValueError('Not a method')
 
 
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to