def op_contains(dct, s_element): dct.dictdef.generalize_key(s_element) if dct._is_empty(): s_bool = SomeBool() s_bool.const = False return s_bool return s_Bool
def union((boo1, boo2)): s = SomeBool() if getattr(boo1, 'const', -1) == getattr(boo2, 'const', -2): s.const = boo1.const if hasattr(boo1, 'knowntypedata') and \ hasattr(boo2, 'knowntypedata'): ktd = merge_knowntypedata(boo1.knowntypedata, boo2.knowntypedata) if ktd: s.knowntypedata = ktd return s
def or_((boo1, boo2)): s = SomeBool() if boo1.is_constant(): if boo1.const: s.const = True else: return boo2 if boo2.is_constant(): if boo2.const: s.const = True return s
def and_((boo1, boo2)): s = SomeBool() if boo1.is_constant(): if not boo1.const: s.const = False else: return boo2 if boo2.is_constant(): if not boo2.const: s.const = False return s
def builtin_isinstance(s_obj, s_type, variables=None): r = SomeBool() if s_type.is_constant(): typ = s_type.const if issubclass(typ, pypy.rlib.rarithmetic.base_int): r.const = issubclass(s_obj.knowntype, typ) else: if typ == long: getbookkeeper().warning("isinstance(., long) is not RPython") if s_obj.is_constant(): r.const = isinstance(s_obj.const, long) else: if type( s_obj ) is not SomeObject: # only SomeObjects could be longs # type(s_obj) < SomeObject -> SomeBool(False) # type(s_obj) == SomeObject -> SomeBool() r.const = False return r assert not issubclass( typ, (int, long)) or typ in (bool, int, long), ( "for integers only isinstance(.,int|r_uint) are supported") if s_obj.is_constant(): r.const = isinstance(s_obj.const, typ) elif our_issubclass(s_obj.knowntype, typ): if not s_obj.can_be_none(): r.const = True elif not our_issubclass(typ, s_obj.knowntype): r.const = False elif s_obj.knowntype == int and typ == bool: # xxx this will explode in case of generalisation # from bool to int, notice that isinstance( , bool|int) # is quite border case for RPython r.const = False # XXX HACK HACK HACK # XXX HACK HACK HACK # XXX HACK HACK HACK bk = getbookkeeper() if variables is None: fn, block, i = bk.position_key op = block.operations[i] assert op.opname == "simple_call" assert len(op.args) == 3 assert op.args[0] == Constant(isinstance) variables = [op.args[1]] for variable in variables: assert bk.annotator.binding(variable) == s_obj r.knowntypedata = {} if (not isinstance(s_type, SomeBuiltin) or typ.__module__ == '__builtin__'): add_knowntypedata(r.knowntypedata, True, variables, bk.valueoftype(typ)) return r
def builtin_hasattr(s_obj, s_attr): if not s_attr.is_constant() or not isinstance(s_attr.const, str): getbookkeeper().warning("hasattr(%r, %r) is not RPythonic enough" % (s_obj, s_attr)) r = SomeBool() if s_obj.is_immutable_constant(): r.const = hasattr(s_obj.const, s_attr.const) elif isinstance(s_obj, SomePBC) and s_obj.getKind() is description.FrozenDesc: answers = {} for d in s_obj.descriptions: answer = d.s_read_attribute(s_attr.const) != s_ImpossibleValue answers[answer] = True if len(answers) == 1: r.const, = answers return r
def annotationoftype(t, bookkeeper=False): from pypy.rpython import extregistry """The most precise SomeValue instance that contains all objects of type t.""" assert isinstance(t, (type, types.ClassType)) if t is bool: return SomeBool() elif t is int: return SomeInteger() elif t is float: return SomeFloat() elif issubclass(t, str): # py.lib uses annotated str subclasses return SomeString() elif t is unicode: return SomeUnicodeString() elif t is list: return SomeList(MOST_GENERAL_LISTDEF) elif t is dict: return SomeDict(MOST_GENERAL_DICTDEF) # can't do tuple elif t is types.NoneType: return s_None elif bookkeeper and extregistry.is_registered_type(t, bookkeeper.policy): entry = extregistry.lookup_type(t, bookkeeper.policy) return entry.compute_annotation_bk(bookkeeper) elif bookkeeper and t.__module__ != '__builtin__' and t not in bookkeeper.pbctypes: classdef = bookkeeper.getuniqueclassdef(t) return SomeInstance(classdef) else: o = SomeObject() if t != object: o.knowntype = t return o
def builtin_hasattr(s_obj, s_attr): if not s_attr.is_constant() or not isinstance(s_attr.const, str): getbookkeeper().warning('hasattr(%r, %r) is not RPythonic enough' % (s_obj, s_attr)) r = SomeBool() if s_obj.is_immutable_constant(): r.const = hasattr(s_obj.const, s_attr.const) elif (isinstance(s_obj, SomePBC) and s_obj.getKind() is description.FrozenDesc): answers = {} for d in s_obj.descriptions: answer = (d.s_read_attribute(s_attr.const) != s_ImpossibleValue) answers[answer] = True if len(answers) == 1: r.const, = answers return r
def builtin_isinstance(s_obj, s_type, variables=None): r = SomeBool() if s_type.is_constant(): typ = s_type.const if issubclass(typ, pypy.rlib.rarithmetic.base_int): r.const = issubclass(s_obj.knowntype, typ) else: if typ == long: getbookkeeper().warning("isinstance(., long) is not RPython") if s_obj.is_constant(): r.const = isinstance(s_obj.const, long) else: if type(s_obj) is not SomeObject: # only SomeObjects could be longs # type(s_obj) < SomeObject -> SomeBool(False) # type(s_obj) == SomeObject -> SomeBool() r.const = False return r assert not issubclass(typ, (int, long)) or typ in ( bool, int, long, ), "for integers only isinstance(.,int|r_uint) are supported" if s_obj.is_constant(): r.const = isinstance(s_obj.const, typ) elif our_issubclass(s_obj.knowntype, typ): if not s_obj.can_be_none(): r.const = True elif not our_issubclass(typ, s_obj.knowntype): r.const = False elif s_obj.knowntype == int and typ == bool: # xxx this will explode in case of generalisation # from bool to int, notice that isinstance( , bool|int) # is quite border case for RPython r.const = False # XXX HACK HACK HACK # XXX HACK HACK HACK # XXX HACK HACK HACK bk = getbookkeeper() if variables is None: fn, block, i = bk.position_key op = block.operations[i] assert op.opname == "simple_call" assert len(op.args) == 3 assert op.args[0] == Constant(isinstance) variables = [op.args[1]] for variable in variables: assert bk.annotator.binding(variable) == s_obj r.knowntypedata = {} if not isinstance(s_type, SomeBuiltin) or typ.__module__ == "__builtin__": add_knowntypedata(r.knowntypedata, True, variables, bk.valueoftype(typ)) return r
def is_((obj1, obj2)): r = SomeBool() if obj2.is_constant(): if obj1.is_constant(): r.const = obj1.const is obj2.const if obj2.const is None and not obj1.can_be_none(): r.const = False elif obj1.is_constant(): if obj1.const is None and not obj2.can_be_none(): r.const = False # XXX HACK HACK HACK # XXX HACK HACK HACK # XXX HACK HACK HACK bk = getbookkeeper() if bk is not None: # for testing knowntypedata = r.knowntypedata = {} fn, block, i = bk.position_key annotator = bk.annotator op = block.operations[i] assert op.opname == "is_" assert len(op.args) == 2 def bind(src_obj, tgt_obj, tgt_arg): if hasattr(tgt_obj, 'is_type_of') and src_obj.is_constant(): add_knowntypedata(knowntypedata, True, tgt_obj.is_type_of, bk.valueoftype(src_obj.const)) assert annotator.binding(op.args[tgt_arg]) == tgt_obj add_knowntypedata(knowntypedata, True, [op.args[tgt_arg]], src_obj) nonnone_obj = tgt_obj if src_obj.is_constant( ) and src_obj.const is None and tgt_obj.can_be_none(): nonnone_obj = tgt_obj.nonnoneify() add_knowntypedata(knowntypedata, False, [op.args[tgt_arg]], nonnone_obj) bind(obj2, obj1, 0) bind(obj1, obj2, 1) return r
def is_true(s_obj): r = SomeBool() s_obj.is_true_behavior(r) bk = getbookkeeper() knowntypedata = r.knowntypedata = {} fn, block, i = bk.position_key op = block.operations[i] assert op.opname == "is_true" or op.opname == "nonzero" assert len(op.args) == 1 arg = op.args[0] s_nonnone_obj = s_obj if s_obj.can_be_none(): s_nonnone_obj = s_obj.nonnoneify() add_knowntypedata(knowntypedata, True, [arg], s_nonnone_obj) return r
def test_str(self): from pypy.annotation.model import SomeBool def f(flag): if flag: x = 'a' else: x = 'brrrrrrr' return len(x + 'a') llinterp, graph = self.llinterpreter_for_transformed_graph( f, [SomeBool()]) res = llinterp.eval_graph(graph, [True]) assert res == f(True) res = llinterp.eval_graph(graph, [False]) assert res == f(False)
def xor((boo1, boo2)): s = SomeBool() if boo1.is_constant() and boo2.is_constant(): s.const = boo1.const ^ boo2.const return s
def immutablevalue(self, x, need_const=True): """The most precise SomeValue instance that contains the immutable value x.""" # convert unbound methods to the underlying function if hasattr(x, 'im_self') and x.im_self is None: x = x.im_func assert not hasattr(x, 'im_self') if x is sys: # special case constant sys to someobject return SomeObject() tp = type(x) if issubclass(tp, Symbolic): # symbolic constants support result = x.annotation() result.const_box = Constant(x) return result if tp is bool: result = SomeBool() elif tp is int: result = SomeInteger(nonneg = x>=0) elif tp is long and 0 <= x <= (sys.maxint * 2 + 1): result = SomeInteger(unsigned = True) elif issubclass(tp, str): # py.lib uses annotated str subclasses if len(x) == 1: result = SomeChar() else: result = SomeString() elif tp is unicode and len(x) == 1: result = SomeUnicodeCodePoint() elif tp is tuple: result = SomeTuple(items = [self.immutablevalue(e, need_const) for e in x]) elif tp is float: result = SomeFloat() elif tp is list: if need_const: key = Constant(x) try: return self.immutable_cache[key] except KeyError: result = SomeList(ListDef(self, s_ImpossibleValue)) self.immutable_cache[key] = result for e in x: result.listdef.generalize(self.immutablevalue(e)) result.const_box = key return result else: listdef = ListDef(self, s_ImpossibleValue) for e in x: listdef.generalize(self.immutablevalue(e, False)) result = SomeList(listdef) elif tp is dict or tp is r_dict: if need_const: key = Constant(x) try: return self.immutable_cache[key] except KeyError: result = SomeDict(DictDef(self, s_ImpossibleValue, s_ImpossibleValue, is_r_dict = tp is r_dict)) self.immutable_cache[key] = result if tp is r_dict: s_eqfn = self.immutablevalue(x.key_eq) s_hashfn = self.immutablevalue(x.key_hash) result.dictdef.dictkey.update_rdict_annotations(s_eqfn, s_hashfn) done = False while not done: try: for ek, ev in x.iteritems(): result.dictdef.generalize_key(self.immutablevalue(ek)) result.dictdef.generalize_value(self.immutablevalue(ev)) except RuntimeError, r: pass else: done = True result.const_box = key return result else: dictdef = DictDef(self, s_ImpossibleValue, s_ImpossibleValue, is_r_dict = tp is r_dict) if tp is r_dict: s_eqfn = self.immutablevalue(x.key_eq) s_hashfn = self.immutablevalue(x.key_hash) dictdef.dictkey.update_rdict_annotations(s_eqfn, s_hashfn) for ek, ev in x.iteritems(): dictdef.generalize_key(self.immutablevalue(ek, False)) dictdef.generalize_value(self.immutablevalue(ev, False)) result = SomeDict(dictdef)
def pow((int1, int2), obj3): knowntype = rarithmetic.compute_restype(int1.knowntype, int2.knowntype) return SomeInteger(nonneg=int1.nonneg, knowntype=knowntype) pow.can_only_throw = [ZeroDivisionError] pow_ovf = _clone(pow, [ZeroDivisionError, OverflowError]) def inplace_pow((int1, int2)): knowntype = rarithmetic.compute_restype(int1.knowntype, int2.knowntype) return SomeInteger(nonneg=int1.nonneg, knowntype=knowntype) inplace_pow.can_only_throw = [ZeroDivisionError] def _compare_helper((int1, int2), opname, operation): r = SomeBool() if int1.is_immutable_constant() and int2.is_immutable_constant(): r.const = operation(int1.const, int2.const) # # The rest of the code propagates nonneg information between # the two arguments. # # Doing the right thing when int1 or int2 change from signed # to unsigned (r_uint) is almost impossible. See test_intcmp_bug. # Instead, we only deduce constrains on the operands in the # case where they are both signed. In other words, if y is # nonneg then "assert x>=y" will let the annotator know that # x is nonneg too, but it will not work if y is unsigned. # if not (rarithmetic.signedtype(int1.knowntype) and rarithmetic.signedtype(int2.knowntype)):
def pow((int1, int2), obj3): knowntype = rarithmetic.compute_restype(int1.knowntype, int2.knowntype) return SomeInteger(nonneg = int1.nonneg, knowntype=knowntype) pow.can_only_throw = [ZeroDivisionError] pow_ovf = _clone(pow, [ZeroDivisionError, OverflowError]) def inplace_pow((int1, int2)): knowntype = rarithmetic.compute_restype(int1.knowntype, int2.knowntype) return SomeInteger(nonneg = int1.nonneg, knowntype=knowntype) inplace_pow.can_only_throw = [ZeroDivisionError] def _compare_helper((int1, int2), opname, operation): r = SomeBool() if int1.is_immutable_constant() and int2.is_immutable_constant(): r.const = operation(int1.const, int2.const) # # The rest of the code propagates nonneg information between # the two arguments. # # Doing the right thing when int1 or int2 change from signed # to unsigned (r_uint) is almost impossible. See test_intcmp_bug. # Instead, we only deduce constrains on the operands in the # case where they are both signed. In other words, if y is # nonneg then "assert x>=y" will let the annotator know that # x is nonneg too, but it will not work if y is unsigned. # if not (rarithmetic.signedtype(int1.knowntype) and rarithmetic.signedtype(int2.knowntype)):
def immutablevalue(self, x, need_const=True): """The most precise SomeValue instance that contains the immutable value x.""" # convert unbound methods to the underlying function if hasattr(x, 'im_self') and x.im_self is None: x = x.im_func assert not hasattr(x, 'im_self') if x is sys: # special case constant sys to someobject return SomeObject() tp = type(x) if issubclass(tp, Symbolic): # symbolic constants support result = x.annotation() result.const_box = Constant(x) return result if tp is bool: result = SomeBool() elif tp is int: result = SomeInteger(nonneg=x >= 0) elif tp is long: if -sys.maxint - 1 <= x <= sys.maxint: x = int(x) result = SomeInteger(nonneg=x >= 0) else: raise Exception("seeing a prebuilt long (value %s)" % hex(x)) elif issubclass(tp, str): # py.lib uses annotated str subclasses if len(x) == 1: result = SomeChar() else: result = SomeString() elif tp is unicode: if len(x) == 1: result = SomeUnicodeCodePoint() else: result = SomeUnicodeString() elif tp is tuple: result = SomeTuple( items=[self.immutablevalue(e, need_const) for e in x]) elif tp is float: result = SomeFloat() elif tp is list: if need_const: key = Constant(x) try: return self.immutable_cache[key] except KeyError: result = SomeList(ListDef(self, s_ImpossibleValue)) self.immutable_cache[key] = result for e in x: result.listdef.generalize(self.immutablevalue(e)) result.const_box = key return result else: listdef = ListDef(self, s_ImpossibleValue) for e in x: listdef.generalize(self.immutablevalue(e, False)) result = SomeList(listdef) elif tp is dict or tp is r_dict: if need_const: key = Constant(x) try: return self.immutable_cache[key] except KeyError: result = SomeDict( DictDef(self, s_ImpossibleValue, s_ImpossibleValue, is_r_dict=tp is r_dict)) self.immutable_cache[key] = result if tp is r_dict: s_eqfn = self.immutablevalue(x.key_eq) s_hashfn = self.immutablevalue(x.key_hash) result.dictdef.dictkey.update_rdict_annotations( s_eqfn, s_hashfn) seen_elements = 0 while seen_elements != len(x): items = x.items() for ek, ev in items: result.dictdef.generalize_key( self.immutablevalue(ek)) result.dictdef.generalize_value( self.immutablevalue(ev)) result.dictdef.seen_prebuilt_key(ek) seen_elements = len(items) # if the dictionary grew during the iteration, # start over again result.const_box = key return result else: dictdef = DictDef(self, s_ImpossibleValue, s_ImpossibleValue, is_r_dict=tp is r_dict) if tp is r_dict: s_eqfn = self.immutablevalue(x.key_eq) s_hashfn = self.immutablevalue(x.key_hash) dictdef.dictkey.update_rdict_annotations(s_eqfn, s_hashfn) for ek, ev in x.iteritems(): dictdef.generalize_key(self.immutablevalue(ek, False)) dictdef.generalize_value(self.immutablevalue(ev, False)) dictdef.seen_prebuilt_key(ek) result = SomeDict(dictdef) elif tp is weakref.ReferenceType: x1 = x() if x1 is None: result = SomeWeakRef(None) # dead weakref else: s1 = self.immutablevalue(x1) assert isinstance(s1, SomeInstance) result = SomeWeakRef(s1.classdef) elif ishashable(x) and x in BUILTIN_ANALYZERS: _module = getattr(x, "__module__", "unknown") result = SomeBuiltin(BUILTIN_ANALYZERS[x], methodname="%s.%s" % (_module, x.__name__)) elif extregistry.is_registered(x, self.policy): entry = extregistry.lookup(x, self.policy) result = entry.compute_annotation_bk(self) elif isinstance(x, lltype._ptr): result = SomePtr(lltype.typeOf(x)) elif isinstance(x, llmemory.fakeaddress): result = SomeAddress() elif isinstance(x, ootype._static_meth): result = SomeOOStaticMeth(ootype.typeOf(x)) elif isinstance(x, ootype._class): result = SomeOOClass(x._INSTANCE) # NB. can be None elif isinstance(x, ootype.instance_impl): # XXX result = SomeOOInstance(ootype.typeOf(x)) elif isinstance(x, (ootype._record, ootype._string)): result = SomeOOInstance(ootype.typeOf(x)) elif isinstance(x, (ootype._object)): result = SomeOOObject() elif callable(x): if hasattr(x, 'im_self') and hasattr(x, 'im_func'): # on top of PyPy, for cases like 'l.append' where 'l' is a # global constant list, the find_method() returns non-None s_self = self.immutablevalue(x.im_self, need_const) result = s_self.find_method(x.im_func.__name__) elif hasattr(x, '__self__') and x.__self__ is not None: # for cases like 'l.append' where 'l' is a global constant list s_self = self.immutablevalue(x.__self__, need_const) result = s_self.find_method(x.__name__) if result is None: result = SomeObject() else: result = None if result is None: if (self.annotator.policy.allow_someobjects and getattr(x, '__module__', None) == '__builtin__' # XXX note that the print support functions are __builtin__ and tp not in (types.FunctionType, types.MethodType)): result = SomeObject() result.knowntype = tp # at least for types this needs to be correct else: result = SomePBC([self.getdesc(x)]) elif hasattr(x, '_freeze_') and x._freeze_(): # user-defined classes can define a method _freeze_(), which # is called when a prebuilt instance is found. If the method # returns True, the instance is considered immutable and becomes # a SomePBC(). Otherwise it's just SomeInstance(). result = SomePBC([self.getdesc(x)]) elif hasattr(x, '__class__') \ and x.__class__.__module__ != '__builtin__': self.see_mutable(x) result = SomeInstance(self.getuniqueclassdef(x.__class__)) elif x is None: return s_None else: result = SomeObject() if need_const: result.const = x return result
def immutablevalue(self, x, need_const=True): """The most precise SomeValue instance that contains the immutable value x.""" # convert unbound methods to the underlying function if hasattr(x, 'im_self') and x.im_self is None: x = x.im_func assert not hasattr(x, 'im_self') if x is sys: # special case constant sys to someobject return SomeObject() tp = type(x) if issubclass(tp, Symbolic): # symbolic constants support result = x.annotation() result.const_box = Constant(x) return result if tp is bool: result = SomeBool() elif tp is int: result = SomeInteger(nonneg = x>=0) elif tp is long: if -sys.maxint-1 <= x <= sys.maxint: x = int(x) result = SomeInteger(nonneg = x>=0) else: raise Exception("seeing a prebuilt long (value %s)" % hex(x)) elif issubclass(tp, str): # py.lib uses annotated str subclasses no_nul = not '\x00' in x if len(x) == 1: result = SomeChar(no_nul=no_nul) else: result = SomeString(no_nul=no_nul) elif tp is unicode: if len(x) == 1: result = SomeUnicodeCodePoint() else: result = SomeUnicodeString() elif tp is tuple: result = SomeTuple(items = [self.immutablevalue(e, need_const) for e in x]) elif tp is float: result = SomeFloat() elif tp is list: if need_const: key = Constant(x) try: return self.immutable_cache[key] except KeyError: result = SomeList(ListDef(self, s_ImpossibleValue)) self.immutable_cache[key] = result for e in x: result.listdef.generalize(self.immutablevalue(e)) result.const_box = key return result else: listdef = ListDef(self, s_ImpossibleValue) for e in x: listdef.generalize(self.immutablevalue(e, False)) result = SomeList(listdef) elif tp is dict or tp is r_dict: if need_const: key = Constant(x) try: return self.immutable_cache[key] except KeyError: result = SomeDict(DictDef(self, s_ImpossibleValue, s_ImpossibleValue, is_r_dict = tp is r_dict)) self.immutable_cache[key] = result if tp is r_dict: s_eqfn = self.immutablevalue(x.key_eq) s_hashfn = self.immutablevalue(x.key_hash) result.dictdef.dictkey.update_rdict_annotations(s_eqfn, s_hashfn) seen_elements = 0 while seen_elements != len(x): items = x.items() for ek, ev in items: result.dictdef.generalize_key(self.immutablevalue(ek)) result.dictdef.generalize_value(self.immutablevalue(ev)) result.dictdef.seen_prebuilt_key(ek) seen_elements = len(items) # if the dictionary grew during the iteration, # start over again result.const_box = key return result else: dictdef = DictDef(self, s_ImpossibleValue, s_ImpossibleValue, is_r_dict = tp is r_dict) if tp is r_dict: s_eqfn = self.immutablevalue(x.key_eq) s_hashfn = self.immutablevalue(x.key_hash) dictdef.dictkey.update_rdict_annotations(s_eqfn, s_hashfn) for ek, ev in x.iteritems(): dictdef.generalize_key(self.immutablevalue(ek, False)) dictdef.generalize_value(self.immutablevalue(ev, False)) dictdef.seen_prebuilt_key(ek) result = SomeDict(dictdef) elif tp is weakref.ReferenceType: x1 = x() if x1 is None: result = SomeWeakRef(None) # dead weakref else: s1 = self.immutablevalue(x1) assert isinstance(s1, SomeInstance) result = SomeWeakRef(s1.classdef) elif ishashable(x) and x in BUILTIN_ANALYZERS: _module = getattr(x,"__module__","unknown") result = SomeBuiltin(BUILTIN_ANALYZERS[x], methodname="%s.%s" % (_module, x.__name__)) elif extregistry.is_registered(x, self.policy): entry = extregistry.lookup(x, self.policy) result = entry.compute_annotation_bk(self) elif isinstance(x, lltype._ptr): result = SomePtr(lltype.typeOf(x)) elif isinstance(x, llmemory.fakeaddress): result = SomeAddress() elif isinstance(x, ootype._static_meth): result = SomeOOStaticMeth(ootype.typeOf(x)) elif isinstance(x, ootype._class): result = SomeOOClass(x._INSTANCE) # NB. can be None elif isinstance(x, ootype.instance_impl): # XXX result = SomeOOInstance(ootype.typeOf(x)) elif isinstance(x, (ootype._record, ootype._string)): result = SomeOOInstance(ootype.typeOf(x)) elif isinstance(x, (ootype._object)): result = SomeOOObject() elif callable(x): if hasattr(x, 'im_self') and hasattr(x, 'im_func'): # on top of PyPy, for cases like 'l.append' where 'l' is a # global constant list, the find_method() returns non-None s_self = self.immutablevalue(x.im_self, need_const) result = s_self.find_method(x.im_func.__name__) elif hasattr(x, '__self__') and x.__self__ is not None: # for cases like 'l.append' where 'l' is a global constant list s_self = self.immutablevalue(x.__self__, need_const) result = s_self.find_method(x.__name__) if result is None: result = SomeObject() else: result = None if result is None: if (self.annotator.policy.allow_someobjects and getattr(x, '__module__', None) == '__builtin__' # XXX note that the print support functions are __builtin__ and tp not in (types.FunctionType, types.MethodType)): result = SomeObject() result.knowntype = tp # at least for types this needs to be correct else: result = SomePBC([self.getdesc(x)]) elif hasattr(x, '_freeze_') and x._freeze_(): # user-defined classes can define a method _freeze_(), which # is called when a prebuilt instance is found. If the method # returns True, the instance is considered immutable and becomes # a SomePBC(). Otherwise it's just SomeInstance(). result = SomePBC([self.getdesc(x)]) elif hasattr(x, '__class__') \ and x.__class__.__module__ != '__builtin__': self.see_mutable(x) result = SomeInstance(self.getuniqueclassdef(x.__class__)) elif x is None: return s_None else: result = SomeObject() if need_const: result.const = x return result