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 method_encode(uni, s_enc): if not s_enc.is_constant(): raise TypeError("Non-constant encoding not supported") enc = s_enc.const if enc not in ('ascii', 'latin-1'): raise TypeError("Encoding %s not supported for unicode" % (enc, )) return SomeString()
def mod((str, s_tuple)): for s_item in s_tuple.items: if isinstance(s_item, (SomeUnicodeCodePoint, SomeUnicodeString)): raise NotImplementedError( "string formatting mixing strings and unicode not supported") getbookkeeper().count('strformat', str, s_tuple) return SomeString()
def lltype_to_annotation(cls, TYPE): if isinstance(TYPE, NativeInstance): return SomeOOInstance(TYPE) elif TYPE is ootype.Char: return SomeChar() elif TYPE is ootype.String: return SomeString(can_be_None=True) else: return lltype_to_annotation(TYPE)
def mod((str, s_tuple)): for s_item in s_tuple.items: if isinstance(s_item, (SomeUnicodeCodePoint, SomeUnicodeString)): raise NotImplementedError( "string formatting mixing strings and unicode not supported" ) getbookkeeper().count('strformat', str, s_tuple) no_nul = str.no_nul for s_item in s_tuple.items: if isinstance(s_item, SomeFloat): pass # or s_item is a subclass, like SomeInteger elif isinstance(s_item, SomeString) and s_item.no_nul: pass else: no_nul = False break return SomeString(no_nul=no_nul)
def register_formatd(self): ll_strtod = self.llexternal('LL_strtod_formatd', [rffi.DOUBLE, rffi.CHAR, rffi.INT], rffi.CCHARP, sandboxsafe=True, threadsafe=False) # Like PyOS_double_to_string(), when PY_NO_SHORT_FLOAT_REPR is defined def llimpl(x, code, precision, flags): upper = False if code == 'r': code = 'g' precision = 17 elif code == 'E': code = 'e' upper = True elif code == 'F': code = 'f' upper = True elif code == 'G': code = 'g' upper = True res = ll_strtod(x, code, precision) s = rffi.charp2str(res) if flags & rfloat.DTSF_ADD_DOT_0: s = ensure_decimal_point(s, precision) # Add sign when requested if flags & rfloat.DTSF_SIGN and s[0] != '-': s = '+' + s # Convert to upper case if upper: s = s.upper() return s def oofakeimpl(x, code, precision, flags): return ootype.oostring(rfloat.formatd(x, code, precision, flags), -1) return extdef([float, lltype.Char, int, int], SomeString(can_be_None=True), 'll_strtod.ll_strtod_formatd', llimpl=llimpl, oofakeimpl=oofakeimpl, sandboxsafe=True)
def register_parts_to_float(self): ll_parts_to_float = self.llexternal('LL_strtod_parts_to_float', [rffi.CCHARP] * 4, rffi.DOUBLE, sandboxsafe=True, threadsafe=False) def llimpl(sign, beforept, afterpt, exponent): res = ll_parts_to_float(sign, beforept, afterpt, exponent) if res == -1 and rposix.get_errno() == 42: raise ValueError("Wrong literal for float") return res def oofakeimpl(sign, beforept, afterpt, exponent): return rfloat.parts_to_float(sign._str, beforept._str, afterpt._str, exponent._str) tp = SomeString(can_be_None=True) return extdef([tp, tp, tp, tp], float, 'll_strtod.ll_strtod_parts_to_float', llimpl=llimpl, oofakeimpl=oofakeimpl, sandboxsafe=True)
def method_lower(str): return SomeString()
def hex(obj): getbookkeeper().count('hex', obj) return SomeString()
def str(obj): getbookkeeper().count('str', obj) return SomeString()
class ModuleInfo: def __init__(self): self.setupterm_called = False module_info = ModuleInfo() class curses_error(Exception): def __init__(self, msg): self.msg = msg from pypy.annotation.classdef import FORCE_ATTRIBUTES_INTO_CLASSES from pypy.annotation.model import SomeString # this is necessary due to annmixlevel FORCE_ATTRIBUTES_INTO_CLASSES[curses_error] = {'msg': SomeString()} def convert_error(space, error): msg = error.msg w_module = space.getbuiltinmodule('_minimal_curses') w_exception_class = space.getattr(w_module, space.wrap('error')) w_exception = space.call_function(w_exception_class, space.wrap(msg)) return OperationError(w_exception_class, w_exception) def _curses_setupterm_null(fd): # NOT_RPYTHON try: _curses.setupterm(None, fd) except _curses.error, e: raise curses_error(e.args[0])
def get_annotation(x): if isinstance(x, basestring) and len(x) > 1: return SomeString() else: return lltype_to_annotation(typeOf(x))
def mutate(self): self.listitem.mutate() def resize(self): self.listitem.mutate() self.listitem.resize() def never_resize(self): if self.listitem.resized: raise ListChangeUnallowed("list already resized") self.listitem.must_not_resize = True def mark_as_immutable(self): # Sets the 'immutable' flag. Note that unlike "never resized", # the immutable flag is only a hint. It is cleared again e.g. # when we merge with a "normal" list that doesn't have it. It # is thus expected to live only shortly, mostly for the case # of writing 'x.list[n]'. self.never_resize() if not self.listitem.mutated: self.listitem.immutable = True #else: it's fine, don't set immutable=True at all (see # test_can_merge_immutable_list_with_regular_list) MOST_GENERAL_LISTDEF = ListDef(None, SomeObject()) s_list_of_strings = SomeList( ListDef(None, SomeString(no_nul=True), resized=True))
self.listitem.immutable and 'I' or '', self.listitem.must_not_resize and '!R' or '') def mutate(self): self.listitem.mutate() def resize(self): self.listitem.mutate() self.listitem.resize() def never_resize(self): if self.listitem.resized: raise ListChangeUnallowed("list already resized") self.listitem.must_not_resize = True def mark_as_immutable(self): # Sets the 'immutable' flag. Note that unlike "never resized", # the immutable flag is only a hint. It is cleared again e.g. # when we merge with a "normal" list that doesn't have it. It # is thus expected to live only shortly, mostly for the case # of writing 'x.list[n]'. self.never_resize() if not self.listitem.mutated: self.listitem.immutable = True #else: it's fine, don't set immutable=True at all (see # test_can_merge_immutable_list_with_regular_list) MOST_GENERAL_LISTDEF = ListDef(None, SomeObject()) s_list_of_strings = SomeList(ListDef(None, SomeString(), resized = True))
result = getattr(self.obj, '__dict__', {}).keys() tp = self.obj.__class__ if isinstance(tp, type): for basetype in tp.__mro__: slots = basetype.__dict__.get('__slots__') if slots: if isinstance(slots, str): result.append(slots) else: result.extend(slots) return result class NoSuchAttrError(Exception): """Raised when an attribute is found on a class where __slots__ or _attrs_ forbits it.""" # ____________________________________________________________ FORCE_ATTRIBUTES_INTO_CLASSES = { OSError: {'errno': SomeInteger()}, } try: import termios except ImportError: pass else: FORCE_ATTRIBUTES_INTO_CLASSES[termios.error] = \ {'args': SomeTuple([SomeInteger(), SomeString()])}
def method_build(self): return SomeString()
def register_os_utime(self): UTIMBUFP = lltype.Ptr(self.UTIMBUF) os_utime = self.llexternal('utime', [rffi.CCHARP, UTIMBUFP], rffi.INT) class CConfig: _compilation_info_ = ExternalCompilationInfo( includes=['sys/time.h'] ) HAVE_UTIMES = platform.Has('utimes') config = platform.configure(CConfig) if config['HAVE_UTIMES']: class CConfig: _compilation_info_ = ExternalCompilationInfo( includes = ['sys/time.h'] ) TIMEVAL = platform.Struct('struct timeval', [('tv_sec', rffi.LONG), ('tv_usec', rffi.LONG)]) config = platform.configure(CConfig) TIMEVAL = config['TIMEVAL'] TIMEVAL2P = rffi.CArrayPtr(TIMEVAL) os_utimes = self.llexternal('utimes', [rffi.CCHARP, TIMEVAL2P], rffi.INT, compilation_info=CConfig._compilation_info_) def os_utime_platform(path, actime, modtime): import math l_times = lltype.malloc(TIMEVAL2P.TO, 2, flavor='raw') fracpart, intpart = math.modf(actime) l_times[0].c_tv_sec = int(intpart) l_times[0].c_tv_usec = int(fracpart * 1E6) fracpart, intpart = math.modf(modtime) l_times[1].c_tv_sec = int(intpart) l_times[1].c_tv_usec = int(fracpart * 1E6) error = os_utimes(path, l_times) lltype.free(l_times, flavor='raw') return error else: # we only have utime(), which does not allow sub-second resolution def os_utime_platform(path, actime, modtime): l_utimbuf = lltype.malloc(UTIMBUFP.TO, flavor='raw') l_utimbuf.c_actime = int(actime) l_utimbuf.c_modtime = int(modtime) error = os_utime(path, l_utimbuf) lltype.free(l_utimbuf, flavor='raw') return error def os_utime_llimpl(path, tp): # NB. this function is specialized; we get one version where # tp is known to be None, and one version where it is known # to be a tuple of 2 floats. if tp is None: error = os_utime(path, lltype.nullptr(UTIMBUFP.TO)) else: actime, modtime = tp error = os_utime_platform(path, actime, modtime) error = rffi.cast(lltype.Signed, error) if error == -1: raise OSError(rposix.get_errno(), "os_utime failed") os_utime_llimpl._annspecialcase_ = 'specialize:argtype(1)' s_string = SomeString() s_tuple_of_2_floats = SomeTuple([SomeFloat(), SomeFloat()]) def os_utime_normalize_args(s_path, s_times): # special handling of the arguments: they can be either # [str, (float, float)] or [str, s_None], and get normalized # to exactly one of these two. if not s_string.contains(s_path): raise Exception("os.utime() arg 1 must be a string, got %s" % ( s_path,)) case1 = s_None.contains(s_times) case2 = s_tuple_of_2_floats.contains(s_times) if case1 and case2: return [s_string, s_ImpossibleValue] #don't know which case yet elif case1: return [s_string, s_None] elif case2: return [s_string, s_tuple_of_2_floats] else: raise Exception("os.utime() arg 2 must be None or a tuple of " "2 floats, got %s" % (s_times,)) return extdef(os_utime_normalize_args, s_None, "ll_os.ll_os_utime", llimpl=os_utime_llimpl)
def add((str1, str2)): # propagate const-ness to help getattr(obj, 'prefix' + const_name) result = SomeString() if str1.is_immutable_constant() and str2.is_immutable_constant(): result.const = str1.const + str2.const return result
from pypy.rlib.rdtoa import strtod return strtod(s) sign, before_point, after_point, exponent = break_up_float(s) if not before_point and not after_point: raise ValueError return parts_to_float(sign, before_point, after_point, exponent) def oo_rstring_to_float(s): from pypy.rpython.annlowlevel import oostr from pypy.rpython.ootypesystem import ootype lls = oostr(s) return ootype.ooparse_float(lls) register_external(rstring_to_float, [SomeString(can_be_None=False)], float, llimpl=rstring_to_float_impl, ooimpl=oo_rstring_to_float, sandboxsafe=True) # float as string -> sign, beforept, afterpt, exponent def break_up_float(s): i = 0 sign = '' before_point = '' after_point = '' exponent = ''
def repr(obj): getbookkeeper().count('repr', obj) return SomeString()
def union((str1, str2)): return SomeString(can_be_None=str1.can_be_None or str2.can_be_None)
def oct(obj): getbookkeeper().count('oct', obj) return SomeString()
def method_upper(str): return SomeString()
def mod((str, args)): getbookkeeper().count('strformat', str, args) return SomeString()
def conf(): return SomeString()
def mul((str1, int2)): # xxx do we want to support this getbookkeeper().count("str_mul", str1, int2) return SomeString()
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 union((str1, str2)): can_be_None = str1.can_be_None or str2.can_be_None no_nul = str1.no_nul and str2.no_nul return SomeString(can_be_None=can_be_None, no_nul=no_nul)